Browse Source

NET-717: DNS Fixes (#2654)

* send dns with complete entry name

* publish dns records on adding host to network from UI

* publish node dns updates when host is removed
Abhishek K 1 year ago
parent
commit
7169db78ea
7 changed files with 126 additions and 86 deletions
  1. 17 41
      controllers/hosts.go
  2. 6 20
      controllers/node.go
  3. 2 1
      logic/dns.go
  4. 15 0
      logic/extpeers.go
  5. 20 22
      logic/nodes.go
  6. 2 2
      mq/handlers.go
  7. 64 0
      mq/publishers.go

+ 17 - 41
controllers/hosts.go

@@ -227,6 +227,19 @@ func deleteHost(w http.ResponseWriter, r *http.Request) {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		return
 		return
 	}
 	}
+	for _, nodeID := range currHost.Nodes {
+		node, err := logic.GetNodeByID(nodeID)
+		if err != nil {
+			slog.Error("failed to get node", "nodeid", nodeID, "error", err)
+			continue
+		}
+		var gwClients []models.ExtClient
+		if node.IsIngressGateway {
+			gwClients = logic.GetGwExtclients(node.ID.String(), node.Network)
+		}
+		go mq.PublishMqUpdatesForDeletedNode(node, false, gwClients)
+
+	}
 	if err = logic.RemoveHost(currHost, forceDelete); err != nil {
 	if err = logic.RemoveHost(currHost, forceDelete); err != nil {
 		logger.Log(0, r.Header.Get("user"), "failed to delete a host:", err.Error())
 		logger.Log(0, r.Header.Get("user"), "failed to delete a host:", err.Error())
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
@@ -286,6 +299,7 @@ func addHostToNetwork(w http.ResponseWriter, r *http.Request) {
 			Node:   *newNode,
 			Node:   *newNode,
 		})
 		})
 		mq.PublishPeerUpdate()
 		mq.PublishPeerUpdate()
+		mq.HandleNewNodeDNS(currHost, newNode)
 	}()
 	}()
 	logger.Log(2, r.Header.Get("user"), fmt.Sprintf("added host %s to network %s", currHost.Name, network))
 	logger.Log(2, r.Header.Get("user"), fmt.Sprintf("added host %s to network %s", currHost.Name, network))
 	w.WriteHeader(http.StatusOK)
 	w.WriteHeader(http.StatusOK)
@@ -343,54 +357,16 @@ func deleteHostFromNetwork(w http.ResponseWriter, r *http.Request) {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		return
 		return
 	}
 	}
-	if node.IsRelayed {
-		// cleanup node from relayednodes on relay node
-		relayNode, err := logic.GetNodeByID(node.RelayedBy)
-		if err == nil {
-			relayedNodes := []string{}
-			for _, relayedNodeID := range relayNode.RelayedNodes {
-				if relayedNodeID == node.ID.String() {
-					continue
-				}
-				relayedNodes = append(relayedNodes, relayedNodeID)
-			}
-			relayNode.RelayedNodes = relayedNodes
-			logic.UpsertNode(&relayNode)
-		}
-	}
-	if node.IsRelay {
-		// unset all the relayed nodes
-		logic.SetRelayedNodes(false, node.ID.String(), node.RelayedNodes)
-	}
+	var gwClients []models.ExtClient
 	if node.IsIngressGateway {
 	if node.IsIngressGateway {
-		// delete ext clients belonging to ingress gateway
-		go func(node models.Node) {
-			if err = logic.DeleteGatewayExtClients(node.ID.String(), node.Network); err != nil {
-				slog.Error("failed to delete extclients", "gatewayid", node.ID.String(), "network", node.Network, "error", err.Error())
-			}
-		}(*node)
+		gwClients = logic.GetGwExtclients(node.ID.String(), node.Network)
 	}
 	}
 	logger.Log(1, "deleting node", node.ID.String(), "from host", currHost.Name)
 	logger.Log(1, "deleting node", node.ID.String(), "from host", currHost.Name)
 	if err := logic.DeleteNode(node, forceDelete); err != nil {
 	if err := logic.DeleteNode(node, forceDelete); err != nil {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("failed to delete node"), "internal"))
 		logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("failed to delete node"), "internal"))
 		return
 		return
 	}
 	}
-	node.Action = models.NODE_DELETE
-	node.PendingDelete = true
-	go func() {
-		// notify node change
-		if err := mq.NodeUpdate(node); err != nil {
-			slog.Error("error publishing node update to node", "node", node.ID, "error", err)
-		}
-		// notify of peer change
-		err = mq.PublishDeletedNodePeerUpdate(node)
-		if err != nil {
-			logger.Log(1, "error publishing peer update ", err.Error())
-		}
-		if err := mq.PublishDNSDelete(node, currHost); err != nil {
-			logger.Log(1, "error publishing dns update", err.Error())
-		}
-	}()
+	go mq.PublishMqUpdatesForDeletedNode(*node, true, gwClients)
 	logger.Log(2, r.Header.Get("user"), fmt.Sprintf("removed host %s from network %s", currHost.Name, network))
 	logger.Log(2, r.Header.Get("user"), fmt.Sprintf("removed host %s from network %s", currHost.Name, network))
 	w.WriteHeader(http.StatusOK)
 	w.WriteHeader(http.StatusOK)
 }
 }

+ 6 - 20
controllers/node.go

@@ -614,6 +614,7 @@ func deleteIngressGateway(w http.ResponseWriter, r *http.Request) {
 				if err := mq.NodeUpdate(&node); err != nil {
 				if err := mq.NodeUpdate(&node); err != nil {
 					slog.Error("error publishing node update to node", "node", node.ID, "error", err)
 					slog.Error("error publishing node update to node", "node", node.ID, "error", err)
 				}
 				}
+				mq.PublishDeleteAllExtclientsDNS(node.Network, removedClients)
 			}()
 			}()
 		}
 		}
 	}
 	}
@@ -725,7 +726,10 @@ func deleteNode(w http.ResponseWriter, r *http.Request) {
 	}
 	}
 	forceDelete := r.URL.Query().Get("force") == "true"
 	forceDelete := r.URL.Query().Get("force") == "true"
 	fromNode := r.Header.Get("requestfrom") == "node"
 	fromNode := r.Header.Get("requestfrom") == "node"
-
+	var gwClients []models.ExtClient
+	if node.IsIngressGateway {
+		gwClients = logic.GetGwExtclients(node.ID.String(), node.Network)
+	}
 	purge := forceDelete || fromNode
 	purge := forceDelete || fromNode
 	if err := logic.DeleteNode(&node, purge); err != nil {
 	if err := logic.DeleteNode(&node, purge); err != nil {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("failed to delete node"), "internal"))
 		logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("failed to delete node"), "internal"))
@@ -734,25 +738,7 @@ func deleteNode(w http.ResponseWriter, r *http.Request) {
 
 
 	logic.ReturnSuccessResponse(w, r, nodeid+" deleted.")
 	logic.ReturnSuccessResponse(w, r, nodeid+" deleted.")
 	logger.Log(1, r.Header.Get("user"), "Deleted node", nodeid, "from network", params["network"])
 	logger.Log(1, r.Header.Get("user"), "Deleted node", nodeid, "from network", params["network"])
-	go func() { // notify of peer change
-		if !fromNode {
-			node.PendingDelete = true
-			node.Action = models.NODE_DELETE
-			if err := mq.NodeUpdate(&node); err != nil {
-				slog.Error("error publishing node update to node", "node", node.ID, "error", err)
-			}
-		}
-		if err := mq.PublishDeletedNodePeerUpdate(&node); err != nil {
-			logger.Log(1, "error publishing peer update ", err.Error())
-		}
-		host, err := logic.GetHost(node.HostID.String())
-		if err != nil {
-			logger.Log(1, "failed to retrieve host for node", node.ID.String(), err.Error())
-		}
-		if err := mq.PublishDNSDelete(&node, host); err != nil {
-			logger.Log(1, "error publishing dns update", err.Error())
-		}
-	}()
+	go mq.PublishMqUpdatesForDeletedNode(node, !fromNode, gwClients)
 }
 }
 
 
 func validateParams(nodeid, netid string) (models.Node, error) {
 func validateParams(nodeid, netid string) (models.Node, error) {

+ 2 - 1
logic/dns.go

@@ -2,6 +2,7 @@ package logic
 
 
 import (
 import (
 	"encoding/json"
 	"encoding/json"
+	"fmt"
 	"os"
 	"os"
 	"regexp"
 	"regexp"
 	"sort"
 	"sort"
@@ -87,7 +88,7 @@ func GetNodeDNS(network string) ([]models.DNSEntry, error) {
 			continue
 			continue
 		}
 		}
 		var entry = models.DNSEntry{}
 		var entry = models.DNSEntry{}
-		entry.Name = host.Name
+		entry.Name = fmt.Sprintf("%s.%s", host.Name, network)
 		entry.Network = network
 		entry.Network = network
 		if node.Address.IP != nil {
 		if node.Address.IP != nil {
 			entry.Address = node.Address.IP.String()
 			entry.Address = node.Address.IP.String()

+ 15 - 0
logic/extpeers.go

@@ -137,6 +137,21 @@ func GetExtClient(clientid string, network string) (models.ExtClient, error) {
 	return extclient, err
 	return extclient, err
 }
 }
 
 
+// GetGwExtclients - return all ext clients attached to the passed gw id
+func GetGwExtclients(nodeID, network string) []models.ExtClient {
+	gwClients := []models.ExtClient{}
+	clients, err := GetNetworkExtClients(network)
+	if err != nil {
+		return gwClients
+	}
+	for _, client := range clients {
+		if client.IngressGatewayID == nodeID {
+			gwClients = append(gwClients, client)
+		}
+	}
+	return gwClients
+}
+
 // GetExtClient - gets a single ext client on a network
 // GetExtClient - gets a single ext client on a network
 func GetExtClientByPubKey(publicKey string, network string) (*models.ExtClient, error) {
 func GetExtClientByPubKey(publicKey string, network string) (*models.ExtClient, error) {
 	netClients, err := GetNetworkExtClients(network)
 	netClients, err := GetNetworkExtClients(network)

+ 20 - 22
logic/nodes.go

@@ -184,32 +184,30 @@ func DeleteNode(node *models.Node, purge bool) error {
 	alreadyDeleted := node.PendingDelete || node.Action == models.NODE_DELETE
 	alreadyDeleted := node.PendingDelete || node.Action == models.NODE_DELETE
 	node.Action = models.NODE_DELETE
 	node.Action = models.NODE_DELETE
 
 
-	if !alreadyDeleted {
-		//delete ext clients if node is ingress gw
-		if node.IsIngressGateway {
-			if err := DeleteGatewayExtClients(node.ID.String(), node.Network); err != nil {
-				slog.Error("failed to delete ext clients", "nodeid", node.ID.String(), "error", err.Error())
-			}
+	//delete ext clients if node is ingress gw
+	if node.IsIngressGateway {
+		if err := DeleteGatewayExtClients(node.ID.String(), node.Network); err != nil {
+			slog.Error("failed to delete ext clients", "nodeid", node.ID.String(), "error", err.Error())
 		}
 		}
-		if node.IsRelayed {
-			// cleanup node from relayednodes on relay node
-			relayNode, err := GetNodeByID(node.RelayedBy)
-			if err == nil {
-				relayedNodes := []string{}
-				for _, relayedNodeID := range relayNode.RelayedNodes {
-					if relayedNodeID == node.ID.String() {
-						continue
-					}
-					relayedNodes = append(relayedNodes, relayedNodeID)
+	}
+	if node.IsRelayed {
+		// cleanup node from relayednodes on relay node
+		relayNode, err := GetNodeByID(node.RelayedBy)
+		if err == nil {
+			relayedNodes := []string{}
+			for _, relayedNodeID := range relayNode.RelayedNodes {
+				if relayedNodeID == node.ID.String() {
+					continue
 				}
 				}
-				relayNode.RelayedNodes = relayedNodes
-				UpsertNode(&relayNode)
+				relayedNodes = append(relayedNodes, relayedNodeID)
 			}
 			}
+			relayNode.RelayedNodes = relayedNodes
+			UpsertNode(&relayNode)
 		}
 		}
-		if node.IsRelay {
-			// unset all the relayed nodes
-			SetRelayedNodes(false, node.ID.String(), node.RelayedNodes)
-		}
+	}
+	if node.IsRelay {
+		// unset all the relayed nodes
+		SetRelayedNodes(false, node.ID.String(), node.RelayedNodes)
 	}
 	}
 
 
 	if !purge && !alreadyDeleted {
 	if !purge && !alreadyDeleted {

+ 2 - 2
mq/handlers.go

@@ -116,7 +116,7 @@ func UpdateHost(client mqtt.Client, msg mqtt.Message) {
 					slog.Error("failed peers publish after join acknowledged", "name", hostUpdate.Host.Name, "id", currentHost.ID, "error", err)
 					slog.Error("failed peers publish after join acknowledged", "name", hostUpdate.Host.Name, "id", currentHost.ID, "error", err)
 					return
 					return
 				}
 				}
-				if err = handleNewNodeDNS(&hu.Host, &hu.Node); err != nil {
+				if err = HandleNewNodeDNS(&hu.Host, &hu.Node); err != nil {
 					slog.Error("failed to send dns update after node added to host", "name", hostUpdate.Host.Name, "id", currentHost.ID, "error", err)
 					slog.Error("failed to send dns update after node added to host", "name", hostUpdate.Host.Name, "id", currentHost.ID, "error", err)
 					return
 					return
 				}
 				}
@@ -217,7 +217,7 @@ func ClientPeerUpdate(client mqtt.Client, msg mqtt.Message) {
 	slog.Info("sent peer updates after signal received from", "id", id)
 	slog.Info("sent peer updates after signal received from", "id", id)
 }
 }
 
 
-func handleNewNodeDNS(host *models.Host, node *models.Node) error {
+func HandleNewNodeDNS(host *models.Host, node *models.Node) error {
 	dns := models.DNSUpdate{
 	dns := models.DNSUpdate{
 		Action: models.DNSInsert,
 		Action: models.DNSInsert,
 		Name:   host.Name + "." + node.Network,
 		Name:   host.Name + "." + node.Network,

+ 64 - 0
mq/publishers.go

@@ -10,6 +10,7 @@ import (
 	"github.com/gravitl/netmaker/logic"
 	"github.com/gravitl/netmaker/logic"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/servercfg"
 	"github.com/gravitl/netmaker/servercfg"
+	"golang.org/x/exp/slog"
 )
 )
 
 
 // PublishPeerUpdate --- determines and publishes a peer update to all the hosts
 // PublishPeerUpdate --- determines and publishes a peer update to all the hosts
@@ -169,6 +170,27 @@ func ServerStartNotify() error {
 	return nil
 	return nil
 }
 }
 
 
+// PublishDNSUpdatev1 - published dns updates to all nodes passed
+func PublishDNSUpdatev1(network string, dns models.DNSUpdate, nodes []models.Node) error {
+	for _, node := range nodes {
+		host, err := logic.GetHost(node.HostID.String())
+		if err != nil {
+			logger.Log(0, "error retrieving host for dns update", node.HostID.String(), err.Error())
+			continue
+		}
+		data, err := json.Marshal(dns)
+		if err != nil {
+			logger.Log(0, "failed to encode dns data for node", node.ID.String(), err.Error())
+		}
+		if err := publish(host, "dns/update/"+host.ID.String()+"/"+servercfg.GetServer(), data); err != nil {
+			logger.Log(0, "error publishing dns update to host", host.ID.String(), err.Error())
+			continue
+		}
+		logger.Log(3, "published dns update to host", host.ID.String())
+	}
+	return nil
+}
+
 // PublishDNSUpdate publishes a dns update to all nodes on a network
 // PublishDNSUpdate publishes a dns update to all nodes on a network
 func PublishDNSUpdate(network string, dns models.DNSUpdate) error {
 func PublishDNSUpdate(network string, dns models.DNSUpdate) error {
 	nodes, err := logic.GetNetworkNodes(network)
 	nodes, err := logic.GetNetworkNodes(network)
@@ -215,6 +237,32 @@ func PublishAllDNS(newnode *models.Node) error {
 	return nil
 	return nil
 }
 }
 
 
+// PublishMqUpdatesForDeletedNode - published all the required updates for deleted node
+func PublishMqUpdatesForDeletedNode(node models.Node, sendNodeUpdate bool, gwClients []models.ExtClient) {
+	// notify of peer change
+	node.PendingDelete = true
+	node.Action = models.NODE_DELETE
+	if sendNodeUpdate {
+		if err := NodeUpdate(&node); err != nil {
+			slog.Error("error publishing node update to node", "node", node.ID, "error", err)
+		}
+	}
+	if err := PublishDeletedNodePeerUpdate(&node); err != nil {
+		logger.Log(1, "error publishing peer update ", err.Error())
+	}
+	host, err := logic.GetHost(node.HostID.String())
+	if err != nil {
+		logger.Log(1, "failed to retrieve host for node", node.ID.String(), err.Error())
+	}
+	if err := PublishDNSDelete(&node, host); err != nil {
+		logger.Log(1, "error publishing dns update", err.Error())
+	}
+	if err := PublishDeleteAllExtclientsDNS(node.Network, gwClients); err != nil {
+		logger.Log(1, "error publishing ext dns update", err.Error())
+	}
+
+}
+
 // PublishDNSDelete publish a dns update deleting a node to all hosts on a network
 // PublishDNSDelete publish a dns update deleting a node to all hosts on a network
 func PublishDNSDelete(node *models.Node, host *models.Host) error {
 func PublishDNSDelete(node *models.Node, host *models.Host) error {
 	dns := models.DNSUpdate{
 	dns := models.DNSUpdate{
@@ -299,6 +347,22 @@ func PublishExtClientDNSUpdate(old, new models.ExtClient, network string) error
 	return nil
 	return nil
 }
 }
 
 
+// PublishDeleteAllExtclientsDNS - publish to delete all passed ext clients dns entries
+func PublishDeleteAllExtclientsDNS(network string, clients []models.ExtClient) error {
+	nodes, err := logic.GetNetworkNodes(network)
+	if err != nil {
+		return err
+	}
+	for _, client := range clients {
+		dns := models.DNSUpdate{
+			Action: models.DNSDeleteByName,
+			Name:   client.ClientID + "." + client.Network,
+		}
+		go PublishDNSUpdatev1(client.Network, dns, nodes)
+	}
+	return nil
+}
+
 // PublishDeleteExtClientDNS publish dns update to delete extclient entry
 // PublishDeleteExtClientDNS publish dns update to delete extclient entry
 func PublishDeleteExtClientDNS(client *models.ExtClient) error {
 func PublishDeleteExtClientDNS(client *models.ExtClient) error {
 	dns := models.DNSUpdate{
 	dns := models.DNSUpdate{