[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 <abhi281342@gmail.com>
This commit is contained in:
Gabriel de Souza Seibel 2023-08-31 23:12:05 -03:00 committed by GitHub
parent 31fcc8cd6d
commit 1a1ba1ccf4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
50 changed files with 753 additions and 716 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -25,7 +25,6 @@ func serverHandlers(r *mux.Router) {
r.HandleFunc("/api/server/usage", Authorize(true, false, "user", http.HandlerFunc(getUsage))).Methods(http.MethodGet) 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) { func getUsage(w http.ResponseWriter, r *http.Request) {
type usage struct { type usage struct {
Hosts int `json:"hosts"` Hosts int `json:"hosts"`
@ -164,9 +163,9 @@ func getConfig(w http.ResponseWriter, r *http.Request) {
// get params // get params
scfg := servercfg.GetServerConfig() scfg := servercfg.GetServerConfig()
scfg.IsEE = "no" scfg.IsPro = "no"
if servercfg.Is_EE { if servercfg.IsPro {
scfg.IsEE = "yes" scfg.IsPro = "yes"
} }
json.NewEncoder(w).Encode(scfg) json.NewEncoder(w).Encode(scfg)
//w.WriteHeader(http.StatusOK) //w.WriteHeader(http.StatusOK)

View file

@ -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
}

View file

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

View file

@ -22,48 +22,15 @@ var (
AllowClientNodeAccess = func(ec *models.ExtClient, clientOrNodeID string) bool { AllowClientNodeAccess = func(ec *models.ExtClient, clientOrNodeID string) bool {
return true return true
} }
) SetClientDefaultACLs = func(ec *models.ExtClient) error {
// SetClientDefaultACLs - set's a client's default ACLs based on network and nodes in network
func SetClientDefaultACLs(ec *models.ExtClient) error {
if !isEE {
return nil return nil
} }
networkNodes, err := GetNetworkNodes(ec.Network) SetClientACLs = func(ec *models.ExtClient, newACLs map[string]struct{}) {
if err != nil {
return err
} }
network, err := GetNetwork(ec.Network) UpdateProNodeACLs = func(node *models.Node) error {
if err != nil { return 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
}
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
}
return IsClientNodeAllowed(&client, clientOrNodeID)
}
// SortExtClient - Sorts slice of ExtClients by their ClientID alphabetically with numbers first // SortExtClient - Sorts slice of ExtClients by their ClientID alphabetically with numbers first
func SortExtClient(unsortedExtClient []models.ExtClient) { func SortExtClient(unsortedExtClient []models.ExtClient) {

View file

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

View file

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

View file

@ -1,39 +1,18 @@
package logic package logic
import ( import (
"encoding/json"
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/models" "github.com/gravitl/netmaker/models"
) )
// GetMetrics - gets the metrics var DeleteMetrics = func(string) error {
func GetMetrics(nodeid string) (*models.Metrics, error) { return nil
}
var UpdateMetrics = func(string, *models.Metrics) error {
return nil
}
var GetMetrics = func(string) (*models.Metrics, error) {
var metrics models.Metrics 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 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)
}

View file

@ -17,7 +17,6 @@ import (
"github.com/gravitl/netmaker/logic/acls" "github.com/gravitl/netmaker/logic/acls"
"github.com/gravitl/netmaker/logic/acls/nodeacls" "github.com/gravitl/netmaker/logic/acls/nodeacls"
"github.com/gravitl/netmaker/logic/pro" "github.com/gravitl/netmaker/logic/pro"
"github.com/gravitl/netmaker/logic/pro/proacls"
"github.com/gravitl/netmaker/models" "github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/servercfg" "github.com/gravitl/netmaker/servercfg"
"github.com/gravitl/netmaker/validation" "github.com/gravitl/netmaker/validation"
@ -150,7 +149,7 @@ func UpdateNode(currentNode *models.Node, newNode *models.Node) error {
} }
} }
nodeACLDelta := currentNode.DefaultACL != newNode.DefaultACL nodeACLDelta := currentNode.DefaultACL != newNode.DefaultACL
newNode.Fill(currentNode, servercfg.Is_EE) newNode.Fill(currentNode, servercfg.IsPro)
// check for un-settable server values // check for un-settable server values
if err := ValidateNode(newNode, true); err != nil { 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 newNode.ID == currentNode.ID {
if nodeACLDelta { 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()) logger.Log(1, "failed to apply node level ACLs during creation of node", newNode.ID.String(), "-", err.Error())
return err return err
} }
@ -208,7 +207,7 @@ func DeleteNode(node *models.Node, purge bool) error {
if err := DissasociateNodeFromHost(node, host); err != nil { if err := DissasociateNodeFromHost(node, host); err != nil {
return err return err
} }
if servercfg.Is_EE { if servercfg.IsPro {
if err := EnterpriseResetAllPeersFailovers(node.ID, node.Network); err != nil { 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) 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 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 // GetAllNodesAPI - get all nodes for api usage
func GetAllNodesAPI(nodes []models.Node) []models.ApiNode { func GetAllNodesAPI(nodes []models.Node) []models.ApiNode {
apiNodes := []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 // createNode - creates a node in database
func createNode(node *models.Node) error { func createNode(node *models.Node) error {
// lock because we need unique IPs and having it concurrent makes parallel calls result in same "unique" IPs // 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 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()) logger.Log(1, "failed to apply node level ACLs during creation of node", node.ID.String(), "-", err.Error())
return err return err
} }
@ -600,5 +570,3 @@ func SortApiNodes(unsortedNodes []models.ApiNode) {
return unsortedNodes[i].ID < unsortedNodes[j].ID return unsortedNodes[i].ID < unsortedNodes[j].ID
}) })
} }
// == END PRO ==

View file

@ -377,36 +377,14 @@ func GetAllowedIPs(node, peer *models.Node, metrics *models.Metrics) []net.IPNet
for _, extPeer := range extPeers { for _, extPeer := range extPeers {
allowedips = append(allowedips, extPeer.AllowedIPs...) 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() { if node.IsRelayed && node.RelayedBy == peer.ID.String() {
allowedips = append(allowedips, getAllowedIpsForRelayed(node, peer)...) allowedips = append(allowedips, GetAllowedIpsForRelayed(node, peer)...)
} }
return allowedips return allowedips
} }
func getEgressIPs(peer *models.Node) []net.IPNet { func GetEgressIPs(peer *models.Node) []net.IPNet {
peerHost, err := GetHost(peer.HostID.String()) peerHost, err := GetHost(peer.HostID.String())
if err != nil { if err != nil {
@ -463,50 +441,15 @@ func getNodeAllowedIPs(peer, node *models.Node) []net.IPNet {
// handle egress gateway peers // handle egress gateway peers
if peer.IsEgressGateway { if peer.IsEgressGateway {
//hasGateway = true //hasGateway = true
egressIPs := getEgressIPs(peer) egressIPs := GetEgressIPs(peer)
allowedips = append(allowedips, egressIPs...) allowedips = append(allowedips, egressIPs...)
} }
if peer.IsRelay { if peer.IsRelay {
for _, relayedNodeID := range peer.RelayedNodes { allowedips = append(allowedips, RelayedAllowedIPs(peer, node)...)
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...)
}
} }
return allowedips 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 { func getCIDRMaskFromAddr(addr string) net.IPMask {
cidr := net.CIDRMask(32, 32) cidr := net.CIDRMask(32, 32)
ipAddr, err := netip.ParseAddr(addr) ipAddr, err := netip.ParseAddr(addr)

View file

@ -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
}

View file

@ -1,149 +1,25 @@
package logic package logic
import ( import (
"errors"
"fmt"
"net"
"github.com/gravitl/netmaker/logger"
"github.com/gravitl/netmaker/models" "github.com/gravitl/netmaker/models"
"net"
) )
// CreateRelay - creates a relay var RelayedAllowedIPs = func(peer, node *models.Node) []net.IPNet {
func CreateRelay(relay models.RelayRequest) ([]models.Node, models.Node, error) { return []net.IPNet{}
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
} }
// SetRelayedNodes- sets and saves node as relayed var GetAllowedIpsForRelayed = func(relayed, relay *models.Node) []net.IPNet {
func SetRelayedNodes(setRelayed bool, relay string, relayed []string) []models.Node { return []net.IPNet{}
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 UpdateRelayed = func(currentNode, newNode *models.Node) {
// 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
} }
// UpdateRelayed - updates relay nodes var SetRelayedNodes = func(setRelayed bool, relay string, relayed []string) []models.Node {
func UpdateRelayed(relay string, oldNodes []string, newNodes []string) []models.Node { return []models.Node{}
_ = SetRelayedNodes(false, relay, oldNodes)
return SetRelayedNodes(true, relay, newNodes)
} }
// DeleteRelay - deletes a relay var RelayUpdates = func(currentNode, newNode *models.Node) bool {
func DeleteRelay(network, nodeid string) ([]models.Node, models.Node, error) { return false
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
}
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
} }

View file

@ -170,7 +170,7 @@ func UserPermissions(reqAdmin bool, netname string, token string) ([]string, str
if len(netname) > 0 && (len(userNetworks) == 0 || !authenticateNetworkUser(netname, userNetworks)) { if len(netname) > 0 && (len(userNetworks) == 0 || !authenticateNetworkUser(netname, userNetworks)) {
return nil, username, Forbidden_Err 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 nil, "", Forbidden_Err
} }
return userNetworks, username, nil return userNetworks, username, nil

View file

@ -13,7 +13,6 @@ import (
// flags to keep for telemetry // flags to keep for telemetry
var isFreeTier bool var isFreeTier bool
var isEE bool
// posthog_pub_key - Key for sending data to PostHog // posthog_pub_key - Key for sending data to PostHog
const posthog_pub_key = "phc_1vEXhPOA1P7HP5jP2dVU9xDTUqXHAelmtravyZ1vvES" const posthog_pub_key = "phc_1vEXhPOA1P7HP5jP2dVU9xDTUqXHAelmtravyZ1vvES"
@ -21,14 +20,8 @@ const posthog_pub_key = "phc_1vEXhPOA1P7HP5jP2dVU9xDTUqXHAelmtravyZ1vvES"
// posthog_endpoint - Endpoint of PostHog server // posthog_endpoint - Endpoint of PostHog server
const posthog_endpoint = "https://app.posthog.com" 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 // 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) { func SetFreeTierForTelemetry(freeTierFlag bool) {
isFreeTier = freeTierFlag isFreeTier = freeTierFlag
} }
@ -73,7 +66,7 @@ func sendTelemetry() error {
Set("docker", d.Count.Docker). Set("docker", d.Count.Docker).
Set("k8s", d.Count.K8S). Set("k8s", d.Count.K8S).
Set("version", d.Version). 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), Set("is_free_tier", isFreeTier),
}) })
} }
@ -82,6 +75,7 @@ func sendTelemetry() error {
func fetchTelemetryData() (telemetryData, error) { func fetchTelemetryData() (telemetryData, error) {
var data telemetryData var data telemetryData
data.IsPro = servercfg.IsPro
data.ExtClients = getDBLength(database.EXT_CLIENT_TABLE_NAME) data.ExtClients = getDBLength(database.EXT_CLIENT_TABLE_NAME)
data.Users = getDBLength(database.USERS_TABLE_NAME) data.Users = getDBLength(database.USERS_TABLE_NAME)
data.Networks = getDBLength(database.NETWORKS_TABLE_NAME) data.Networks = getDBLength(database.NETWORKS_TABLE_NAME)
@ -176,7 +170,7 @@ type telemetryData struct {
Networks int Networks int
Servers int Servers int
Version string Version string
IsEE bool IsPro bool
IsFreeTier bool IsFreeTier bool
} }

View file

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

View file

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

View file

@ -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) // 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.ID = currentNode.ID
newNode.HostID = currentNode.HostID newNode.HostID = currentNode.HostID
// Revisit the logic for boolean values // 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 { if newNode.RelayedNodes == nil {
newNode.RelayedNodes = currentNode.RelayedNodes newNode.RelayedNodes = currentNode.RelayedNodes
} }
if newNode.IsRelay != currentNode.IsRelay && isEE { if newNode.IsRelay != currentNode.IsRelay && isPro {
newNode.IsRelay = currentNode.IsRelay newNode.IsRelay = currentNode.IsRelay
} }
if newNode.IsRelayed == currentNode.IsRelayed && isEE { if newNode.IsRelayed == currentNode.IsRelayed && isPro {
newNode.IsRelayed = currentNode.IsRelayed newNode.IsRelayed = currentNode.IsRelayed
} }
if newNode.Server == "" { if newNode.Server == "" {

View file

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

View file

@ -3,12 +3,10 @@ package mq
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"math"
"time"
mqtt "github.com/eclipse/paho.mqtt.golang" mqtt "github.com/eclipse/paho.mqtt.golang"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/gravitl/netmaker/database" "github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/logger"
"github.com/gravitl/netmaker/logic" "github.com/gravitl/netmaker/logic"
"github.com/gravitl/netmaker/logic/hostactions" "github.com/gravitl/netmaker/logic/hostactions"
"github.com/gravitl/netmaker/models" "github.com/gravitl/netmaker/models"
@ -18,6 +16,19 @@ import (
"golang.zx2c4.com/wireguard/wgctrl/wgtypes" "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 // DefaultHandler default message queue handler -- NOT USED
func DefaultHandler(client mqtt.Client, msg mqtt.Message) { func DefaultHandler(client mqtt.Client, msg mqtt.Message) {
slog.Info("mqtt default handler", "topic", msg.Topic(), "message", msg.Payload()) 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 // UpdateNode message Handler -- handles updates from client nodes
func UpdateNode(client mqtt.Client, msg mqtt.Message) { func UpdateNode(client mqtt.Client, msg mqtt.Message) {
id, err := getID(msg.Topic()) id, err := GetID(msg.Topic())
if err != nil { if err != nil {
slog.Error("error getting node.ID ", "topic", msg.Topic(), "error", err) slog.Error("error getting node.ID ", "topic", msg.Topic(), "error", err)
return return
@ -35,7 +46,7 @@ func UpdateNode(client mqtt.Client, msg mqtt.Message) {
slog.Error("error getting node", "id", id, "error", err) slog.Error("error getting node", "id", id, "error", err)
return return
} }
decrypted, decryptErr := decryptMsg(&currentNode, msg.Payload()) decrypted, decryptErr := DecryptMsg(&currentNode, msg.Payload())
if decryptErr != nil { if decryptErr != nil {
slog.Error("failed to decrypt message for node", "id", id, "error", decryptErr) slog.Error("failed to decrypt message for node", "id", id, "error", decryptErr)
return return
@ -47,7 +58,7 @@ func UpdateNode(client mqtt.Client, msg mqtt.Message) {
} }
ifaceDelta := logic.IfaceDelta(&currentNode, &newNode) ifaceDelta := logic.IfaceDelta(&currentNode, &newNode)
if servercfg.Is_EE && ifaceDelta { if servercfg.IsPro && ifaceDelta {
if err = logic.EnterpriseResetAllPeersFailovers(currentNode.ID, currentNode.Network); err != nil { 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) 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 // UpdateHost message Handler -- handles host updates from clients
func UpdateHost(client mqtt.Client, msg mqtt.Message) { func UpdateHost(client mqtt.Client, msg mqtt.Message) {
id, err := getID(msg.Topic()) id, err := GetID(msg.Topic())
if err != nil { if err != nil {
slog.Error("error getting host.ID sent on ", "topic", msg.Topic(), "error", err) slog.Error("error getting host.ID sent on ", "topic", msg.Topic(), "error", err)
return return
@ -183,77 +194,11 @@ func UpdateHost(client mqtt.Client, msg mqtt.Message) {
slog.Error("failed to publish peer update", "error", err) 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 // ClientPeerUpdate message handler -- handles updating peers after signal from client nodes
func ClientPeerUpdate(client mqtt.Client, msg mqtt.Message) { func ClientPeerUpdate(client mqtt.Client, msg mqtt.Message) {
id, err := getID(msg.Topic()) id, err := GetID(msg.Topic())
if err != nil { if err != nil {
slog.Error("error getting node.ID sent on ", "topic", msg.Topic(), "error", err) slog.Error("error getting node.ID sent on ", "topic", msg.Topic(), "error", err)
return return
@ -263,7 +208,7 @@ func ClientPeerUpdate(client mqtt.Client, msg mqtt.Message) {
slog.Error("error getting node", "id", id, "error", err) slog.Error("error getting node", "id", id, "error", err)
return return
} }
decrypted, decryptErr := decryptMsg(&currentNode, msg.Payload()) decrypted, decryptErr := DecryptMsg(&currentNode, msg.Payload())
if decryptErr != nil { if decryptErr != nil {
slog.Error("failed to decrypt message for node", "id", id, "error", decryptErr) slog.Error("failed to decrypt message for node", "id", id, "error", decryptErr)
return return
@ -281,105 +226,6 @@ func ClientPeerUpdate(client mqtt.Client, msg mqtt.Message) {
slog.Info("sent peer updates after signal received from", "id", id) slog.Info("sent peer updates after signal received from", "id", id)
} }
func 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 { func handleNewNodeDNS(host *models.Host, node *models.Node) error {
dns := models.DNSUpdate{ dns := models.DNSUpdate{
Action: models.DNSInsert, Action: models.DNSInsert,

View file

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

View file

@ -32,7 +32,7 @@ func decryptMsgWithHost(host *models.Host, msg []byte) ([]byte, error) {
return ncutils.DeChunk(msg, nodePubTKey, serverPrivTKey) 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 if len(msg) <= 24 { // make sure message is of appropriate length
return nil, fmt.Errorf("recieved invalid message from broker %v", msg) 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 // 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, "/") parts := strings.Split(topic, "/")
count := len(parts) count := len(parts)
if count == 1 { if count == 1 {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

114
pro/logic/ext_acls.go Normal file
View file

@ -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
}

View file

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

203
pro/logic/metrics.go Normal file
View file

@ -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
pro/logic/nodes.go Normal file
View file

@ -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
pro/logic/relays.go Normal file
View file

@ -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
}

View file

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

View file

@ -1,4 +1,7 @@
package ee //go:build ee
// +build ee
package pro
import ( import (
"encoding/base64" "encoding/base64"
@ -6,14 +9,6 @@ import (
"github.com/gravitl/netmaker/logic" "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 // base64encode - base64 encode helper function
func base64encode(input []byte) string { func base64encode(input []byte) string {
return base64.StdEncoding.EncodeToString(input) return base64.StdEncoding.EncodeToString(input)

View file

@ -8,7 +8,7 @@
- Upgrade Process from v0.17.1 to latest version can be now done seamlessly, please refer docs for more information - 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 - Expired nodes clean up is handled correctly now
- Ext client config generation fixed for ipv6 endpoints - 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 - support for ARM machines on install script
## known issues ## known issues

View file

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

View file

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

View file

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

View file

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