add dns controller tests

This commit is contained in:
Matthew R Kasun 2021-05-05 17:24:24 -04:00
parent a827f8caad
commit 4b74e52f83
8 changed files with 437 additions and 257 deletions

View file

@ -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) {

View 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")
})
}

View file

@ -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"

View file

@ -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) {

View file

@ -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
}

View file

@ -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"`
}

View file

@ -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)
}

View file

@ -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)