Forráskód Böngészése

resolve merge conflicts

abhishek9686 1 éve
szülő
commit
1ccb666218

+ 20 - 0
cli/cmd/failover/disable.go

@@ -0,0 +1,20 @@
+package failover
+
+import (
+	"github.com/gravitl/netmaker/cli/functions"
+	"github.com/spf13/cobra"
+)
+
+var disableFailoverCmd = &cobra.Command{
+	Use:   "disable [NODE ID]",
+	Args:  cobra.ExactArgs(1),
+	Short: "Disable failover for a given Node",
+	Long:  `Disable failover for a given Node`,
+	Run: func(cmd *cobra.Command, args []string) {
+		functions.PrettyPrint(functions.DisableNodeFailover(args[0]))
+	},
+}
+
+func init() {
+	rootCmd.AddCommand(disableFailoverCmd)
+}

+ 20 - 0
cli/cmd/failover/enable.go

@@ -0,0 +1,20 @@
+package failover
+
+import (
+	"github.com/gravitl/netmaker/cli/functions"
+	"github.com/spf13/cobra"
+)
+
+var enableFailoverCmd = &cobra.Command{
+	Use:   "enable [NODE ID]",
+	Args:  cobra.ExactArgs(1),
+	Short: "Enable failover for a given Node",
+	Long:  `Enable failover for a given Node`,
+	Run: func(cmd *cobra.Command, args []string) {
+		functions.PrettyPrint(functions.EnableNodeFailover(args[0]))
+	},
+}
+
+func init() {
+	rootCmd.AddCommand(enableFailoverCmd)
+}

+ 28 - 0
cli/cmd/failover/root.go

@@ -0,0 +1,28 @@
+package failover
+
+import (
+	"os"
+
+	"github.com/spf13/cobra"
+)
+
+// rootCmd represents the base command when called without any subcommands
+var rootCmd = &cobra.Command{
+	Use:   "failover",
+	Short: "Enable/Disable failover for a node associated with a network",
+	Long:  `Enable/Disable failover for a node associated with a network`,
+}
+
+// GetRoot returns the root subcommand
+func GetRoot() *cobra.Command {
+	return rootCmd
+}
+
+// Execute adds all child commands to the root command and sets flags appropriately.
+// This is called by main.main(). It only needs to happen once to the rootCmd.
+func Execute() {
+	err := rootCmd.Execute()
+	if err != nil {
+		os.Exit(1)
+	}
+}

+ 2 - 0
cli/cmd/root.go

@@ -9,6 +9,7 @@ import (
 	"github.com/gravitl/netmaker/cli/cmd/dns"
 	"github.com/gravitl/netmaker/cli/cmd/enrollment_key"
 	"github.com/gravitl/netmaker/cli/cmd/ext_client"
+	"github.com/gravitl/netmaker/cli/cmd/failover"
 	"github.com/gravitl/netmaker/cli/cmd/host"
 	"github.com/gravitl/netmaker/cli/cmd/metrics"
 	"github.com/gravitl/netmaker/cli/cmd/network"
@@ -53,4 +54,5 @@ func init() {
 	rootCmd.AddCommand(metrics.GetRoot())
 	rootCmd.AddCommand(host.GetRoot())
 	rootCmd.AddCommand(enrollment_key.GetRoot())
+	rootCmd.AddCommand(failover.GetRoot())
 }

+ 18 - 0
cli/functions/failover.go

@@ -0,0 +1,18 @@
+package functions
+
+import (
+	"fmt"
+	"net/http"
+
+	"github.com/gravitl/netmaker/models"
+)
+
+// EnableNodeFailover - Enable failover for a given Node
+func EnableNodeFailover(nodeID string) *models.SuccessResponse {
+	return request[models.SuccessResponse](http.MethodPost, fmt.Sprintf("/api/v1/node/%s/failover", nodeID), nil)
+}
+
+// DisableNodeFailover - Disable failover for a given Node
+func DisableNodeFailover(nodeID string) *models.SuccessResponse {
+	return request[models.SuccessResponse](http.MethodDelete, fmt.Sprintf("/api/v1/node/%s/failover", nodeID), nil)
+}

+ 32 - 0
controllers/hosts.go

@@ -32,6 +32,7 @@ func hostHandlers(r *mux.Router) {
 	r.HandleFunc("/api/v1/host", Authorize(true, false, "host", http.HandlerFunc(pull))).Methods(http.MethodGet)
 	r.HandleFunc("/api/v1/host/{hostid}/signalpeer", Authorize(true, false, "host", http.HandlerFunc(signalPeer))).Methods(http.MethodPost)
 	r.HandleFunc("/api/v1/fallback/host/{hostid}", Authorize(true, false, "host", http.HandlerFunc(hostUpdateFallback))).Methods(http.MethodPut)
+	r.HandleFunc("/api/emqx/hosts", logic.SecurityCheck(true, http.HandlerFunc(delEmqxHosts))).Methods(http.MethodDelete)
 	r.HandleFunc("/api/v1/auth-register/host", socketHandler)
 }
 
@@ -749,3 +750,34 @@ func syncHost(w http.ResponseWriter, r *http.Request) {
 	slog.Info("requested host pull", "user", r.Header.Get("user"), "host", host.ID)
 	w.WriteHeader(http.StatusOK)
 }
+
+// swagger:route DELETE /api/emqx/hosts hosts delEmqxHosts
+//
+// Lists all hosts.
+//
+//			Schemes: https
+//
+//			Security:
+//	  		oauth
+//
+//			Responses:
+//				200: apiHostResponse
+func delEmqxHosts(w http.ResponseWriter, r *http.Request) {
+	currentHosts, err := logic.GetAllHosts()
+	if err != nil {
+		logger.Log(0, r.Header.Get("user"), "failed to fetch hosts: ", err.Error())
+		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
+		return
+	}
+	for _, host := range currentHosts {
+		// delete EMQX credentials for host
+		if err := mq.GetEmqxHandler().DeleteEmqxUser(host.ID.String()); err != nil {
+			slog.Error("failed to remove host credentials from EMQX", "id", host.ID, "error", err)
+		}
+	}
+	err = mq.GetEmqxHandler().DeleteEmqxUser(servercfg.GetMqUserName())
+	if err != nil {
+		slog.Error("failed to remove server credentials from EMQX", "user", servercfg.GetMqUserName(), "error", err)
+	}
+	logic.ReturnSuccessResponse(w, r, "deleted hosts data on emqx")
+}

+ 34 - 12
logic/telemetry.go

@@ -2,6 +2,7 @@ package logic
 
 import (
 	"encoding/json"
+	"os"
 	"time"
 
 	"github.com/gravitl/netmaker/database"
@@ -9,6 +10,7 @@ import (
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/servercfg"
 	"github.com/posthog/posthog-go"
+	"golang.org/x/exp/slog"
 )
 
 // flags to keep for telemetry
@@ -39,14 +41,18 @@ func sendTelemetry() error {
 	// get telemetry data
 	d, err := FetchTelemetryData()
 	if err != nil {
-		return err
+		slog.Error("error fetching telemetry data", "error", err)
 	}
+	// get tenant admin email
+	adminEmail := os.Getenv("NM_EMAIL")
 	client, err := posthog.NewWithConfig(posthog_pub_key, posthog.Config{Endpoint: posthog_endpoint})
 	if err != nil {
 		return err
 	}
 	defer client.Close()
 
+	slog.Info("sending telemetry data to posthog", "data", d)
+
 	// send to posthog
 	return client.Enqueue(posthog.Capture{
 		DistinctId: telRecord.UUID,
@@ -67,7 +73,11 @@ func sendTelemetry() error {
 			Set("k8s", d.Count.K8S).
 			Set("version", d.Version).
 			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).
+			Set("is_pro_trial", d.IsProTrial).
+			Set("pro_trial_end_date", d.ProTrialEndDate.In(time.UTC).Format("2006-01-02")).
+			Set("admin_email", adminEmail).
+			Set("is_saas_tenant", d.IsSaasTenant),
 	})
 }
 
@@ -87,6 +97,15 @@ func FetchTelemetryData() (telemetryData, error) {
 		data.Nodes = len(nodes)
 		data.Count = getClientCount(nodes)
 	}
+	endDate, err := GetTrialEndDate()
+	if err != nil {
+		logger.Log(0, "error getting trial end date", err.Error())
+	}
+	data.ProTrialEndDate = endDate
+	if endDate.After(time.Now()) {
+		data.IsProTrial = true
+	}
+	data.IsSaasTenant = servercfg.DeployedByOperator()
 	return data, err
 }
 
@@ -162,16 +181,19 @@ func getDBLength(dbname string) int {
 
 // telemetryData - What data to send to posthog
 type telemetryData struct {
-	Nodes      int
-	Hosts      int
-	ExtClients int
-	Users      int
-	Count      clientCount
-	Networks   int
-	Servers    int
-	Version    string
-	IsPro      bool
-	IsFreeTier bool
+	Nodes           int
+	Hosts           int
+	ExtClients      int
+	Users           int
+	Count           clientCount
+	Networks        int
+	Servers         int
+	Version         string
+	IsPro           bool
+	IsFreeTier      bool
+	IsProTrial      bool
+	ProTrialEndDate time.Time
+	IsSaasTenant    bool
 }
 
 // clientCount - What types of netclients we're tallying

+ 2 - 1
mq/mq.go

@@ -33,8 +33,9 @@ func setMqOptions(user, password string, opts *mqtt.ClientOptions) {
 	opts.SetPassword(password)
 	opts.SetAutoReconnect(true)
 	opts.SetConnectRetry(true)
-	opts.SetConnectRetryInterval(time.Second << 2)
+	opts.SetConnectRetryInterval(time.Second * 4)
 	opts.SetKeepAlive(time.Minute)
+	opts.SetCleanSession(true)
 	opts.SetWriteTimeout(time.Minute)
 }
 

+ 5 - 2
pro/controllers/metrics.go

@@ -2,9 +2,11 @@ package controllers
 
 import (
 	"encoding/json"
-	proLogic "github.com/gravitl/netmaker/pro/logic"
 	"net/http"
 
+	proLogic "github.com/gravitl/netmaker/pro/logic"
+	"golang.org/x/exp/slog"
+
 	"github.com/gorilla/mux"
 	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/logger"
@@ -122,12 +124,13 @@ func getNetworkExtMetrics(w http.ResponseWriter, r *http.Request) {
 				continue
 			}
 			// if metrics for that client have been reported, append them
-			if len(ingressMetrics.Connectivity[clients[j].ClientID].NodeName) > 0 {
+			if _, ok := ingressMetrics.Connectivity[clients[j].ClientID]; ok {
 				networkMetrics.Connectivity[clients[j].ClientID] = ingressMetrics.Connectivity[clients[j].ClientID]
 			}
 		}
 	}
 
+	slog.Debug("sending collected client metrics", "metrics", networkMetrics.Connectivity)
 	logger.Log(1, r.Header.Get("user"), "fetched ext client metrics for network", network)
 	w.WriteHeader(http.StatusOK)
 	json.NewEncoder(w).Encode(networkMetrics.Connectivity)

+ 13 - 4
pro/controllers/middleware.go

@@ -1,16 +1,25 @@
 package controllers
 
 import (
+	"net/http"
+
 	"github.com/gravitl/netmaker/logic"
 	"github.com/gravitl/netmaker/servercfg"
-	"net/http"
 )
 
+var limitedApis = map[string]struct{}{
+	"/api/server/status":          {},
+	"/api/emqx/hosts":             {},
+	"/api/users/adm/authenticate": {},
+}
+
 func OnlyServerAPIWhenUnlicensedMiddleware(handler http.Handler) http.Handler {
 	return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
-		if servercfg.ErrLicenseValidation != nil && request.URL.Path != "/api/server/status" {
-			logic.ReturnErrorResponse(writer, request, logic.FormatError(servercfg.ErrLicenseValidation, "forbidden"))
-			return
+		if servercfg.ErrLicenseValidation != nil {
+			if _, ok := limitedApis[request.URL.Path]; !ok {
+				logic.ReturnErrorResponse(writer, request, logic.FormatError(servercfg.ErrLicenseValidation, "forbidden"))
+				return
+			}
 		}
 		handler.ServeHTTP(writer, request)
 	})

+ 1 - 1
pro/license.go

@@ -246,7 +246,7 @@ func validateLicenseKey(encryptedData []byte, publicKey *[32]byte) ([]byte, bool
 	slog.Warn(err.Error())
 
 	// try to use cache if we had a temporary error
-	if code == http.StatusServiceUnavailable || code == http.StatusGatewayTimeout {
+	if code == http.StatusServiceUnavailable || code == http.StatusGatewayTimeout || code == http.StatusBadGateway {
 		slog.Warn("Netmaker API may be down, will retry later...", "code", code)
 		return nil, true, nil
 	}

+ 8 - 19
pro/logic/metrics.go

@@ -104,7 +104,6 @@ func MQUpdateMetrics(client mqtt.Client, msg mqtt.Message) {
 }
 
 func updateNodeMetrics(currentNode *models.Node, newMetrics *models.Metrics) {
-
 	oldMetrics, err := logic.GetMetrics(currentNode.ID.String())
 	if err != nil {
 		slog.Error("error finding old metrics for node", "id", currentNode.ID, "error", err)
@@ -121,21 +120,13 @@ func updateNodeMetrics(currentNode *models.Node, newMetrics *models.Metrics) {
 	if newMetrics.Connectivity == nil {
 		newMetrics.Connectivity = make(map[string]models.Metric)
 	}
-	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
-		}
+	for i := range attachedClients {
+		slog.Debug("[metrics] processing attached client", "client", attachedClients[i].ClientID, "public key", attachedClients[i].PublicKey)
+		clientMetric := newMetrics.Connectivity[attachedClients[i].PublicKey]
+		clientMetric.NodeName = attachedClients[i].ClientID
+		newMetrics.Connectivity[attachedClients[i].ClientID] = clientMetric
+		delete(newMetrics.Connectivity, attachedClients[i].PublicKey)
+		slog.Debug("[metrics] attached client metric", "metric", clientMetric)
 	}
 
 	// run through metrics for each peer
@@ -168,7 +159,5 @@ func updateNodeMetrics(currentNode *models.Node, newMetrics *models.Metrics) {
 
 	}
 
-	for k := range oldMetrics.Connectivity { // cleanup any left over data, self healing
-		delete(newMetrics.Connectivity, k)
-	}
+	slog.Debug("[metrics] node metrics data", "node ID", currentNode.ID, "metrics", newMetrics)
 }

+ 1 - 4
pro/trial.go

@@ -42,10 +42,7 @@ const trial_data_key = "trialdata"
 
 // stores trial end date
 func initTrial() error {
-	telData, err := logic.FetchTelemetryData()
-	if err != nil {
-		return err
-	}
+	telData, _ := logic.FetchTelemetryData()
 	if telData.Hosts > 0 || telData.Networks > 0 || telData.Users > 0 {
 		return nil // database is already populated, so skip creating trial
 	}

+ 4 - 18
scripts/nm-quick.sh

@@ -470,23 +470,11 @@ set_install_vars() {
 
 	wait_seconds 1
 
-
 	unset GET_EMAIL
-	unset RAND_EMAIL
-	RAND_EMAIL="$(echo $RANDOM | md5sum | head -c 16)@email.com"
-	# suggest the prev email or a random one
-	EMAIL_SUGGESTED=${NM_EMAIL:-$RAND_EMAIL}
-	read -p "Email Address for Domain Registration (click 'enter' to use $EMAIL_SUGGESTED): " GET_EMAIL
-	if [ -z "$GET_EMAIL" ]; then
-		EMAIL="$EMAIL_SUGGESTED"
-		if [ "$EMAIL" = "$NM_EMAIL" ]; then
-			echo "using config email"
-		else
-			echo "using rand email"
-		fi
-	else
-		EMAIL="$GET_EMAIL"
-	fi
+	while [ -z "$GET_EMAIL" ]; do
+		read -p "Email Address for Domain Registration: " GET_EMAIL
+	done
+	EMAIL="$GET_EMAIL"
 
 	wait_seconds 1
 
@@ -592,8 +580,6 @@ install_netmaker() {
 
 	echo "Starting containers..."
 
-	
-
 	# start docker and rebuild containers / networks
 	cd "${SCRIPT_DIR}"
 	docker-compose up -d --force-recreate