Jelajahi Sumber

Introduce new free tier limits

gabrielseibel1 2 tahun lalu
induk
melakukan
82899d4fdd
7 mengubah file dengan 126 tambahan dan 22 penghapusan
  1. 3 0
      config/config.go
  2. 1 1
      controllers/ext_client.go
  3. 49 8
      controllers/limits.go
  4. 2 2
      controllers/node.go
  5. 37 10
      logic/gateway.go
  6. 10 1
      logic/serverconf.go
  7. 24 0
      servercfg/serverconf.go

+ 3 - 0
config/config.go

@@ -85,6 +85,9 @@ type ServerConfig struct {
 	ClientsLimit               int    `yaml:"client_limit"`
 	NetworksLimit              int    `yaml:"network_limit"`
 	HostsLimit                 int    `yaml:"host_limit"`
+	MachinesLimit              int    `yaml:"machines_limit"`
+	IngressesLimit             int    `yaml:"ingresses_limit"`
+	EgressesLimit              int    `yaml:"egresses_limit"`
 	DeployedByOperator         bool   `yaml:"deployed_by_operator"`
 }
 

+ 1 - 1
controllers/ext_client.go

@@ -29,7 +29,7 @@ func extClientHandlers(r *mux.Router) {
 	r.HandleFunc("/api/extclients/{network}/{clientid}/{type}", logic.NetUserSecurityCheck(false, true, http.HandlerFunc(getExtClientConf))).Methods(http.MethodGet)
 	r.HandleFunc("/api/extclients/{network}/{clientid}", logic.NetUserSecurityCheck(false, true, http.HandlerFunc(updateExtClient))).Methods(http.MethodPut)
 	r.HandleFunc("/api/extclients/{network}/{clientid}", logic.NetUserSecurityCheck(false, true, http.HandlerFunc(deleteExtClient))).Methods(http.MethodDelete)
-	r.HandleFunc("/api/extclients/{network}/{nodeid}", logic.NetUserSecurityCheck(false, true, checkFreeTierLimits(limitChoiceClients, http.HandlerFunc(createExtClient)))).Methods(http.MethodPost)
+	r.HandleFunc("/api/extclients/{network}/{nodeid}", logic.NetUserSecurityCheck(false, true, checkFreeTierLimits(limitChoiceMachines, http.HandlerFunc(createExtClient)))).Methods(http.MethodPost)
 }
 
 func checkIngressExists(nodeID string) bool {

+ 49 - 8
controllers/limits.go

@@ -10,37 +10,78 @@ import (
 
 // limit consts
 const (
-	limitChoiceNodes = iota
-	limitChoiceNetworks
+	limitChoiceNetworks = iota
 	limitChoiceUsers
+	limitChoiceHosts
 	limitChoiceClients
+	limitChoiceMachines
+	limitChoiceIngress
+	limitChoiceEgress
 )
 
 func checkFreeTierLimits(limitChoice int, next http.Handler) http.HandlerFunc {
 	return func(w http.ResponseWriter, r *http.Request) {
 		var errorResponse = models.ErrorResponse{
-			Code: http.StatusForbidden, Message: "free tier limits exceeded on networks",
+			Code: http.StatusForbidden, Message: "free tier limits exceeded on ",
 		}
 
 		if logic.FreeTier { // check that free tier limits not exceeded
 			switch limitChoice {
 			case limitChoiceNetworks:
 				currentNetworks, err := logic.GetNetworks()
-				if (err != nil && !database.IsEmptyRecord(err)) || len(currentNetworks) >= logic.NetworksLimit {
+				if (err != nil && !database.IsEmptyRecord(err)) ||
+					len(currentNetworks) >= logic.NetworksLimit {
+					errorResponse.Message += "networks"
 					logic.ReturnErrorResponse(w, r, errorResponse)
 					return
 				}
 			case limitChoiceUsers:
 				users, err := logic.GetUsers()
-				if (err != nil && !database.IsEmptyRecord(err)) || len(users) >= logic.UsersLimit {
-					errorResponse.Message = "free tier limits exceeded on users"
+				if (err != nil && !database.IsEmptyRecord(err)) ||
+					len(users) >= logic.UsersLimit {
+					errorResponse.Message += "users"
 					logic.ReturnErrorResponse(w, r, errorResponse)
 					return
 				}
 			case limitChoiceClients:
 				clients, err := logic.GetAllExtClients()
-				if (err != nil && !database.IsEmptyRecord(err)) || len(clients) >= logic.ClientsLimit {
-					errorResponse.Message = "free tier limits exceeded on external clients"
+				if (err != nil && !database.IsEmptyRecord(err)) ||
+					len(clients) >= logic.ClientsLimit {
+					errorResponse.Message += "clients"
+					logic.ReturnErrorResponse(w, r, errorResponse)
+					return
+				}
+			case limitChoiceHosts:
+				hosts, err := logic.GetAllHosts()
+				if (err != nil && !database.IsEmptyRecord(err)) ||
+					len(hosts) >= logic.HostsLimit {
+					errorResponse.Message += "hosts"
+					logic.ReturnErrorResponse(w, r, errorResponse)
+					return
+				}
+			case limitChoiceMachines:
+				hosts, hErr := logic.GetAllHosts()
+				clients, cErr := logic.GetAllExtClients()
+				if (hErr != nil && !database.IsEmptyRecord(hErr)) ||
+					(cErr != nil && !database.IsEmptyRecord(cErr)) ||
+					len(hosts)+len(clients) >= logic.MachinesLimit {
+					errorResponse.Message += "machines"
+					logic.ReturnErrorResponse(w, r, errorResponse)
+					return
+				}
+			case limitChoiceIngress:
+				ingresses, err := logic.GetAllIngresses()
+				if (err != nil && !database.IsEmptyRecord(err)) ||
+					len(ingresses) >= logic.IngressesLimit {
+					errorResponse.Message += "ingresses"
+					logic.ReturnErrorResponse(w, r, errorResponse)
+					return
+				}
+			case limitChoiceEgress:
+				egresses, err := logic.GetAllEgresses()
+				if (err != nil && !database.IsEmptyRecord(err)) ||
+					len(egresses) >= logic.EgressesLimit {
+					errorResponse.Message += "egresses"
 					logic.ReturnErrorResponse(w, r, errorResponse)
 					return
 				}

+ 2 - 2
controllers/node.go

@@ -27,9 +27,9 @@ func nodeHandlers(r *mux.Router) {
 	r.HandleFunc("/api/nodes/{network}/{nodeid}", Authorize(true, true, "node", http.HandlerFunc(getNode))).Methods(http.MethodGet)
 	r.HandleFunc("/api/nodes/{network}/{nodeid}", Authorize(false, true, "node", http.HandlerFunc(updateNode))).Methods(http.MethodPut)
 	r.HandleFunc("/api/nodes/{network}/{nodeid}", Authorize(true, true, "node", http.HandlerFunc(deleteNode))).Methods(http.MethodDelete)
-	r.HandleFunc("/api/nodes/{network}/{nodeid}/creategateway", Authorize(false, true, "user", http.HandlerFunc(createEgressGateway))).Methods(http.MethodPost)
+	r.HandleFunc("/api/nodes/{network}/{nodeid}/creategateway", Authorize(false, true, "user", checkFreeTierLimits(limitChoiceEgress, http.HandlerFunc(createEgressGateway)))).Methods(http.MethodPost)
 	r.HandleFunc("/api/nodes/{network}/{nodeid}/deletegateway", Authorize(false, true, "user", http.HandlerFunc(deleteEgressGateway))).Methods(http.MethodDelete)
-	r.HandleFunc("/api/nodes/{network}/{nodeid}/createingress", logic.SecurityCheck(false, http.HandlerFunc(createIngressGateway))).Methods(http.MethodPost)
+	r.HandleFunc("/api/nodes/{network}/{nodeid}/createingress", logic.SecurityCheck(false, checkFreeTierLimits(limitChoiceIngress, http.HandlerFunc(createIngressGateway)))).Methods(http.MethodPost)
 	r.HandleFunc("/api/nodes/{network}/{nodeid}/deleteingress", logic.SecurityCheck(false, http.HandlerFunc(deleteIngressGateway))).Methods(http.MethodDelete)
 	r.HandleFunc("/api/nodes/{network}/{nodeid}", Authorize(true, true, "node", http.HandlerFunc(updateNode))).Methods(http.MethodPost)
 	r.HandleFunc("/api/nodes/adm/{network}/authenticate", authenticate).Methods(http.MethodPost)

+ 37 - 10
logic/gateway.go

@@ -2,7 +2,6 @@ package logic
 
 import (
 	"errors"
-	"fmt"
 	"time"
 
 	"github.com/gravitl/netmaker/database"
@@ -11,6 +10,36 @@ import (
 	"github.com/gravitl/netmaker/servercfg"
 )
 
+// GetAllIngresses - gets all the hosts that are ingresses
+func GetAllIngresses() ([]models.Node, error) {
+	nodes, err := GetAllNodes()
+	if err != nil {
+		return nil, err
+	}
+	ingresses := make([]models.Node, 0)
+	for _, node := range nodes {
+		if node.IsIngressGateway {
+			ingresses = append(ingresses, node)
+		}
+	}
+	return ingresses, nil
+}
+
+// GetAllEgresses - gets all the hosts that are egresses
+func GetAllEgresses() ([]models.Node, error) {
+	nodes, err := GetAllNodes()
+	if err != nil {
+		return nil, err
+	}
+	egresses := make([]models.Node, 0)
+	for _, node := range nodes {
+		if node.IsEgressGateway {
+			egresses = append(egresses, node)
+		}
+	}
+	return egresses, nil
+}
+
 // CreateEgressGateway - creates an egress gateway
 func CreateEgressGateway(gateway models.EgressGatewayRequest) (models.Node, error) {
 	node, err := GetNodeByID(gateway.NodeID)
@@ -28,6 +57,13 @@ func CreateEgressGateway(gateway models.EgressGatewayRequest) (models.Node, erro
 		return models.Node{}, errors.New("firewall is not supported for egress gateways")
 	}
 	for i := len(gateway.Ranges) - 1; i >= 0; i-- {
+		// check if internet gateway IPv4
+		if gateway.Ranges[i] == "0.0.0.0/0" && FreeTier {
+			logger.Log(0, "currently IPv4 internet gateways are not supported on the free tier", gateway.Ranges[i])
+			gateway.Ranges = append(gateway.Ranges[:i], gateway.Ranges[i+1:]...)
+			continue
+		}
+		// check if internet gateway IPv6
 		if gateway.Ranges[i] == "::/0" {
 			logger.Log(0, "currently IPv6 internet gateways are not supported", gateway.Ranges[i])
 			gateway.Ranges = append(gateway.Ranges[:i], gateway.Ranges[i+1:]...)
@@ -150,15 +186,6 @@ func DeleteIngressGateway(nodeid string) (models.Node, bool, []models.ExtClient,
 	node.IsIngressGateway = false
 	node.IngressGatewayRange = ""
 	node.Failover = false
-
-	//logger.Log(3, "deleting ingress gateway firewall in use is '", host.FirewallInUse, "' and isEgressGateway is", node.IsEgressGateway)
-	if node.EgressGatewayRequest.NodeID != "" {
-		_, err := CreateEgressGateway(node.EgressGatewayRequest)
-		if err != nil {
-			logger.Log(0, fmt.Sprintf("failed to create egress gateway on node [%s] on network [%s]: %v",
-				node.EgressGatewayRequest.NodeID, node.EgressGatewayRequest.NetID, err))
-		}
-	}
 	err = UpsertNode(&node)
 	if err != nil {
 		return models.Node{}, wasFailover, removedClients, err

+ 10 - 1
logic/serverconf.go

@@ -2,7 +2,6 @@ package logic
 
 import (
 	"encoding/json"
-
 	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/servercfg"
 )
@@ -12,10 +11,16 @@ var (
 	NetworksLimit = 1000000000
 	// UsersLimit - dummy var for community
 	UsersLimit = 1000000000
+	// MachinesLimit - dummy var for community
+	MachinesLimit = 1000000000
 	// ClientsLimit - dummy var for community
 	ClientsLimit = 1000000000
 	// HostsLimit - dummy var for community
 	HostsLimit = 1000000000
+	// IngressesLimit - dummy var for community
+	IngressesLimit = 1000000000
+	// EgressesLimit - dummy var for community
+	EgressesLimit = 1000000000
 	// FreeTier - specifies if free tier
 	FreeTier = false
 )
@@ -87,10 +92,14 @@ func StoreJWTSecret(privateKey string) error {
 	return database.Insert("nm-jwt-secret", string(data), database.SERVERCONF_TABLE_NAME)
 }
 
+// SetFreeTierLimits - sets limits for free tier
 func SetFreeTierLimits() {
 	FreeTier = true
 	UsersLimit = servercfg.GetUserLimit()
 	ClientsLimit = servercfg.GetClientLimit()
 	NetworksLimit = servercfg.GetNetworkLimit()
 	HostsLimit = servercfg.GetHostLimit()
+	MachinesLimit = servercfg.GetMachinesLimit()
+	IngressesLimit = servercfg.GetIngressLimit()
+	EgressesLimit = servercfg.GetEgressLimit()
 }

+ 24 - 0
servercfg/serverconf.go

@@ -774,6 +774,30 @@ func GetHostLimit() int {
 	return hostsLimit
 }
 
+// GetMachinesLimit - fetches free tier limits on machines (clients + hosts)
+func GetMachinesLimit() int {
+	if l, err := strconv.Atoi(os.Getenv("MACHINES_LIMIT")); err == nil {
+		return l
+	}
+	return config.Config.Server.MachinesLimit
+}
+
+// GetIngressLimit - fetches free tier limits on ingresses
+func GetIngressLimit() int {
+	if l, err := strconv.Atoi(os.Getenv("INGRESSES_LIMIT")); err == nil {
+		return l
+	}
+	return config.Config.Server.IngressesLimit
+}
+
+// GetEgressLimit - fetches free tier limits on egresses
+func GetEgressLimit() int {
+	if l, err := strconv.Atoi(os.Getenv("EGRESSES_LIMIT")); err == nil {
+		return l
+	}
+	return config.Config.Server.EgressesLimit
+}
+
 // DeployedByOperator - returns true if the instance is deployed by netmaker operator
 func DeployedByOperator() bool {
 	if os.Getenv("DEPLOYED_BY_OPERATOR") != "" {