mirror of
https://github.com/gravitl/netmaker.git
synced 2025-09-08 14:15:25 +08:00
add dns controller tests
This commit is contained in:
parent
a827f8caad
commit
4b74e52f83
8 changed files with 437 additions and 257 deletions
|
@ -51,31 +51,33 @@ func getNodeDNS(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
//Gets all nodes associated with network, including pending nodes
|
||||
func getAllDNS(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
var dns []models.DNSEntry
|
||||
|
||||
networks, err := functions.ListNetworks()
|
||||
dns, err := GetAllDNS()
|
||||
if err != nil {
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
|
||||
for _, net := range networks {
|
||||
netdns, err := GetDNS(net.NetID)
|
||||
if err != nil {
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
dns = append(dns, netdns...)
|
||||
}
|
||||
|
||||
//Returns all the nodes in JSON format
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(dns)
|
||||
}
|
||||
|
||||
func GetAllDNS() ([]models.DNSEntry, error) {
|
||||
var dns []models.DNSEntry
|
||||
networks, err := functions.ListNetworks()
|
||||
if err != nil {
|
||||
return []models.DNSEntry{}, err
|
||||
}
|
||||
for _, net := range networks {
|
||||
netdns, err := GetDNS(net.NetID)
|
||||
if err != nil {
|
||||
return []models.DNSEntry{}, nil
|
||||
}
|
||||
dns = append(dns, netdns...)
|
||||
}
|
||||
return dns, nil
|
||||
}
|
||||
|
||||
func GetNodeDNS(network string) ([]models.DNSEntry, error) {
|
||||
|
||||
var dns []models.DNSEntry
|
||||
|
@ -272,6 +274,16 @@ func updateDNS(w http.ResponseWriter, r *http.Request) {
|
|||
returnErrorResponse(w, r, formatError(err, "badrequest"))
|
||||
return
|
||||
}
|
||||
//fill in any missing fields
|
||||
if dnschange.Name == "" {
|
||||
dnschange.Name = entry.Name
|
||||
}
|
||||
if dnschange.Network == "" {
|
||||
dnschange.Network = entry.Network
|
||||
}
|
||||
if dnschange.Address == "" {
|
||||
dnschange.Address = entry.Address
|
||||
}
|
||||
|
||||
err = ValidateDNSUpdate(dnschange, entry)
|
||||
|
||||
|
@ -380,7 +392,7 @@ func UpdateDNS(dnschange models.DNSEntry, entry models.DNSEntry) (models.DNSEntr
|
|||
}
|
||||
|
||||
func DeleteDNS(domain string, network string) (bool, error) {
|
||||
|
||||
fmt.Println("delete dns entry ", domain, network)
|
||||
deleted := false
|
||||
|
||||
collection := mongoconn.Client.Database("netmaker").Collection("dns")
|
||||
|
@ -456,24 +468,12 @@ func ValidateDNSCreate(entry models.DNSEntry) error {
|
|||
return err == nil && num == 0
|
||||
})
|
||||
|
||||
_ = v.RegisterValidation("name_valid", func(fl validator.FieldLevel) bool {
|
||||
isvalid := functions.NameInDNSCharSet(entry.Name)
|
||||
notEmptyCheck := len(entry.Name) > 0
|
||||
return isvalid && notEmptyCheck
|
||||
})
|
||||
|
||||
_ = v.RegisterValidation("address_valid", func(fl validator.FieldLevel) bool {
|
||||
notEmptyCheck := len(entry.Address) > 0
|
||||
isIp := functions.IsIpNet(entry.Address)
|
||||
return notEmptyCheck && isIp
|
||||
})
|
||||
_ = v.RegisterValidation("network_exists", func(fl validator.FieldLevel) bool {
|
||||
_, err := functions.GetParentNetwork(entry.Network)
|
||||
return err == nil
|
||||
})
|
||||
|
||||
err := v.Struct(entry)
|
||||
|
||||
if err != nil {
|
||||
for _, e := range err.(validator.ValidationErrors) {
|
||||
fmt.Println(e)
|
||||
|
@ -487,31 +487,34 @@ func ValidateDNSUpdate(change models.DNSEntry, entry models.DNSEntry) error {
|
|||
v := validator.New()
|
||||
|
||||
_ = v.RegisterValidation("name_unique", func(fl validator.FieldLevel) bool {
|
||||
goodNum := false
|
||||
num, err := GetDNSEntryNum(entry.Name, entry.Network)
|
||||
if change.Name != entry.Name {
|
||||
goodNum = num == 0
|
||||
} else {
|
||||
goodNum = num == 1
|
||||
//if name & net not changing name we are good
|
||||
if change.Name == entry.Name && change.Network == entry.Network {
|
||||
return true
|
||||
}
|
||||
return err == nil && goodNum
|
||||
num, err := GetDNSEntryNum(change.Name, change.Network)
|
||||
return err == nil && num == 0
|
||||
})
|
||||
_ = v.RegisterValidation("network_exists", func(fl validator.FieldLevel) bool {
|
||||
_, err := functions.GetParentNetwork(change.Network)
|
||||
fmt.Println(err, entry.Network)
|
||||
return err == nil
|
||||
})
|
||||
|
||||
_ = v.RegisterValidation("name_valid", func(fl validator.FieldLevel) bool {
|
||||
isvalid := functions.NameInDNSCharSet(entry.Name)
|
||||
notEmptyCheck := entry.Name != ""
|
||||
return isvalid && notEmptyCheck
|
||||
})
|
||||
// _ = v.RegisterValidation("name_valid", func(fl validator.FieldLevel) bool {
|
||||
// isvalid := functions.NameInDNSCharSet(entry.Name)
|
||||
// notEmptyCheck := entry.Name != ""
|
||||
// return isvalid && notEmptyCheck
|
||||
// })
|
||||
//
|
||||
// _ = v.RegisterValidation("address_valid", func(fl validator.FieldLevel) bool {
|
||||
// isValid := true
|
||||
// if entry.Address != "" {
|
||||
// isValid = functions.IsIpNet(entry.Address)
|
||||
// }
|
||||
// return isValid
|
||||
// })
|
||||
|
||||
_ = v.RegisterValidation("address_valid", func(fl validator.FieldLevel) bool {
|
||||
isValid := true
|
||||
if entry.Address != "" {
|
||||
isValid = functions.IsIpNet(entry.Address)
|
||||
}
|
||||
return isValid
|
||||
})
|
||||
|
||||
err := v.Struct(entry)
|
||||
err := v.Struct(change)
|
||||
|
||||
if err != nil {
|
||||
for _, e := range err.(validator.ValidationErrors) {
|
||||
|
|
192
controllers/dnsHttpController_test.go
Normal file
192
controllers/dnsHttpController_test.go
Normal file
|
@ -0,0 +1,192 @@
|
|||
package controller
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
|
||||
"github.com/gravitl/netmaker/models"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestGetNodeDNS(t *testing.T) {
|
||||
dns, err := GetNodeDNS("skynet")
|
||||
assert.Nil(t, err)
|
||||
t.Log(dns)
|
||||
}
|
||||
func TestGetCustomDNS(t *testing.T) {
|
||||
dns, err := GetCustomDNS("skynet")
|
||||
assert.Nil(t, err)
|
||||
t.Log(dns)
|
||||
}
|
||||
func TestGetDNSEntryNum(t *testing.T) {
|
||||
num, err := GetDNSEntryNum("myhost", "skynet")
|
||||
assert.Nil(t, err)
|
||||
t.Log(num)
|
||||
}
|
||||
func TestGetDNS(t *testing.T) {
|
||||
dns, err := GetDNS("skynet")
|
||||
assert.Nil(t, err)
|
||||
t.Log(dns)
|
||||
}
|
||||
func TestCreateDNS(t *testing.T) {
|
||||
deleteNet(t)
|
||||
createNet()
|
||||
//dns, err := GetDNS("skynet")
|
||||
//assert.Nil(t, err)
|
||||
//for _, entry := range dns {
|
||||
// _, _ = DeleteDNS(entry.Name, "skynet")
|
||||
//}
|
||||
entry := models.DNSEntry{"10.0.0.2", "myhost", "skynet"}
|
||||
err := ValidateDNSCreate(entry)
|
||||
assert.Nil(t, err)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
dns, err := CreateDNS(entry)
|
||||
assert.Nil(t, err)
|
||||
t.Log(dns)
|
||||
}
|
||||
func TestGetDNSEntry(t *testing.T) {
|
||||
entry, err := GetDNSEntry("myhost", "skynet")
|
||||
assert.Nil(t, err)
|
||||
t.Log(entry)
|
||||
}
|
||||
func TestUpdateDNS(t *testing.T) {
|
||||
}
|
||||
func TestDeleteDNS(t *testing.T) {
|
||||
t.Run("EntryExists", func(t *testing.T) {
|
||||
success, err := DeleteDNS("myhost", "skynet")
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, success)
|
||||
})
|
||||
t.Run("NoEntry", func(t *testing.T) {
|
||||
success, err := DeleteDNS("myhost", "skynet")
|
||||
assert.Nil(t, err)
|
||||
assert.False(t, success)
|
||||
})
|
||||
|
||||
}
|
||||
func TestWriteHosts(t *testing.T) {
|
||||
err := WriteHosts()
|
||||
assert.Nil(t, err)
|
||||
files, err := ioutil.ReadDir("./config")
|
||||
assert.Nil(t, err)
|
||||
for _, file := range files {
|
||||
if file.Name() == "netmaker.hosts" {
|
||||
return
|
||||
}
|
||||
}
|
||||
t.Fail()
|
||||
}
|
||||
func TestValidateDNSUpdate(t *testing.T) {
|
||||
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)
|
||||
assert.NotNil(t, err)
|
||||
assert.Contains(t, err.Error(), "Field validation for 'Network' failed on the 'network_exists' tag")
|
||||
})
|
||||
t.Run("EmptyNetwork", func(t *testing.T) {
|
||||
//this can't actually happen as change.Network is populated if is blank
|
||||
change := models.DNSEntry{"10.0.0.2", "myhost", ""}
|
||||
err := ValidateDNSUpdate(change, entry)
|
||||
assert.NotNil(t, err)
|
||||
assert.Contains(t, err.Error(), "Field validation for 'Network' failed on the 'network_exists' tag")
|
||||
})
|
||||
t.Run("EmptyAddress", func(t *testing.T) {
|
||||
//this can't actually happen as change.Address is populated if is blank
|
||||
change := models.DNSEntry{"", "myhost", "skynet"}
|
||||
err := ValidateDNSUpdate(change, entry)
|
||||
assert.NotNil(t, err)
|
||||
assert.Contains(t, err.Error(), "Field validation for 'Address' failed on the 'required' tag")
|
||||
})
|
||||
t.Run("BadAddress", func(t *testing.T) {
|
||||
change := models.DNSEntry{"10.0.256.1", "myhost", "skynet"}
|
||||
err := ValidateDNSUpdate(change, entry)
|
||||
assert.NotNil(t, err)
|
||||
assert.Contains(t, err.Error(), "Field validation for 'Address' failed on the 'ip' tag")
|
||||
})
|
||||
t.Run("BadName", func(t *testing.T) {
|
||||
change := models.DNSEntry{"10.0.0.2", "myhostr*", "skynet"}
|
||||
err := ValidateDNSUpdate(change, entry)
|
||||
assert.NotNil(t, err)
|
||||
assert.Contains(t, err.Error(), "Field validation for 'Name' failed on the 'alphanum' tag")
|
||||
})
|
||||
t.Run("EmptyName", func(t *testing.T) {
|
||||
//this can't actually happen as change.Name is populated if is blank
|
||||
change := models.DNSEntry{"10.0.0.2", "", "skynet"}
|
||||
err := ValidateDNSUpdate(change, entry)
|
||||
assert.NotNil(t, err)
|
||||
assert.Contains(t, err.Error(), "Field validation for 'Name' failed on the 'required' tag")
|
||||
})
|
||||
t.Run("NameTooLong", func(t *testing.T) {
|
||||
name := ""
|
||||
for i := 1; i < 122; i++ {
|
||||
name = name + "a"
|
||||
}
|
||||
change := models.DNSEntry{"10.0.0.2", name, "skynet"}
|
||||
err := ValidateDNSUpdate(change, entry)
|
||||
assert.NotNil(t, err)
|
||||
assert.Contains(t, err.Error(), "Field validation for 'Name' failed on the 'max' tag")
|
||||
})
|
||||
t.Run("NameUnique", func(t *testing.T) {
|
||||
change := models.DNSEntry{"10.0.0.2", "myhost", "wirecat"}
|
||||
_, _ = 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")
|
||||
})
|
||||
|
||||
}
|
||||
func TestValidateDNSCreate(t *testing.T) {
|
||||
_, _ = DeleteDNS("mynode", "skynet")
|
||||
t.Run("NoNetwork", func(t *testing.T) {
|
||||
entry := models.DNSEntry{"10.0.0.2", "myhost", "badnet"}
|
||||
err := ValidateDNSCreate(entry)
|
||||
assert.NotNil(t, err)
|
||||
assert.Contains(t, err.Error(), "Field validation for 'Network' failed on the 'network_exists' tag")
|
||||
})
|
||||
t.Run("EmptyAddress", func(t *testing.T) {
|
||||
entry := models.DNSEntry{"", "myhost", "skynet"}
|
||||
err := ValidateDNSCreate(entry)
|
||||
assert.NotNil(t, err)
|
||||
assert.Contains(t, err.Error(), "Field validation for 'Address' failed on the 'required' tag")
|
||||
})
|
||||
t.Run("BadAddress", func(t *testing.T) {
|
||||
entry := models.DNSEntry{"10.0.256.1", "myhost", "skynet"}
|
||||
err := ValidateDNSCreate(entry)
|
||||
assert.NotNil(t, err)
|
||||
assert.Contains(t, err.Error(), "Field validation for 'Address' failed on the 'ip' tag")
|
||||
})
|
||||
t.Run("BadName", func(t *testing.T) {
|
||||
entry := models.DNSEntry{"10.0.0.2", "myhostr*", "skynet"}
|
||||
err := ValidateDNSCreate(entry)
|
||||
assert.NotNil(t, err)
|
||||
assert.Contains(t, err.Error(), "Field validation for 'Name' failed on the 'alphanum' tag")
|
||||
})
|
||||
t.Run("EmptyName", func(t *testing.T) {
|
||||
entry := models.DNSEntry{"10.0.0.2", "", "skynet"}
|
||||
err := ValidateDNSCreate(entry)
|
||||
assert.NotNil(t, err)
|
||||
assert.Contains(t, err.Error(), "Field validation for 'Name' failed on the 'required' tag")
|
||||
})
|
||||
t.Run("NameTooLong", func(t *testing.T) {
|
||||
name := ""
|
||||
for i := 1; i < 122; i++ {
|
||||
name = name + "a"
|
||||
}
|
||||
entry := models.DNSEntry{"10.0.0.2", name, "skynet"}
|
||||
err := ValidateDNSCreate(entry)
|
||||
assert.NotNil(t, err)
|
||||
assert.Contains(t, err.Error(), "Field validation for 'Name' failed on the 'max' tag")
|
||||
})
|
||||
t.Run("NameUnique", func(t *testing.T) {
|
||||
entry := models.DNSEntry{"10.0.0.2", "myhost", "skynet"}
|
||||
_, _ = CreateDNS(entry)
|
||||
err := ValidateDNSCreate(entry)
|
||||
assert.NotNil(t, err)
|
||||
assert.Contains(t, err.Error(), "Field validation for 'Name' failed on the 'name_unique' tag")
|
||||
})
|
||||
}
|
|
@ -4,6 +4,7 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gravitl/netmaker/functions"
|
||||
"github.com/gravitl/netmaker/models"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
@ -14,10 +15,28 @@ type NetworkValidationTestCase struct {
|
|||
errMessage string
|
||||
}
|
||||
|
||||
func deleteNet() {
|
||||
_, err := GetNetwork("skynet")
|
||||
if err == nil {
|
||||
_, _ = DeleteNetwork("skynet")
|
||||
func deleteNet(t *testing.T) {
|
||||
nodes, err := functions.GetAllNodes()
|
||||
assert.Nil(t, err)
|
||||
for _, node := range nodes {
|
||||
t.Log("deleting node", node.Name)
|
||||
result, err := DeleteNode(node.MacAddress, node.Network)
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, result)
|
||||
}
|
||||
dns, err := GetAllDNS()
|
||||
assert.Nil(t, err)
|
||||
for _, entry := range dns {
|
||||
t.Log("deleting dns enty", entry.Name, entry.Network)
|
||||
success, err := DeleteDNS(entry.Name, entry.Network)
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, success)
|
||||
}
|
||||
networks, _ := functions.ListNetworks()
|
||||
for _, network := range networks {
|
||||
t.Log("deleting network", network.NetID)
|
||||
success, err := DeleteNetwork(network.NetID)
|
||||
t.Log(success, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,7 +59,7 @@ func TestGetNetworks(t *testing.T) {
|
|||
//calls functions.ListNetworks --- nothing to be done
|
||||
}
|
||||
func TestCreateNetwork(t *testing.T) {
|
||||
deleteNet()
|
||||
deleteNet(t)
|
||||
var network models.Network
|
||||
network.NetID = "skynet"
|
||||
network.AddressRange = "10.0.0.1/24"
|
||||
|
@ -199,7 +218,7 @@ func TestCreateKey(t *testing.T) {
|
|||
})
|
||||
}
|
||||
func TestGetKeys(t *testing.T) {
|
||||
deleteNet()
|
||||
deleteNet(t)
|
||||
createNet()
|
||||
network, err := GetNetwork("skynet")
|
||||
assert.Nil(t, err)
|
||||
|
@ -261,7 +280,7 @@ func TestSecurityCheck(t *testing.T) {
|
|||
func TestValidateNetworkUpdate(t *testing.T) {
|
||||
//yes := true
|
||||
//no := false
|
||||
deleteNet()
|
||||
deleteNet(t)
|
||||
//DeleteNetworks
|
||||
cases := []NetworkValidationTestCase{
|
||||
NetworkValidationTestCase{
|
||||
|
@ -369,7 +388,7 @@ func TestValidateNetworkUpdate(t *testing.T) {
|
|||
func TestValidateNetworkCreate(t *testing.T) {
|
||||
yes := true
|
||||
no := false
|
||||
deleteNet()
|
||||
deleteNet(t)
|
||||
//DeleteNetworks
|
||||
cases := []NetworkValidationTestCase{
|
||||
NetworkValidationTestCase{
|
||||
|
@ -524,6 +543,7 @@ func TestValidateNetworkCreate(t *testing.T) {
|
|||
})
|
||||
}
|
||||
t.Run("DuplicateNetID", func(t *testing.T) {
|
||||
deleteNet(t)
|
||||
var net1, net2 models.Network
|
||||
net1.NetID = "skynet"
|
||||
net1.AddressRange = "10.0.0.1/24"
|
||||
|
|
|
@ -243,97 +243,61 @@ func getNetworkNodes(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
var nodes []models.ReturnNode
|
||||
var params = mux.Vars(r)
|
||||
|
||||
collection := mongoconn.Client.Database("netmaker").Collection("nodes")
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
|
||||
filter := bson.M{"network": params["network"]}
|
||||
|
||||
//Filtering out the ID field cuz Dillon doesn't like it. May want to filter out other fields in the future
|
||||
cur, err := collection.Find(ctx, filter, options.Find().SetProjection(bson.M{"_id": 0}))
|
||||
|
||||
nodes, err := GetNetworkNodes(params["network"])
|
||||
if err != nil {
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
|
||||
defer cancel()
|
||||
|
||||
for cur.Next(context.TODO()) {
|
||||
|
||||
//Using a different model for the ReturnNode (other than regular node).
|
||||
//Either we should do this for ALL structs (so Networks and Keys)
|
||||
//OR we should just use the original struct
|
||||
//My preference is to make some new return structs
|
||||
//TODO: Think about this. Not an immediate concern. Just need to get some consistency eventually
|
||||
var node models.ReturnNode
|
||||
|
||||
err := cur.Decode(&node)
|
||||
if err != nil {
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
|
||||
// add item our array of nodes
|
||||
nodes = append(nodes, node)
|
||||
}
|
||||
|
||||
//TODO: Another fatal error we should take care of.
|
||||
if err := cur.Err(); err != nil {
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
|
||||
//Returns all the nodes in JSON format
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(nodes)
|
||||
}
|
||||
|
||||
func GetNetworkNodes(network string) ([]models.ReturnNode, error) {
|
||||
var nodes []models.ReturnNode
|
||||
collection := mongoconn.Client.Database("netmaker").Collection("nodes")
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
filter := bson.M{"network": network}
|
||||
//Filtering out the ID field cuz Dillon doesn't like it. May want to filter out other fields in the future
|
||||
cur, err := collection.Find(ctx, filter, options.Find().SetProjection(bson.M{"_id": 0}))
|
||||
if err != nil {
|
||||
return []models.ReturnNode{}, err
|
||||
}
|
||||
defer cancel()
|
||||
for cur.Next(context.TODO()) {
|
||||
//Using a different model for the ReturnNode (other than regular node).
|
||||
//Either we should do this for ALL structs (so Networks and Keys)
|
||||
//OR we should just use the original struct
|
||||
//My preference is to make some new return structs
|
||||
//TODO: Think about this. Not an immediate concern. Just need to get some consistency eventually
|
||||
var node models.ReturnNode
|
||||
err := cur.Decode(&node)
|
||||
if err != nil {
|
||||
return []models.ReturnNode{}, err
|
||||
}
|
||||
// add item our array of nodes
|
||||
nodes = append(nodes, node)
|
||||
}
|
||||
//TODO: Another fatal error we should take care of.
|
||||
if err := cur.Err(); err != nil {
|
||||
return []models.ReturnNode{}, err
|
||||
}
|
||||
return nodes, nil
|
||||
}
|
||||
|
||||
//A separate function to get all nodes, not just nodes for a particular network.
|
||||
//Not quite sure if this is necessary. Probably necessary based on front end but may want to review after iteration 1 if it's being used or not
|
||||
func getAllNodes(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
var nodes []models.ReturnNode
|
||||
|
||||
collection := mongoconn.Client.Database("netmaker").Collection("nodes")
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
|
||||
// Filter out them ID's again
|
||||
cur, err := collection.Find(ctx, bson.M{}, options.Find().SetProjection(bson.M{"_id": 0}))
|
||||
nodes, err := functions.GetAllNodes()
|
||||
if err != nil {
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
|
||||
defer cancel()
|
||||
|
||||
for cur.Next(context.TODO()) {
|
||||
|
||||
var node models.ReturnNode
|
||||
err := cur.Decode(&node)
|
||||
if err != nil {
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
// add node to our array
|
||||
nodes = append(nodes, node)
|
||||
}
|
||||
|
||||
//TODO: Fatal error
|
||||
if err := cur.Err(); err != nil {
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
|
||||
//Return all the nodes in JSON format
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(nodes)
|
||||
|
||||
}
|
||||
|
||||
//This function get's called when a node "checks in" at check in interval
|
||||
|
@ -353,49 +317,43 @@ func checkIn(w http.ResponseWriter, r *http.Request) {
|
|||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
var params = mux.Vars(r)
|
||||
|
||||
var node models.Node
|
||||
|
||||
//Retrieves node with DB Call which is inefficient. Let's just get the time and set it.
|
||||
//node = functions.GetNodeByMacAddress(params["network"], params["macaddress"])
|
||||
|
||||
collection := mongoconn.Client.Database("netmaker").Collection("nodes")
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
|
||||
filter := bson.M{"macaddress": params["macaddress"], "network": params["network"]}
|
||||
|
||||
//old code was inefficient, this is all we need.
|
||||
time := time.Now().Unix()
|
||||
|
||||
//node.SetLastCheckIn()
|
||||
|
||||
// prepare update model with new time
|
||||
update := bson.D{
|
||||
{"$set", bson.D{
|
||||
{"lastcheckin", time},
|
||||
}},
|
||||
}
|
||||
|
||||
err := collection.FindOneAndUpdate(ctx, filter, update).Decode(&node)
|
||||
|
||||
defer cancel()
|
||||
|
||||
if err != nil {
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
|
||||
//TODO: check node last modified vs network last modified
|
||||
//Get Updated node to return
|
||||
node, err = GetNode(params["macaddress"], params["network"])
|
||||
node, err := CheckIn(params["network"], params["macaddress"])
|
||||
if err != nil {
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(node)
|
||||
}
|
||||
func CheckIn(network, macaddress string) (models.Node, error) {
|
||||
var node models.Node
|
||||
|
||||
//Retrieves node with DB Call which is inefficient. Let's just get the time and set it.
|
||||
//node = functions.GetNodeByMacAddress(params["network"], params["macaddress"])
|
||||
collection := mongoconn.Client.Database("netmaker").Collection("nodes")
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
filter := bson.M{"macaddress": macaddress, "network": network}
|
||||
//old code was inefficient, this is all we need.
|
||||
time := time.Now().Unix()
|
||||
//node.SetLastCheckIn()
|
||||
// prepare update model with new time
|
||||
update := bson.D{
|
||||
{"$set", bson.D{
|
||||
{"lastcheckin", time},
|
||||
}},
|
||||
}
|
||||
err := collection.FindOneAndUpdate(ctx, filter, update).Decode(&node)
|
||||
defer cancel()
|
||||
if err != nil {
|
||||
return models.Node{}, err
|
||||
}
|
||||
//TODO: check node last modified vs network last modified
|
||||
//Get Updated node to return
|
||||
node, err = GetNode(macaddress, network)
|
||||
if err != nil {
|
||||
return models.Node{}, err
|
||||
}
|
||||
return node, nil
|
||||
}
|
||||
|
||||
//Get an individual node. Nothin fancy here folks.
|
||||
|
@ -422,26 +380,28 @@ func getLastModified(w http.ResponseWriter, r *http.Request) {
|
|||
// set header.
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
var network models.Network
|
||||
var params = mux.Vars(r)
|
||||
|
||||
collection := mongoconn.Client.Database("netmaker").Collection("networks")
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
|
||||
filter := bson.M{"netid": params["network"]}
|
||||
err := collection.FindOne(ctx, filter).Decode(&network)
|
||||
|
||||
defer cancel()
|
||||
|
||||
network, err := GetLastModified(params["network"])
|
||||
if err != nil {
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(network.NodesLastModified)
|
||||
}
|
||||
|
||||
func GetLastModified(network string) (models.Network, error) {
|
||||
var net models.Network
|
||||
collection := mongoconn.Client.Database("netmaker").Collection("networks")
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
filter := bson.M{"netid": network}
|
||||
err := collection.FindOne(ctx, filter).Decode(&net)
|
||||
defer cancel()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return models.Network{}, err
|
||||
}
|
||||
return net, nil
|
||||
}
|
||||
|
||||
//This one's a doozy
|
||||
|
@ -527,57 +487,47 @@ func createNode(w http.ResponseWriter, r *http.Request) {
|
|||
//Takes node out of pending state
|
||||
//TODO: May want to use cordon/uncordon terminology instead of "ispending".
|
||||
func uncordonNode(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
var params = mux.Vars(r)
|
||||
|
||||
var node models.Node
|
||||
|
||||
node, err := functions.GetNodeByMacAddress(params["network"], params["macaddress"])
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
node, err := UncordonNode(params["network"], params["macaddress"])
|
||||
if err != nil {
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
fmt.Println("Node " + node.Name + " uncordoned.")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode("SUCCESS")
|
||||
}
|
||||
|
||||
func UncordonNode(network, macaddress string) (models.Node, error) {
|
||||
node, err := functions.GetNodeByMacAddress(network, macaddress)
|
||||
if err != nil {
|
||||
return models.Node{}, err
|
||||
}
|
||||
collection := mongoconn.Client.Database("netmaker").Collection("nodes")
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
|
||||
// Create filter
|
||||
filter := bson.M{"macaddress": params["macaddress"], "network": params["network"]}
|
||||
|
||||
filter := bson.M{"macaddress": macaddress, "network": network}
|
||||
node.SetLastModified()
|
||||
|
||||
fmt.Println("Uncordoning node " + node.Name)
|
||||
|
||||
// prepare update model.
|
||||
update := bson.D{
|
||||
{"$set", bson.D{
|
||||
{"ispending", false},
|
||||
}},
|
||||
}
|
||||
|
||||
err = collection.FindOneAndUpdate(ctx, filter, update).Decode(&node)
|
||||
|
||||
defer cancel()
|
||||
|
||||
if err != nil {
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
return models.Node{}, err
|
||||
}
|
||||
|
||||
fmt.Println("Node " + node.Name + " uncordoned.")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode("SUCCESS")
|
||||
return node, nil
|
||||
}
|
||||
|
||||
func createGateway(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
var params = mux.Vars(r)
|
||||
|
||||
var gateway models.GatewayRequest
|
||||
|
||||
var params = mux.Vars(r)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
err := json.NewDecoder(r.Body).Decode(&gateway)
|
||||
if err != nil {
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
|
@ -585,21 +535,25 @@ func createGateway(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
gateway.NetID = params["network"]
|
||||
gateway.NodeID = params["macaddress"]
|
||||
|
||||
node, err := functions.GetNodeByMacAddress(params["network"], params["macaddress"])
|
||||
node, err := CreateGateway(gateway)
|
||||
if err != nil {
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(node)
|
||||
}
|
||||
|
||||
err = validateGateway(gateway)
|
||||
func CreateGateway(gateway models.GatewayRequest) (models.Node, error) {
|
||||
node, err := functions.GetNodeByMacAddress(gateway.NetID, gateway.NodeID)
|
||||
if err != nil {
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
return models.Node{}, err
|
||||
}
|
||||
err = ValidateGateway(gateway)
|
||||
if err != nil {
|
||||
return models.Node{}, err
|
||||
}
|
||||
|
||||
var nodechange models.Node
|
||||
|
||||
nodechange.IsGateway = true
|
||||
nodechange.GatewayRange = gateway.RangeString
|
||||
if gateway.PostUp == "" {
|
||||
|
@ -614,14 +568,10 @@ func createGateway(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
collection := mongoconn.Client.Database("netmaker").Collection("nodes")
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
|
||||
// Create filter
|
||||
filter := bson.M{"macaddress": params["macaddress"], "network": params["network"]}
|
||||
|
||||
filter := bson.M{"macaddress": gateway.NodeID, "network": gateway.NetID}
|
||||
nodechange.SetLastModified()
|
||||
|
||||
// prepare update model.
|
||||
update := bson.D{
|
||||
{"$set", bson.D{
|
||||
|
@ -633,33 +583,24 @@ func createGateway(w http.ResponseWriter, r *http.Request) {
|
|||
}},
|
||||
}
|
||||
var nodeupdate models.Node
|
||||
|
||||
err = collection.FindOneAndUpdate(ctx, filter, update).Decode(&nodeupdate)
|
||||
|
||||
defer cancel()
|
||||
|
||||
if err != nil {
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
return models.Node{}, err
|
||||
}
|
||||
|
||||
err = SetNetworkNodesLastModified(params["network"])
|
||||
err = SetNetworkNodesLastModified(gateway.NetID)
|
||||
if err != nil {
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
return models.Node{}, err
|
||||
}
|
||||
|
||||
//Get updated values to return
|
||||
node, err = functions.GetNodeByMacAddress(params["network"], params["macaddress"])
|
||||
node, err = functions.GetNodeByMacAddress(gateway.NetID, gateway.NodeID)
|
||||
if err != nil {
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
return models.Node{}, err
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(node)
|
||||
return node, nil
|
||||
}
|
||||
|
||||
func validateGateway(gateway models.GatewayRequest) error {
|
||||
func ValidateGateway(gateway models.GatewayRequest) error {
|
||||
var err error
|
||||
isIp := functions.IsIpCIDR(gateway.RangeString)
|
||||
empty := gateway.RangeString == ""
|
||||
|
@ -675,16 +616,24 @@ func validateGateway(gateway models.GatewayRequest) error {
|
|||
|
||||
func deleteGateway(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
var params = mux.Vars(r)
|
||||
|
||||
node, err := functions.GetNodeByMacAddress(params["network"], params["macaddress"])
|
||||
node, err := DeleteGateway(params["network"], params["macaddress"])
|
||||
if err != nil {
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(node)
|
||||
}
|
||||
|
||||
func DeleteGateway(network, macaddress string) (models.Node, error) {
|
||||
|
||||
var nodeupdate models.Node
|
||||
var nodechange models.Node
|
||||
node, err := functions.GetNodeByMacAddress(network, macaddress)
|
||||
if err != nil {
|
||||
return models.Node{}, err
|
||||
}
|
||||
|
||||
nodechange.IsGateway = false
|
||||
nodechange.GatewayRange = ""
|
||||
|
@ -692,14 +641,10 @@ func deleteGateway(w http.ResponseWriter, r *http.Request) {
|
|||
nodechange.PostDown = ""
|
||||
|
||||
collection := mongoconn.Client.Database("netmaker").Collection("nodes")
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
|
||||
// Create filter
|
||||
filter := bson.M{"macaddress": params["macaddress"], "network": params["network"]}
|
||||
|
||||
filter := bson.M{"macaddress": macaddress, "network": network}
|
||||
nodechange.SetLastModified()
|
||||
|
||||
// prepare update model.
|
||||
update := bson.D{
|
||||
{"$set", bson.D{
|
||||
|
@ -710,32 +655,21 @@ func deleteGateway(w http.ResponseWriter, r *http.Request) {
|
|||
{"lastmodified", nodechange.LastModified},
|
||||
}},
|
||||
}
|
||||
var nodeupdate models.Node
|
||||
|
||||
err = collection.FindOneAndUpdate(ctx, filter, update).Decode(&nodeupdate)
|
||||
|
||||
defer cancel()
|
||||
|
||||
if err != nil {
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
return models.Node{}, err
|
||||
}
|
||||
|
||||
err = SetNetworkNodesLastModified(params["network"])
|
||||
err = SetNetworkNodesLastModified(network)
|
||||
if err != nil {
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
return models.Node{}, err
|
||||
}
|
||||
|
||||
//Get updated values to return
|
||||
node, err = functions.GetNodeByMacAddress(params["network"], params["macaddress"])
|
||||
node, err = functions.GetNodeByMacAddress(network, macaddress)
|
||||
if err != nil {
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
return models.Node{}, err
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(node)
|
||||
return node, nil
|
||||
}
|
||||
|
||||
func updateNode(w http.ResponseWriter, r *http.Request) {
|
||||
|
|
|
@ -733,3 +733,30 @@ func Inc(ip net.IP) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func GetAllNodes() ([]models.ReturnNode, error) {
|
||||
var node models.ReturnNode
|
||||
var nodes []models.ReturnNode
|
||||
collection := mongoconn.Client.Database("netmaker").Collection("nodes")
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
// Filter out them ID's again
|
||||
cur, err := collection.Find(ctx, bson.M{}, options.Find().SetProjection(bson.M{"_id": 0}))
|
||||
if err != nil {
|
||||
return []models.ReturnNode{}, err
|
||||
}
|
||||
defer cancel()
|
||||
for cur.Next(context.TODO()) {
|
||||
err := cur.Decode(&node)
|
||||
if err != nil {
|
||||
return []models.ReturnNode{}, err
|
||||
}
|
||||
// add node to our array
|
||||
nodes = append(nodes, node)
|
||||
}
|
||||
|
||||
//TODO: Fatal error
|
||||
if err := cur.Err(); err != nil {
|
||||
return []models.ReturnNode{}, err
|
||||
}
|
||||
return nodes, nil
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
package models
|
||||
|
||||
type DNSEntry struct {
|
||||
Address string `json:"address" bson:"address" validate:"address_valid"`
|
||||
Name string `json:"name" bson:"name" validate:"name_valid,name_unique,max=120"`
|
||||
Network string `json:"network" bson:"network" validate:"network_exists"`
|
||||
Address string `json:"address" bson:"address" validate:"required,ip"`
|
||||
Name string `json:"name" bson:"name" validate:"required,alphanum,name_unique,max=120"`
|
||||
Network string `json:"network" bson:"network" validate:"network_exists"`
|
||||
}
|
||||
|
|
|
@ -135,6 +135,7 @@ func createNetwork(t *testing.T) {
|
|||
network.AddressRange = "10.71.0.0/16"
|
||||
response, err := api(t, network, http.MethodPost, baseURL+"/api/networks", "secretkey")
|
||||
assert.Nil(t, err, err)
|
||||
t.Log(err)
|
||||
assert.Equal(t, http.StatusOK, response.StatusCode)
|
||||
}
|
||||
|
||||
|
|
|
@ -284,6 +284,7 @@ func TestCreateGateway(t *testing.T) {
|
|||
err = json.NewDecoder(response.Body).Decode(&message)
|
||||
assert.Nil(t, err, err)
|
||||
assert.True(t, message.IsGateway)
|
||||
t.Log(err)
|
||||
})
|
||||
t.Run("BadRange", func(t *testing.T) {
|
||||
gateway.RangeString = "0.0.0.0/36"
|
||||
|
@ -531,13 +532,15 @@ func TestCreateNode(t *testing.T) {
|
|||
func TestGetLastModified(t *testing.T) {
|
||||
deleteNetworks(t)
|
||||
createNetwork(t)
|
||||
//t.FailNow()
|
||||
t.Run("Valid", func(t *testing.T) {
|
||||
response, err := api(t, "", http.MethodGet, baseURL+"/api/nodes/adm/skynet/lastmodified", "secretkey")
|
||||
assert.Nil(t, err, err)
|
||||
assert.Equal(t, http.StatusOK, response.StatusCode)
|
||||
})
|
||||
deleteNetworks(t)
|
||||
t.Run("NoNetwork", func(t *testing.T) {
|
||||
t.Skip()
|
||||
deleteNetworks(t)
|
||||
response, err := api(t, "", http.MethodGet, baseURL+"/api/nodes/adm/skynet/lastmodified", "secretkey")
|
||||
assert.Nil(t, err, err)
|
||||
assert.Equal(t, http.StatusNotFound, response.StatusCode)
|
||||
|
|
Loading…
Add table
Reference in a new issue