Browse Source

[NET-546] Move ee code to ee package, unify ee status and terminology (#2538)

* Move ee code to ee package and unify ee status to IsPro

* Consolidate naming for paid/professional/enterprise version as "pro". Notes:

- Changes image tags
- Changes build tags
- Changes package names
- Doesn't change links to docs that mention "ee"
- Doesn't change parameters sent to PostHog that mention "ee"

* Revert docker image tag being -pro, back to -ee

* Revert go build tag being pro, back to ee

* Add build tags for some ee content

* [2] Revert go build tag being pro, back to ee

* Fix test workflow

* Add a json tag to be backwards compatible with frontend "IsEE" check

* Add a json tag for the serverconfig struct for IsEE

* Ammend json tag to Is_EE

* fix ee tags

---------

Co-authored-by: Abhishek Kondur <[email protected]>
Gabriel de Souza Seibel 1 year ago
parent
commit
1a1ba1ccf4

+ 1 - 1
.github/workflows/publish-docker.yml

@@ -53,7 +53,7 @@ jobs:
           build-args: | 
             tags=ce
 
-  docker-ee:
+  docker-pro:
     runs-on: ubuntu-latest
     steps:
       -

+ 1 - 1
.github/workflows/test.yml

@@ -51,7 +51,7 @@ jobs:
         run: |
           go vet ./...
           go test -p 1 ./... -v
-          go test -p 1 ./ee -v --tags ee
+          go test -p 1 ./pro -v --tags ee
         env:
           DATABASE: sqlite
           CLIENT_MODE: "off"

+ 3 - 3
cli/functions/network_user.go

@@ -4,8 +4,8 @@ import (
 	"fmt"
 	"net/http"
 
-	"github.com/gravitl/netmaker/ee/ee_controllers"
 	"github.com/gravitl/netmaker/models/promodels"
+	proControllers "github.com/gravitl/netmaker/pro/controllers"
 )
 
 // GetAllNetworkUsers - fetch all network users
@@ -34,8 +34,8 @@ func UpdateNetworkUser(networkName string, payload *promodels.NetworkUser) {
 }
 
 // GetNetworkUserData - fetch a network user's complete data
-func GetNetworkUserData(networkUserName string) *ee_controllers.NetworkUserDataMap {
-	return request[ee_controllers.NetworkUserDataMap](http.MethodGet, fmt.Sprintf("/api/networkusers/data/%s/me", networkUserName), nil)
+func GetNetworkUserData(networkUserName string) *proControllers.NetworkUserDataMap {
+	return request[proControllers.NetworkUserDataMap](http.MethodGet, fmt.Sprintf("/api/networkusers/data/%s/me", networkUserName), nil)
 }
 
 // DeleteNetworkUser - delete a network user

+ 0 - 0
compose/docker-compose.ee.yml → compose/docker-compose.pro.yml


+ 1 - 1
config/config.go

@@ -72,7 +72,7 @@ type ServerConfig struct {
 	BasicAuth                  string `yaml:"basic_auth"`
 	LicenseValue               string `yaml:"license_value"`
 	NetmakerTenantID           string `yaml:"netmaker_tenant_id"`
-	IsEE                       string `yaml:"is_ee"`
+	IsPro                      string `yaml:"is_ee" json:"IsEE"`
 	StunPort                   int    `yaml:"stun_port"`
 	StunList                   string `yaml:"stun_list"`
 	TurnServer                 string `yaml:"turn_server"`

+ 1 - 1
controllers/hosts.go

@@ -336,7 +336,7 @@ func deleteHostFromNetwork(w http.ResponseWriter, r *http.Request) {
 	node.Action = models.NODE_DELETE
 	node.PendingDelete = true
 	// notify node change
-	runUpdates(node, false)
+	mq.RunUpdates(node, false)
 	go func() { // notify of peer change
 		err = mq.PublishDeletedNodePeerUpdate(node)
 		if err != nil {

+ 1 - 1
controllers/migrate.go

@@ -123,7 +123,7 @@ func migrate(w http.ResponseWriter, r *http.Request) {
 			if err != nil {
 				logger.Log(0, "error creating ingress gateway for node", node.ID, err.Error())
 			}
-			runUpdates(&ingressNode, true)
+			mq.RunUpdates(&ingressNode, true)
 		}
 	}
 }

+ 14 - 39
controllers/node.go

@@ -415,7 +415,7 @@ func getNode(w http.ResponseWriter, r *http.Request) {
 		PeerIDs:      hostPeerUpdate.PeerIDs,
 	}
 
-	if servercfg.Is_EE && nodeRequest {
+	if servercfg.IsPro && nodeRequest {
 		if err = logic.EnterpriseResetAllPeersFailovers(node.ID, node.Network); err != nil {
 			logger.Log(1, "failed to reset failover list during node config pull", node.ID.String(), node.Network)
 		}
@@ -471,7 +471,7 @@ func createEgressGateway(w http.ResponseWriter, r *http.Request) {
 	go func() {
 		mq.PublishPeerUpdate()
 	}()
-	runUpdates(&node, true)
+	mq.RunUpdates(&node, true)
 }
 
 // swagger:route DELETE /api/nodes/{network}/{nodeid}/deletegateway nodes deleteEgressGateway
@@ -512,7 +512,7 @@ func deleteEgressGateway(w http.ResponseWriter, r *http.Request) {
 	go func() {
 		mq.PublishPeerUpdate()
 	}()
-	runUpdates(&node, true)
+	mq.RunUpdates(&node, true)
 }
 
 // == INGRESS ==
@@ -549,7 +549,7 @@ func createIngressGateway(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	if servercfg.Is_EE && request.Failover {
+	if servercfg.IsPro && request.Failover {
 		if err = logic.EnterpriseResetFailoverFunc(node.Network); err != nil {
 			logger.Log(1, "failed to reset failover list during failover create", node.ID.String(), node.Network)
 		}
@@ -560,7 +560,7 @@ func createIngressGateway(w http.ResponseWriter, r *http.Request) {
 	w.WriteHeader(http.StatusOK)
 	json.NewEncoder(w).Encode(apiNode)
 
-	runUpdates(&node, true)
+	mq.RunUpdates(&node, true)
 }
 
 // swagger:route DELETE /api/nodes/{network}/{nodeid}/deleteingress nodes deleteIngressGateway
@@ -593,7 +593,7 @@ func deleteIngressGateway(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	if servercfg.Is_EE && wasFailover {
+	if servercfg.IsPro && wasFailover {
 		if err = logic.EnterpriseResetFailoverFunc(node.Network); err != nil {
 			logger.Log(1, "failed to reset failover list during failover create", node.ID.String(), node.Network)
 		}
@@ -620,7 +620,7 @@ func deleteIngressGateway(w http.ResponseWriter, r *http.Request) {
 		}
 	}
 
-	runUpdates(&node, true)
+	mq.RunUpdates(&node, true)
 }
 
 // swagger:route PUT /api/nodes/{network}/{nodeid} nodes updateNode
@@ -655,18 +655,7 @@ func updateNode(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 	newNode := newData.ConvertToServerNode(&currentNode)
-	relayupdate := false
-	if servercfg.Is_EE && newNode.IsRelay && len(newNode.RelayedNodes) > 0 {
-		if len(newNode.RelayedNodes) != len(currentNode.RelayedNodes) {
-			relayupdate = true
-		} else {
-			for i, node := range newNode.RelayedNodes {
-				if node != currentNode.RelayedNodes[i] {
-					relayupdate = true
-				}
-			}
-		}
-	}
+	relayUpdate := logic.RelayUpdates(&currentNode, newNode)
 	host, err := logic.GetHost(newNode.HostID.String())
 	if err != nil {
 		logger.Log(0, r.Header.Get("user"),
@@ -676,7 +665,7 @@ func updateNode(w http.ResponseWriter, r *http.Request) {
 	}
 	ifaceDelta := logic.IfaceDelta(&currentNode, newNode)
 	aclUpdate := currentNode.DefaultACL != newNode.DefaultACL
-	if ifaceDelta && servercfg.Is_EE {
+	if ifaceDelta && servercfg.IsPro {
 		if err = logic.EnterpriseResetAllPeersFailovers(currentNode.ID, currentNode.Network); err != nil {
 			logger.Log(0, "failed to reset failover lists during node update for node", currentNode.ID.String(), currentNode.Network)
 		}
@@ -689,13 +678,8 @@ func updateNode(w http.ResponseWriter, r *http.Request) {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		return
 	}
-	if relayupdate {
-		updatenodes := logic.UpdateRelayed(currentNode.ID.String(), currentNode.RelayedNodes, newNode.RelayedNodes)
-		if len(updatenodes) > 0 {
-			for _, relayedNode := range updatenodes {
-				runUpdates(&relayedNode, false)
-			}
-		}
+	if relayUpdate {
+		logic.UpdateRelayed(&currentNode, newNode)
 	}
 	if servercfg.IsDNSMode() {
 		logic.SetDNS()
@@ -705,7 +689,7 @@ func updateNode(w http.ResponseWriter, r *http.Request) {
 	logger.Log(1, r.Header.Get("user"), "updated node", currentNode.ID.String(), "on network", currentNode.Network)
 	w.WriteHeader(http.StatusOK)
 	json.NewEncoder(w).Encode(apiNode)
-	runUpdates(newNode, ifaceDelta)
+	mq.RunUpdates(newNode, ifaceDelta)
 	go func(aclUpdate, relayupdate bool, newNode *models.Node) {
 		if aclUpdate || relayupdate {
 			if err := mq.PublishPeerUpdate(); err != nil {
@@ -715,7 +699,7 @@ func updateNode(w http.ResponseWriter, r *http.Request) {
 		if err := mq.PublishReplaceDNS(&currentNode, newNode, host); err != nil {
 			logger.Log(1, "failed to publish dns update", err.Error())
 		}
-	}(aclUpdate, relayupdate, newNode)
+	}(aclUpdate, relayUpdate, newNode)
 }
 
 // swagger:route DELETE /api/nodes/{network}/{nodeid} nodes deleteNode
@@ -778,7 +762,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"])
 	if !fromNode { // notify node change
-		runUpdates(&node, false)
+		mq.RunUpdates(&node, false)
 	}
 	go func() { // notify of peer change
 		var err error
@@ -796,15 +780,6 @@ func deleteNode(w http.ResponseWriter, r *http.Request) {
 	}()
 }
 
-func runUpdates(node *models.Node, ifaceDelta bool) {
-	go func() { // don't block http response
-		// publish node update if not server
-		if err := mq.NodeUpdate(node); err != nil {
-			logger.Log(1, "error publishing node update to node", node.ID.String(), err.Error())
-		}
-	}()
-}
-
 func doesUserOwnNode(username, network, nodeID string) bool {
 	u, err := logic.GetUser(username)
 	if err != nil {

+ 3 - 4
controllers/server.go

@@ -25,7 +25,6 @@ func serverHandlers(r *mux.Router) {
 	r.HandleFunc("/api/server/usage", Authorize(true, false, "user", http.HandlerFunc(getUsage))).Methods(http.MethodGet)
 }
 
-// TODO move to EE package? there is a function and a type there for that already
 func getUsage(w http.ResponseWriter, r *http.Request) {
 	type usage struct {
 		Hosts     int `json:"hosts"`
@@ -164,9 +163,9 @@ func getConfig(w http.ResponseWriter, r *http.Request) {
 	// get params
 
 	scfg := servercfg.GetServerConfig()
-	scfg.IsEE = "no"
-	if servercfg.Is_EE {
-		scfg.IsEE = "yes"
+	scfg.IsPro = "no"
+	if servercfg.IsPro {
+		scfg.IsPro = "yes"
 	}
 	json.NewEncoder(w).Encode(scfg)
 	//w.WriteHeader(http.StatusOK)

+ 0 - 0
docker/Caddyfile-EE → docker/Caddyfile-pro


+ 0 - 41
ee/logic/ext_acls.go

@@ -1,41 +0,0 @@
-package logic
-
-import "github.com/gravitl/netmaker/models"
-
-// DenyClientNode - add a denied node to an ext client's list
-func DenyClientNode(ec *models.ExtClient, clientOrNodeID string) (ok bool) {
-	if ec == nil || len(clientOrNodeID) == 0 {
-		return
-	}
-	if ec.DeniedACLs == nil {
-		ec.DeniedACLs = map[string]struct{}{}
-	}
-	ok = true
-	ec.DeniedACLs[clientOrNodeID] = struct{}{}
-	return
-}
-
-// IsClientNodeAllowed - checks if given ext client and node are allowed to communicate
-func IsClientNodeAllowed(ec *models.ExtClient, clientOrNodeID string) bool {
-	if ec == nil || len(clientOrNodeID) == 0 {
-		return false
-	}
-	if ec.DeniedACLs == nil {
-		return true
-	}
-	_, ok := ec.DeniedACLs[clientOrNodeID]
-	return !ok
-}
-
-// RemoveDeniedNodeFromClient - removes a node id from set of denied nodes
-func RemoveDeniedNodeFromClient(ec *models.ExtClient, clientOrNodeID string) bool {
-	if ec.DeniedACLs == nil {
-		return true
-	}
-	_, ok := ec.DeniedACLs[clientOrNodeID]
-	if !ok {
-		return false
-	}
-	delete(ec.DeniedACLs, clientOrNodeID)
-	return true
-}

+ 1 - 1
logic/auth.go

@@ -128,7 +128,7 @@ func CreateUser(user *models.User) error {
 
 		// legacy
 		if StringSliceContains(user.Networks, currentNets[i].NetID) {
-			if !servercfg.Is_EE {
+			if !servercfg.IsPro {
 				newUser.AccessLevel = pro.NET_ADMIN
 			}
 		}

+ 5 - 38
logic/clients.go

@@ -22,48 +22,15 @@ var (
 	AllowClientNodeAccess = func(ec *models.ExtClient, clientOrNodeID string) bool {
 		return true
 	}
-)
-
-// SetClientDefaultACLs - set's a client's default ACLs based on network and nodes in network
-func SetClientDefaultACLs(ec *models.ExtClient) error {
-	if !isEE {
+	SetClientDefaultACLs = func(ec *models.ExtClient) error {
 		return nil
 	}
-	networkNodes, err := GetNetworkNodes(ec.Network)
-	if err != nil {
-		return err
-	}
-	network, err := GetNetwork(ec.Network)
-	if err != nil {
-		return err
-	}
-	for i := range networkNodes {
-		currNode := networkNodes[i]
-		if network.DefaultACL == "no" || currNode.DefaultACL == "no" {
-			DenyClientNodeAccess(ec, currNode.ID.String())
-		} else {
-			AllowClientNodeAccess(ec, currNode.ID.String())
-		}
-	}
-	return nil
-}
-
-// SetClientACLs - overwrites an ext client's ACL
-func SetClientACLs(ec *models.ExtClient, newACLs map[string]struct{}) {
-	if ec == nil || newACLs == nil || !isEE {
-		return
+	SetClientACLs = func(ec *models.ExtClient, newACLs map[string]struct{}) {
 	}
-	ec.DeniedACLs = newACLs
-}
-
-// IsClientNodeAllowedByID - checks if a given ext client ID + nodeID are allowed
-func IsClientNodeAllowedByID(clientID, networkName, clientOrNodeID string) bool {
-	client, err := GetExtClient(clientID, networkName)
-	if err != nil {
-		return false
+	UpdateProNodeACLs = func(node *models.Node) error {
+		return nil
 	}
-	return IsClientNodeAllowed(&client, clientOrNodeID)
-}
+)
 
 // SortExtClient - Sorts slice of ExtClients by their ClientID alphabetically with numbers first
 func SortExtClient(unsortedExtClient []models.ExtClient) {

+ 1 - 1
logic/gateway.go

@@ -148,7 +148,7 @@ func CreateIngressGateway(netid string, nodeid string, ingress models.IngressReq
 	node.IngressGatewayRange6 = network.AddressRange6
 	node.IngressDNS = ingress.ExtclientDNS
 	node.SetLastModified()
-	if ingress.Failover && servercfg.Is_EE {
+	if ingress.Failover && servercfg.IsPro {
 		node.Failover = true
 	}
 	err = UpsertNode(&node)

+ 1 - 1
logic/hosts.go

@@ -382,7 +382,7 @@ func DissasociateNodeFromHost(n *models.Node, h *models.Host) error {
 		h.Nodes = RemoveStringSlice(h.Nodes, index)
 	}
 	go func() {
-		if servercfg.Is_EE {
+		if servercfg.IsPro {
 			if clients, err := GetNetworkExtClients(n.Network); err != nil {
 				for i := range clients {
 					AllowClientNodeAccess(&clients[i], n.ID.String())

+ 7 - 28
logic/metrics.go

@@ -1,39 +1,18 @@
 package logic
 
 import (
-	"encoding/json"
-
-	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/models"
 )
 
-// GetMetrics - gets the metrics
-func GetMetrics(nodeid string) (*models.Metrics, error) {
-	var metrics models.Metrics
-	record, err := database.FetchRecord(database.METRICS_TABLE_NAME, nodeid)
-	if err != nil {
-		if database.IsEmptyRecord(err) {
-			return &metrics, nil
-		}
-		return &metrics, err
-	}
-	err = json.Unmarshal([]byte(record), &metrics)
-	if err != nil {
-		return &metrics, err
-	}
-	return &metrics, nil
+var DeleteMetrics = func(string) error {
+	return nil
 }
 
-// UpdateMetrics - updates the metrics of a given client
-func UpdateMetrics(nodeid string, metrics *models.Metrics) error {
-	data, err := json.Marshal(metrics)
-	if err != nil {
-		return err
-	}
-	return database.Insert(nodeid, string(data), database.METRICS_TABLE_NAME)
+var UpdateMetrics = func(string, *models.Metrics) error {
+	return nil
 }
 
-// DeleteMetrics - deletes metrics of a given node
-func DeleteMetrics(nodeid string) error {
-	return database.DeleteRecord(database.METRICS_TABLE_NAME, nodeid)
+var GetMetrics = func(string) (*models.Metrics, error) {
+	var metrics models.Metrics
+	return &metrics, nil
 }

+ 4 - 36
logic/nodes.go

@@ -17,7 +17,6 @@ import (
 	"github.com/gravitl/netmaker/logic/acls"
 	"github.com/gravitl/netmaker/logic/acls/nodeacls"
 	"github.com/gravitl/netmaker/logic/pro"
-	"github.com/gravitl/netmaker/logic/pro/proacls"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/servercfg"
 	"github.com/gravitl/netmaker/validation"
@@ -150,7 +149,7 @@ func UpdateNode(currentNode *models.Node, newNode *models.Node) error {
 		}
 	}
 	nodeACLDelta := currentNode.DefaultACL != newNode.DefaultACL
-	newNode.Fill(currentNode, servercfg.Is_EE)
+	newNode.Fill(currentNode, servercfg.IsPro)
 
 	// check for un-settable server values
 	if err := ValidateNode(newNode, true); err != nil {
@@ -159,7 +158,7 @@ func UpdateNode(currentNode *models.Node, newNode *models.Node) error {
 
 	if newNode.ID == currentNode.ID {
 		if nodeACLDelta {
-			if err := updateProNodeACLS(newNode); err != nil {
+			if err := UpdateProNodeACLs(newNode); err != nil {
 				logger.Log(1, "failed to apply node level ACLs during creation of node", newNode.ID.String(), "-", err.Error())
 				return err
 			}
@@ -208,7 +207,7 @@ func DeleteNode(node *models.Node, purge bool) error {
 	if err := DissasociateNodeFromHost(node, host); err != nil {
 		return err
 	}
-	if servercfg.Is_EE {
+	if servercfg.IsPro {
 		if err := EnterpriseResetAllPeersFailovers(node.ID, node.Network); err != nil {
 			logger.Log(0, "failed to reset failover lists during node delete for node", host.Name, node.Network)
 		}
@@ -421,21 +420,6 @@ func FindRelay(node *models.Node) *models.Node {
 	return &relay
 }
 
-// GetNetworkIngresses - gets the gateways of a network
-func GetNetworkIngresses(network string) ([]models.Node, error) {
-	var ingresses []models.Node
-	netNodes, err := GetNetworkNodes(network)
-	if err != nil {
-		return []models.Node{}, err
-	}
-	for i := range netNodes {
-		if netNodes[i].IsIngressGateway {
-			ingresses = append(ingresses, netNodes[i])
-		}
-	}
-	return ingresses, nil
-}
-
 // GetAllNodesAPI - get all nodes for api usage
 func GetAllNodesAPI(nodes []models.Node) []models.ApiNode {
 	apiNodes := []models.ApiNode{}
@@ -475,20 +459,6 @@ func DeleteExpiredNodes(ctx context.Context, peerUpdate chan *models.Node) {
 	}
 }
 
-// == PRO ==
-
-func updateProNodeACLS(node *models.Node) error {
-	// == PRO node ACLs ==
-	networkNodes, err := GetNetworkNodes(node.Network)
-	if err != nil {
-		return err
-	}
-	if err = proacls.AdjustNodeAcls(node, networkNodes[:]); err != nil {
-		return err
-	}
-	return nil
-}
-
 // createNode - creates a node in database
 func createNode(node *models.Node) error {
 	// lock because we need unique IPs and having it concurrent makes parallel calls result in same "unique" IPs
@@ -578,7 +548,7 @@ func createNode(node *models.Node) error {
 		return err
 	}
 
-	if err = updateProNodeACLS(node); err != nil {
+	if err = UpdateProNodeACLs(node); err != nil {
 		logger.Log(1, "failed to apply node level ACLs during creation of node", node.ID.String(), "-", err.Error())
 		return err
 	}
@@ -600,5 +570,3 @@ func SortApiNodes(unsortedNodes []models.ApiNode) {
 		return unsortedNodes[i].ID < unsortedNodes[j].ID
 	})
 }
-
-// == END PRO ==

+ 4 - 61
logic/peers.go

@@ -377,36 +377,14 @@ func GetAllowedIPs(node, peer *models.Node, metrics *models.Metrics) []net.IPNet
 		for _, extPeer := range extPeers {
 			allowedips = append(allowedips, extPeer.AllowedIPs...)
 		}
-		// if node is a failover node, add allowed ips from nodes it is handling
-		if metrics != nil && peer.Failover && metrics.FailoverPeers != nil {
-			// traverse through nodes that need handling
-			logger.Log(3, "peer", peer.ID.String(), "was found to be failover for", node.ID.String(), "checking failover peers...")
-			for k := range metrics.FailoverPeers {
-				// if FailoverNode is me for this node, add allowedips
-				if metrics.FailoverPeers[k] == peer.ID.String() {
-					// get original node so we can traverse the allowed ips
-					nodeToFailover, err := GetNodeByID(k)
-					if err == nil {
-						failoverNodeMetrics, err := GetMetrics(nodeToFailover.ID.String())
-						if err == nil && failoverNodeMetrics != nil {
-							if len(failoverNodeMetrics.NodeName) > 0 {
-								allowedips = append(allowedips, getNodeAllowedIPs(&nodeToFailover, peer)...)
-								logger.Log(0, "failing over node", nodeToFailover.ID.String(), nodeToFailover.PrimaryAddress(), "to failover node", peer.ID.String())
-							}
-						}
-					}
-				}
-			}
-		}
 	}
 	if node.IsRelayed && node.RelayedBy == peer.ID.String() {
-		allowedips = append(allowedips, getAllowedIpsForRelayed(node, peer)...)
-
+		allowedips = append(allowedips, GetAllowedIpsForRelayed(node, peer)...)
 	}
 	return allowedips
 }
 
-func getEgressIPs(peer *models.Node) []net.IPNet {
+func GetEgressIPs(peer *models.Node) []net.IPNet {
 
 	peerHost, err := GetHost(peer.HostID.String())
 	if err != nil {
@@ -463,50 +441,15 @@ func getNodeAllowedIPs(peer, node *models.Node) []net.IPNet {
 	// handle egress gateway peers
 	if peer.IsEgressGateway {
 		//hasGateway = true
-		egressIPs := getEgressIPs(peer)
+		egressIPs := GetEgressIPs(peer)
 		allowedips = append(allowedips, egressIPs...)
 	}
 	if peer.IsRelay {
-		for _, relayedNodeID := range peer.RelayedNodes {
-			if node.ID.String() == relayedNodeID {
-				continue
-			}
-			relayedNode, err := GetNodeByID(relayedNodeID)
-			if err != nil {
-				continue
-			}
-			allowed := getRelayedAddresses(relayedNodeID)
-			if relayedNode.IsEgressGateway {
-				allowed = append(allowed, getEgressIPs(&relayedNode)...)
-			}
-			allowedips = append(allowedips, allowed...)
-		}
+		allowedips = append(allowedips, RelayedAllowedIPs(peer, node)...)
 	}
 	return allowedips
 }
 
-// getAllowedIpsForRelayed - returns the peerConfig for a node relayed by relay
-func getAllowedIpsForRelayed(relayed, relay *models.Node) (allowedIPs []net.IPNet) {
-	if relayed.RelayedBy != relay.ID.String() {
-		logger.Log(0, "RelayedByRelay called with invalid parameters")
-		return
-	}
-	peers, err := GetNetworkNodes(relay.Network)
-	if err != nil {
-		logger.Log(0, "error getting network clients", err.Error())
-		return
-	}
-	for _, peer := range peers {
-		if peer.ID == relayed.ID || peer.ID == relay.ID {
-			continue
-		}
-		if nodeacls.AreNodesAllowed(nodeacls.NetworkID(relayed.Network), nodeacls.NodeID(relayed.ID.String()), nodeacls.NodeID(peer.ID.String())) {
-			allowedIPs = append(allowedIPs, GetAllowedIPs(relayed, &peer, nil)...)
-		}
-	}
-	return
-}
-
 func getCIDRMaskFromAddr(addr string) net.IPMask {
 	cidr := net.CIDRMask(32, 32)
 	ipAddr, err := netip.ParseAddr(addr)

+ 0 - 35
logic/pro/proacls/nodes.go

@@ -1,35 +0,0 @@
-package proacls
-
-import (
-	"github.com/gravitl/netmaker/logic/acls"
-	"github.com/gravitl/netmaker/logic/acls/nodeacls"
-	"github.com/gravitl/netmaker/models"
-)
-
-// AdjustNodeAcls - adjusts ACLs based on a node's default value
-func AdjustNodeAcls(node *models.Node, networkNodes []models.Node) error {
-	networkID := nodeacls.NetworkID(node.Network)
-	nodeID := nodeacls.NodeID(node.ID.String())
-	currentACLs, err := nodeacls.FetchAllACLs(networkID)
-	if err != nil {
-		return err
-	}
-
-	for i := range networkNodes {
-		currentNodeID := nodeacls.NodeID(networkNodes[i].ID.String())
-		if currentNodeID == nodeID {
-			continue
-		}
-		// 2 cases
-		// both allow - allow
-		// either 1 denies - deny
-		if node.DoesACLDeny() || networkNodes[i].DoesACLDeny() {
-			currentACLs.ChangeAccess(acls.AclID(nodeID), acls.AclID(currentNodeID), acls.NotAllowed)
-		} else if node.DoesACLAllow() || networkNodes[i].DoesACLAllow() {
-			currentACLs.ChangeAccess(acls.AclID(nodeID), acls.AclID(currentNodeID), acls.Allowed)
-		}
-	}
-
-	_, err = currentACLs.Save(acls.ContainerID(node.Network))
-	return err
-}

+ 10 - 134
logic/relay.go

@@ -1,149 +1,25 @@
 package logic
 
 import (
-	"errors"
-	"fmt"
-	"net"
-
-	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/models"
+	"net"
 )
 
-// CreateRelay - creates a relay
-func CreateRelay(relay models.RelayRequest) ([]models.Node, models.Node, error) {
-	var returnnodes []models.Node
-
-	node, err := GetNodeByID(relay.NodeID)
-	if err != nil {
-		return returnnodes, models.Node{}, err
-	}
-	host, err := GetHost(node.HostID.String())
-	if err != nil {
-		return returnnodes, models.Node{}, err
-	}
-	if host.OS != "linux" {
-		return returnnodes, models.Node{}, fmt.Errorf("only linux machines can be relay nodes")
-	}
-	err = ValidateRelay(relay)
-	if err != nil {
-		return returnnodes, models.Node{}, err
-	}
-	node.IsRelay = true
-	node.RelayedNodes = relay.RelayedNodes
-	node.SetLastModified()
-	err = UpsertNode(&node)
-	if err != nil {
-		return returnnodes, node, err
-	}
-	returnnodes = SetRelayedNodes(true, relay.NodeID, relay.RelayedNodes)
-	return returnnodes, node, nil
+var RelayedAllowedIPs = func(peer, node *models.Node) []net.IPNet {
+	return []net.IPNet{}
 }
 
-// SetRelayedNodes- sets and saves node as relayed
-func SetRelayedNodes(setRelayed bool, relay string, relayed []string) []models.Node {
-	var returnnodes []models.Node
-	for _, id := range relayed {
-		node, err := GetNodeByID(id)
-		if err != nil {
-			logger.Log(0, "setRelayedNodes.GetNodebyID", err.Error())
-			continue
-		}
-		node.IsRelayed = setRelayed
-		if node.IsRelayed {
-			node.RelayedBy = relay
-		} else {
-			node.RelayedBy = ""
-		}
-		node.SetLastModified()
-		if err := UpsertNode(&node); err != nil {
-			logger.Log(0, "setRelayedNodes.Insert", err.Error())
-			continue
-		}
-		returnnodes = append(returnnodes, node)
-	}
-	return returnnodes
-}
-
-//func GetRelayedNodes(relayNode *models.Node) (models.Node, error) {
-//	var returnnodes []models.Node
-//	networkNodes, err := GetNetworkNodes(relayNode.Network)
-//	if err != nil {
-//		return returnnodes, err
-//	}
-//	for _, node := range networkNodes {
-//		for _, addr := range relayNode.RelayAddrs {
-//			if addr == node.Address.IP.String() || addr == node.Address6.IP.String() {
-//				returnnodes = append(returnnodes, node)
-//			}
-//		}
-//	}
-//	return returnnodes, nil
-//}
-
-// ValidateRelay - checks if relay is valid
-func ValidateRelay(relay models.RelayRequest) error {
-	var err error
-	//isIp := functions.IsIpCIDR(gateway.RangeString)
-	empty := len(relay.RelayedNodes) == 0
-	if empty {
-		return errors.New("IP Ranges Cannot Be Empty")
-	}
-	node, err := GetNodeByID(relay.NodeID)
-	if err != nil {
-		return err
-	}
-	if node.IsRelay {
-		return errors.New("node is already acting as a relay")
-	}
-	for _, relayedNodeID := range relay.RelayedNodes {
-		relayedNode, err := GetNodeByID(relayedNodeID)
-		if err != nil {
-			return err
-		}
-		if relayedNode.IsIngressGateway {
-			return errors.New("cannot relay an ingress gateway (" + relayedNodeID + ")")
-		}
-	}
-	return err
+var GetAllowedIpsForRelayed = func(relayed, relay *models.Node) []net.IPNet {
+	return []net.IPNet{}
 }
 
-// UpdateRelayed - updates relay nodes
-func UpdateRelayed(relay string, oldNodes []string, newNodes []string) []models.Node {
-	_ = SetRelayedNodes(false, relay, oldNodes)
-	return SetRelayedNodes(true, relay, newNodes)
+var UpdateRelayed = func(currentNode, newNode *models.Node) {
 }
 
-// DeleteRelay - deletes a relay
-func DeleteRelay(network, nodeid string) ([]models.Node, models.Node, error) {
-	var returnnodes []models.Node
-	node, err := GetNodeByID(nodeid)
-	if err != nil {
-		return returnnodes, models.Node{}, err
-	}
-	returnnodes = SetRelayedNodes(false, nodeid, node.RelayedNodes)
-	node.IsRelay = false
-	node.RelayedNodes = []string{}
-	node.SetLastModified()
-	if err = UpsertNode(&node); err != nil {
-		return returnnodes, models.Node{}, err
-	}
-	return returnnodes, node, nil
+var SetRelayedNodes = func(setRelayed bool, relay string, relayed []string) []models.Node {
+	return []models.Node{}
 }
 
-func getRelayedAddresses(id string) []net.IPNet {
-	addrs := []net.IPNet{}
-	node, err := GetNodeByID(id)
-	if err != nil {
-		logger.Log(0, "getRelayedAddresses: "+err.Error())
-		return addrs
-	}
-	if node.Address.IP != nil {
-		node.Address.Mask = net.CIDRMask(32, 32)
-		addrs = append(addrs, node.Address)
-	}
-	if node.Address6.IP != nil {
-		node.Address.Mask = net.CIDRMask(128, 128)
-		addrs = append(addrs, node.Address6)
-	}
-	return addrs
+var RelayUpdates = func(currentNode, newNode *models.Node) bool {
+	return false
 }

+ 1 - 1
logic/security.go

@@ -170,7 +170,7 @@ func UserPermissions(reqAdmin bool, netname string, token string) ([]string, str
 	if len(netname) > 0 && (len(userNetworks) == 0 || !authenticateNetworkUser(netname, userNetworks)) {
 		return nil, username, Forbidden_Err
 	}
-	if isEE && len(netname) > 0 && !pro.IsUserNetAdmin(netname, username) {
+	if servercfg.IsPro && len(netname) > 0 && !pro.IsUserNetAdmin(netname, username) {
 		return nil, "", Forbidden_Err
 	}
 	return userNetworks, username, nil

+ 4 - 10
logic/telemetry.go

@@ -13,7 +13,6 @@ import (
 
 // flags to keep for telemetry
 var isFreeTier bool
-var isEE bool
 
 // posthog_pub_key - Key for sending data to PostHog
 const posthog_pub_key = "phc_1vEXhPOA1P7HP5jP2dVU9xDTUqXHAelmtravyZ1vvES"
@@ -21,14 +20,8 @@ const posthog_pub_key = "phc_1vEXhPOA1P7HP5jP2dVU9xDTUqXHAelmtravyZ1vvES"
 // posthog_endpoint - Endpoint of PostHog server
 const posthog_endpoint = "https://app.posthog.com"
 
-// setEEForTelemetry - store EE flag without having an import cycle when used for telemetry
-// (as the ee package needs the logic package as currently written).
-func SetEEForTelemetry(eeFlag bool) {
-	isEE = eeFlag
-}
-
 // setFreeTierForTelemetry - store free tier flag without having an import cycle when used for telemetry
-// (as the ee package needs the logic package as currently written).
+// (as the pro package needs the logic package as currently written).
 func SetFreeTierForTelemetry(freeTierFlag bool) {
 	isFreeTier = freeTierFlag
 }
@@ -73,7 +66,7 @@ func sendTelemetry() error {
 			Set("docker", d.Count.Docker).
 			Set("k8s", d.Count.K8S).
 			Set("version", d.Version).
-			Set("is_ee", isEE).
+			Set("is_ee", d.IsPro). // TODO change is_ee to is_pro for consistency, but probably needs changes in posthog
 			Set("is_free_tier", isFreeTier),
 	})
 }
@@ -82,6 +75,7 @@ func sendTelemetry() error {
 func fetchTelemetryData() (telemetryData, error) {
 	var data telemetryData
 
+	data.IsPro = servercfg.IsPro
 	data.ExtClients = getDBLength(database.EXT_CLIENT_TABLE_NAME)
 	data.Users = getDBLength(database.USERS_TABLE_NAME)
 	data.Networks = getDBLength(database.NETWORKS_TABLE_NAME)
@@ -176,7 +170,7 @@ type telemetryData struct {
 	Networks   int
 	Servers    int
 	Version    string
-	IsEE       bool
+	IsPro      bool
 	IsFreeTier bool
 }
 

+ 1 - 1
main.go

@@ -41,7 +41,7 @@ func main() {
 	initialize()                       // initial db and acls
 	setGarbageCollection()
 	setVerbosity()
-	if servercfg.DeployedByOperator() && !servercfg.Is_EE {
+	if servercfg.DeployedByOperator() && !servercfg.IsPro {
 		logic.SetFreeTierLimits()
 	}
 	defer database.CloseDB()

+ 2 - 4
main_ee.go

@@ -3,10 +3,8 @@
 
 package main
 
-import (
-	"github.com/gravitl/netmaker/ee"
-)
+import "github.com/gravitl/netmaker/pro"
 
 func init() {
-	ee.InitEE()
+	pro.InitPro()
 }

+ 3 - 3
models/node.go

@@ -357,7 +357,7 @@ func (node *LegacyNode) SetDefaultFailover() {
 }
 
 // Node.Fill - fills other node data into calling node data if not set on calling node (skips DNSOn)
-func (newNode *Node) Fill(currentNode *Node, isEE bool) { // TODO add new field for nftables present
+func (newNode *Node) Fill(currentNode *Node, isPro bool) { // TODO add new field for nftables present
 	newNode.ID = currentNode.ID
 	newNode.HostID = currentNode.HostID
 	// Revisit the logic for boolean values
@@ -408,10 +408,10 @@ func (newNode *Node) Fill(currentNode *Node, isEE bool) { // TODO add new field
 	if newNode.RelayedNodes == nil {
 		newNode.RelayedNodes = currentNode.RelayedNodes
 	}
-	if newNode.IsRelay != currentNode.IsRelay && isEE {
+	if newNode.IsRelay != currentNode.IsRelay && isPro {
 		newNode.IsRelay = currentNode.IsRelay
 	}
-	if newNode.IsRelayed == currentNode.IsRelayed && isEE {
+	if newNode.IsRelayed == currentNode.IsRelayed && isPro {
 		newNode.IsRelayed = currentNode.IsRelayed
 	}
 	if newNode.Server == "" {

+ 1 - 1
models/structs.go

@@ -238,7 +238,7 @@ type ServerConfig struct {
 	MQPassword  string       `yaml:"mq_password"`
 	Server      string       `yaml:"server"`
 	Broker      string       `yaml:"broker"`
-	Is_EE       bool         `yaml:"isee"`
+	IsPro       bool         `yaml:"isee" json:"Is_EE"`
 	StunPort    int          `yaml:"stun_port"`
 	StunList    []StunServer `yaml:"stun_list"`
 	TrafficKey  []byte       `yaml:"traffickey"`

+ 20 - 174
mq/handlers.go

@@ -3,12 +3,10 @@ package mq
 import (
 	"encoding/json"
 	"fmt"
-	"math"
-	"time"
-
 	mqtt "github.com/eclipse/paho.mqtt.golang"
 	"github.com/google/uuid"
 	"github.com/gravitl/netmaker/database"
+	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/logic"
 	"github.com/gravitl/netmaker/logic/hostactions"
 	"github.com/gravitl/netmaker/models"
@@ -18,6 +16,19 @@ import (
 	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
 )
 
+// UpdateMetrics  message Handler -- handles updates from client nodes for metrics
+var UpdateMetrics = func(client mqtt.Client, msg mqtt.Message) {
+}
+
+func RunUpdates(node *models.Node, ifaceDelta bool) {
+	go func() { // don't block http response
+		// publish node update if not server
+		if err := NodeUpdate(node); err != nil {
+			logger.Log(1, "error publishing node update to node", node.ID.String(), err.Error())
+		}
+	}()
+}
+
 // DefaultHandler default message queue handler  -- NOT USED
 func DefaultHandler(client mqtt.Client, msg mqtt.Message) {
 	slog.Info("mqtt default handler", "topic", msg.Topic(), "message", msg.Payload())
@@ -25,7 +36,7 @@ func DefaultHandler(client mqtt.Client, msg mqtt.Message) {
 
 // UpdateNode  message Handler -- handles updates from client nodes
 func UpdateNode(client mqtt.Client, msg mqtt.Message) {
-	id, err := getID(msg.Topic())
+	id, err := GetID(msg.Topic())
 	if err != nil {
 		slog.Error("error getting node.ID ", "topic", msg.Topic(), "error", err)
 		return
@@ -35,7 +46,7 @@ func UpdateNode(client mqtt.Client, msg mqtt.Message) {
 		slog.Error("error getting node", "id", id, "error", err)
 		return
 	}
-	decrypted, decryptErr := decryptMsg(&currentNode, msg.Payload())
+	decrypted, decryptErr := DecryptMsg(&currentNode, msg.Payload())
 	if decryptErr != nil {
 		slog.Error("failed to decrypt message for node", "id", id, "error", decryptErr)
 		return
@@ -47,7 +58,7 @@ func UpdateNode(client mqtt.Client, msg mqtt.Message) {
 	}
 
 	ifaceDelta := logic.IfaceDelta(&currentNode, &newNode)
-	if servercfg.Is_EE && ifaceDelta {
+	if servercfg.IsPro && ifaceDelta {
 		if err = logic.EnterpriseResetAllPeersFailovers(currentNode.ID, currentNode.Network); err != nil {
 			slog.Warn("failed to reset failover list during node update", "nodeid", currentNode.ID, "network", currentNode.Network)
 		}
@@ -68,7 +79,7 @@ func UpdateNode(client mqtt.Client, msg mqtt.Message) {
 
 // UpdateHost  message Handler -- handles host updates from clients
 func UpdateHost(client mqtt.Client, msg mqtt.Message) {
-	id, err := getID(msg.Topic())
+	id, err := GetID(msg.Topic())
 	if err != nil {
 		slog.Error("error getting host.ID sent on ", "topic", msg.Topic(), "error", err)
 		return
@@ -183,77 +194,11 @@ func UpdateHost(client mqtt.Client, msg mqtt.Message) {
 			slog.Error("failed to publish peer update", "error", err)
 		}
 	}
-	// if servercfg.Is_EE && ifaceDelta {
-	// 	if err = logic.EnterpriseResetAllPeersFailovers(currentHost.ID.String(), currentHost.Network); err != nil {
-	// 		logger.Log(1, "failed to reset failover list during node update", currentHost.ID.String(), currentHost.Network)
-	// 	}
-	// }
-}
-
-// UpdateMetrics  message Handler -- handles updates from client nodes for metrics
-func UpdateMetrics(client mqtt.Client, msg mqtt.Message) {
-	if servercfg.Is_EE {
-		id, err := getID(msg.Topic())
-		if err != nil {
-			slog.Error("error getting ID sent on ", "topic", msg.Topic(), "error", err)
-			return
-		}
-		currentNode, err := logic.GetNodeByID(id)
-		if err != nil {
-			slog.Error("error getting node", "id", id, "error", err)
-			return
-		}
-		decrypted, decryptErr := decryptMsg(&currentNode, msg.Payload())
-		if decryptErr != nil {
-			slog.Error("failed to decrypt message for node", "id", id, "error", decryptErr)
-			return
-		}
-
-		var newMetrics models.Metrics
-		if err := json.Unmarshal(decrypted, &newMetrics); err != nil {
-			slog.Error("error unmarshaling payload", "error", err)
-			return
-		}
-
-		shouldUpdate := updateNodeMetrics(&currentNode, &newMetrics)
-
-		if err = logic.UpdateMetrics(id, &newMetrics); err != nil {
-			slog.Error("failed to update node metrics", "id", id, "error", err)
-			return
-		}
-		if servercfg.IsMetricsExporter() {
-			if err := pushMetricsToExporter(newMetrics); err != nil {
-				slog.Error("failed to push node metrics to exporter", "id", currentNode.ID, "error", err)
-			}
-		}
-
-		if newMetrics.Connectivity != nil {
-			err := logic.EnterpriseFailoverFunc(&currentNode)
-			if err != nil {
-				slog.Error("failed to failover for node", "id", currentNode.ID, "network", currentNode.Network, "error", err)
-			}
-		}
-
-		if shouldUpdate {
-			slog.Info("updating peers after node detected connectivity issues", "id", currentNode.ID, "network", currentNode.Network)
-			host, err := logic.GetHost(currentNode.HostID.String())
-			if err == nil {
-				nodes, err := logic.GetAllNodes()
-				if err != nil {
-					return
-				}
-				if err = PublishSingleHostPeerUpdate(host, nodes, nil, nil); err != nil {
-					slog.Warn("failed to publish update after failover peer change for node", "id", currentNode.ID, "network", currentNode.Network, "error", err)
-				}
-			}
-		}
-		slog.Debug("updated node metrics", "id", id)
-	}
 }
 
 // ClientPeerUpdate  message handler -- handles updating peers after signal from client nodes
 func ClientPeerUpdate(client mqtt.Client, msg mqtt.Message) {
-	id, err := getID(msg.Topic())
+	id, err := GetID(msg.Topic())
 	if err != nil {
 		slog.Error("error getting node.ID sent on ", "topic", msg.Topic(), "error", err)
 		return
@@ -263,7 +208,7 @@ func ClientPeerUpdate(client mqtt.Client, msg mqtt.Message) {
 		slog.Error("error getting node", "id", id, "error", err)
 		return
 	}
-	decrypted, decryptErr := decryptMsg(&currentNode, msg.Payload())
+	decrypted, decryptErr := DecryptMsg(&currentNode, msg.Payload())
 	if decryptErr != nil {
 		slog.Error("failed to decrypt message for node", "id", id, "error", decryptErr)
 		return
@@ -281,105 +226,6 @@ func ClientPeerUpdate(client mqtt.Client, msg mqtt.Message) {
 	slog.Info("sent peer updates after signal received from", "id", id)
 }
 
-func updateNodeMetrics(currentNode *models.Node, newMetrics *models.Metrics) bool {
-	if newMetrics.FailoverPeers == nil {
-		newMetrics.FailoverPeers = make(map[string]string)
-	}
-	oldMetrics, err := logic.GetMetrics(currentNode.ID.String())
-	if err != nil {
-		slog.Error("error finding old metrics for node", "id", currentNode.ID, "error", err)
-		return false
-	}
-	if oldMetrics.FailoverPeers == nil {
-		oldMetrics.FailoverPeers = make(map[string]string)
-	}
-
-	var attachedClients []models.ExtClient
-	if currentNode.IsIngressGateway {
-		clients, err := logic.GetExtClientsByID(currentNode.ID.String(), currentNode.Network)
-		if err == nil {
-			attachedClients = clients
-		}
-	}
-	if len(attachedClients) > 0 {
-		// associate ext clients with IDs
-		for i := range attachedClients {
-			extMetric := newMetrics.Connectivity[attachedClients[i].PublicKey]
-			if len(extMetric.NodeName) == 0 &&
-				len(newMetrics.Connectivity[attachedClients[i].ClientID].NodeName) > 0 { // cover server clients
-				extMetric = newMetrics.Connectivity[attachedClients[i].ClientID]
-				if extMetric.TotalReceived > 0 && extMetric.TotalSent > 0 {
-					extMetric.Connected = true
-				}
-			}
-			extMetric.NodeName = attachedClients[i].ClientID
-			delete(newMetrics.Connectivity, attachedClients[i].PublicKey)
-			newMetrics.Connectivity[attachedClients[i].ClientID] = extMetric
-		}
-	}
-
-	// run through metrics for each peer
-	for k := range newMetrics.Connectivity {
-		currMetric := newMetrics.Connectivity[k]
-		oldMetric := oldMetrics.Connectivity[k]
-		currMetric.TotalTime += oldMetric.TotalTime
-		currMetric.Uptime += oldMetric.Uptime // get the total uptime for this connection
-
-		if currMetric.TotalReceived < oldMetric.TotalReceived {
-			currMetric.TotalReceived += oldMetric.TotalReceived
-		} else {
-			currMetric.TotalReceived += int64(math.Abs(float64(currMetric.TotalReceived) - float64(oldMetric.TotalReceived)))
-		}
-		if currMetric.TotalSent < oldMetric.TotalSent {
-			currMetric.TotalSent += oldMetric.TotalSent
-		} else {
-			currMetric.TotalSent += int64(math.Abs(float64(currMetric.TotalSent) - float64(oldMetric.TotalSent)))
-		}
-
-		if currMetric.Uptime == 0 || currMetric.TotalTime == 0 {
-			currMetric.PercentUp = 0
-		} else {
-			currMetric.PercentUp = 100.0 * (float64(currMetric.Uptime) / float64(currMetric.TotalTime))
-		}
-		totalUpMinutes := currMetric.Uptime * ncutils.CheckInInterval
-		currMetric.ActualUptime = time.Duration(totalUpMinutes) * time.Minute
-		delete(oldMetrics.Connectivity, k) // remove from old data
-		newMetrics.Connectivity[k] = currMetric
-
-	}
-
-	// add nodes that need failover
-	nodes, err := logic.GetNetworkNodes(currentNode.Network)
-	if err != nil {
-		slog.Error("failed to retrieve nodes while updating metrics", "error", err)
-		return false
-	}
-	for _, node := range nodes {
-		if !newMetrics.Connectivity[node.ID.String()].Connected &&
-			len(newMetrics.Connectivity[node.ID.String()].NodeName) > 0 &&
-			node.Connected &&
-			len(node.FailoverNode) > 0 &&
-			!node.Failover {
-			newMetrics.FailoverPeers[node.ID.String()] = node.FailoverNode.String()
-		}
-	}
-	shouldUpdate := len(oldMetrics.FailoverPeers) == 0 && len(newMetrics.FailoverPeers) > 0
-	for k, v := range oldMetrics.FailoverPeers {
-		if len(newMetrics.FailoverPeers[k]) > 0 && len(v) == 0 {
-			shouldUpdate = true
-		}
-
-		if len(v) > 0 && len(newMetrics.FailoverPeers[k]) == 0 {
-			newMetrics.FailoverPeers[k] = v
-		}
-	}
-
-	for k := range oldMetrics.Connectivity { // cleanup any left over data, self healing
-		delete(newMetrics.Connectivity, k)
-	}
-	return shouldUpdate
-}
-
 func handleNewNodeDNS(host *models.Host, node *models.Node) error {
 	dns := models.DNSUpdate{
 		Action: models.DNSInsert,

+ 1 - 1
mq/publishers.go

@@ -344,7 +344,7 @@ func PublishHostDNSUpdate(old, new *models.Host, networks []string) error {
 	return nil
 }
 
-func pushMetricsToExporter(metrics models.Metrics) error {
+func PushMetricsToExporter(metrics models.Metrics) error {
 	logger.Log(2, "----> Pushing metrics to exporter")
 	data, err := json.Marshal(metrics)
 	if err != nil {

+ 2 - 2
mq/util.go

@@ -32,7 +32,7 @@ func decryptMsgWithHost(host *models.Host, msg []byte) ([]byte, error) {
 	return ncutils.DeChunk(msg, nodePubTKey, serverPrivTKey)
 }
 
-func decryptMsg(node *models.Node, msg []byte) ([]byte, error) {
+func DecryptMsg(node *models.Node, msg []byte) ([]byte, error) {
 	if len(msg) <= 24 { // make sure message is of appropriate length
 		return nil, fmt.Errorf("recieved invalid message from broker %v", msg)
 	}
@@ -93,7 +93,7 @@ func publish(host *models.Host, dest string, msg []byte) error {
 }
 
 // decodes a message queue topic and returns the embedded node.ID
-func getID(topic string) (string, error) {
+func GetID(topic string) (string, error) {
 	parts := strings.Split(topic, "/")
 	count := len(parts)
 	if count == 1 {

+ 0 - 0
ee/LICENSE → pro/LICENSE


+ 7 - 6
ee/ee_controllers/metrics.go → pro/controllers/metrics.go

@@ -1,7 +1,8 @@
-package ee_controllers
+package controllers
 
 import (
 	"encoding/json"
+	proLogic "github.com/gravitl/netmaker/pro/logic"
 	"net/http"
 
 	"github.com/gorilla/mux"
@@ -11,7 +12,7 @@ import (
 	"github.com/gravitl/netmaker/models"
 )
 
-// MetricHandlers - How we handle EE Metrics
+// MetricHandlers - How we handle Pro Metrics
 func MetricHandlers(r *mux.Router) {
 	r.HandleFunc("/api/metrics/{network}/{nodeid}", logic.SecurityCheck(true, http.HandlerFunc(getNodeMetrics))).Methods(http.MethodGet)
 	r.HandleFunc("/api/metrics/{network}", logic.SecurityCheck(true, http.HandlerFunc(getNetworkNodesMetrics))).Methods(http.MethodGet)
@@ -61,7 +62,7 @@ func getNetworkNodesMetrics(w http.ResponseWriter, r *http.Request) {
 
 	for i := range networkNodes {
 		id := networkNodes[i].ID
-		metrics, err := logic.GetMetrics(id.String())
+		metrics, err := proLogic.GetMetrics(id.String())
 		if err != nil {
 			logger.Log(1, r.Header.Get("user"), "failed to append metrics of node", id.String(), "during network metrics fetch", err.Error())
 			continue
@@ -83,7 +84,7 @@ func getNetworkExtMetrics(w http.ResponseWriter, r *http.Request) {
 	network := params["network"]
 
 	logger.Log(1, r.Header.Get("user"), "requested fetching external client metrics on network", network)
-	ingresses, err := logic.GetNetworkIngresses(network) // grab all the ingress gateways
+	ingresses, err := proLogic.GetNetworkIngresses(network) // grab all the ingress gateways
 	if err != nil {
 		logger.Log(1, r.Header.Get("user"), "failed to fetch metrics of ext clients in network", network, err.Error())
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
@@ -108,7 +109,7 @@ func getNetworkExtMetrics(w http.ResponseWriter, r *http.Request) {
 
 	for i := range ingresses {
 		id := ingresses[i].ID
-		ingressMetrics, err := logic.GetMetrics(id.String())
+		ingressMetrics, err := proLogic.GetMetrics(id.String())
 		if err != nil {
 			logger.Log(1, r.Header.Get("user"), "failed to append external client metrics from ingress node", id.String(), err.Error())
 			continue
@@ -149,7 +150,7 @@ func getAllMetrics(w http.ResponseWriter, r *http.Request) {
 
 	for i := range allNodes {
 		id := allNodes[i].ID
-		metrics, err := logic.GetMetrics(id.String())
+		metrics, err := proLogic.GetMetrics(id.String())
 		if err != nil {
 			logger.Log(1, r.Header.Get("user"), "failed to append metrics of node", id.String(), "during all nodes metrics fetch", err.Error())
 			continue

+ 1 - 1
ee/ee_controllers/middleware.go → pro/controllers/middleware.go

@@ -1,4 +1,4 @@
-package ee_controllers
+package controllers
 
 import (
 	"github.com/gravitl/netmaker/logic"

+ 1 - 1
ee/ee_controllers/networkusers.go → pro/controllers/networkusers.go

@@ -1,4 +1,4 @@
-package ee_controllers
+package controllers
 
 import (
 	"encoding/json"

+ 5 - 4
ee/ee_controllers/relay.go → pro/controllers/relay.go

@@ -1,8 +1,9 @@
-package ee_controllers
+package controllers
 
 import (
 	"encoding/json"
 	"fmt"
+	proLogic "github.com/gravitl/netmaker/pro/logic"
 	"net/http"
 
 	"github.com/gorilla/mux"
@@ -13,7 +14,7 @@ import (
 	"github.com/gravitl/netmaker/mq"
 )
 
-// RelayHandlers - handle EE Relays
+// RelayHandlers - handle Pro Relays
 func RelayHandlers(r *mux.Router) {
 
 	r.HandleFunc("/api/nodes/{network}/{nodeid}/createrelay", controller.Authorize(false, true, "user", http.HandlerFunc(createRelay))).Methods(http.MethodPost)
@@ -43,7 +44,7 @@ func createRelay(w http.ResponseWriter, r *http.Request) {
 	}
 	relayRequest.NetID = params["network"]
 	relayRequest.NodeID = params["nodeid"]
-	_, relayNode, err := logic.CreateRelay(relayRequest)
+	_, relayNode, err := proLogic.CreateRelay(relayRequest)
 	if err != nil {
 		logger.Log(0, r.Header.Get("user"),
 			fmt.Sprintf("failed to create relay on node [%s] on network [%s]: %v", relayRequest.NodeID, relayRequest.NetID, err))
@@ -73,7 +74,7 @@ func deleteRelay(w http.ResponseWriter, r *http.Request) {
 	var params = mux.Vars(r)
 	nodeid := params["nodeid"]
 	netid := params["network"]
-	updateNodes, node, err := logic.DeleteRelay(netid, nodeid)
+	updateNodes, node, err := proLogic.DeleteRelay(netid, nodeid)
 	if err != nil {
 		logger.Log(0, r.Header.Get("user"), "error decoding request body: ", err.Error())
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))

+ 1 - 1
ee/ee_controllers/usergroups.go → pro/controllers/usergroups.go

@@ -1,4 +1,4 @@
-package ee_controllers
+package controllers
 
 import (
 	"encoding/json"

+ 33 - 21
ee/initialize.go → pro/initialize.go

@@ -1,33 +1,33 @@
 //go:build ee
 // +build ee
 
-package ee
+package pro
 
 import (
 	controller "github.com/gravitl/netmaker/controllers"
-	"github.com/gravitl/netmaker/ee/ee_controllers"
-	eelogic "github.com/gravitl/netmaker/ee/logic"
 	"github.com/gravitl/netmaker/logic"
 	"github.com/gravitl/netmaker/models"
+	"github.com/gravitl/netmaker/mq"
+	proControllers "github.com/gravitl/netmaker/pro/controllers"
+	proLogic "github.com/gravitl/netmaker/pro/logic"
 	"github.com/gravitl/netmaker/servercfg"
 	"golang.org/x/exp/slog"
 )
 
-// InitEE - Initialize EE Logic
-func InitEE() {
-	setIsEnterprise()
-	servercfg.Is_EE = true
-	models.SetLogo(retrieveEELogo())
+// InitPro - Initialize Pro Logic
+func InitPro() {
+	servercfg.IsPro = true
+	models.SetLogo(retrieveProLogo())
 	controller.HttpMiddlewares = append(
 		controller.HttpMiddlewares,
-		ee_controllers.OnlyServerAPIWhenUnlicensedMiddleware,
+		proControllers.OnlyServerAPIWhenUnlicensedMiddleware,
 	)
 	controller.HttpHandlers = append(
 		controller.HttpHandlers,
-		ee_controllers.MetricHandlers,
-		ee_controllers.NetworkUsersHandlers,
-		ee_controllers.UserGroupsHandlers,
-		ee_controllers.RelayHandlers,
+		proControllers.MetricHandlers,
+		proControllers.NetworkUsersHandlers,
+		proControllers.UserGroupsHandlers,
+		proControllers.RelayHandlers,
 	)
 	logic.EnterpriseCheckFuncs = append(logic.EnterpriseCheckFuncs, func() {
 		// == License Handling ==
@@ -41,19 +41,31 @@ func InitEE() {
 		AddLicenseHooks()
 		resetFailover()
 	})
-	logic.EnterpriseFailoverFunc = eelogic.SetFailover
-	logic.EnterpriseResetFailoverFunc = eelogic.ResetFailover
-	logic.EnterpriseResetAllPeersFailovers = eelogic.WipeAffectedFailoversOnly
-	logic.DenyClientNodeAccess = eelogic.DenyClientNode
-	logic.IsClientNodeAllowed = eelogic.IsClientNodeAllowed
-	logic.AllowClientNodeAccess = eelogic.RemoveDeniedNodeFromClient
+	logic.EnterpriseFailoverFunc = proLogic.SetFailover
+	logic.EnterpriseResetFailoverFunc = proLogic.ResetFailover
+	logic.EnterpriseResetAllPeersFailovers = proLogic.WipeAffectedFailoversOnly
+	logic.DenyClientNodeAccess = proLogic.DenyClientNode
+	logic.IsClientNodeAllowed = proLogic.IsClientNodeAllowed
+	logic.AllowClientNodeAccess = proLogic.RemoveDeniedNodeFromClient
+	logic.SetClientDefaultACLs = proLogic.SetClientDefaultACLs
+	logic.SetClientACLs = proLogic.SetClientACLs
+	logic.UpdateProNodeACLs = proLogic.UpdateProNodeACLs
+	logic.GetMetrics = proLogic.GetMetrics
+	logic.UpdateMetrics = proLogic.UpdateMetrics
+	logic.DeleteMetrics = proLogic.DeleteMetrics
+	logic.GetAllowedIpsForRelayed = proLogic.GetAllowedIpsForRelayed
+	logic.RelayedAllowedIPs = proLogic.RelayedAllowedIPs
+	logic.UpdateRelayed = proLogic.UpdateRelayed
+	logic.SetRelayedNodes = proLogic.SetRelayedNodes
+	logic.RelayUpdates = proLogic.RelayUpdates
+	mq.UpdateMetrics = proLogic.MQUpdateMetrics
 }
 
 func resetFailover() {
 	nets, err := logic.GetNetworks()
 	if err == nil {
 		for _, net := range nets {
-			err = eelogic.ResetFailover(net.NetID)
+			err = proLogic.ResetFailover(net.NetID)
 			if err != nil {
 				slog.Error("failed to reset failover", "network", net.NetID, "error", err.Error())
 			}
@@ -61,7 +73,7 @@ func resetFailover() {
 	}
 }
 
-func retrieveEELogo() string {
+func retrieveProLogo() string {
 	return `              
  __   __     ______     ______   __    __     ______     __  __     ______     ______    
 /\ "-.\ \   /\  ___\   /\__  _\ /\ "-./  \   /\  __ \   /\ \/ /    /\  ___\   /\  == \   

+ 1 - 1
ee/license.go → pro/license.go

@@ -1,7 +1,7 @@
 //go:build ee
 // +build ee
 
-package ee
+package pro
 
 import (
 	"bytes"

+ 1 - 1
ee/license_test.go → pro/license_test.go

@@ -1,7 +1,7 @@
 //go:build ee
 // +build ee
 
-package ee
+package pro
 
 import (
 	"github.com/gravitl/netmaker/config"

+ 114 - 0
pro/logic/ext_acls.go

@@ -0,0 +1,114 @@
+package logic
+
+import (
+	"github.com/gravitl/netmaker/logic"
+	"github.com/gravitl/netmaker/logic/acls"
+	"github.com/gravitl/netmaker/logic/acls/nodeacls"
+	"github.com/gravitl/netmaker/models"
+)
+
+// DenyClientNode - add a denied node to an ext client's list
+func DenyClientNode(ec *models.ExtClient, clientOrNodeID string) (ok bool) {
+	if ec == nil || len(clientOrNodeID) == 0 {
+		return
+	}
+	if ec.DeniedACLs == nil {
+		ec.DeniedACLs = map[string]struct{}{}
+	}
+	ok = true
+	ec.DeniedACLs[clientOrNodeID] = struct{}{}
+	return
+}
+
+// IsClientNodeAllowed - checks if given ext client and node are allowed to communicate
+func IsClientNodeAllowed(ec *models.ExtClient, clientOrNodeID string) bool {
+	if ec == nil || len(clientOrNodeID) == 0 {
+		return false
+	}
+	if ec.DeniedACLs == nil {
+		return true
+	}
+	_, ok := ec.DeniedACLs[clientOrNodeID]
+	return !ok
+}
+
+// RemoveDeniedNodeFromClient - removes a node id from set of denied nodes
+func RemoveDeniedNodeFromClient(ec *models.ExtClient, clientOrNodeID string) bool {
+	if ec.DeniedACLs == nil {
+		return true
+	}
+	_, ok := ec.DeniedACLs[clientOrNodeID]
+	if !ok {
+		return false
+	}
+	delete(ec.DeniedACLs, clientOrNodeID)
+	return true
+}
+
+// SetClientDefaultACLs - set's a client's default ACLs based on network and nodes in network
+func SetClientDefaultACLs(ec *models.ExtClient) error {
+	networkNodes, err := logic.GetNetworkNodes(ec.Network)
+	if err != nil {
+		return err
+	}
+	network, err := logic.GetNetwork(ec.Network)
+	if err != nil {
+		return err
+	}
+	for i := range networkNodes {
+		currNode := networkNodes[i]
+		if network.DefaultACL == "no" || currNode.DefaultACL == "no" {
+			DenyClientNode(ec, currNode.ID.String())
+		} else {
+			RemoveDeniedNodeFromClient(ec, currNode.ID.String())
+		}
+	}
+	return nil
+}
+
+// SetClientACLs - overwrites an ext client's ACL
+func SetClientACLs(ec *models.ExtClient, newACLs map[string]struct{}) {
+	if ec == nil || newACLs == nil {
+		return
+	}
+	ec.DeniedACLs = newACLs
+}
+
+func UpdateProNodeACLs(node *models.Node) error {
+	networkNodes, err := logic.GetNetworkNodes(node.Network)
+	if err != nil {
+		return err
+	}
+	if err = adjustNodeAcls(node, networkNodes[:]); err != nil {
+		return err
+	}
+	return nil
+}
+
+// adjustNodeAcls - adjusts ACLs based on a node's default value
+func adjustNodeAcls(node *models.Node, networkNodes []models.Node) error {
+	networkID := nodeacls.NetworkID(node.Network)
+	nodeID := nodeacls.NodeID(node.ID.String())
+	currentACLs, err := nodeacls.FetchAllACLs(networkID)
+	if err != nil {
+		return err
+	}
+
+	for i := range networkNodes {
+		currentNodeID := nodeacls.NodeID(networkNodes[i].ID.String())
+		if currentNodeID == nodeID {
+			continue
+		}
+		// 2 cases
+		// both allow - allow
+		// either 1 denies - deny
+		if node.DoesACLDeny() || networkNodes[i].DoesACLDeny() {
+			currentACLs.ChangeAccess(acls.AclID(nodeID), acls.AclID(currentNodeID), acls.NotAllowed)
+		} else if node.DoesACLAllow() || networkNodes[i].DoesACLAllow() {
+			currentACLs.ChangeAccess(acls.AclID(nodeID), acls.AclID(currentNodeID), acls.Allowed)
+		}
+	}
+
+	_, err = currentACLs.Save(acls.ContainerID(node.Network))
+	return err
+}

+ 3 - 3
ee/logic/failover.go → pro/logic/failover.go

@@ -45,7 +45,7 @@ func determineFailoverCandidate(nodeToBeRelayed *models.Node) *models.Node {
 		return nil
 	}
 
-	currentMetrics, err := logic.GetMetrics(nodeToBeRelayed.ID.String())
+	currentMetrics, err := GetMetrics(nodeToBeRelayed.ID.String())
 	if err != nil || currentMetrics == nil || currentMetrics.Connectivity == nil {
 		return nil
 	}
@@ -84,7 +84,7 @@ func setFailoverNode(failoverNode, node *models.Node) error {
 
 // WipeFailover - removes the failover peers of given node (ID)
 func WipeFailover(nodeid string) error {
-	metrics, err := logic.GetMetrics(nodeid)
+	metrics, err := GetMetrics(nodeid)
 	if err != nil {
 		return err
 	}
@@ -109,7 +109,7 @@ func WipeAffectedFailoversOnly(nodeid uuid.UUID, network string) error {
 		if currNodeID == nodeid {
 			continue
 		}
-		currMetrics, err := logic.GetMetrics(currNodeID.String())
+		currMetrics, err := GetMetrics(currNodeID.String())
 		if err != nil || currMetrics == nil {
 			continue
 		}

+ 203 - 0
pro/logic/metrics.go

@@ -0,0 +1,203 @@
+package logic
+
+import (
+	"encoding/json"
+	mqtt "github.com/eclipse/paho.mqtt.golang"
+	"github.com/gravitl/netmaker/database"
+	"github.com/gravitl/netmaker/logic"
+	"github.com/gravitl/netmaker/models"
+	"github.com/gravitl/netmaker/mq"
+	"github.com/gravitl/netmaker/netclient/ncutils"
+	"github.com/gravitl/netmaker/servercfg"
+	"golang.org/x/exp/slog"
+	"math"
+	"time"
+)
+
+// GetMetrics - gets the metrics
+func GetMetrics(nodeid string) (*models.Metrics, error) {
+	var metrics models.Metrics
+	record, err := database.FetchRecord(database.METRICS_TABLE_NAME, nodeid)
+	if err != nil {
+		if database.IsEmptyRecord(err) {
+			return &metrics, nil
+		}
+		return &metrics, err
+	}
+	err = json.Unmarshal([]byte(record), &metrics)
+	if err != nil {
+		return &metrics, err
+	}
+	return &metrics, nil
+}
+
+// UpdateMetrics - updates the metrics of a given client
+func UpdateMetrics(nodeid string, metrics *models.Metrics) error {
+	data, err := json.Marshal(metrics)
+	if err != nil {
+		return err
+	}
+	return database.Insert(nodeid, string(data), database.METRICS_TABLE_NAME)
+}
+
+// DeleteMetrics - deletes metrics of a given node
+func DeleteMetrics(nodeid string) error {
+	return database.DeleteRecord(database.METRICS_TABLE_NAME, nodeid)
+}
+
+func MQUpdateMetrics(client mqtt.Client, msg mqtt.Message) {
+	id, err := mq.GetID(msg.Topic())
+	if err != nil {
+		slog.Error("error getting ID sent on ", "topic", msg.Topic(), "error", err)
+		return
+	}
+	currentNode, err := logic.GetNodeByID(id)
+	if err != nil {
+		slog.Error("error getting node", "id", id, "error", err)
+		return
+	}
+	decrypted, decryptErr := mq.DecryptMsg(&currentNode, msg.Payload())
+	if decryptErr != nil {
+		slog.Error("failed to decrypt message for node", "id", id, "error", decryptErr)
+		return
+	}
+
+	var newMetrics models.Metrics
+	if err := json.Unmarshal(decrypted, &newMetrics); err != nil {
+		slog.Error("error unmarshaling payload", "error", err)
+		return
+	}
+
+	shouldUpdate := updateNodeMetrics(&currentNode, &newMetrics)
+
+	if err = logic.UpdateMetrics(id, &newMetrics); err != nil {
+		slog.Error("failed to update node metrics", "id", id, "error", err)
+		return
+	}
+	if servercfg.IsMetricsExporter() {
+		if err := mq.PushMetricsToExporter(newMetrics); err != nil {
+			slog.Error("failed to push node metrics to exporter", "id", currentNode.ID, "error", err)
+		}
+	}
+
+	if newMetrics.Connectivity != nil {
+		err := logic.EnterpriseFailoverFunc(&currentNode)
+		if err != nil {
+			slog.Error("failed to failover for node", "id", currentNode.ID, "network", currentNode.Network, "error", err)
+		}
+	}
+
+	if shouldUpdate {
+		slog.Info("updating peers after node detected connectivity issues", "id", currentNode.ID, "network", currentNode.Network)
+		host, err := logic.GetHost(currentNode.HostID.String())
+		if err == nil {
+			nodes, err := logic.GetAllNodes()
+			if err != nil {
+				return
+			}
+			if err = mq.PublishSingleHostPeerUpdate(host, nodes, nil, nil); err != nil {
+				slog.Warn("failed to publish update after failover peer change for node", "id", currentNode.ID, "network", currentNode.Network, "error", err)
+			}
+		}
+	}
+	slog.Debug("updated node metrics", "id", id)
+}
+
+func updateNodeMetrics(currentNode *models.Node, newMetrics *models.Metrics) bool {
+	if newMetrics.FailoverPeers == nil {
+		newMetrics.FailoverPeers = make(map[string]string)
+	}
+	oldMetrics, err := logic.GetMetrics(currentNode.ID.String())
+	if err != nil {
+		slog.Error("error finding old metrics for node", "id", currentNode.ID, "error", err)
+		return false
+	}
+	if oldMetrics.FailoverPeers == nil {
+		oldMetrics.FailoverPeers = make(map[string]string)
+	}
+
+	var attachedClients []models.ExtClient
+	if currentNode.IsIngressGateway {
+		clients, err := logic.GetExtClientsByID(currentNode.ID.String(), currentNode.Network)
+		if err == nil {
+			attachedClients = clients
+		}
+	}
+	if len(attachedClients) > 0 {
+		// associate ext clients with IDs
+		for i := range attachedClients {
+			extMetric := newMetrics.Connectivity[attachedClients[i].PublicKey]
+			if len(extMetric.NodeName) == 0 &&
+				len(newMetrics.Connectivity[attachedClients[i].ClientID].NodeName) > 0 { // cover server clients
+				extMetric = newMetrics.Connectivity[attachedClients[i].ClientID]
+				if extMetric.TotalReceived > 0 && extMetric.TotalSent > 0 {
+					extMetric.Connected = true
+				}
+			}
+			extMetric.NodeName = attachedClients[i].ClientID
+			delete(newMetrics.Connectivity, attachedClients[i].PublicKey)
+			newMetrics.Connectivity[attachedClients[i].ClientID] = extMetric
+		}
+	}
+
+	// run through metrics for each peer
+	for k := range newMetrics.Connectivity {
+		currMetric := newMetrics.Connectivity[k]
+		oldMetric := oldMetrics.Connectivity[k]
+		currMetric.TotalTime += oldMetric.TotalTime
+		currMetric.Uptime += oldMetric.Uptime // get the total uptime for this connection
+
+		if currMetric.TotalReceived < oldMetric.TotalReceived {
+			currMetric.TotalReceived += oldMetric.TotalReceived
+		} else {
+			currMetric.TotalReceived += int64(math.Abs(float64(currMetric.TotalReceived) - float64(oldMetric.TotalReceived)))
+		}
+		if currMetric.TotalSent < oldMetric.TotalSent {
+			currMetric.TotalSent += oldMetric.TotalSent
+		} else {
+			currMetric.TotalSent += int64(math.Abs(float64(currMetric.TotalSent) - float64(oldMetric.TotalSent)))
+		}
+
+		if currMetric.Uptime == 0 || currMetric.TotalTime == 0 {
+			currMetric.PercentUp = 0
+		} else {
+			currMetric.PercentUp = 100.0 * (float64(currMetric.Uptime) / float64(currMetric.TotalTime))
+		}
+		totalUpMinutes := currMetric.Uptime * ncutils.CheckInInterval
+		currMetric.ActualUptime = time.Duration(totalUpMinutes) * time.Minute
+		delete(oldMetrics.Connectivity, k) // remove from old data
+		newMetrics.Connectivity[k] = currMetric
+
+	}
+
+	// add nodes that need failover
+	nodes, err := logic.GetNetworkNodes(currentNode.Network)
+	if err != nil {
+		slog.Error("failed to retrieve nodes while updating metrics", "error", err)
+		return false
+	}
+	for _, node := range nodes {
+		if !newMetrics.Connectivity[node.ID.String()].Connected &&
+			len(newMetrics.Connectivity[node.ID.String()].NodeName) > 0 &&
+			node.Connected &&
+			len(node.FailoverNode) > 0 &&
+			!node.Failover {
+			newMetrics.FailoverPeers[node.ID.String()] = node.FailoverNode.String()
+		}
+	}
+	shouldUpdate := len(oldMetrics.FailoverPeers) == 0 && len(newMetrics.FailoverPeers) > 0
+	for k, v := range oldMetrics.FailoverPeers {
+		if len(newMetrics.FailoverPeers[k]) > 0 && len(v) == 0 {
+			shouldUpdate = true
+		}
+
+		if len(v) > 0 && len(newMetrics.FailoverPeers[k]) == 0 {
+			newMetrics.FailoverPeers[k] = v
+		}
+	}
+
+	for k := range oldMetrics.Connectivity { // cleanup any left over data, self healing
+		delete(newMetrics.Connectivity, k)
+	}
+	return shouldUpdate
+}

+ 21 - 0
pro/logic/nodes.go

@@ -0,0 +1,21 @@
+package logic
+
+import (
+	celogic "github.com/gravitl/netmaker/logic"
+	"github.com/gravitl/netmaker/models"
+)
+
+// GetNetworkIngresses - gets the gateways of a network
+func GetNetworkIngresses(network string) ([]models.Node, error) {
+	var ingresses []models.Node
+	netNodes, err := celogic.GetNetworkNodes(network)
+	if err != nil {
+		return []models.Node{}, err
+	}
+	for i := range netNodes {
+		if netNodes[i].IsIngressGateway {
+			ingresses = append(ingresses, netNodes[i])
+		}
+	}
+	return ingresses, nil
+}

+ 218 - 0
pro/logic/relays.go

@@ -0,0 +1,218 @@
+package logic
+
+import (
+	"errors"
+	"fmt"
+	"github.com/gravitl/netmaker/logger"
+	"github.com/gravitl/netmaker/logic"
+	"github.com/gravitl/netmaker/logic/acls/nodeacls"
+	"github.com/gravitl/netmaker/models"
+	"github.com/gravitl/netmaker/mq"
+	"github.com/gravitl/netmaker/servercfg"
+	"net"
+)
+
+// CreateRelay - creates a relay
+func CreateRelay(relay models.RelayRequest) ([]models.Node, models.Node, error) {
+	var returnnodes []models.Node
+
+	node, err := logic.GetNodeByID(relay.NodeID)
+	if err != nil {
+		return returnnodes, models.Node{}, err
+	}
+	host, err := logic.GetHost(node.HostID.String())
+	if err != nil {
+		return returnnodes, models.Node{}, err
+	}
+	if host.OS != "linux" {
+		return returnnodes, models.Node{}, fmt.Errorf("only linux machines can be relay nodes")
+	}
+	err = ValidateRelay(relay)
+	if err != nil {
+		return returnnodes, models.Node{}, err
+	}
+	node.IsRelay = true
+	node.RelayedNodes = relay.RelayedNodes
+	node.SetLastModified()
+	err = logic.UpsertNode(&node)
+	if err != nil {
+		return returnnodes, node, err
+	}
+	returnnodes = SetRelayedNodes(true, relay.NodeID, relay.RelayedNodes)
+	return returnnodes, node, nil
+}
+
+// SetRelayedNodes- sets and saves node as relayed
+func SetRelayedNodes(setRelayed bool, relay string, relayed []string) []models.Node {
+	var returnnodes []models.Node
+	for _, id := range relayed {
+		node, err := logic.GetNodeByID(id)
+		if err != nil {
+			logger.Log(0, "setRelayedNodes.GetNodebyID", err.Error())
+			continue
+		}
+		node.IsRelayed = setRelayed
+		if node.IsRelayed {
+			node.RelayedBy = relay
+		} else {
+			node.RelayedBy = ""
+		}
+		node.SetLastModified()
+		if err := logic.UpsertNode(&node); err != nil {
+			logger.Log(0, "setRelayedNodes.Insert", err.Error())
+			continue
+		}
+		returnnodes = append(returnnodes, node)
+	}
+	return returnnodes
+}
+
+//func GetRelayedNodes(relayNode *models.Node) (models.Node, error) {
+//	var returnnodes []models.Node
+//	networkNodes, err := GetNetworkNodes(relayNode.Network)
+//	if err != nil {
+//		return returnnodes, err
+//	}
+//	for _, node := range networkNodes {
+//		for _, addr := range relayNode.RelayAddrs {
+//			if addr == node.Address.IP.String() || addr == node.Address6.IP.String() {
+//				returnnodes = append(returnnodes, node)
+//			}
+//		}
+//	}
+//	return returnnodes, nil
+//}
+
+// ValidateRelay - checks if relay is valid
+func ValidateRelay(relay models.RelayRequest) error {
+	var err error
+	//isIp := functions.IsIpCIDR(gateway.RangeString)
+	empty := len(relay.RelayedNodes) == 0
+	if empty {
+		return errors.New("IP Ranges Cannot Be Empty")
+	}
+	node, err := logic.GetNodeByID(relay.NodeID)
+	if err != nil {
+		return err
+	}
+	if node.IsRelay {
+		return errors.New("node is already acting as a relay")
+	}
+	for _, relayedNodeID := range relay.RelayedNodes {
+		relayedNode, err := logic.GetNodeByID(relayedNodeID)
+		if err != nil {
+			return err
+		}
+		if relayedNode.IsIngressGateway {
+			return errors.New("cannot relay an ingress gateway (" + relayedNodeID + ")")
+		}
+	}
+	return err
+}
+
+// UpdateRelayNodes - updates relay nodes
+func updateRelayNodes(relay string, oldNodes []string, newNodes []string) []models.Node {
+	_ = SetRelayedNodes(false, relay, oldNodes)
+	return SetRelayedNodes(true, relay, newNodes)
+}
+
+func RelayUpdates(currentNode, newNode *models.Node) bool {
+	relayUpdates := false
+	if servercfg.IsPro && newNode.IsRelay && len(newNode.RelayedNodes) > 0 {
+		if len(newNode.RelayedNodes) != len(currentNode.RelayedNodes) {
+			relayUpdates = true
+		} else {
+			for i, node := range newNode.RelayedNodes {
+				if node != currentNode.RelayedNodes[i] {
+					relayUpdates = true
+				}
+			}
+		}
+	}
+	return relayUpdates
+}
+
+func UpdateRelayed(currentNode, newNode *models.Node) {
+	updatenodes := updateRelayNodes(currentNode.ID.String(), currentNode.RelayedNodes, newNode.RelayedNodes)
+	if len(updatenodes) > 0 {
+		for _, relayedNode := range updatenodes {
+			mq.RunUpdates(&relayedNode, false)
+		}
+	}
+}
+
+// DeleteRelay - deletes a relay
+func DeleteRelay(network, nodeid string) ([]models.Node, models.Node, error) {
+	var returnnodes []models.Node
+	node, err := logic.GetNodeByID(nodeid)
+	if err != nil {
+		return returnnodes, models.Node{}, err
+	}
+	returnnodes = SetRelayedNodes(false, nodeid, node.RelayedNodes)
+	node.IsRelay = false
+	node.RelayedNodes = []string{}
+	node.SetLastModified()
+	if err = logic.UpsertNode(&node); err != nil {
+		return returnnodes, models.Node{}, err
+	}
+	return returnnodes, node, nil
+}
+
+func RelayedAllowedIPs(peer, node *models.Node) []net.IPNet {
+	var allowedIPs = []net.IPNet{}
+	for _, relayedNodeID := range peer.RelayedNodes {
+		if node.ID.String() == relayedNodeID {
+			continue
+		}
+		relayedNode, err := logic.GetNodeByID(relayedNodeID)
+		if err != nil {
+			continue
+		}
+		allowed := getRelayedAddresses(relayedNodeID)
+		if relayedNode.IsEgressGateway {
+			allowed = append(allowed, logic.GetEgressIPs(&relayedNode)...)
+		}
+		allowedIPs = append(allowedIPs, allowed...)
+	}
+	return allowedIPs
+}
+
+// GetAllowedIpsForRelayed - returns the peerConfig for a node relayed by relay
+func GetAllowedIpsForRelayed(relayed, relay *models.Node) (allowedIPs []net.IPNet) {
+	if relayed.RelayedBy != relay.ID.String() {
+		logger.Log(0, "RelayedByRelay called with invalid parameters")
+		return
+	}
+	peers, err := logic.GetNetworkNodes(relay.Network)
+	if err != nil {
+		logger.Log(0, "error getting network clients", err.Error())
+		return
+	}
+	for _, peer := range peers {
+		if peer.ID == relayed.ID || peer.ID == relay.ID {
+			continue
+		}
+		if nodeacls.AreNodesAllowed(nodeacls.NetworkID(relayed.Network), nodeacls.NodeID(relayed.ID.String()), nodeacls.NodeID(peer.ID.String())) {
+			allowedIPs = append(allowedIPs, logic.GetAllowedIPs(relayed, &peer, nil)...)
+		}
+	}
+	return
+}
+
+func getRelayedAddresses(id string) []net.IPNet {
+	addrs := []net.IPNet{}
+	node, err := logic.GetNodeByID(id)
+	if err != nil {
+		logger.Log(0, "getRelayedAddresses: "+err.Error())
+		return addrs
+	}
+	if node.Address.IP != nil {
+		node.Address.Mask = net.CIDRMask(32, 32)
+		addrs = append(addrs, node.Address)
+	}
+	if node.Address6.IP != nil {
+		node.Address.Mask = net.CIDRMask(128, 128)
+		addrs = append(addrs, node.Address6)
+	}
+	return addrs
+}

+ 4 - 1
ee/types.go → pro/types.go

@@ -1,4 +1,7 @@
-package ee
+//go:build ee
+// +build ee
+
+package pro
 
 import (
 	"fmt"

+ 4 - 9
ee/util.go → pro/util.go

@@ -1,4 +1,7 @@
-package ee
+//go:build ee
+// +build ee
+
+package pro
 
 import (
 	"encoding/base64"
@@ -6,14 +9,6 @@ import (
 	"github.com/gravitl/netmaker/logic"
 )
 
-var isEnterprise bool
-
-// setIsEnterprise - sets server to use enterprise features
-func setIsEnterprise() {
-	isEnterprise = true
-	logic.SetEEForTelemetry(isEnterprise)
-}
-
 // base64encode - base64 encode helper function
 func base64encode(input []byte) string {
 	return base64.StdEncoding.EncodeToString(input)

+ 1 - 1
release.md

@@ -8,7 +8,7 @@
 - Upgrade Process from v0.17.1 to latest version can be now done seamlessly, please refer docs for more information
 - Expired nodes clean up is handled correctly now
 - Ext client config generation fixed for ipv6 endpoints
-- installation process will only generate certs required for required Domains based on CE or EE
+- installation process will only generate certs required for required Domains based on CE or Pro
 - support for ARM machines on install script
      
 ## known issues

+ 1 - 1
scripts/nm-certs.sh

@@ -39,7 +39,7 @@ if [ "$INSTALL_TYPE" = "ce" ]; then
 		-d turnapi.$NM_DOMAIN
 EOF
 )
-elif [ "$INSTALL_TYPE" = "ee" ]; then
+elif [ "$INSTALL_TYPE" = "pro" ]; then
 	CERTBOT_PARAMS=$(cat <<EOF
 	certonly --standalone \
 		--non-interactive --expand --agree-tos \

+ 20 - 20
scripts/nm-quick.sh

@@ -23,7 +23,7 @@ unset NETMAKER_BASE_DOMAIN
 usage() {
 	echo "nm-quick.sh v$NM_QUICK_VERSION"
 	echo "usage: ./nm-quick.sh [-e] [-b buildtype] [-t tag] [-a auto] [-d domain]"
-	echo "  -e      if specified, will install netmaker EE"
+	echo "  -e      if specified, will install netmaker pro"
 	echo "  -b      type of build; options:"
 	echo "          \"version\" - will install a specific version of Netmaker using remote git and dockerhub"
 	echo "          \"local\": - will install by cloning repo and building images from git"
@@ -42,7 +42,7 @@ usage() {
 while getopts evab:d:t: flag; do
 	case "${flag}" in
 	e)
-		INSTALL_TYPE="ee"
+		INSTALL_TYPE="pro"
 		UPGRADE_FLAG="yes"
 		;;
 	v)
@@ -112,16 +112,16 @@ set_buildinfo() {
 
 	if [ "$1" = "ce" ]; then
 		INSTALL_TYPE="ce"
-	elif [ "$1" = "ee" ]; then
-		INSTALL_TYPE="ee"
+	elif [ "$1" = "pro" ]; then
+		INSTALL_TYPE="pro"
 	fi
 
 	if [ "$AUTO_BUILD" = "on" ] && [ -z "$INSTALL_TYPE" ]; then
 		INSTALL_TYPE="ce"
 	elif [ -z "$INSTALL_TYPE" ]; then
 		echo "-----------------------------------------------------"
-		echo "Would you like to install Netmaker Community Edition (CE), or Netmaker Enterprise Edition (EE)?"
-		echo "EE will require you to create an account at https://app.netmaker.io"
+		echo "Would you like to install Netmaker Community Edition (CE), or Netmaker Enterprise Edition (pro)?"
+		echo "pro will require you to create an account at https://app.netmaker.io"
 		echo "-----------------------------------------------------"
 		select install_option in "Community Edition" "Enterprise Edition"; do
 			case $REPLY in
@@ -131,8 +131,8 @@ set_buildinfo() {
 				break
 				;;
 			2)
-				echo "installing Netmaker EE"
-				INSTALL_TYPE="ee"
+				echo "installing Netmaker pro"
+				INSTALL_TYPE="pro"
 				break
 				;;
 			*) echo "invalid option $REPLY" ;;
@@ -140,7 +140,7 @@ set_buildinfo() {
 		done
 	fi
 	echo "-----------Build Options-----------------------------"
-	echo "    EE or CE: $INSTALL_TYPE"
+	echo "   Pro or CE: $INSTALL_TYPE"
 	echo "  Build Type: $BUILD_TYPE"
 	echo "   Build Tag: $BUILD_TAG"
 	echo "   Image Tag: $IMAGE_TAG"
@@ -289,7 +289,7 @@ save_config() { (
 		save_config_item UI_IMAGE_TAG "$IMAGE_TAG"
 	fi
 	# version-specific entries
-	if [ "$INSTALL_TYPE" = "ee" ]; then
+	if [ "$INSTALL_TYPE" = "pro" ]; then
 		save_config_item NETMAKER_TENANT_ID "$TENANT_ID"
 		save_config_item LICENSE_KEY "$LICENSE_KEY"
 		save_config_item METRICS_EXPORTER "on"
@@ -364,9 +364,9 @@ local_install_setup() { (
 		echo "Skipping build on NM_SKIP_BUILD"
 	fi
 	cp compose/docker-compose.yml "$SCRIPT_DIR/docker-compose.yml"
-	if [ "$INSTALL_TYPE" = "ee" ]; then
+	if [ "$INSTALL_TYPE" = "pro" ]; then
 		cp compose/docker-compose.ee.yml "$SCRIPT_DIR/docker-compose.override.yml"
-		cp docker/Caddyfile-EE "$SCRIPT_DIR/Caddyfile"
+		cp docker/Caddyfile-pro "$SCRIPT_DIR/Caddyfile"
 	else
 		cp docker/Caddyfile "$SCRIPT_DIR/Caddyfile"
 	fi
@@ -554,7 +554,7 @@ set_install_vars() {
 	echo "               turn.$NETMAKER_BASE_DOMAIN"
 	echo "            turnapi.$NETMAKER_BASE_DOMAIN"
 
-	if [ "$INSTALL_TYPE" = "ee" ]; then
+	if [ "$INSTALL_TYPE" = "pro" ]; then
 		echo "         prometheus.$NETMAKER_BASE_DOMAIN"
 		echo "  netmaker-exporter.$NETMAKER_BASE_DOMAIN"
 		echo "            grafana.$NETMAKER_BASE_DOMAIN"
@@ -569,10 +569,10 @@ set_install_vars() {
 
 	wait_seconds 1
 
-	if [ "$INSTALL_TYPE" = "ee" ]; then
+	if [ "$INSTALL_TYPE" = "pro" ]; then
 
 		echo "-----------------------------------------------------"
-		echo "Provide Details for EE installation:"
+		echo "Provide Details for pro installation:"
 		echo "    1. Log into https://app.netmaker.io"
 		echo "    2. follow instructions to get a license at: https://docs.netmaker.io/ee/ee-setup.html"
 		echo "    3. Retrieve License and Tenant ID"
@@ -715,7 +715,7 @@ set_install_vars() {
 	echo "        domain: $NETMAKER_BASE_DOMAIN"
 	echo "         email: $EMAIL"
 	echo "     public ip: $SERVER_HOST"
-	if [ "$INSTALL_TYPE" = "ee" ]; then
+	if [ "$INSTALL_TYPE" = "pro" ]; then
 		echo "       license: $LICENSE_KEY"
 		echo "    account id: $TENANT_ID"
 	fi
@@ -748,9 +748,9 @@ install_netmaker() {
 
 		local COMPOSE_URL="$BASE_URL/compose/docker-compose.yml"
 		local CADDY_URL="$BASE_URL/docker/Caddyfile"
-		if [ "$INSTALL_TYPE" = "ee" ]; then
-			local COMPOSE_OVERRIDE_URL="$BASE_URL/compose/docker-compose.ee.yml"
-			local CADDY_URL="$BASE_URL/docker/Caddyfile-EE"
+		if [ "$INSTALL_TYPE" = "pro" ]; then
+			local COMPOSE_OVERRIDE_URL="$BASE_URL/compose/docker-compose.pro.yml"
+			local CADDY_URL="$BASE_URL/docker/Caddyfile-pro"
 		fi
 		wget -qO "$SCRIPT_DIR"/docker-compose.yml $COMPOSE_URL
 		if test -n "$COMPOSE_OVERRIDE_URL"; then
@@ -889,7 +889,7 @@ if [ -f "$CONFIG_PATH" ]; then
 	echo "Using config: $CONFIG_PATH"
 	source "$CONFIG_PATH"
 	if [ "$UPGRADE_FLAG" = "yes" ]; then
-		INSTALL_TYPE="ee"
+		INSTALL_TYPE="pro"
 	fi
 fi
 

+ 14 - 14
scripts/nm-upgrade.sh

@@ -66,8 +66,8 @@ set_buildinfo() {
 
 
 		echo "-----------------------------------------------------"
-		echo "Would you like to install Netmaker Community Edition (CE), or Netmaker Enterprise Edition (EE)?"
-		echo "EE will require you to create an account at https://app.netmaker.io"
+		echo "Would you like to install Netmaker Community Edition (CE), or Netmaker Professional (Pro)?"
+		echo "Pro will require you to create an account at https://app.netmaker.io"
 		echo "-----------------------------------------------------"
 		select install_option in "Community Edition" "Enterprise Edition"; do
 			case $REPLY in
@@ -77,8 +77,8 @@ set_buildinfo() {
 				break
 				;;
 			2)
-				echo "installing Netmaker EE"
-				INSTALL_TYPE="ee"
+				echo "installing Netmaker Pro"
+				INSTALL_TYPE="pro"
 				break
 				;;
 			*) echo "invalid option $REPLY" ;;
@@ -86,7 +86,7 @@ set_buildinfo() {
 		done
 
 	echo "-----------Build Options-----------------------------"
-	echo "    EE or CE: $INSTALL_TYPE"
+	echo "   Pro or CE: $INSTALL_TYPE"
 	echo "   Version: $LATEST"
 	echo "   Installer: v$NM_QUICK_VERSION"
 	echo "-----------------------------------------------------"
@@ -163,7 +163,7 @@ save_config() { (
 	save_config_item NM_DOMAIN "$NETMAKER_BASE_DOMAIN"
 	save_config_item UI_IMAGE_TAG "$LATEST"
 	# version-specific entries
-	if [ "$INSTALL_TYPE" = "ee" ]; then
+	if [ "$INSTALL_TYPE" = "pro" ]; then
 		save_config_item NETMAKER_TENANT_ID "$TENANT_ID"
 		save_config_item LICENSE_KEY "$LICENSE_KEY"
 		save_config_item METRICS_EXPORTER "on"
@@ -359,7 +359,7 @@ set_install_vars() {
 	echo "               turn.$NETMAKER_BASE_DOMAIN"
 	echo "            turnapi.$NETMAKER_BASE_DOMAIN"
 
-	if [ "$INSTALL_TYPE" = "ee" ]; then
+	if [ "$INSTALL_TYPE" = "pro" ]; then
 		echo "         prometheus.$NETMAKER_BASE_DOMAIN"
 		echo "  netmaker-exporter.$NETMAKER_BASE_DOMAIN"
 		echo "            grafana.$NETMAKER_BASE_DOMAIN"
@@ -367,10 +367,10 @@ set_install_vars() {
 
 	echo "-----------------------------------------------------"
 
-	if [ "$INSTALL_TYPE" = "ee" ]; then
+	if [ "$INSTALL_TYPE" = "pro" ]; then
 
 		echo "-----------------------------------------------------"
-		echo "Provide Details for EE installation:"
+		echo "Provide Details for Pro installation:"
 		echo "    1. Log into https://app.netmaker.io"
 		echo "    2. follow instructions to get a license at: https://docs.netmaker.io/ee/ee-setup.html"
 		echo "    3. Retrieve License and Tenant ID"
@@ -405,7 +405,7 @@ set_install_vars() {
 	echo "        domain: $NETMAKER_BASE_DOMAIN"
 	echo "         email: $EMAIL"
 	echo "     public ip: $SERVER_HOST"
-	if [ "$INSTALL_TYPE" = "ee" ]; then
+	if [ "$INSTALL_TYPE" = "pro" ]; then
 		echo "       license: $LICENSE_KEY"
 		echo "    account id: $TENANT_ID"
 	fi
@@ -431,9 +431,9 @@ install_netmaker() {
 
 		local COMPOSE_URL="$BASE_URL/compose/docker-compose.yml"
 		local CADDY_URL="$BASE_URL/docker/Caddyfile"
-		if [ "$INSTALL_TYPE" = "ee" ]; then
-			local COMPOSE_OVERRIDE_URL="$BASE_URL/compose/docker-compose.ee.yml"
-			local CADDY_URL="$BASE_URL/docker/Caddyfile-EE"
+		if [ "$INSTALL_TYPE" = "pro" ]; then
+			local COMPOSE_OVERRIDE_URL="$BASE_URL/compose/docker-compose.pro.yml"
+			local CADDY_URL="$BASE_URL/docker/Caddyfile-pro"
 		fi
 		wget -qO "$SCRIPT_DIR"/docker-compose.yml $COMPOSE_URL
 		if test -n "$COMPOSE_OVERRIDE_URL"; then
@@ -528,7 +528,7 @@ if [ -f "$CONFIG_PATH" ]; then
 	echo "Using config: $CONFIG_PATH"
 	source "$CONFIG_PATH"
 	if [ "$UPGRADE_FLAG" = "yes" ]; then
-		INSTALL_TYPE="ee"
+		INSTALL_TYPE="pro"
 	fi
 fi
 

+ 5 - 5
servercfg/serverconf.go

@@ -19,7 +19,7 @@ const EmqxBrokerType = "emqx"
 
 var (
 	Version              = "dev"
-	Is_EE                = false
+	IsPro                = false
 	ErrLicenseValidation error
 )
 
@@ -87,9 +87,9 @@ func GetServerConfig() config.ServerConfig {
 	cfg.Server = GetServer()
 	cfg.StunList = GetStunListString()
 	cfg.Verbosity = GetVerbosity()
-	cfg.IsEE = "no"
-	if Is_EE {
-		cfg.IsEE = "yes"
+	cfg.IsPro = "no"
+	if IsPro {
+		cfg.IsPro = "yes"
 	}
 
 	return cfg
@@ -110,7 +110,7 @@ func GetServerInfo() models.ServerConfig {
 		cfg.DNSMode = "on"
 	}
 	cfg.Version = GetVersion()
-	cfg.Is_EE = Is_EE
+	cfg.IsPro = IsPro
 	cfg.StunPort = GetStunPort()
 	cfg.StunList = GetStunList()
 	cfg.TurnDomain = GetTurnHost()