Browse Source

Merge branch 'develop' into bugfix_v0.22.0_bump-gorqlite-to-a8a425b1a6aa

Seongbin Hong 1 year ago
parent
commit
ea235a5d3f

+ 1 - 0
.github/ISSUE_TEMPLATE/bug-report.yml

@@ -31,6 +31,7 @@ body:
       label: Version
       description: What version are you running?
       options:
+        - v0.22.1
         - v0.22.0
         - v0.21.2
         - v0.21.1

+ 6 - 6
README.md

@@ -16,7 +16,7 @@
 
 <p align="center">
   <a href="https://github.com/gravitl/netmaker/releases">
-    <img src="https://img.shields.io/badge/Version-0.22.0-informational?style=flat-square" />
+    <img src="https://img.shields.io/badge/Version-0.22.1-informational?style=flat-square" />
   </a>
   <a href="https://hub.docker.com/r/gravitl/netmaker/tags">
     <img src="https://img.shields.io/docker/pulls/gravitl/netmaker?label=downloads" />
@@ -47,13 +47,13 @@
 | :heavy_check_mark: Mesh VPNs              | :heavy_check_mark: Private DNS          | :heavy_check_mark: Mac                  |
 | :heavy_check_mark: Site-to-Site           | :heavy_check_mark: Access Control Lists | :heavy_check_mark: Windows              |
 
-# Try Online  
+# Try Netmaker SaaS  
 
-If you're just looking to use Netmaker, you can create an account for free at [netmaker.io](https://account.netmaker.io).  
+If you're looking for a managed service, you can get started with just few clicks, visit [netmaker.io](https://account.netmaker.io) to create your netmaker server.  
 
 # Self-Hosted Quick Start  
 
-These are the instructions for deploying a Netmaker server on your own cloud VM as quickly as possible. For more detailed instructions, visit the [Install Docs](https://netmaker.readthedocs.io/en/master/install.html).  
+These are the instructions for deploying a Netmaker server on your own cloud VM as quickly as possible. For more detailed instructions, visit the [Install Docs](https://docs.netmaker.io/install.html).  
 
 1. Get a cloud VM with Ubuntu 22.04 and a public IP.
 2. Open ports 443, 80, 3479, 8089 and 51821-51830/udp on the VM firewall and in cloud security settings.
@@ -62,13 +62,13 @@ These are the instructions for deploying a Netmaker server on your own cloud VM
 
 `sudo wget -qO /root/nm-quick.sh https://raw.githubusercontent.com/gravitl/netmaker/master/scripts/nm-quick.sh && sudo chmod +x /root/nm-quick.sh && sudo /root/nm-quick.sh`  
 
-This script gives you the option to deploy the Community or Enterprise version of Netmaker. It also gives you the option to use your own domain (recommended) or an auto-generated domain. 
+This script by default installs PRO version with 14-day trial, check out these instructions for post trial period https://docs.netmaker.io/install.html#after-trial-period-ends. It also gives you the option to use your own domain (recommended) or an auto-generated domain. 
 
 <p float="left" align="middle">
 <img src="https://raw.githubusercontent.com/gravitl/netmaker-docs/master/images/netmaker-github/readme.gif" />
 </p>
 
-After installing Netmaker, check out the [Walkthrough](https://itnext.io/getting-started-with-netmaker-a-wireguard-virtual-networking-platform-3d563fbd87f0) and [Getting Started](https://netmaker.readthedocs.io/en/master/getting-started.html) guides to learn more about configuring networks. Or, check out some of our other [Tutorials](https://www.netmaker.io/blog) for different use cases, including Kubernetes.
+After installing Netmaker, check out the [Walkthrough](https://itnext.io/getting-started-with-netmaker-a-wireguard-virtual-networking-platform-3d563fbd87f0) and [Getting Started](https://docs.netmaker.io/getting-started.html) guides to learn more about configuring networks. Or, check out some of our other [Tutorials](https://www.netmaker.io/blog) for different use cases, including Kubernetes.
 
 # Get Support
 

+ 18 - 0
auth/host_session.go

@@ -86,6 +86,24 @@ func SessionHandler(conn *websocket.Conn) {
 			return
 		}
 		req.Pass = req.Host.ID.String()
+		user, err := logic.GetUser(req.User)
+		if err != nil {
+			logger.Log(0, "failed to get user", req.User, "from database")
+			err = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
+			if err != nil {
+				logger.Log(0, "error during message writing:", err.Error())
+			}
+			return
+		}
+		if !user.IsAdmin && !user.IsSuperAdmin {
+			logger.Log(0, "user", req.User, "is neither an admin or superadmin. denying registeration")
+			conn.WriteMessage(messageType, []byte("cannot register with a non-admin or non-superadmin"))
+			err = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
+			if err != nil {
+				logger.Log(0, "error during message writing:", err.Error())
+			}
+			return
+		}
 
 		if err = netcache.Set(stateStr, req); err != nil { // give the user's host access in the DB
 			logger.Log(0, "machine failed to complete join on network,", registerMessage.Network, "-", err.Error())

+ 1 - 1
compose/docker-compose.netclient.yml

@@ -3,7 +3,7 @@ version: "3.4"
 services:
   netclient:
     container_name: netclient
-    image: 'gravitl/netclient:v0.22.0'
+    image: 'gravitl/netclient:v0.22.1'
     hostname: netmaker-1
     network_mode: host
     restart: on-failure

+ 1 - 1
controllers/docs.go

@@ -10,7 +10,7 @@
 //
 //	Schemes: https
 //	BasePath: /
-//	Version: 0.22.0
+//	Version: 0.22.1
 //	Host: api.demo.netmaker.io
 //
 //	Consumes:

+ 1 - 1
controllers/hosts.go

@@ -254,7 +254,7 @@ func hostUpdateFallback(w http.ResponseWriter, r *http.Request) {
 			return
 		}
 	case models.UpdateMetrics:
-		// mq.UpdateMetricsFallBack(hostUpdate.Node.ID.String(), hostUpdate.NewMetrics)
+		mq.UpdateMetricsFallBack(hostUpdate.Node.ID.String(), hostUpdate.NewMetrics)
 	}
 	logic.ReturnSuccessResponse(w, r, "updated host data")
 

+ 24 - 9
controllers/server.go

@@ -5,6 +5,7 @@ import (
 	"net/http"
 	"strings"
 	"syscall"
+	"time"
 
 	"github.com/gorilla/mux"
 	"golang.org/x/exp/slog"
@@ -109,22 +110,36 @@ func getUsage(w http.ResponseWriter, _ *http.Request) {
 //				200: serverConfigResponse
 func getStatus(w http.ResponseWriter, r *http.Request) {
 	type status struct {
-		DB           bool   `json:"db_connected"`
-		Broker       bool   `json:"broker_connected"`
-		LicenseError string `json:"license_error"`
-		IsPro        bool   `json:"is_pro"`
+		DB               bool      `json:"db_connected"`
+		Broker           bool      `json:"broker_connected"`
+		LicenseError     string    `json:"license_error"`
+		IsPro            bool      `json:"is_pro"`
+		TrialEndDate     time.Time `json:"trial_end_date"`
+		IsOnTrialLicense bool      `json:"is_on_trial_license"`
 	}
 
 	licenseErr := ""
 	if servercfg.ErrLicenseValidation != nil {
 		licenseErr = servercfg.ErrLicenseValidation.Error()
 	}
-
+	var trialEndDate time.Time
+	var err error
+	isOnTrial := false
+	if servercfg.IsPro && (servercfg.GetLicenseKey() == "" || servercfg.GetNetmakerTenantID() == "") {
+		trialEndDate, err = logic.GetTrialEndDate()
+		if err != nil {
+			slog.Error("failed to get trial end date", "error", err)
+		} else {
+			isOnTrial = true
+		}
+	}
 	currentServerStatus := status{
-		DB:           database.IsConnected(),
-		Broker:       mq.IsConnected(),
-		LicenseError: licenseErr,
-		IsPro:        servercfg.IsPro,
+		DB:               database.IsConnected(),
+		Broker:           mq.IsConnected(),
+		LicenseError:     licenseErr,
+		IsPro:            servercfg.IsPro,
+		TrialEndDate:     trialEndDate,
+		IsOnTrialLicense: isOnTrial,
 	}
 
 	w.Header().Set("Content-Type", "application/json")

+ 22 - 22
database/database.go

@@ -124,29 +124,29 @@ func InitializeDatabase() error {
 }
 
 func createTables() {
-	createTable(NETWORKS_TABLE_NAME)
-	createTable(NODES_TABLE_NAME)
-	createTable(CERTS_TABLE_NAME)
-	createTable(DELETED_NODES_TABLE_NAME)
-	createTable(USERS_TABLE_NAME)
-	createTable(DNS_TABLE_NAME)
-	createTable(EXT_CLIENT_TABLE_NAME)
-	createTable(PEERS_TABLE_NAME)
-	createTable(SERVERCONF_TABLE_NAME)
-	createTable(SERVER_UUID_TABLE_NAME)
-	createTable(GENERATED_TABLE_NAME)
-	createTable(NODE_ACLS_TABLE_NAME)
-	createTable(SSO_STATE_CACHE)
-	createTable(METRICS_TABLE_NAME)
-	createTable(NETWORK_USER_TABLE_NAME)
-	createTable(USER_GROUPS_TABLE_NAME)
-	createTable(CACHE_TABLE_NAME)
-	createTable(HOSTS_TABLE_NAME)
-	createTable(ENROLLMENT_KEYS_TABLE_NAME)
-	createTable(HOST_ACTIONS_TABLE_NAME)
+	CreateTable(NETWORKS_TABLE_NAME)
+	CreateTable(NODES_TABLE_NAME)
+	CreateTable(CERTS_TABLE_NAME)
+	CreateTable(DELETED_NODES_TABLE_NAME)
+	CreateTable(USERS_TABLE_NAME)
+	CreateTable(DNS_TABLE_NAME)
+	CreateTable(EXT_CLIENT_TABLE_NAME)
+	CreateTable(PEERS_TABLE_NAME)
+	CreateTable(SERVERCONF_TABLE_NAME)
+	CreateTable(SERVER_UUID_TABLE_NAME)
+	CreateTable(GENERATED_TABLE_NAME)
+	CreateTable(NODE_ACLS_TABLE_NAME)
+	CreateTable(SSO_STATE_CACHE)
+	CreateTable(METRICS_TABLE_NAME)
+	CreateTable(NETWORK_USER_TABLE_NAME)
+	CreateTable(USER_GROUPS_TABLE_NAME)
+	CreateTable(CACHE_TABLE_NAME)
+	CreateTable(HOSTS_TABLE_NAME)
+	CreateTable(ENROLLMENT_KEYS_TABLE_NAME)
+	CreateTable(HOST_ACTIONS_TABLE_NAME)
 }
 
-func createTable(tableName string) error {
+func CreateTable(tableName string) error {
 	return getCurrentDB()[CREATE_TABLE].(func(string) error)(tableName)
 }
 
@@ -194,7 +194,7 @@ func DeleteAllRecords(tableName string) error {
 	if err != nil {
 		return err
 	}
-	err = createTable(tableName)
+	err = CreateTable(tableName)
 	if err != nil {
 		return err
 	}

+ 6 - 6
go.mod

@@ -4,7 +4,7 @@ go 1.19
 
 require (
 	github.com/eclipse/paho.mqtt.golang v1.4.3
-	github.com/go-playground/validator/v10 v10.16.0
+	github.com/go-playground/validator/v10 v10.17.0
 	github.com/golang-jwt/jwt/v4 v4.5.0
 	github.com/google/uuid v1.5.0
 	github.com/gorilla/handlers v1.5.2
@@ -15,10 +15,10 @@ require (
 	github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
 	github.com/stretchr/testify v1.8.4
 	github.com/txn2/txeh v1.5.5
-	golang.org/x/crypto v0.17.0
-	golang.org/x/net v0.19.0 // indirect
-	golang.org/x/oauth2 v0.15.0
-	golang.org/x/sys v0.15.0 // indirect
+	golang.org/x/crypto v0.18.0
+	golang.org/x/net v0.20.0 // indirect
+	golang.org/x/oauth2 v0.16.0
+	golang.org/x/sys v0.16.0 // indirect
 	golang.org/x/text v0.14.0 // indirect
 	golang.zx2c4.com/wireguard/wgctrl v0.0.0-20221104135756-97bc4ad4a1cb
 	google.golang.org/protobuf v1.31.0 // indirect
@@ -27,7 +27,7 @@ require (
 
 require (
 	filippo.io/edwards25519 v1.1.0
-	github.com/c-robinson/iplib v1.0.7
+	github.com/c-robinson/iplib v1.0.8
 	github.com/posthog/posthog-go v0.0.0-20211028072449-93c17c49e2b0
 )
 

+ 12 - 12
go.sum

@@ -5,8 +5,8 @@ cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2Aawl
 filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
 filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
-github.com/c-robinson/iplib v1.0.7 h1:Dh9AINAlkc+NsNzZuFiVs+pi3AjN+0B7mu01KHdJKHU=
-github.com/c-robinson/iplib v1.0.7/go.mod h1:i3LuuFL1hRT5gFpBRnEydzw8R6yhGkF4szNDIbF8pgo=
+github.com/c-robinson/iplib v1.0.8 h1:exDRViDyL9UBLcfmlxxkY5odWX5092nPsQIykHXhIn4=
+github.com/c-robinson/iplib v1.0.8/go.mod h1:i3LuuFL1hRT5gFpBRnEydzw8R6yhGkF4szNDIbF8pgo=
 github.com/coreos/go-oidc/v3 v3.9.0 h1:0J/ogVOd4y8P0f0xUh8l9t07xRP/d8tccvjHl2dcsSo=
 github.com/coreos/go-oidc/v3 v3.9.0/go.mod h1:rTKz2PYwftcrtoCzV5g5kvfJoWcm0Mk8AF8y1iAQro4=
 github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
@@ -27,8 +27,8 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o
 github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
 github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
 github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
-github.com/go-playground/validator/v10 v10.16.0 h1:x+plE831WK4vaKHO/jpgUGsvLKIqRRkz6M78GuJAfGE=
-github.com/go-playground/validator/v10 v10.16.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
+github.com/go-playground/validator/v10 v10.17.0 h1:SmVVlfAOtlZncTxRuinDPomC2DkXJ4E5T9gDA0AIH74=
+github.com/go-playground/validator/v10 v10.17.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
 github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
 github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
 github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
@@ -104,8 +104,8 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
-golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
+golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
+golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
 golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc=
 golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
@@ -113,10 +113,10 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
-golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
-golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ=
-golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM=
+golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
+golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
+golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ=
+golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
@@ -127,8 +127,8 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
-golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
+golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

+ 1 - 1
k8s/client/netclient-daemonset.yaml

@@ -16,7 +16,7 @@ spec:
       hostNetwork: true
       containers:
       - name: netclient
-        image: gravitl/netclient:v0.22.0
+        image: gravitl/netclient:v0.22.1
         env:
         - name: TOKEN
           value: "TOKEN_VALUE"

+ 1 - 1
k8s/client/netclient.yaml

@@ -28,7 +28,7 @@ spec:
       #           - "<node label value>"
       containers:
       - name: netclient
-        image: gravitl/netclient:v0.22.0
+        image: gravitl/netclient:v0.22.1
         env:
         - name: TOKEN
           value: "TOKEN_VALUE"

+ 1 - 1
k8s/server/netmaker-ui.yaml

@@ -15,7 +15,7 @@ spec:
     spec:
       containers:
       - name: netmaker-ui
-        image: gravitl/netmaker-ui:v0.22.0
+        image: gravitl/netmaker-ui:v0.22.1
         ports:
         - containerPort: 443
         env:

+ 14 - 33
logic/peers.go

@@ -24,6 +24,10 @@ var (
 	ResetFailedOverPeer = func(failedOverNode *models.Node) error {
 		return nil
 	}
+	// GetFailOverPeerIps - gets failover peerips
+	GetFailOverPeerIps = func(peer, node *models.Node) []net.IPNet {
+		return []net.IPNet{}
+	}
 )
 
 // GetPeerUpdateForHost - gets the consolidated peer update for the host from all networks
@@ -144,16 +148,18 @@ func GetPeerUpdateForHost(network string, host *models.Host, allNodes []models.N
 				hostPeerUpdate.EgressRoutes = append(hostPeerUpdate.EgressRoutes, getExtpeersExtraRoutes(peer.Network)...)
 			}
 			_, isFailOverPeer := node.FailOverPeers[peer.ID.String()]
-			if (node.IsRelayed && node.RelayedBy != peer.ID.String()) ||
-				(peer.IsRelayed && peer.RelayedBy != node.ID.String()) || isFailOverPeer {
-				// if node is relayed and peer is not the relay, set remove to true
-				if _, ok := peerIndexMap[peerHost.PublicKey.String()]; ok {
+			if servercfg.IsPro {
+				if (node.IsRelayed && node.RelayedBy != peer.ID.String()) ||
+					(peer.IsRelayed && peer.RelayedBy != node.ID.String()) || isFailOverPeer {
+					// if node is relayed and peer is not the relay, set remove to true
+					if _, ok := peerIndexMap[peerHost.PublicKey.String()]; ok {
+						continue
+					}
+					peerConfig.Remove = true
+					hostPeerUpdate.Peers = append(hostPeerUpdate.Peers, peerConfig)
+					peerIndexMap[peerHost.PublicKey.String()] = len(hostPeerUpdate.Peers) - 1
 					continue
 				}
-				peerConfig.Remove = true
-				hostPeerUpdate.Peers = append(hostPeerUpdate.Peers, peerConfig)
-				peerIndexMap[peerHost.PublicKey.String()] = len(hostPeerUpdate.Peers) - 1
-				continue
 			}
 
 			uselocal := false
@@ -362,31 +368,6 @@ func GetAllowedIPs(node, peer *models.Node, metrics *models.Metrics) []net.IPNet
 	return allowedips
 }
 
-func GetFailOverPeerIps(peer, node *models.Node) []net.IPNet {
-	allowedips := []net.IPNet{}
-	for failOverpeerID := range node.FailOverPeers {
-		failOverpeer, err := GetNodeByID(failOverpeerID)
-		if err == nil && failOverpeer.FailedOverBy == peer.ID {
-			if failOverpeer.Address.IP != nil {
-				allowed := net.IPNet{
-					IP:   failOverpeer.Address.IP,
-					Mask: net.CIDRMask(32, 32),
-				}
-				allowedips = append(allowedips, allowed)
-			}
-			if failOverpeer.Address6.IP != nil {
-				allowed := net.IPNet{
-					IP:   failOverpeer.Address6.IP,
-					Mask: net.CIDRMask(128, 128),
-				}
-				allowedips = append(allowedips, allowed)
-			}
-
-		}
-	}
-	return allowedips
-}
-
 func GetEgressIPs(peer *models.Node) []net.IPNet {
 
 	peerHost, err := GetHost(peer.HostID.String())

+ 6 - 34
logic/serverconf.go

@@ -2,6 +2,8 @@ package logic
 
 import (
 	"encoding/json"
+	"time"
+
 	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/servercfg"
 )
@@ -19,46 +21,16 @@ var (
 	EgressesLimit = 1000000000
 	// FreeTier - specifies if free tier
 	FreeTier = false
+
+	GetTrialEndDate = func() (time.Time, error) {
+		return time.Time{}, nil
+	}
 )
 
 type serverData struct {
 	PrivateKey string `json:"privatekey,omitempty" bson:"privatekey,omitempty"`
 }
 
-// StorePrivKey - stores server client WireGuard privatekey if needed
-func StorePrivKey(serverID string, privateKey string) error {
-	var newData = serverData{}
-	var err error
-	var data []byte
-	newData.PrivateKey = privateKey
-	data, err = json.Marshal(&newData)
-	if err != nil {
-		return err
-	}
-	return database.Insert(serverID, string(data), database.SERVERCONF_TABLE_NAME)
-}
-
-// FetchPrivKey - fetches private key
-func FetchPrivKey(serverID string) (string, error) {
-	var dbData string
-	var err error
-	var fetchedData = serverData{}
-	dbData, err = database.FetchRecord(database.SERVERCONF_TABLE_NAME, serverID)
-	if err != nil {
-		return "", err
-	}
-	err = json.Unmarshal([]byte(dbData), &fetchedData)
-	if err != nil {
-		return "", err
-	}
-	return fetchedData.PrivateKey, nil
-}
-
-// RemovePrivKey - removes a private key
-func RemovePrivKey(serverID string) error {
-	return database.DeleteRecord(database.SERVERCONF_TABLE_NAME, serverID)
-}
-
 // FetchJWTSecret - fetches jwt secret from db
 func FetchJWTSecret() (string, error) {
 	var dbData string

+ 6 - 6
logic/telemetry.go

@@ -32,12 +32,12 @@ func sendTelemetry() error {
 		return nil
 	}
 
-	var telRecord, err = fetchTelemetryRecord()
+	var telRecord, err = FetchTelemetryRecord()
 	if err != nil {
 		return err
 	}
 	// get telemetry data
-	d, err := fetchTelemetryData()
+	d, err := FetchTelemetryData()
 	if err != nil {
 		return err
 	}
@@ -71,8 +71,8 @@ func sendTelemetry() error {
 	})
 }
 
-// fetchTelemetry - fetches telemetry data: count of various object types in DB
-func fetchTelemetryData() (telemetryData, error) {
+// FetchTelemetryData - fetches telemetry data: count of various object types in DB
+func FetchTelemetryData() (telemetryData, error) {
 	var data telemetryData
 
 	data.IsPro = servercfg.IsPro
@@ -138,8 +138,8 @@ func getClientCount(nodes []models.Node) clientCount {
 	return count
 }
 
-// fetchTelemetryRecord - get the existing UUID and Timestamp from the DB
-func fetchTelemetryRecord() (models.Telemetry, error) {
+// FetchTelemetryRecord - get the existing UUID and Timestamp from the DB
+func FetchTelemetryRecord() (models.Telemetry, error) {
 	var rawData string
 	var telObj models.Telemetry
 	var err error

+ 4 - 3
logic/timer.go

@@ -3,11 +3,12 @@ package logic
 import (
 	"context"
 	"fmt"
-	"github.com/gravitl/netmaker/logger"
-	"golang.org/x/exp/slog"
 	"sync"
 	"time"
 
+	"github.com/gravitl/netmaker/logger"
+	"golang.org/x/exp/slog"
+
 	"github.com/gravitl/netmaker/models"
 )
 
@@ -24,7 +25,7 @@ var HookManagerCh = make(chan models.HookDetails, 3)
 // TimerCheckpoint - Checks if 24 hours has passed since telemetry was last sent. If so, sends telemetry data to posthog
 func TimerCheckpoint() error {
 	// get the telemetry record in the DB, which contains a timestamp
-	telRecord, err := fetchTelemetryRecord()
+	telRecord, err := FetchTelemetryRecord()
 	if err != nil {
 		return err
 	}

+ 2 - 2
logic/traffic.go

@@ -2,7 +2,7 @@ package logic
 
 // RetrievePrivateTrafficKey - retrieves private key of server
 func RetrievePrivateTrafficKey() ([]byte, error) {
-	var telRecord, err = fetchTelemetryRecord()
+	var telRecord, err = FetchTelemetryRecord()
 	if err != nil {
 		return nil, err
 	}
@@ -12,7 +12,7 @@ func RetrievePrivateTrafficKey() ([]byte, error) {
 
 // RetrievePublicTrafficKey - retrieves public key of server
 func RetrievePublicTrafficKey() ([]byte, error) {
-	var telRecord, err = fetchTelemetryRecord()
+	var telRecord, err = FetchTelemetryRecord()
 	if err != nil {
 		return nil, err
 	}

+ 1 - 1
main.go

@@ -28,7 +28,7 @@ import (
 	"golang.org/x/exp/slog"
 )
 
-var version = "v0.22.0"
+var version = "v0.22.1"
 
 // Start DB Connection and start API Request Handler
 func main() {

+ 47 - 8
pro/initialize.go

@@ -4,7 +4,10 @@
 package pro
 
 import (
+	"time"
+
 	controller "github.com/gravitl/netmaker/controllers"
+	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/logic"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/mq"
@@ -31,21 +34,56 @@ func InitPro() {
 	)
 	logic.EnterpriseCheckFuncs = append(logic.EnterpriseCheckFuncs, func() {
 		// == License Handling ==
-		ClearLicenseCache()
-		if err := ValidateLicense(); err != nil {
-			slog.Error(err.Error())
-			return
+		enableLicenseHook := false
+		licenseKeyValue := servercfg.GetLicenseKey()
+		netmakerTenantID := servercfg.GetNetmakerTenantID()
+		if licenseKeyValue != "" && netmakerTenantID != "" {
+			enableLicenseHook = true
+		}
+		if !enableLicenseHook {
+			err := initTrial()
+			if err != nil {
+				logger.Log(0, "failed to init trial", err.Error())
+				enableLicenseHook = true
+			}
+			trialEndDate, err := getTrialEndDate()
+			if err != nil {
+				slog.Error("failed to get trial end date", "error", err)
+				enableLicenseHook = true
+			} else {
+				// check if trial ended
+				if time.Now().After(trialEndDate) {
+					// trial ended already
+					enableLicenseHook = true
+				}
+			}
+
 		}
-		slog.Info("proceeding with Paid Tier license")
-		logic.SetFreeTierForTelemetry(false)
-		// == End License Handling ==
-		AddLicenseHooks()
+
+		if enableLicenseHook {
+			logger.Log(0, "starting license checker")
+			ClearLicenseCache()
+			if err := ValidateLicense(); err != nil {
+				slog.Error(err.Error())
+				return
+			}
+			logger.Log(0, "proceeding with Paid Tier license")
+			logic.SetFreeTierForTelemetry(false)
+			// == End License Handling ==
+			AddLicenseHooks()
+		} else {
+			logger.Log(0, "starting trial license hook")
+			addTrialLicenseHook()
+		}
+
 		if servercfg.GetServerConfig().RacAutoDisable {
 			AddRacHooks()
 		}
+
 	})
 	logic.ResetFailOver = proLogic.ResetFailOver
 	logic.ResetFailedOverPeer = proLogic.ResetFailedOverPeer
+	logic.GetFailOverPeerIps = proLogic.GetFailOverPeerIps
 	logic.DenyClientNodeAccess = proLogic.DenyClientNode
 	logic.IsClientNodeAllowed = proLogic.IsClientNodeAllowed
 	logic.AllowClientNodeAccess = proLogic.RemoveDeniedNodeFromClient
@@ -63,6 +101,7 @@ func InitPro() {
 	logic.RelayUpdates = proLogic.RelayUpdates
 	logic.IsInternetGw = proLogic.IsInternetGw
 	logic.SetInternetGw = proLogic.SetInternetGw
+	logic.GetTrialEndDate = getTrialEndDate
 	mq.UpdateMetrics = proLogic.MQUpdateMetrics
 	mq.UpdateMetricsFallBack = proLogic.MQUpdateMetricsFallBack
 }

+ 27 - 0
pro/logic/failover.go

@@ -2,6 +2,7 @@ package logic
 
 import (
 	"errors"
+	"net"
 
 	"github.com/google/uuid"
 	"github.com/gravitl/netmaker/logic"
@@ -96,3 +97,29 @@ func ResetFailOver(failOverNode *models.Node) error {
 	}
 	return nil
 }
+
+// GetFailOverPeerIps - adds the failedOvered peerIps by the peer
+func GetFailOverPeerIps(peer, node *models.Node) []net.IPNet {
+	allowedips := []net.IPNet{}
+	for failOverpeerID := range node.FailOverPeers {
+		failOverpeer, err := logic.GetNodeByID(failOverpeerID)
+		if err == nil && failOverpeer.FailedOverBy == peer.ID {
+			if failOverpeer.Address.IP != nil {
+				allowed := net.IPNet{
+					IP:   failOverpeer.Address.IP,
+					Mask: net.CIDRMask(32, 32),
+				}
+				allowedips = append(allowedips, allowed)
+			}
+			if failOverpeer.Address6.IP != nil {
+				allowed := net.IPNet{
+					IP:   failOverpeer.Address6.IP,
+					Mask: net.CIDRMask(128, 128),
+				}
+				allowedips = append(allowedips, allowed)
+			}
+
+		}
+	}
+	return allowedips
+}

+ 3 - 0
pro/remote_access_client.go

@@ -1,3 +1,6 @@
+//go:build ee
+// +build ee
+
 package pro
 
 import (

+ 164 - 0
pro/trial.go

@@ -0,0 +1,164 @@
+//go:build ee
+// +build ee
+
+package pro
+
+import (
+	"crypto/rand"
+	"encoding/json"
+	"errors"
+	"time"
+
+	"github.com/gravitl/netmaker/database"
+	"github.com/gravitl/netmaker/logger"
+	"github.com/gravitl/netmaker/logic"
+	"github.com/gravitl/netmaker/models"
+	"github.com/gravitl/netmaker/netclient/ncutils"
+	"github.com/gravitl/netmaker/servercfg"
+	"golang.org/x/crypto/nacl/box"
+)
+
+type TrialInfo struct {
+	PrivKey []byte `json:"priv_key"`
+	PubKey  []byte `json:"pub_key"`
+	Secret  []byte `json:"secret"`
+}
+
+func addTrialLicenseHook() {
+	logic.HookManagerCh <- models.HookDetails{
+		Hook:     TrialLicenseHook,
+		Interval: time.Hour,
+	}
+}
+
+type TrialDates struct {
+	TrialStartedAt time.Time `json:"trial_started_at"`
+	TrialEndsAt    time.Time `json:"trial_ends_at"`
+}
+
+const trial_table_name = "trial"
+
+const trial_data_key = "trialdata"
+
+// stores trial end date
+func initTrial() error {
+	telData, err := logic.FetchTelemetryData()
+	if err != nil {
+		return err
+	}
+	if telData.Hosts > 0 || telData.Networks > 0 || telData.Users > 0 {
+		return nil // database is already populated, so skip creating trial
+	}
+	database.CreateTable(trial_table_name)
+	records, err := database.FetchRecords(trial_table_name)
+	if err != nil && !database.IsEmptyRecord(err) {
+		return err
+	}
+	if len(records) > 0 {
+		return nil
+	}
+	// setup encryption keys
+	trafficPubKey, trafficPrivKey, err := box.GenerateKey(rand.Reader) // generate traffic keys
+	if err != nil {
+		return err
+	}
+	tPriv, err := ncutils.ConvertKeyToBytes(trafficPrivKey)
+	if err != nil {
+		return err
+	}
+
+	tPub, err := ncutils.ConvertKeyToBytes(trafficPubKey)
+	if err != nil {
+		return err
+	}
+	trialDates := TrialDates{
+		TrialStartedAt: time.Now(),
+		TrialEndsAt:    time.Now().Add(time.Hour * 24 * 14),
+	}
+	t := TrialInfo{
+		PrivKey: tPriv,
+		PubKey:  tPub,
+	}
+	tel, err := logic.FetchTelemetryRecord()
+	if err != nil {
+		return err
+	}
+
+	trialDatesData, err := json.Marshal(trialDates)
+	if err != nil {
+		return err
+	}
+	telePubKey, err := ncutils.ConvertBytesToKey(tel.TrafficKeyPub)
+	if err != nil {
+		return err
+	}
+	trialDatesSecret, err := ncutils.BoxEncrypt(trialDatesData, telePubKey, trafficPrivKey)
+	if err != nil {
+		return err
+	}
+	t.Secret = trialDatesSecret
+	trialData, err := json.Marshal(t)
+	if err != nil {
+		return err
+	}
+	err = database.Insert(trial_data_key, string(trialData), trial_table_name)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+// TrialLicenseHook - hook func to check if pro trial has ended
+func TrialLicenseHook() error {
+	endDate, err := getTrialEndDate()
+	if err != nil {
+		logger.FatalLog0("failed to trial end date", err.Error())
+	}
+	if time.Now().After(endDate) {
+		logger.Log(0, "***IMPORTANT: Your Trial Has Ended, to continue using pro version, please visit https://app.netmaker.io/ and create on-prem tenant to obtain a license***\nIf you wish to downgrade to community version, please run this command `/root/nm-quick.sh -d`")
+		err = errors.New("your trial has ended")
+		servercfg.ErrLicenseValidation = err
+		return err
+	}
+	return nil
+}
+
+// get trial date
+func getTrialEndDate() (time.Time, error) {
+	record, err := database.FetchRecord(trial_table_name, trial_data_key)
+	if err != nil {
+		return time.Time{}, err
+	}
+	var trialInfo TrialInfo
+	err = json.Unmarshal([]byte(record), &trialInfo)
+	if err != nil {
+		return time.Time{}, err
+	}
+	tel, err := logic.FetchTelemetryRecord()
+	if err != nil {
+		return time.Time{}, err
+	}
+	telePrivKey, err := ncutils.ConvertBytesToKey(tel.TrafficKeyPriv)
+	if err != nil {
+		return time.Time{}, err
+	}
+	trialPubKey, err := ncutils.ConvertBytesToKey(trialInfo.PubKey)
+	if err != nil {
+		return time.Time{}, err
+	}
+	// decrypt secret
+	secretDecrypt, err := ncutils.BoxDecrypt(trialInfo.Secret, trialPubKey, telePrivKey)
+	if err != nil {
+		return time.Time{}, err
+	}
+	trialDates := TrialDates{}
+	err = json.Unmarshal(secretDecrypt, &trialDates)
+	if err != nil {
+		return time.Time{}, err
+	}
+	if trialDates.TrialEndsAt.IsZero() {
+		return time.Time{}, errors.New("invalid date")
+	}
+	return trialDates.TrialEndsAt, nil
+
+}

+ 0 - 1
pro/types.go

@@ -1,4 +1,3 @@
-// go:build ee
 //go:build ee
 // +build ee
 

+ 1 - 1
release.md

@@ -1,5 +1,5 @@
 
-# Netmaker v0.22.0
+# Netmaker v0.22.1
 
 ## Whats New
 - Revamped Internet Gateways

+ 206 - 264
scripts/nm-quick.sh

@@ -11,64 +11,25 @@ if [ $(id -u) -ne 0 ]; then
 	echo "This script must be run as root"
 	exit 1
 fi
-
+# increase the timeouts
+export DOCKER_CLIENT_TIMEOUT=120
+export COMPOSE_HTTP_TIMEOUT=120
 unset INSTALL_TYPE
-unset BUILD_TYPE
 unset BUILD_TAG
 unset IMAGE_TAG
-unset AUTO_BUILD
 unset NETMAKER_BASE_DOMAIN
-
+unset UPGRADE_FLAG
 # usage - displays usage instructions
 usage() {
 	echo "nm-quick.sh v$NM_QUICK_VERSION"
-	echo "usage: ./nm-quick.sh [-e] [-b buildtype] [-t tag] [-a auto] [-d domain]"
-	echo "  -e      if specified, will install netmaker pro"
-	echo "  -b      type of build; options:"
-	echo "          \"version\" - will install a specific version of Netmaker using remote git and dockerhub"
-	echo "          \"local\": - will install by cloning repo and building images from git"
-	echo "          \"branch\": - will install a specific branch using remote git and dockerhub"
-	echo "  -t      tag of build; if buildtype=version, tag=version. If builtype=branch or builtype=local, tag=branch"
-	echo "  -a      auto-build; skip prompts and use defaults, if none provided"
-	echo "  -d      domain; if specified, will use this domain instead of auto-generating one"
-	echo "examples:"
-	echo "          nm-quick.sh -e -b version -t $LATEST"
-	echo "          nm-quick.sh -e -b local -t feature_v0.17.2_newfeature"
-	echo "          nm-quick.sh -e -b branch -t develop"
-	echo "          nm-quick.sh -e -b version -t $LATEST -a -d example.com"
+	echo "usage: ./nm-quick.sh [-c]"
+	echo " -c  if specified, will install netmaker community version"
+	echo " -u  if specified, will upgrade netmaker to pro version"
+	echo " -d if specified, will downgrade netmaker to community version"
 	exit 1
 }
 
-while getopts evab:d:t: flag; do
-	case "${flag}" in
-	e)
-		INSTALL_TYPE="pro"
-		UPGRADE_FLAG="yes"
-		;;
-	v)
-		usage
-		exit 0
-		;;
-	a)
-		AUTO_BUILD="on"
-		;;
-	b)
-		BUILD_TYPE=${OPTARG}
-		if [[ ! "$BUILD_TYPE" =~ ^(version|local|branch)$ ]]; then
-			echo "error: $BUILD_TYPE is invalid"
-			echo "valid options: version, local, branch"
-			usage
-			exit 1
-		fi
-		;;
-	t)
-		BUILD_TAG=${OPTARG}
-		;;
-	d)
-		NETMAKER_BASE_DOMAIN=${OPTARG}
-		;;
-	esac
-done
+
 
 # print_logo - prints the netmaker logo
 print_logo() {
@@ -93,32 +54,12 @@ EOF
 # set_buildinfo - sets the information based on script input for how the installation should be run
 set_buildinfo() {
 
-	if [ -z "$BUILD_TYPE" ]; then
-		BUILD_TYPE="version"
-		BUILD_TAG=$LATEST
-	fi
-
-	if [ -z "$BUILD_TAG" ] && [ "$BUILD_TYPE" = "version" ]; then
-		BUILD_TAG=$LATEST
-	fi
-
-	if [ -z "$BUILD_TAG" ] && [ ! -z "$BUILD_TYPE" ]; then
-		echo "error: must specify build tag when build type \"$BUILD_TYPE\" is specified"
-		usage
-		exit 1
-	fi
 
+	
+	BUILD_TAG=$LATEST
 	IMAGE_TAG=$(sed 's/\//-/g' <<<"$BUILD_TAG")
 
-	if [ "$1" = "ce" ]; then
-		INSTALL_TYPE="ce"
-	elif [ "$1" = "pro" ]; then
-		INSTALL_TYPE="pro"
-	fi
-
-	if [ "$AUTO_BUILD" = "on" ] && [ -z "$INSTALL_TYPE" ]; then
-		INSTALL_TYPE="ce"
-	elif [ -z "$INSTALL_TYPE" ]; then
+	if [ -z "$INSTALL_TYPE" ]; then
 		echo "-----------------------------------------------------"
 		echo "Would you like to install Netmaker Community Edition (CE), or Netmaker Enterprise Edition (pro)?"
 		echo "pro will require you to create an account at https://app.netmaker.io"
@@ -141,7 +82,6 @@ set_buildinfo() {
 	fi
 	echo "-----------Build Options-----------------------------"
 	echo "   Pro or CE: $INSTALL_TYPE"
-	echo "  Build Type: $BUILD_TYPE"
 	echo "   Build Tag: $BUILD_TAG"
 	echo "   Image Tag: $IMAGE_TAG"
 	echo "   Installer: v$NM_QUICK_VERSION"
@@ -173,7 +113,9 @@ install_yq() {
 setup_netclient() {
 
 	set +e
-	netclient uninstall
+	if [ -x "$(command -v netclient)" ]; then
+		netclient uninstall
+	fi
 	set -e
 
 	wget -qO netclient https://github.com/gravitl/netclient/releases/download/$LATEST/netclient-linux-$ARCH
@@ -257,9 +199,6 @@ wait_seconds() { (
 
 # confirm - get user input to confirm that they want to perform the next step
 confirm() { (
-	if [ "$AUTO_BUILD" = "on" ]; then
-		return 0
-	fi
 	while true; do
 		read -p 'Does everything look right? [y/n]: ' yn
 		case $yn in
@@ -277,28 +216,26 @@ confirm() { (
 	done
 ) }
 
+
 save_config() { (
 	echo "Saving the config to $CONFIG_PATH"
 	touch "$CONFIG_PATH"
-	save_config_item NM_EMAIL "$EMAIL"
-	save_config_item NM_DOMAIN "$NETMAKER_BASE_DOMAIN"
-	save_config_item UI_IMAGE_TAG "$IMAGE_TAG"
-	if [ "$BUILD_TYPE" = "local" ]; then
-		save_config_item UI_IMAGE_TAG "$LATEST"
-	else
-		save_config_item UI_IMAGE_TAG "$IMAGE_TAG"
+	if [ -n "$EMAIL" ]; then 
+		save_config_item NM_EMAIL "$EMAIL"
+	fi
+	if [ -n "$NETMAKER_BASE_DOMAIN" ]; then
+		save_config_item NM_DOMAIN "$NETMAKER_BASE_DOMAIN"
 	fi
+	save_config_item UI_IMAGE_TAG "$IMAGE_TAG"
 	# version-specific entries
 	if [ "$INSTALL_TYPE" = "pro" ]; then
 		save_config_item NETMAKER_TENANT_ID "$TENANT_ID"
 		save_config_item LICENSE_KEY "$LICENSE_KEY"
-		save_config_item METRICS_EXPORTER "on"
-		save_config_item PROMETHEUS "on"
-		if [ "$BUILD_TYPE" = "version" ]; then
-			save_config_item SERVER_IMAGE_TAG "$IMAGE_TAG-ee"
-		else
-			save_config_item SERVER_IMAGE_TAG "$IMAGE_TAG"
+		if [ "$UPGRADE_FLAG" = "yes" ];then
+			save_config_item METRICS_EXPORTER "on"
+			save_config_item PROMETHEUS "on"
 		fi
+		save_config_item SERVER_IMAGE_TAG "$IMAGE_TAG-ee"
 	else
 		save_config_item METRICS_EXPORTER "off"
 		save_config_item PROMETHEUS "off"
@@ -309,7 +246,7 @@ save_config() { (
 		"INSTALL_TYPE" "NODE_ID" "DNS_MODE" "NETCLIENT_AUTO_UPDATE" "API_PORT"
 		"CORS_ALLOWED_ORIGIN" "DISPLAY_KEYS" "DATABASE" "SERVER_BROKER_ENDPOINT" "VERBOSITY"
 		"DEBUG_MODE"  "REST_BACKEND" "DISABLE_REMOTE_IP_CHECK" "TELEMETRY" "AUTH_PROVIDER" "CLIENT_ID" "CLIENT_SECRET"
-		"FRONTEND_URL" "AZURE_TENANT" "OIDC_ISSUER" "EXPORTER_API_PORT" "JWT_VALIDITY_DURATION" "RAC_AUTO_DISABLE")
+		"FRONTEND_URL" "AZURE_TENANT" "OIDC_ISSUER" "EXPORTER_API_PORT" "JWT_VALIDITY_DURATION" "RAC_AUTO_DISABLE" "CACHING_ENABLED")
 	for name in "${toCopy[@]}"; do
 		save_config_item $name "${!name}"
 	done
@@ -345,38 +282,7 @@ save_config_item() { (
 	fi
 ); }
 
-# local_install_setup - builds artifacts based on specified branch locally to use in install
-local_install_setup() { (
-	if test -z "$NM_SKIP_CLONE"; then
-		rm -rf netmaker-tmp
-		mkdir netmaker-tmp
-		cd netmaker-tmp
-		git clone --single-branch --depth=1 --branch=$BUILD_TAG https://www.github.com/gravitl/netmaker
-	else
-		cd netmaker-tmp
-		echo "Skipping git clone on NM_SKIP_CLONE"
-	fi
-	cd netmaker
-	if test -z "$NM_SKIP_BUILD"; then
-		docker build --no-cache --build-arg version=$IMAGE_TAG -t gravitl/netmaker:$IMAGE_TAG .
-	else
-		echo "Skipping build on NM_SKIP_BUILD"
-	fi
-	cp compose/docker-compose.yml "$SCRIPT_DIR/docker-compose.yml"
-	if [ "$INSTALL_TYPE" = "pro" ]; then
-		cp compose/docker-compose.ee.yml "$SCRIPT_DIR/docker-compose.override.yml"
-		cp docker/Caddyfile-pro "$SCRIPT_DIR/Caddyfile"
-	else
-		cp docker/Caddyfile "$SCRIPT_DIR/Caddyfile"
-	fi
-	cp scripts/netmaker.default.env "$SCRIPT_DIR/netmaker.default.env"
-	cp docker/mosquitto.conf "$SCRIPT_DIR/mosquitto.conf"
-	cp docker/wait.sh "$SCRIPT_DIR/wait.sh"
-	cd ../../
-	if test -z "$NM_SKIP_CLONE"; then
-		rm -rf netmaker-tmp
-	fi
-); }
+
 
 # install_dependencies - install necessary packages to run netmaker
 install_dependencies() {
@@ -520,27 +426,23 @@ set_install_vars() {
 	echo "For this reason, we STRONGLY RECOMMEND using your own domain. Using the auto-generated domain may lead to a failed installation due to rate limiting."
 	echo "-----------------------------------------------------"
 
-	if [ "$AUTO_BUILD" = "on" ]; then
-		DOMAIN_TYPE="auto"
-	else
-		select domain_option in "Auto Generated ($NETMAKER_BASE_DOMAIN)" "Custom Domain (e.x: netmaker.example.com)"; do
-			case $REPLY in
-			1)
-				echo "using $NETMAKER_BASE_DOMAIN for base domain"
-				DOMAIN_TYPE="auto"
-				break
-				;;
-			2)
-				read -p "Enter Custom Domain (make sure  *.domain points to $SERVER_HOST first): " domain
-				NETMAKER_BASE_DOMAIN=$domain
-				echo "using $NETMAKER_BASE_DOMAIN"
-				DOMAIN_TYPE="custom"
-				break
-				;;
-			*) echo "invalid option $REPLY" ;;
-			esac
-		done
-	fi
+	select domain_option in "Auto Generated ($NETMAKER_BASE_DOMAIN)" "Custom Domain (e.x: netmaker.example.com)"; do
+		case $REPLY in
+		1)
+			echo "using $NETMAKER_BASE_DOMAIN for base domain"
+			DOMAIN_TYPE="auto"
+			break
+			;;
+		2)
+			read -p "Enter Custom Domain (make sure  *.domain points to $SERVER_HOST first): " domain
+			NETMAKER_BASE_DOMAIN=$domain
+			echo "using $NETMAKER_BASE_DOMAIN"
+			DOMAIN_TYPE="custom"
+			break
+			;;
+		*) echo "invalid option $REPLY" ;;
+		esac
+	done
 
 	wait_seconds 2
 
@@ -550,7 +452,7 @@ set_install_vars() {
 	echo "                api.$NETMAKER_BASE_DOMAIN"
 	echo "             broker.$NETMAKER_BASE_DOMAIN"
 
-	if [ "$INSTALL_TYPE" = "pro" ]; then
+	if [ "$UPGRADE_FLAG" = "yes" ]; then
 		echo "         prometheus.$NETMAKER_BASE_DOMAIN"
 		echo "  netmaker-exporter.$NETMAKER_BASE_DOMAIN"
 		echo "            grafana.$NETMAKER_BASE_DOMAIN"
@@ -565,33 +467,13 @@ set_install_vars() {
 
 	wait_seconds 1
 
-	if [ "$INSTALL_TYPE" = "pro" ]; then
-
-		echo "-----------------------------------------------------"
-		echo "Provide Details for pro installation:"
-		echo "    1. Log into https://app.netmaker.io"
-		echo "    2. follow instructions to get a license at: https://docs.netmaker.io/ee/ee-setup.html"
-		echo "    3. Retrieve License and Tenant ID"
-		echo "    4. note email address"
-		echo "-----------------------------------------------------"
-		unset LICENSE_KEY
-		while [ -z "$LICENSE_KEY" ]; do
-			read -p "License Key: " LICENSE_KEY
-		done
-		unset TENANT_ID
-		while [ -z ${TENANT_ID} ]; do
-			read -p "Tenant ID: " TENANT_ID
-		done
-	fi
 
 	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}
-	if [ -z $AUTO_BUILD ]; then
-		read -p "Email Address for Domain Registration (click 'enter' to use $EMAIL_SUGGESTED): " GET_EMAIL
-	fi
+	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
@@ -609,9 +491,8 @@ set_install_vars() {
 	unset GET_MQ_PASSWORD
 	unset CONFIRM_MQ_PASSWORD
 	echo "Enter Credentials For MQ..."
-	if [ -z $AUTO_BUILD ]; then
-		read -p "MQ Username (click 'enter' to use 'netmaker'): " GET_MQ_USERNAME
-	fi
+	
+	read -p "MQ Username (click 'enter' to use 'netmaker'): " GET_MQ_USERNAME
 	if [ -z "$GET_MQ_USERNAME" ]; then
 		echo "using default username for mq"
 		MQ_USERNAME="netmaker"
@@ -626,33 +507,33 @@ set_install_vars() {
 		)
 	fi
 
-	if [ -z $AUTO_BUILD ]; then
-		select domain_option in "Auto Generated / Config Password" "Input Your Own Password"; do
-			case $REPLY in
-			1)
-				echo "using random password for mq"
-				break
-				;;
-			2)
-				while true; do
-					echo "Enter your Password For MQ: "
-					read -s GET_MQ_PASSWORD
-					echo "Enter your password again to confirm: "
-					read -s CONFIRM_MQ_PASSWORD
-					if [ ${GET_MQ_PASSWORD} != ${CONFIRM_MQ_PASSWORD} ]; then
-						echo "wrong password entered, try again..."
-						continue
-					fi
-					MQ_PASSWORD="$GET_MQ_PASSWORD"
-					echo "MQ Password Saved Successfully!!"
-					break
-				done
+
+	select domain_option in "Auto Generated / Config Password" "Input Your Own Password"; do
+		case $REPLY in
+		1)
+			echo "using random password for mq"
+			break
+			;;
+		2)
+			while true; do
+				echo "Enter your Password For MQ: "
+				read -s GET_MQ_PASSWORD
+				echo "Enter your password again to confirm: "
+				read -s CONFIRM_MQ_PASSWORD
+				if [ ${GET_MQ_PASSWORD} != ${CONFIRM_MQ_PASSWORD} ]; then
+					echo "wrong password entered, try again..."
+					continue
+				fi
+				MQ_PASSWORD="$GET_MQ_PASSWORD"
+				echo "MQ Password Saved Successfully!!"
 				break
-				;;
-			*) echo "invalid option $REPLY" ;;
-			esac
-		done
-	fi
+			done
+			break
+			;;
+		*) echo "invalid option $REPLY" ;;
+		esac
+	done
+	
 
 	wait_seconds 2
 
@@ -662,18 +543,10 @@ set_install_vars() {
 	echo "        domain: $NETMAKER_BASE_DOMAIN"
 	echo "         email: $EMAIL"
 	echo "     public ip: $SERVER_HOST"
-	if [ "$INSTALL_TYPE" = "pro" ]; then
-		echo "       license: $LICENSE_KEY"
-		echo "    account id: $TENANT_ID"
-	fi
 	echo "-----------------------------------------------------------------"
 	echo "Confirm Settings for Installation"
 	echo "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
 
-	if [ ! "$BUILD_TYPE" = "local" ]; then
-		IMAGE_TAG="$LATEST"
-	fi
-
 	confirm
 }
 
@@ -688,26 +561,24 @@ install_netmaker() {
 
 	echo "Pulling config files..."
 
-	if [ "$BUILD_TYPE" = "local" ]; then
-		local_install_setup
-	else
-		local BASE_URL="https://raw.githubusercontent.com/gravitl/netmaker/$BUILD_TAG"
-
-		local COMPOSE_URL="$BASE_URL/compose/docker-compose.yml"
-		local CADDY_URL="$BASE_URL/docker/Caddyfile"
-		if [ "$INSTALL_TYPE" = "pro" ]; then
-			local COMPOSE_OVERRIDE_URL="$BASE_URL/compose/docker-compose.pro.yml"
-			local CADDY_URL="$BASE_URL/docker/Caddyfile-pro"
-		fi
-		wget -qO "$SCRIPT_DIR"/docker-compose.yml $COMPOSE_URL
-		if test -n "$COMPOSE_OVERRIDE_URL"; then
-			wget -qO "$SCRIPT_DIR"/docker-compose.override.yml $COMPOSE_OVERRIDE_URL
-		fi
-		wget -qO "$SCRIPT_DIR"/Caddyfile "$CADDY_URL"
-		wget -qO "$SCRIPT_DIR"/netmaker.default.env "$BASE_URL/scripts/netmaker.default.env"
-		wget -qO "$SCRIPT_DIR"/mosquitto.conf "$BASE_URL/docker/mosquitto.conf"
-		wget -qO "$SCRIPT_DIR"/wait.sh "$BASE_URL/docker/wait.sh"
+	
+	local BASE_URL="https://raw.githubusercontent.com/gravitl/netmaker/$BUILD_TAG"
+	local COMPOSE_URL="$BASE_URL/compose/docker-compose.yml"
+	local CADDY_URL="$BASE_URL/docker/Caddyfile"
+	if [ "$INSTALL_TYPE" = "pro" ]; then
+		local COMPOSE_OVERRIDE_URL="$BASE_URL/compose/docker-compose.pro.yml"
+		local CADDY_URL="$BASE_URL/docker/Caddyfile-pro"
+	fi
+	wget -qO "$SCRIPT_DIR"/docker-compose.yml $COMPOSE_URL
+	if [ "$UPGRADE_FLAG" = "yes" ]; then
+		wget -qO "$SCRIPT_DIR"/docker-compose.override.yml $COMPOSE_OVERRIDE_URL
+	elif [ -a "$SCRIPT_DIR"/docker-compose.override.yml ]; then
+		rm -f "$SCRIPT_DIR"/docker-compose.override.yml
 	fi
+	wget -qO "$SCRIPT_DIR"/Caddyfile "$CADDY_URL"
+	wget -qO "$SCRIPT_DIR"/netmaker.default.env "$BASE_URL/scripts/netmaker.default.env"
+	wget -qO "$SCRIPT_DIR"/mosquitto.conf "$BASE_URL/docker/mosquitto.conf"
+	wget -qO "$SCRIPT_DIR"/wait.sh "$BASE_URL/docker/wait.sh"
 
 	chmod +x "$SCRIPT_DIR"/wait.sh
 	mkdir -p /etc/netmaker
@@ -718,9 +589,7 @@ install_netmaker() {
 
 	echo "Starting containers..."
 
-	# increase the timeouts
-	export DOCKER_CLIENT_TIMEOUT=120
-	export COMPOSE_HTTP_TIMEOUT=120
+	
 
 	# start docker and rebuild containers / networks
 	cd "${SCRIPT_DIR}"
@@ -800,6 +669,9 @@ print_success() {
 
 cleanup() {
 	# remove the existing netclient's instance from the existing network
+	if ! command -v netclient >/dev/null 2>&1; then
+		return
+	fi
 	if command -v nmctl >/dev/null 2>&1; then
 		local node_id=$(netclient list | jq '.[0].node_id' 2>/dev/null)
 		# trim doublequotes
@@ -810,7 +682,11 @@ cleanup() {
 		fi
 	fi
 
-	echo "Stopping all containers..."
+	stop_services
+}
+
+stop_services(){
+	echo "Stopping all containers, this will take a while please wait..."
 	local containers=("mq" "netmaker-ui" "coredns" "turn" "caddy" "netmaker" "netmaker-exporter" "prometheus" "grafana")
 	for name in "${containers[@]}"; do
 		local running=$(docker ps | grep -w "$name")
@@ -824,61 +700,127 @@ cleanup() {
 	done
 }
 
-# 1. print netmaker logo
-print_logo
+upgrade() {
+	print_logo
+	unset IMAGE_TAG
+	unset BUILD_TAG
+	IMAGE_TAG=$UI_IMAGE_TAG
+	BUILD_TAG=$UI_IMAGE_TAG
+	echo "-----------------------------------------------------"
+	echo "Provide Details for pro installation:"
+	echo "    1. Log into https://app.netmaker.io"
+	echo "    2. follow instructions to get a license at: https://docs.netmaker.io/pro/pro-setup.html"
+	echo "    3. Retrieve License and Tenant ID"
+	echo "-----------------------------------------------------"
+	unset LICENSE_KEY
+	while [ -z "$LICENSE_KEY" ]; do
+		read -p "License Key: " LICENSE_KEY
+	done
+	unset TENANT_ID
+	while [ -z ${TENANT_ID} ]; do
+		read -p "Tenant ID: " TENANT_ID
+	done
+	save_config
+	# start docker and rebuild containers / networks
+	stop_services
+	install_netmaker
+}
 
-# read the config
-if [ -f "$CONFIG_PATH" ]; then
-	echo "Using config: $CONFIG_PATH"
-	source "$CONFIG_PATH"
-	if [ "$UPGRADE_FLAG" = "yes" ]; then
-		INSTALL_TYPE="pro"
+downgrade () {
+	print_logo
+	unset IMAGE_TAG
+	unset BUILD_TAG
+	IMAGE_TAG=$UI_IMAGE_TAG
+	BUILD_TAG=$UI_IMAGE_TAG
+	save_config
+	if [ -a "$SCRIPT_DIR"/docker-compose.override.yml ]; then
+		rm -f "$SCRIPT_DIR"/docker-compose.override.yml
 	fi
-fi
+	# start docker and rebuild containers / networks
+	stop_services
+	install_netmaker
+}
+
+
+main (){
 
-# 2. setup the build instructions
-set_buildinfo
+	# read the config
+	if [ -f "$CONFIG_PATH" ]; then
+		echo "Using config: $CONFIG_PATH"
+		source "$CONFIG_PATH"
+	fi
+
+	INSTALL_TYPE="pro"
+	while getopts :cudv flag; do
+	case "${flag}" in
+	c)
+		INSTALL_TYPE="ce"
+		;;
+	u)
+		echo "upgrading to pro version..."
+		INSTALL_TYPE="pro"
+		UPGRADE_FLAG="yes"
+		upgrade
+		exit 0
+		;;
+	d) 
+		echo "downgrading to community version..."
+		INSTALL_TYPE="ce"
+		downgrade
+		exit 0
+		;;
+	v)
+		usage
+		exit 0
+		;;
+	esac
+done
 
-set +e
+	# 1. print netmaker logo
+	print_logo
 
-# 3. install necessary packages
-install_dependencies
+	# 2. setup the build instructions
+	set_buildinfo
+	set +e
+	# 3. install necessary packages
+	install_dependencies
 
-# 4. install yq if necessary
-install_yq
+	# 4. install yq if necessary
+	install_yq
 
-set -e
+	set -e
 
-# 6. get user input for variables
-set_install_vars
+	# 6. get user input for variables
+	set_install_vars
 
-set +e
-cleanup
-set -e
+	set +e
+	cleanup
+	set -e
 
-# 7. get and set config files, startup docker-compose
-install_netmaker
+	# 7. get and set config files, startup docker-compose
+	install_netmaker
 
-set +e
+	set +e
 
-# 8. make sure Caddy certs are working
-test_connection
+	# 8. make sure Caddy certs are working
+	test_connection
 
-# 9. install the netmaker CLI
-setup_nmctl
+	# 9. install the netmaker CLI
+	setup_nmctl
 
-# 10. create a default mesh network for netmaker
-setup_mesh
+	# 10. create a default mesh network for netmaker
+	setup_mesh
 
-set -e
+	set -e
 
-# 11. add netclient to docker-compose and start it up
-setup_netclient
+	# 11. add netclient to docker-compose and start it up
+	setup_netclient
 
-# 12. make the netclient a default host and ingress gw
-configure_netclient
+	# 12. make the netclient a default host and ingress gw
+	configure_netclient
 
-# 13. print success message
-print_success
+	# 13. print success message
+	print_success
+}
 
-# cp -f /etc/skel/.bashrc /root/.bashrc
+main "${@}"

+ 1 - 1
swagger.yml

@@ -1149,7 +1149,7 @@ info:
 
         API calls must be authenticated via a header of the format -H “Authorization: Bearer <YOUR_SECRET_KEY>” There are two methods to obtain YOUR_SECRET_KEY: 1. Using the masterkey. By default, this value is “secret key,” but you should change this on your instance and keep it secure. This value can be set via env var at startup or in a config file (config/environments/< env >.yaml). See the [Netmaker](https://docs.netmaker.org/index.html) documentation for more details. 2. Using a JWT received for a node. This can be retrieved by calling the /api/nodes/<network>/authenticate endpoint, as documented below.
     title: Netmaker
-    version: 0.22.0
+    version: 0.22.1
 paths:
     /api/dns:
         get: