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"))
 		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 {
 		logger.Log(0, r.Header.Get("user"), "failed to delete a host:", err.Error())
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
@@ -286,6 +299,7 @@ func addHostToNetwork(w http.ResponseWriter, r *http.Request) {
 			Node:   *newNode,
 		})
 		mq.PublishPeerUpdate()
+		mq.HandleNewNodeDNS(currHost, newNode)
 	}()
 	logger.Log(2, r.Header.Get("user"), fmt.Sprintf("added host %s to network %s", currHost.Name, network))
 	w.WriteHeader(http.StatusOK)
@@ -343,54 +357,16 @@ func deleteHostFromNetwork(w http.ResponseWriter, r *http.Request) {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		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 {
-		// 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)
 	if err := logic.DeleteNode(node, forceDelete); err != nil {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("failed to delete node"), "internal"))
 		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))
 	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 {
 					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"
 	fromNode := r.Header.Get("requestfrom") == "node"
-
+	var gwClients []models.ExtClient
+	if node.IsIngressGateway {
+		gwClients = logic.GetGwExtclients(node.ID.String(), node.Network)
+	}
 	purge := forceDelete || fromNode
 	if err := logic.DeleteNode(&node, purge); err != nil {
 		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.")
 	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) {

+ 2 - 1
logic/dns.go

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

+ 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)
 					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)
 					return
 				}
@@ -217,7 +217,7 @@ func ClientPeerUpdate(client mqtt.Client, msg mqtt.Message) {
 	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{
 		Action: models.DNSInsert,
 		Name:   host.Name + "." + node.Network,

+ 64 - 0
mq/publishers.go

@@ -10,6 +10,7 @@ import (
 	"github.com/gravitl/netmaker/logic"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/servercfg"
+	"golang.org/x/exp/slog"
 )
 
 // PublishPeerUpdate --- determines and publishes a peer update to all the hosts
@@ -169,6 +170,27 @@ func ServerStartNotify() error {
 	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
 func PublishDNSUpdate(network string, dns models.DNSUpdate) error {
 	nodes, err := logic.GetNetworkNodes(network)
@@ -215,6 +237,32 @@ func PublishAllDNS(newnode *models.Node) error {
 	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
 func PublishDNSDelete(node *models.Node, host *models.Host) error {
 	dns := models.DNSUpdate{
@@ -299,6 +347,22 @@ func PublishExtClientDNSUpdate(old, new models.ExtClient, network string) error
 	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
 func PublishDeleteExtClientDNS(client *models.ExtClient) error {
 	dns := models.DNSUpdate{