diff --git a/controllers/hosts.go b/controllers/hosts.go index 5babd54a4..b79fbb813 100644 --- a/controllers/hosts.go +++ b/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) } diff --git a/controllers/node.go b/controllers/node.go index c75666fa1..4acfd4f7f 100644 --- a/controllers/node.go +++ b/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) { diff --git a/logic/dns.go b/logic/dns.go index af244c9dd..54c97f393 100644 --- a/logic/dns.go +++ b/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() diff --git a/logic/extpeers.go b/logic/extpeers.go index abad1ef84..e19b2edc8 100644 --- a/logic/extpeers.go +++ b/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) diff --git a/logic/nodes.go b/logic/nodes.go index 9a643e9d3..f5889da2b 100644 --- a/logic/nodes.go +++ b/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 { diff --git a/mq/handlers.go b/mq/handlers.go index 84ffc81e4..fc0defd91 100644 --- a/mq/handlers.go +++ b/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, diff --git a/mq/publishers.go b/mq/publishers.go index 83de5e63f..e9de776b1 100644 --- a/mq/publishers.go +++ b/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{