فهرست منبع

Merge branch 'develop' of https://github.com/gravitl/netmaker into feature_v0.8.4_serverconfs

afeiszli 3 سال پیش
والد
کامیت
f02cffd89b

+ 1 - 1
controllers/common_test.go

@@ -124,7 +124,7 @@ func TestSetNetworkNodesLastModified(t *testing.T) {
 }
 
 func createTestNode() models.Node {
-	createnode := models.Node{PublicKey: "DM5qhLAE20PG9BbfBCger+Ac9D2NDOwCtY1rbYDLf34=", Endpoint: "10.0.0.1", MacAddress: "01:02:03:04:05:06", Password: "password", Network: "skynet"}
+	createnode := models.Node{PublicKey: "DM5qhLAE20PG9BbfBCger+Ac9D2NDOwCtY1rbYDLf34=", Name: "testnode", Endpoint: "10.0.0.1", MacAddress: "01:02:03:04:05:06", Password: "password", Network: "skynet"}
 	node, _ := logic.CreateNode(createnode, "skynet")
 	return node
 }

+ 251 - 41
controllers/dnsHttpController_test.go

@@ -1,100 +1,309 @@
 package controller
 
 import (
+	"io/ioutil"
+	"os"
 	"testing"
 
 	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/dnslogic"
+	"github.com/gravitl/netmaker/logic"
 	"github.com/gravitl/netmaker/models"
 	"github.com/stretchr/testify/assert"
 )
 
+func TestGetAllDNS(t *testing.T) {
+	database.InitializeDatabase()
+	deleteAllDNS(t)
+	deleteAllNetworks()
+	createNet()
+	t.Run("NoEntries", func(t *testing.T) {
+		entries, err := GetAllDNS()
+		assert.Nil(t, err)
+		assert.Equal(t, []models.DNSEntry(nil), entries)
+	})
+	t.Run("OneEntry", func(t *testing.T) {
+		entry := models.DNSEntry{"10.0.0.3", "newhost", "skynet"}
+		CreateDNS(entry)
+		entries, err := GetAllDNS()
+		assert.Nil(t, err)
+		assert.Equal(t, 1, len(entries))
+	})
+	t.Run("MultipleEntry", func(t *testing.T) {
+		entry := models.DNSEntry{"10.0.0.7", "anotherhost", "skynet"}
+		CreateDNS(entry)
+		entries, err := GetAllDNS()
+		assert.Nil(t, err)
+		assert.Equal(t, 2, len(entries))
+	})
+}
+
 func TestGetNodeDNS(t *testing.T) {
 	database.InitializeDatabase()
+	deleteAllDNS(t)
 	deleteAllNetworks()
 	createNet()
-	createTestNode()
-	dns, err := GetNodeDNS("skynet")
-	assert.Nil(t, err)
-	t.Log(dns)
+	t.Run("NoNodes", func(t *testing.T) {
+		dns, err := GetNodeDNS("skynet")
+		assert.EqualError(t, err, "could not find any records")
+		assert.Equal(t, []models.DNSEntry(nil), dns)
+	})
+	t.Run("NodeExists", func(t *testing.T) {
+		createTestNode()
+		dns, err := GetNodeDNS("skynet")
+		assert.Nil(t, err)
+		assert.Equal(t, "10.0.0.1", dns[0].Address)
+	})
+	t.Run("MultipleNodes", func(t *testing.T) {
+		createnode := models.Node{PublicKey: "DM5qhLAE20PG9BbfBCger+Ac9D2NDOwCtY1rbYDLf34=", Endpoint: "10.100.100.3", MacAddress: "01:02:03:04:05:07", Password: "password", Network: "skynet"}
+		_, err := logic.CreateNode(createnode, "skynet")
+		assert.Nil(t, err)
+		dns, err := GetNodeDNS("skynet")
+		assert.Nil(t, err)
+		assert.Equal(t, 2, len(dns))
+	})
 }
 func TestGetCustomDNS(t *testing.T) {
-	t.Skip()
 	database.InitializeDatabase()
+	deleteAllDNS(t)
 	deleteAllNetworks()
-	createNet()
-	createTestNode()
-	dns, err := dnslogic.GetCustomDNS("skynet")
-	assert.Nil(t, err)
-	t.Log(dns)
+	t.Run("NoNetworks", func(t *testing.T) {
+		dns, err := dnslogic.GetCustomDNS("skynet")
+		assert.EqualError(t, err, "could not find any records")
+		assert.Equal(t, []models.DNSEntry(nil), dns)
+	})
+	t.Run("NoNodes", func(t *testing.T) {
+		createNet()
+		dns, err := dnslogic.GetCustomDNS("skynet")
+		assert.EqualError(t, err, "could not find any records")
+		assert.Equal(t, []models.DNSEntry(nil), dns)
+	})
+	t.Run("NodeExists", func(t *testing.T) {
+		createTestNode()
+		dns, err := dnslogic.GetCustomDNS("skynet")
+		assert.EqualError(t, err, "could not find any records")
+		assert.Equal(t, 0, len(dns))
+	})
+	t.Run("EntryExist", func(t *testing.T) {
+		entry := models.DNSEntry{"10.0.0.3", "newhost", "skynet"}
+		CreateDNS(entry)
+		dns, err := dnslogic.GetCustomDNS("skynet")
+		assert.Nil(t, err)
+		assert.Equal(t, 1, len(dns))
+	})
+	t.Run("MultipleEntries", func(t *testing.T) {
+		entry := models.DNSEntry{"10.0.0.4", "host4", "skynet"}
+		CreateDNS(entry)
+		dns, err := dnslogic.GetCustomDNS("skynet")
+		assert.Nil(t, err)
+		assert.Equal(t, 2, len(dns))
+	})
 }
+
 func TestGetDNSEntryNum(t *testing.T) {
 	database.InitializeDatabase()
+	deleteAllDNS(t)
 	deleteAllNetworks()
 	createNet()
-	createTestNode()
-	num, err := GetDNSEntryNum("myhost", "skynet")
-	assert.Nil(t, err)
-	t.Log(num)
+	t.Run("NoNodes", func(t *testing.T) {
+		num, err := GetDNSEntryNum("myhost", "skynet")
+		assert.Nil(t, err)
+		assert.Equal(t, 0, num)
+	})
+	t.Run("NodeExists", func(t *testing.T) {
+		entry := models.DNSEntry{"10.0.0.2", "newhost", "skynet"}
+		_, err := CreateDNS(entry)
+		assert.Nil(t, err)
+		num, err := GetDNSEntryNum("newhost", "skynet")
+		assert.Nil(t, err)
+		assert.Equal(t, 1, num)
+	})
 }
 func TestGetDNS(t *testing.T) {
 	database.InitializeDatabase()
+	deleteAllDNS(t)
 	deleteAllNetworks()
-	dns, err := dnslogic.GetDNS("skynet")
-	assert.Nil(t, err)
-	t.Log(dns)
+	createNet()
+	t.Run("NoEntries", func(t *testing.T) {
+		dns, err := dnslogic.GetDNS("skynet")
+		assert.Nil(t, err)
+		assert.Nil(t, dns)
+	})
+	t.Run("CustomDNSExists", func(t *testing.T) {
+		entry := models.DNSEntry{"10.0.0.2", "newhost", "skynet"}
+		_, err := CreateDNS(entry)
+		assert.Nil(t, err)
+		dns, err := dnslogic.GetDNS("skynet")
+		t.Log(dns)
+		assert.Nil(t, err)
+		assert.NotNil(t, dns)
+		assert.Equal(t, "skynet", dns[0].Network)
+		assert.Equal(t, 1, len(dns))
+	})
+	t.Run("NodeExists", func(t *testing.T) {
+		deleteAllDNS(t)
+		createTestNode()
+		dns, err := dnslogic.GetDNS("skynet")
+		assert.Nil(t, err)
+		assert.NotNil(t, dns)
+		assert.Equal(t, "skynet", dns[0].Network)
+		assert.Equal(t, 1, len(dns))
+	})
+	t.Run("NodeAndCustomDNS", func(t *testing.T) {
+		entry := models.DNSEntry{"10.0.0.2", "newhost", "skynet"}
+		_, err := CreateDNS(entry)
+		dns, err := dnslogic.GetDNS("skynet")
+		t.Log(dns)
+		assert.Nil(t, err)
+		assert.NotNil(t, dns)
+		assert.Equal(t, "skynet", dns[0].Network)
+		assert.Equal(t, "skynet", dns[1].Network)
+		assert.Equal(t, 2, len(dns))
+	})
 }
+
 func TestCreateDNS(t *testing.T) {
 	database.InitializeDatabase()
-	deleteAllNetworks()
 	deleteAllDNS(t)
+	deleteAllNetworks()
 	createNet()
-	//dns, err := GetDNS("skynet")
-	//assert.Nil(t, err)
-	//for _, entry := range dns {
-	//	_, _ = DeleteDNS(entry.Name, "skynet")
-	//}
 	entry := models.DNSEntry{"10.0.0.2", "newhost", "skynet"}
-	err := ValidateDNSCreate(entry)
-	assert.Nil(t, err)
-	if err != nil {
-		t.Log(err)
-	}
 	dns, err := CreateDNS(entry)
 	assert.Nil(t, err)
-	t.Log(dns)
+	assert.Equal(t, "newhost", dns.Name)
+}
+
+func TestSetDNS(t *testing.T) {
+	database.InitializeDatabase()
+	deleteAllDNS(t)
+	deleteAllNetworks()
+	t.Run("NoNetworks", func(t *testing.T) {
+		err := dnslogic.SetDNS()
+		assert.Nil(t, err)
+		info, err := os.Stat("./config/dnsconfig/netmaker.hosts")
+		assert.Nil(t, err)
+		assert.False(t, info.IsDir())
+		assert.Equal(t, int64(0), info.Size())
+	})
+	t.Run("NoEntries", func(t *testing.T) {
+		createNet()
+		err := dnslogic.SetDNS()
+		assert.Nil(t, err)
+		info, err := os.Stat("./config/dnsconfig/netmaker.hosts")
+		assert.Nil(t, err)
+		assert.False(t, info.IsDir())
+		assert.Equal(t, int64(0), info.Size())
+	})
+	t.Run("NodeExists", func(t *testing.T) {
+		createTestNode()
+		err := dnslogic.SetDNS()
+		assert.Nil(t, err)
+		info, err := os.Stat("./config/dnsconfig/netmaker.hosts")
+		assert.Nil(t, err)
+		assert.False(t, info.IsDir())
+		content, err := ioutil.ReadFile("./config/dnsconfig/netmaker.hosts")
+		assert.Nil(t, err)
+		assert.Contains(t, string(content), "testnode.skynet")
+	})
+	t.Run("EntryExists", func(t *testing.T) {
+		entry := models.DNSEntry{"10.0.0.3", "newhost", "skynet"}
+		CreateDNS(entry)
+		err := dnslogic.SetDNS()
+		assert.Nil(t, err)
+		info, err := os.Stat("./config/dnsconfig/netmaker.hosts")
+		assert.Nil(t, err)
+		assert.False(t, info.IsDir())
+		content, err := ioutil.ReadFile("./config/dnsconfig/netmaker.hosts")
+		assert.Nil(t, err)
+		assert.Contains(t, string(content), "newhost.skynet")
+	})
+
 }
+
 func TestGetDNSEntry(t *testing.T) {
 	database.InitializeDatabase()
+	deleteAllDNS(t)
 	deleteAllNetworks()
 	createNet()
 	createTestNode()
 	entry := models.DNSEntry{"10.0.0.2", "newhost", "skynet"}
 	CreateDNS(entry)
-	entry, err := GetDNSEntry("newhost", "skynet")
-	assert.Nil(t, err)
-	t.Log(entry)
+	t.Run("wrong net", func(t *testing.T) {
+		entry, err := GetDNSEntry("newhost", "w286 Toronto Street South, Uxbridge, ONirecat")
+		assert.EqualError(t, err, "no result found")
+		assert.Equal(t, models.DNSEntry{}, entry)
+	})
+	t.Run("wrong host", func(t *testing.T) {
+		entry, err := GetDNSEntry("badhost", "skynet")
+		assert.EqualError(t, err, "no result found")
+		assert.Equal(t, models.DNSEntry{}, entry)
+	})
+	t.Run("good host", func(t *testing.T) {
+		entry, err := GetDNSEntry("newhost", "skynet")
+		assert.Nil(t, err)
+		assert.Equal(t, "newhost", entry.Name)
+	})
+	t.Run("node", func(t *testing.T) {
+		entry, err := GetDNSEntry("testnode", "skynet")
+		assert.EqualError(t, err, "no result found")
+		assert.Equal(t, models.DNSEntry{}, entry)
+	})
 }
 func TestUpdateDNS(t *testing.T) {
+	var newentry models.DNSEntry
 	database.InitializeDatabase()
+	deleteAllDNS(t)
+	deleteAllNetworks()
+	createNet()
+	entry := models.DNSEntry{"10.0.0.2", "newhost", "skynet"}
+	CreateDNS(entry)
+	t.Run("change address", func(t *testing.T) {
+		newentry.Address = "10.0.0.75"
+		updated, err := UpdateDNS(newentry, entry)
+		assert.Nil(t, err)
+		assert.Equal(t, newentry.Address, updated.Address)
+	})
+	t.Run("change name", func(t *testing.T) {
+		newentry.Name = "newname"
+		updated, err := UpdateDNS(newentry, entry)
+		assert.Nil(t, err)
+		assert.Equal(t, newentry.Name, updated.Name)
+	})
+	t.Run("change network", func(t *testing.T) {
+		newentry.Network = "wirecat"
+		updated, err := UpdateDNS(newentry, entry)
+		assert.Nil(t, err)
+		assert.NotEqual(t, newentry.Network, updated.Network)
+	})
 }
 func TestDeleteDNS(t *testing.T) {
 	database.InitializeDatabase()
+	deleteAllDNS(t)
+	deleteAllNetworks()
+	createNet()
+	entry := models.DNSEntry{"10.0.0.2", "newhost", "skynet"}
+	CreateDNS(entry)
 	t.Run("EntryExists", func(t *testing.T) {
-		err := DeleteDNS("myhost", "skynet")
+		err := DeleteDNS("newhost", "skynet")
 		assert.Nil(t, err)
 	})
-	t.Run("NoEntry", func(t *testing.T) {
+	t.Run("NodeExists", func(t *testing.T) {
 		err := DeleteDNS("myhost", "skynet")
 		assert.Nil(t, err)
 	})
 
+	t.Run("NoEntries", func(t *testing.T) {
+		err := DeleteDNS("myhost", "skynet")
+		assert.Nil(t, err)
+	})
 }
 
 func TestValidateDNSUpdate(t *testing.T) {
 	database.InitializeDatabase()
+	deleteAllDNS(t)
+	deleteAllNetworks()
+	createNet()
 	entry := models.DNSEntry{"10.0.0.2", "myhost", "skynet"}
-	_ = DeleteDNS("mynode", "skynet")
 	t.Run("BadNetwork", func(t *testing.T) {
 		change := models.DNSEntry{"10.0.0.2", "myhost", "badnet"}
 		err := ValidateDNSUpdate(change, entry)
@@ -140,11 +349,14 @@ func TestValidateDNSUpdate(t *testing.T) {
 	})
 	t.Run("NameUnique", func(t *testing.T) {
 		change := models.DNSEntry{"10.0.0.2", "myhost", "wirecat"}
-		_, _ = CreateDNS(entry)
-		_, _ = CreateDNS(change)
+		CreateDNS(entry)
+		CreateDNS(change)
 		err := ValidateDNSUpdate(change, entry)
 		assert.NotNil(t, err)
 		assert.Contains(t, err.Error(), "Field validation for 'Name' failed on the 'name_unique' tag")
+		//cleanup
+		err = DeleteDNS("myhost", "wirecat")
+		assert.Nil(t, err)
 	})
 
 }
@@ -196,11 +408,9 @@ func TestValidateDNSCreate(t *testing.T) {
 
 func deleteAllDNS(t *testing.T) {
 	dns, err := GetAllDNS()
-	t.Log(err)
-	t.Log(dns)
+	assert.Nil(t, err)
 	for _, record := range dns {
-		t.Log(dns)
 		err := DeleteDNS(record.Name, record.Network)
-		t.Log(err)
+		assert.Nil(t, err)
 	}
 }

+ 14 - 2
controllers/userHttpController.go

@@ -348,8 +348,8 @@ func createAdmin(w http.ResponseWriter, r *http.Request) {
 	var admin models.User
 	// get node from body of request
 	_ = json.NewDecoder(r.Body).Decode(&admin)
-	admin.IsAdmin = true
-	admin, err := CreateUser(admin)
+
+	admin, err := CreateAdmin(admin)
 
 	if err != nil {
 		returnErrorResponse(w, r, formatError(err, "badrequest"))
@@ -359,6 +359,18 @@ func createAdmin(w http.ResponseWriter, r *http.Request) {
 	json.NewEncoder(w).Encode(admin)
 }
 
+func CreateAdmin(admin models.User) (models.User, error) {
+	hasadmin, err := HasAdmin()
+	if err != nil {
+		return models.User{}, err
+	}
+	if hasadmin {
+		return models.User{}, errors.New("admin user already exists")
+	}
+	admin.IsAdmin = true
+	return CreateUser(admin)
+}
+
 func createUser(w http.ResponseWriter, r *http.Request) {
 	w.Header().Set("Content-Type", "application/json")
 

+ 63 - 0
controllers/userHttpController_test.go

@@ -71,6 +71,26 @@ func TestCreateUser(t *testing.T) {
 	})
 }
 
+func TestCreateAdmin(t *testing.T) {
+	database.InitializeDatabase()
+	deleteAllUsers()
+	var user models.User
+	t.Run("NoAdmin", func(t *testing.T) {
+		user.UserName = "admin"
+		user.Password = "password"
+		admin, err := CreateAdmin(user)
+		assert.Nil(t, err)
+		assert.Equal(t, user.UserName, admin.UserName)
+	})
+	t.Run("AdminExists", func(t *testing.T) {
+		user.UserName = "admin2"
+		user.Password = "password1"
+		admin, err := CreateAdmin(user)
+		assert.EqualError(t, err, "admin user already exists")
+		assert.Equal(t, admin, models.User{})
+	})
+}
+
 func TestDeleteUser(t *testing.T) {
 	database.InitializeDatabase()
 	deleteAllUsers()
@@ -153,6 +173,49 @@ func TestGetUser(t *testing.T) {
 	})
 }
 
+func TestGetUserInternal(t *testing.T) {
+	database.InitializeDatabase()
+	deleteAllUsers()
+	t.Run("NonExistantUser", func(t *testing.T) {
+		admin, err := GetUserInternal("admin")
+		assert.EqualError(t, err, "could not find any records")
+		assert.Equal(t, "", admin.UserName)
+	})
+	t.Run("UserExisits", func(t *testing.T) {
+		user := models.User{"admin", "password", nil, true}
+		CreateUser(user)
+		admin, err := GetUserInternal("admin")
+		assert.Nil(t, err)
+		assert.Equal(t, user.UserName, admin.UserName)
+	})
+}
+
+func TestGetUsers(t *testing.T) {
+	database.InitializeDatabase()
+	deleteAllUsers()
+	t.Run("NonExistantUser", func(t *testing.T) {
+		admin, err := GetUsers()
+		assert.EqualError(t, err, "could not find any records")
+		assert.Equal(t, []models.ReturnUser(nil), admin)
+	})
+	t.Run("UserExisits", func(t *testing.T) {
+		user := models.User{"admin", "password", nil, true}
+		CreateUser(user)
+		admins, err := GetUsers()
+		assert.Nil(t, err)
+		assert.Equal(t, user.UserName, admins[0].UserName)
+	})
+	t.Run("MulipleUsers", func(t *testing.T) {
+		user := models.User{"user", "password", nil, true}
+		CreateUser(user)
+		admins, err := GetUsers()
+		assert.Nil(t, err)
+		assert.Equal(t, "admin", admins[0].UserName)
+		assert.Equal(t, user.UserName, admins[1].UserName)
+	})
+
+}
+
 func TestUpdateUser(t *testing.T) {
 	database.InitializeDatabase()
 	deleteAllUsers()

+ 1 - 1
go.mod

@@ -8,7 +8,7 @@ require (
 	github.com/golang/protobuf v1.5.2 // indirect
 	github.com/gorilla/handlers v1.5.1
 	github.com/gorilla/mux v1.8.0
-	github.com/lib/pq v1.10.3 // indirect
+	github.com/lib/pq v1.10.3
 	github.com/mattn/go-sqlite3 v1.14.8
 	github.com/rqlite/gorqlite v0.0.0-20210514125552-08ff1e76b22f
 	github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e

+ 17 - 0
go.sum

@@ -1,8 +1,12 @@
+cloud.google.com/go v0.26.0 h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ=
 cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
+github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403 h1:cqQfy1jclcSy/FwLjemeg3SR1yaINm74aQyupQ0Bl8M=
 github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
 github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
 github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
@@ -16,7 +20,9 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
 github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad h1:EmNYJhPYy0pOFjCx2PrgtaBXmee0iUX9hLlxE1xHOJE=
 github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
+github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A=
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
 github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
@@ -31,6 +37,7 @@ github.com/go-playground/validator/v10 v10.5.0 h1:X9rflw/KmpACwT8zdrm1upefpvdy6u
 github.com/go-playground/validator/v10 v10.5.0/go.mod h1:xm76BBt941f7yWdGnI2DVPFFg1UK3YY04qifoXU3lOk=
 github.com/golang-jwt/jwt/v4 v4.0.0 h1:RAqyYixv1p7uEnocuy8P1nru5wprCh/MH2BIlW5z5/o=
 github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
 github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
 github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -54,12 +61,14 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
 github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
 github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
 github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
 github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q=
 github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
 github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
 github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
+github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
 github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
 github.com/josharian/native v0.0.0-20200817173448-b6b71def0850 h1:uhL5Gw7BINiiPAo24A2sxkcDI0Jt/sqp1v5xQCniEFA=
 github.com/josharian/native v0.0.0-20200817173448-b6b71def0850/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
@@ -112,10 +121,13 @@ github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1
 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
 github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
 github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
+github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s=
 github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
 github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
+github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
 github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
+github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
@@ -156,6 +168,7 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
 golang.org/x/net v0.0.0-20210504132125-bbd867fde50d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985 h1:4CSI6oo7cOjJKajidEljs9h+uP0rRZBPPPhcCbj5mw8=
 golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -187,6 +200,7 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e h1:XMgFehsDnnLGtjvjOfqWSUzt0alpTR1RSEuznObga2c=
 golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
@@ -198,6 +212,7 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
 golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135 h1:5Beo0mZN8dRzgrMMkDp0jc8YXQKx9DiJ2k1dkvGsn5A=
 golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
@@ -208,6 +223,7 @@ golang.zx2c4.com/wireguard v0.0.0-20210805125648-3957e9b9dd19/go.mod h1:laHzsbfM
 golang.zx2c4.com/wireguard/wgctrl v0.0.0-20210913210325-91d1988e44de h1:M9Jc92kgqmVmidpnOeegP2VgO2DfHEcsUWtWMmBwNFQ=
 golang.zx2c4.com/wireguard/wgctrl v0.0.0-20210913210325-91d1988e44de/go.mod h1:+1XihzyZUBJcSc5WO9SwNA7v26puQwOEDwanaxfNXPQ=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
 google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
@@ -236,6 +252,7 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.3 h1:fvjTMHxHEw/mxHbtzPi3JCcKXQRAnQTBRo6YCJSVHKI=
 gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

+ 1 - 0
logic/util.go

@@ -280,6 +280,7 @@ func setPeerInfo(node models.Node) models.Node {
 	peer.IsRelayed = node.IsRelayed
 	peer.PublicKey = node.PublicKey
 	peer.Endpoint = node.Endpoint
+	peer.Name = node.Name
 	peer.LocalAddress = node.LocalAddress
 	peer.ListenPort = node.ListenPort
 	peer.AllowedIPs = node.AllowedIPs

+ 1 - 1
netclient/command/commands.go

@@ -192,7 +192,7 @@ func Pull(cfg config.ClientConfig) error {
 }
 
 func List(cfg config.ClientConfig) error {
-	err := functions.List()
+	err := functions.List(cfg.Network)
 	return err
 }
 

+ 7 - 0
netclient/daemon/systemd.go

@@ -97,6 +97,13 @@ WantedBy=timers.target
 	return nil
 }
 
+func CleanupLinux() {
+	err := os.RemoveAll(ncutils.GetNetclientPath())
+	if err != nil {
+		ncutils.PrintLog("Removing netclient binary: "+err.Error(), 1)
+	}
+}
+
 // RemoveSystemDServices - removes the systemd services on a machine
 func RemoveSystemDServices() error {
 	//sysExec, err := exec.LookPath("systemctl")

+ 2 - 26
netclient/functions/common.go

@@ -158,6 +158,8 @@ func Uninstall() error {
 		daemon.CleanupWindows()
 	} else if ncutils.IsMac() {
 		daemon.CleanupMac()
+	} else if ncutils.IsLinux() {
+		daemon.CleanupLinux()
 	} else if !ncutils.IsKernel() {
 		ncutils.PrintLog("manual cleanup required", 1)
 	}
@@ -255,32 +257,6 @@ func DeleteInterface(ifacename string, postdown string) error {
 	return err
 }
 
-// List - lists all networks on local machine
-func List() error {
-
-	networks, err := ncutils.GetSystemNetworks()
-	if err != nil {
-		return err
-	}
-	for _, network := range networks {
-		cfg, err := config.ReadConfig(network)
-		if err == nil {
-			jsoncfg, _ := json.Marshal(
-				map[string]string{
-					"Name":           cfg.Node.Name,
-					"Interface":      cfg.Node.Interface,
-					"PrivateIPv4":    cfg.Node.Address,
-					"PrivateIPv6":    cfg.Node.Address6,
-					"PublicEndpoint": cfg.Node.Endpoint,
-				})
-			fmt.Println(network + ": " + string(jsoncfg))
-		} else {
-			ncutils.PrintLog(network+": Could not retrieve network configuration.", 1)
-		}
-	}
-	return nil
-}
-
 // WipeLocal - wipes local instance
 func WipeLocal(network string) error {
 	cfg, err := config.ReadConfig(network)

+ 128 - 0
netclient/functions/list.go

@@ -0,0 +1,128 @@
+package functions
+
+import (
+	"encoding/json"
+	"fmt"
+
+	nodepb "github.com/gravitl/netmaker/grpc"
+	"github.com/gravitl/netmaker/models"
+	"github.com/gravitl/netmaker/netclient/auth"
+	"github.com/gravitl/netmaker/netclient/config"
+	"github.com/gravitl/netmaker/netclient/ncutils"
+	"google.golang.org/grpc"
+	"google.golang.org/grpc/metadata"
+)
+
+type Peer struct {
+	Name           string `json:"name"`
+	Interface      string `json:"interface,omitempty"`
+	PrivateIPv4    string `json:"private_ipv4,omitempty"`
+	PrivateIPv6    string `json:"private_ipv6,omitempty"`
+	PublicEndpoint string `json:"public_endoint,omitempty"`
+}
+
+type Network struct {
+	Name        string `json:"name"`
+	CurrentNode Peer   `json:"current_node"`
+	Peers       []Peer `json:"peers"`
+}
+
+func List(network string) error {
+	nets := []Network{}
+	var err error
+	var networks []string
+	if network == "all" {
+		networks, err = ncutils.GetSystemNetworks()
+		if err != nil {
+			return err
+		}
+	} else {
+		networks = append(networks, network)
+	}
+
+	for _, network := range networks {
+		net, err := getNetwork(network)
+		if err != nil {
+			ncutils.PrintLog(network+": Could not retrieve network configuration.", 1)
+			return err
+		}
+		nets = append(nets, net)
+	}
+
+	jsoncfg, _ := json.Marshal(struct {
+		Networks []Network `json:"networks"`
+	}{nets})
+	fmt.Println(string(jsoncfg))
+
+	return nil
+}
+
+func getNetwork(network string) (Network, error) {
+	cfg, err := config.ReadConfig(network)
+	if err != nil {
+		return Network{}, fmt.Errorf("reading configuration for network %v: %w", network, err)
+	}
+	peers, err := getPeers(network)
+	if err != nil {
+		return Network{}, fmt.Errorf("listing peers for network %v: %w", network, err)
+	}
+	return Network{
+		Name:  network,
+		Peers: peers,
+		CurrentNode: Peer{
+			Name:           cfg.Node.Name,
+			Interface:      cfg.Node.Interface,
+			PrivateIPv4:    cfg.Node.Address,
+			PrivateIPv6:    cfg.Node.Address6,
+			PublicEndpoint: cfg.Node.Endpoint,
+		},
+	}, nil
+}
+
+func getPeers(network string) ([]Peer, error) {
+	cfg, err := config.ReadConfig(network)
+	if err != nil {
+		return []Peer{}, err
+	}
+	nodecfg := cfg.Node
+	var nodes []models.Node
+
+	var wcclient nodepb.NodeServiceClient
+	conn, err := grpc.Dial(cfg.Server.GRPCAddress,
+		ncutils.GRPCRequestOpts(cfg.Server.GRPCSSL))
+
+	if err != nil {
+		return []Peer{}, fmt.Errorf("connecting to %v: %w", cfg.Server.GRPCAddress, err)
+	}
+	defer conn.Close()
+	// Instantiate the BlogServiceClient with our client connection to the server
+	wcclient = nodepb.NewNodeServiceClient(conn)
+
+	req := &nodepb.Object{
+		Data: nodecfg.MacAddress + "###" + nodecfg.Network,
+		Type: nodepb.STRING_TYPE,
+	}
+
+	ctx, err := auth.SetJWT(wcclient, network)
+	if err != nil {
+		return []Peer{}, fmt.Errorf("authenticating: %w", err)
+	}
+	var header metadata.MD
+
+	response, err := wcclient.GetPeers(ctx, req, grpc.Header(&header))
+	if err != nil {
+		return []Peer{}, fmt.Errorf("retrieving peers: %w", err)
+	}
+	if err := json.Unmarshal([]byte(response.GetData()), &nodes); err != nil {
+		return []Peer{}, fmt.Errorf("unmarshaling data for peers: %w", err)
+	}
+
+	peers := []Peer{}
+	for _, node := range nodes {
+		if node.Name != cfg.Node.Name {
+			peers = append(peers, Peer{Name: fmt.Sprintf("%v.%v", node.Name, network), PrivateIPv4: node.Address, PrivateIPv6: node.Address6})
+		}
+	}
+
+	return peers, nil
+}

+ 6 - 1
netclient/main.go

@@ -26,6 +26,11 @@ func main() {
 	app.Usage = "Netmaker's netclient agent and CLI. Used to perform interactions with Netmaker server and set local WireGuard config."
 	app.Version = "v0.8.4"
 
+	hostname, err := os.Hostname()
+	if err != nil {
+		hostname = ""
+	}
+
 	cliFlags := []cli.Flag{
 		&cli.StringFlag{
 			Name:    "network",
@@ -91,7 +96,7 @@ func main() {
 		&cli.StringFlag{
 			Name:    "name",
 			EnvVars: []string{"NETCLIENT_NAME"},
-			Value:   "",
+			Value:   hostname,
 			Usage:   "Identifiable name for machine within Netmaker network.",
 		},
 		&cli.StringFlag{

+ 1 - 1
scripts/netclient-install.sh

@@ -2,7 +2,7 @@
 set -e
 
 if [[ $EUID -ne 0 ]]; then
-   echo "This script must be run as root" 
+   echo "This script must be run as root"
    exit 1
 fi