Browse Source

added ifs to update

afeiszli 4 years ago
parent
commit
b35cac8c5e

+ 10 - 10
controllers/common.go

@@ -20,9 +20,9 @@ func GetPeersList(networkName string) ([]models.PeersResponse, error) {
 
 
 	var peers []models.PeersResponse
 	var peers []models.PeersResponse
 	collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
 	collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
-        if err != nil {
-                log.Println(err)
-        }
+	if err != nil {
+		log.Println(err)
+	}
 	udppeers, errN := serverctl.GetPeers(networkName)
 	udppeers, errN := serverctl.GetPeers(networkName)
 	if errN != nil {
 	if errN != nil {
 		log.Println(errN)
 		log.Println(errN)
@@ -38,7 +38,7 @@ func GetPeersList(networkName string) ([]models.PeersResponse, error) {
 		if err != nil {
 		if err != nil {
 			continue
 			continue
 		}
 		}
-		if node.Network == networkName && !node.IsPending {
+		if node.Network == networkName && node.IsPending != "yes" {
 			if node.UDPHolePunch == "yes" && errN == nil {
 			if node.UDPHolePunch == "yes" && errN == nil {
 				endpointstring := udppeers[peer.PublicKey]
 				endpointstring := udppeers[peer.PublicKey]
 				endpointarr := strings.Split(endpointstring, ":")
 				endpointarr := strings.Split(endpointstring, ":")
@@ -178,10 +178,10 @@ func CreateNode(node models.Node, networkName string) (models.Node, error) {
 		//returnErrorResponse(w, r, errorResponse)
 		//returnErrorResponse(w, r, errorResponse)
 		return node, err
 		return node, err
 	}
 	}
-        err = node.Validate(false)
-        if err != nil {
-                return node, err
-        }
+	err = node.Validate(false)
+	if err != nil {
+		return node, err
+	}
 
 
 	key, err := functions.GetRecordKey(node.MacAddress, node.Network)
 	key, err := functions.GetRecordKey(node.MacAddress, node.Network)
 	if err != nil {
 	if err != nil {
@@ -195,7 +195,7 @@ func CreateNode(node models.Node, networkName string) (models.Node, error) {
 	if err != nil {
 	if err != nil {
 		return node, err
 		return node, err
 	}
 	}
-	if !node.IsPending {
+	if node.IsPending != "yes" {
 		functions.DecrimentKey(node.Network, node.AccessKey)
 		functions.DecrimentKey(node.Network, node.AccessKey)
 	}
 	}
 	SetNetworkNodesLastModified(node.Network)
 	SetNetworkNodesLastModified(node.Network)
@@ -220,7 +220,7 @@ func NodeCheckIn(node models.Node, networkName string) (models.CheckInResponse,
 		err = fmt.Errorf("%w; Couldnt Get Node "+node.MacAddress, err)
 		err = fmt.Errorf("%w; Couldnt Get Node "+node.MacAddress, err)
 		return response, err
 		return response, err
 	}
 	}
-	if parentnode.IsPending {
+	if parentnode.IsPending == "yes" {
 		err = fmt.Errorf("%w; Node checking in is still pending: "+node.MacAddress, err)
 		err = fmt.Errorf("%w; Node checking in is still pending: "+node.MacAddress, err)
 		response.IsPending = true
 		response.IsPending = true
 		return response, err
 		return response, err

+ 1 - 1
controllers/extClientHttpController.go

@@ -73,7 +73,7 @@ func checkIngressExists(network string, macaddress string) bool {
 	if err != nil {
 	if err != nil {
 		return false
 		return false
 	}
 	}
-	return node.IsIngressGateway
+	return node.IsIngressGateway == "yes"
 }
 }
 
 
 //Gets all extclients associated with network, including pending extclients
 //Gets all extclients associated with network, including pending extclients

+ 11 - 12
controllers/nodeGrpcController.go

@@ -4,6 +4,7 @@ import (
 	"context"
 	"context"
 	"fmt"
 	"fmt"
 	"log"
 	"log"
+
 	"github.com/gravitl/netmaker/functions"
 	"github.com/gravitl/netmaker/functions"
 	nodepb "github.com/gravitl/netmaker/grpc"
 	nodepb "github.com/gravitl/netmaker/grpc"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/models"
@@ -50,8 +51,8 @@ func (s *NodeServiceServer) ReadNode(ctx context.Context, req *nodepb.ReadNodeRe
 			Postup:              node.PostUp,
 			Postup:              node.PostUp,
 			Checkininterval:     node.CheckInInterval,
 			Checkininterval:     node.CheckInInterval,
 			Dnsoff:              !servercfg.IsDNSMode(),
 			Dnsoff:              !servercfg.IsDNSMode(),
-			Ispending:           node.IsPending,
-			Isingressgateway:    node.IsIngressGateway,
+			Ispending:           node.IsPending == "yes",
+			Isingressgateway:    node.IsIngressGateway == "yes",
 			Ingressgatewayrange: node.IngressGatewayRange,
 			Ingressgatewayrange: node.IngressGatewayRange,
 			Publickey:           node.PublicKey,
 			Publickey:           node.PublicKey,
 			Listenport:          node.ListenPort,
 			Listenport:          node.ListenPort,
@@ -83,7 +84,6 @@ func (s *NodeServiceServer) CreateNode(ctx context.Context, req *nodepb.CreateNo
 		Password:            data.GetPassword(),
 		Password:            data.GetPassword(),
 		Interface:           data.GetInterface(),
 		Interface:           data.GetInterface(),
 		Network:             data.GetNodenetwork(),
 		Network:             data.GetNodenetwork(),
-		IsPending:           data.GetIspending(),
 		PublicKey:           data.GetPublickey(),
 		PublicKey:           data.GetPublickey(),
 		ListenPort:          data.GetListenport(),
 		ListenPort:          data.GetListenport(),
 		UDPHolePunch:        data.GetUdpholepunch(),
 		UDPHolePunch:        data.GetUdpholepunch(),
@@ -101,7 +101,7 @@ func (s *NodeServiceServer) CreateNode(ctx context.Context, req *nodepb.CreateNo
 		//Check to see if network will allow manual sign up
 		//Check to see if network will allow manual sign up
 		//may want to switch this up with the valid key check and avoid a DB call that way.
 		//may want to switch this up with the valid key check and avoid a DB call that way.
 		if network.AllowManualSignUp == "yes" {
 		if network.AllowManualSignUp == "yes" {
-			node.IsPending = true
+			node.IsPending = "yes"
 		} else {
 		} else {
 			return nil, status.Errorf(
 			return nil, status.Errorf(
 				codes.Internal,
 				codes.Internal,
@@ -133,7 +133,7 @@ func (s *NodeServiceServer) CreateNode(ctx context.Context, req *nodepb.CreateNo
 			Interface:    node.Interface,
 			Interface:    node.Interface,
 			Nodenetwork:  node.Network,
 			Nodenetwork:  node.Network,
 			Dnsoff:       !servercfg.IsDNSMode(),
 			Dnsoff:       !servercfg.IsDNSMode(),
-			Ispending:    node.IsPending,
+			Ispending:    node.IsPending == "yes",
 			Publickey:    node.PublicKey,
 			Publickey:    node.PublicKey,
 			Listenport:   node.ListenPort,
 			Listenport:   node.ListenPort,
 			Keepalive:    node.PersistentKeepalive,
 			Keepalive:    node.PersistentKeepalive,
@@ -157,7 +157,7 @@ func (s *NodeServiceServer) CheckIn(ctx context.Context, req *nodepb.CheckInReq)
 	data := req.GetNode()
 	data := req.GetNode()
 	//postchanges := req.GetPostchanges()
 	//postchanges := req.GetPostchanges()
 	// Now we have to convert this into a NodeItem type to convert into BSON
 	// Now we have to convert this into a NodeItem type to convert into BSON
-	log.Println("checkin data:",data)
+	log.Println("checkin data:", data)
 	node := models.Node{
 	node := models.Node{
 		// ID:       primitive.NilObjectID,
 		// ID:       primitive.NilObjectID,
 		MacAddress:          data.GetMacaddress(),
 		MacAddress:          data.GetMacaddress(),
@@ -171,7 +171,7 @@ func (s *NodeServiceServer) CheckIn(ctx context.Context, req *nodepb.CheckInReq)
 		PersistentKeepalive: data.GetKeepalive(),
 		PersistentKeepalive: data.GetKeepalive(),
 		PublicKey:           data.GetPublickey(),
 		PublicKey:           data.GetPublickey(),
 		UDPHolePunch:        data.GetUdpholepunch(),
 		UDPHolePunch:        data.GetUdpholepunch(),
-		SaveConfig:        data.GetSaveconfig(),
+		SaveConfig:          data.GetSaveconfig(),
 	}
 	}
 
 
 	checkinresponse, err := NodeCheckIn(node, node.Network)
 	checkinresponse, err := NodeCheckIn(node, node.Network)
@@ -203,7 +203,7 @@ func (s *NodeServiceServer) CheckIn(ctx context.Context, req *nodepb.CheckInReq)
 func (s *NodeServiceServer) UpdateNode(ctx context.Context, req *nodepb.UpdateNodeReq) (*nodepb.UpdateNodeRes, error) {
 func (s *NodeServiceServer) UpdateNode(ctx context.Context, req *nodepb.UpdateNodeReq) (*nodepb.UpdateNodeRes, error) {
 	// Get the node data from the request
 	// Get the node data from the request
 	data := req.GetNode()
 	data := req.GetNode()
-	log.Println("DATA:",data)
+	log.Println("DATA:", data)
 	// Now we have to convert this into a NodeItem type to convert into BSON
 	// Now we have to convert this into a NodeItem type to convert into BSON
 	newnode := models.Node{
 	newnode := models.Node{
 		// ID:       primitive.NilObjectID,
 		// ID:       primitive.NilObjectID,
@@ -219,11 +219,10 @@ func (s *NodeServiceServer) UpdateNode(ctx context.Context, req *nodepb.UpdateNo
 		Interface:           data.GetInterface(),
 		Interface:           data.GetInterface(),
 		PostDown:            data.GetPostdown(),
 		PostDown:            data.GetPostdown(),
 		PostUp:              data.GetPostup(),
 		PostUp:              data.GetPostup(),
-		IsPending:           data.GetIspending(),
 		PublicKey:           data.GetPublickey(),
 		PublicKey:           data.GetPublickey(),
 		ListenPort:          data.GetListenport(),
 		ListenPort:          data.GetListenport(),
 		UDPHolePunch:        data.GetUdpholepunch(),
 		UDPHolePunch:        data.GetUdpholepunch(),
-		SaveConfig:        data.GetSaveconfig(),
+		SaveConfig:          data.GetSaveconfig(),
 	}
 	}
 
 
 	// Convert the Id string to a MongoDB ObjectId
 	// Convert the Id string to a MongoDB ObjectId
@@ -231,7 +230,7 @@ func (s *NodeServiceServer) UpdateNode(ctx context.Context, req *nodepb.UpdateNo
 	networkName := newnode.Network
 	networkName := newnode.Network
 	network, _ := functions.GetParentNetwork(networkName)
 	network, _ := functions.GetParentNetwork(networkName)
 
 
-	log.Println("NODE SAVECONFIG:",newnode.SaveConfig)
+	log.Println("NODE SAVECONFIG:", newnode.SaveConfig)
 	node, err := functions.GetNodeByMacAddress(networkName, macaddress)
 	node, err := functions.GetNodeByMacAddress(networkName, macaddress)
 	if err != nil {
 	if err != nil {
 		return nil, status.Errorf(
 		return nil, status.Errorf(
@@ -261,7 +260,7 @@ func (s *NodeServiceServer) UpdateNode(ctx context.Context, req *nodepb.UpdateNo
 			Postdown:     newnode.PostDown,
 			Postdown:     newnode.PostDown,
 			Postup:       newnode.PostUp,
 			Postup:       newnode.PostUp,
 			Nodenetwork:  newnode.Network,
 			Nodenetwork:  newnode.Network,
-			Ispending:    newnode.IsPending,
+			Ispending:    newnode.IsPending == "yes",
 			Publickey:    newnode.PublicKey,
 			Publickey:    newnode.PublicKey,
 			Dnsoff:       !servercfg.IsDNSMode(),
 			Dnsoff:       !servercfg.IsDNSMode(),
 			Listenport:   newnode.ListenPort,
 			Listenport:   newnode.ListenPort,

+ 7 - 7
controllers/nodeHttpController.go

@@ -83,7 +83,7 @@ func authenticate(response http.ResponseWriter, request *http.Request) {
 				if err := json.Unmarshal([]byte(value), &result); err != nil {
 				if err := json.Unmarshal([]byte(value), &result); err != nil {
 					continue
 					continue
 				}
 				}
-				if result.MacAddress == authRequest.MacAddress && !result.IsPending && result.Network == networkname {
+				if result.MacAddress == authRequest.MacAddress && result.IsPending != "yes" && result.Network == networkname {
 					break
 					break
 				}
 				}
 			}
 			}
@@ -476,7 +476,7 @@ func createNode(w http.ResponseWriter, r *http.Request) {
 		//Check to see if network will allow manual sign up
 		//Check to see if network will allow manual sign up
 		//may want to switch this up with the valid key check and avoid a DB call that way.
 		//may want to switch this up with the valid key check and avoid a DB call that way.
 		if network.AllowManualSignUp == "yes" {
 		if network.AllowManualSignUp == "yes" {
-			node.IsPending = true
+			node.IsPending = "yes"
 		} else {
 		} else {
 			errorResponse = models.ErrorResponse{
 			errorResponse = models.ErrorResponse{
 				Code: http.StatusUnauthorized, Message: "W1R3: Key invalid, or none provided.",
 				Code: http.StatusUnauthorized, Message: "W1R3: Key invalid, or none provided.",
@@ -517,7 +517,7 @@ func UncordonNode(network, macaddress string) (models.Node, error) {
 		return models.Node{}, err
 		return models.Node{}, err
 	}
 	}
 	node.SetLastModified()
 	node.SetLastModified()
-	node.IsPending = false
+	node.IsPending = "no"
 	data, err := json.Marshal(&node)
 	data, err := json.Marshal(&node)
 	if err != nil {
 	if err != nil {
 		return node, err
 		return node, err
@@ -561,7 +561,7 @@ func CreateEgressGateway(gateway models.EgressGatewayRequest) (models.Node, erro
 	if err != nil {
 	if err != nil {
 		return models.Node{}, err
 		return models.Node{}, err
 	}
 	}
-	node.IsEgressGateway = true
+	node.IsEgressGateway = "yes"
 	node.EgressGatewayRanges = gateway.Ranges
 	node.EgressGatewayRanges = gateway.Ranges
 	postUpCmd := "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT; iptables -t nat -A POSTROUTING -o " + gateway.Interface + " -j MASQUERADE"
 	postUpCmd := "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT; iptables -t nat -A POSTROUTING -o " + gateway.Interface + " -j MASQUERADE"
 	postDownCmd := "iptables -D FORWARD -i " + node.Interface + " -j ACCEPT; iptables -t nat -D POSTROUTING -o " + gateway.Interface + " -j MASQUERADE"
 	postDownCmd := "iptables -D FORWARD -i " + node.Interface + " -j ACCEPT; iptables -t nat -D POSTROUTING -o " + gateway.Interface + " -j MASQUERADE"
@@ -635,7 +635,7 @@ func DeleteEgressGateway(network, macaddress string) (models.Node, error) {
 		return models.Node{}, err
 		return models.Node{}, err
 	}
 	}
 
 
-	node.IsEgressGateway = false
+	node.IsEgressGateway = "no"
 	node.EgressGatewayRanges = []string{}
 	node.EgressGatewayRanges = []string{}
 	node.PostUp = ""
 	node.PostUp = ""
 	node.PostDown = ""
 	node.PostDown = ""
@@ -687,7 +687,7 @@ func CreateIngressGateway(netid string, macaddress string) (models.Node, error)
 		log.Println("Could not find network.")
 		log.Println("Could not find network.")
 		return models.Node{}, err
 		return models.Node{}, err
 	}
 	}
-	node.IsIngressGateway = true
+	node.IsIngressGateway = "yes"
 	node.IngressGatewayRange = network.AddressRange
 	node.IngressGatewayRange = network.AddressRange
 	postUpCmd := "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT; iptables -t nat -A POSTROUTING -o " + node.Interface + " -j MASQUERADE"
 	postUpCmd := "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT; iptables -t nat -A POSTROUTING -o " + node.Interface + " -j MASQUERADE"
 	postDownCmd := "iptables -D FORWARD -i " + node.Interface + " -j ACCEPT; iptables -t nat -D POSTROUTING -o " + node.Interface + " -j MASQUERADE"
 	postDownCmd := "iptables -D FORWARD -i " + node.Interface + " -j ACCEPT; iptables -t nat -D POSTROUTING -o " + node.Interface + " -j MASQUERADE"
@@ -740,7 +740,7 @@ func DeleteIngressGateway(network, macaddress string) (models.Node, error) {
 		return models.Node{}, err
 		return models.Node{}, err
 	}
 	}
 	node.LastModified = time.Now().Unix()
 	node.LastModified = time.Now().Unix()
-	node.IsIngressGateway = false
+	node.IsIngressGateway = "no"
 	key, err := functions.GetRecordKey(node.MacAddress, node.Network)
 	key, err := functions.GetRecordKey(node.MacAddress, node.Network)
 	if err != nil {
 	if err != nil {
 		return models.Node{}, err
 		return models.Node{}, err

+ 1 - 1
go.mod

@@ -4,7 +4,7 @@ go 1.15
 
 
 require (
 require (
 	github.com/aws/aws-sdk-go v1.34.28
 	github.com/aws/aws-sdk-go v1.34.28
-	github.com/davecgh/go-spew v1.1.1 // indirect
+	github.com/davecgh/go-spew v1.1.1
 	github.com/dgrijalva/jwt-go v3.2.0+incompatible
 	github.com/dgrijalva/jwt-go v3.2.0+incompatible
 	github.com/go-playground/validator/v10 v10.5.0
 	github.com/go-playground/validator/v10 v10.5.0
 	github.com/go-sql-driver/mysql v1.6.0 // indirect
 	github.com/go-sql-driver/mysql v1.6.0 // indirect

+ 147 - 6
models/node.go

@@ -3,13 +3,15 @@ package models
 import (
 import (
 	"encoding/json"
 	"encoding/json"
 	"errors"
 	"errors"
+	"log"
 	"math/rand"
 	"math/rand"
 	"net"
 	"net"
 	"strings"
 	"strings"
 	"time"
 	"time"
-	"log"
+
 	"github.com/go-playground/validator/v10"
 	"github.com/go-playground/validator/v10"
 	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/database"
+	"golang.org/x/crypto/bcrypt"
 )
 )
 
 
 const charset = "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
 const charset = "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
@@ -43,9 +45,9 @@ type Node struct {
 	CheckInInterval     int32    `json:"checkininterval" bson:"checkininterval"`
 	CheckInInterval     int32    `json:"checkininterval" bson:"checkininterval"`
 	Password            string   `json:"password" bson:"password" validate:"required,min=6"`
 	Password            string   `json:"password" bson:"password" validate:"required,min=6"`
 	Network             string   `json:"network" bson:"network" validate:"network_exists"`
 	Network             string   `json:"network" bson:"network" validate:"network_exists"`
-	IsPending           bool     `json:"ispending" bson:"ispending"`
-	IsEgressGateway     bool     `json:"isegressgateway" bson:"isegressgateway"`
-	IsIngressGateway    bool     `json:"isingressgateway" bson:"isingressgateway"`
+	IsPending           string   `json:"ispending" bson:"ispending"`
+	IsEgressGateway     string   `json:"isegressgateway" bson:"isegressgateway"`
+	IsIngressGateway    string   `json:"isingressgateway" bson:"isingressgateway"`
 	EgressGatewayRanges []string `json:"egressgatewayranges" bson:"egressgatewayranges"`
 	EgressGatewayRanges []string `json:"egressgatewayranges" bson:"egressgatewayranges"`
 	IngressGatewayRange string   `json:"ingressgatewayrange" bson:"ingressgatewayrange"`
 	IngressGatewayRange string   `json:"ingressgatewayrange" bson:"ingressgatewayrange"`
 	PostChanges         string   `json:"postchanges" bson:"postchanges"`
 	PostChanges         string   `json:"postchanges" bson:"postchanges"`
@@ -148,13 +150,126 @@ func (node *Node) SetDefaults() {
 	node.KeyUpdateTimeStamp = time.Now().Unix()
 	node.KeyUpdateTimeStamp = time.Now().Unix()
 }
 }
 
 
+func (newNode *Node) Fill(currentNode *Node) {
+	if newNode.ID == "" {
+		newNode.ID = currentNode.ID
+	}
+	if newNode.Address == "" {
+		newNode.Address = currentNode.Address
+	}
+	if newNode.Address6 == "" {
+		newNode.Address6 = currentNode.Address6
+	}
+	if newNode.LocalAddress == "" {
+		newNode.LocalAddress = currentNode.LocalAddress
+	}
+	if newNode.Name == "" {
+		newNode.Name = currentNode.Name
+	}
+	if newNode.ListenPort == 0 {
+		newNode.ListenPort = currentNode.ListenPort
+	}
+	if newNode.PublicKey == "" {
+		newNode.PublicKey = currentNode.PublicKey
+	}
+	if newNode.Endpoint == "" {
+		newNode.Endpoint = currentNode.Endpoint
+	}
+	if newNode.PostUp == "" {
+		newNode.PostUp = currentNode.PostUp
+	}
+	if newNode.PostDown == "" {
+		newNode.PostDown = currentNode.PostDown
+	}
+	if newNode.AllowedIPs == nil {
+		newNode.AllowedIPs = currentNode.AllowedIPs
+	}
+	if newNode.PersistentKeepalive == 0 {
+		newNode.PersistentKeepalive = currentNode.PersistentKeepalive
+	}
+	if newNode.SaveConfig == "" {
+		newNode.SaveConfig = currentNode.SaveConfig
+	}
+	if newNode.AccessKey == "" {
+		newNode.AccessKey = currentNode.AccessKey
+	}
+	if newNode.Interface == "" {
+		newNode.Interface = currentNode.Interface
+	}
+	if newNode.LastModified == 0 {
+		newNode.LastModified = currentNode.LastModified
+	}
+	if newNode.KeyUpdateTimeStamp == 0 {
+		newNode.LastModified = currentNode.LastModified
+	}
+	if newNode.ExpirationDateTime == 0 {
+		newNode.ExpirationDateTime = currentNode.ExpirationDateTime
+	}
+	if newNode.LastPeerUpdate == 0 {
+		newNode.LastPeerUpdate = currentNode.LastPeerUpdate
+	}
+	if newNode.LastCheckIn == 0 {
+		newNode.LastCheckIn = currentNode.LastCheckIn
+	}
+	if newNode.MacAddress == "" {
+		newNode.MacAddress = currentNode.MacAddress
+	}
+	if newNode.CheckInInterval == 0 {
+		newNode.CheckInInterval = currentNode.CheckInInterval
+	}
+	if newNode.Password != "" {
+		err := bcrypt.CompareHashAndPassword([]byte(newNode.Password), []byte(currentNode.Password))
+		if err != nil && currentNode.Password != newNode.Password {
+			hash, err := bcrypt.GenerateFromPassword([]byte(newNode.Password), 5)
+			if err == nil {
+				newNode.Password = string(hash)
+			}
+		}
+	} else {
+		newNode.Password = currentNode.Password
+	}
+	if newNode.Network == "" {
+		newNode.Network = currentNode.Network
+	}
+	if newNode.IsPending == "" {
+		newNode.IsPending = currentNode.IsPending
+	}
+	if newNode.IsEgressGateway == "" {
+		newNode.IsEgressGateway = currentNode.IsEgressGateway
+	}
+	if newNode.IsIngressGateway == "" {
+		newNode.IsIngressGateway = currentNode.IsIngressGateway
+	}
+	if newNode.EgressGatewayRanges == nil {
+		newNode.EgressGatewayRanges = currentNode.EgressGatewayRanges
+	}
+	if newNode.IngressGatewayRange == "" {
+		newNode.IngressGatewayRange = currentNode.IngressGatewayRange
+	}
+	if newNode.StaticIP == "" {
+		newNode.StaticIP = currentNode.StaticIP
+	}
+	if newNode.StaticIP == "" {
+		newNode.StaticIP = currentNode.StaticIP
+	}
+	if newNode.StaticPubKey == "" {
+		newNode.StaticPubKey = currentNode.StaticPubKey
+	}
+	if newNode.UDPHolePunch == "" {
+		newNode.UDPHolePunch = currentNode.SaveConfig
+	}
+
+	newNode.PostChanges = "no"
+}
+
 func (currentNode *Node) Update(newNode *Node) error {
 func (currentNode *Node) Update(newNode *Node) error {
-	log.Println("Node SaveConfig:",newNode.SaveConfig)
+	log.Println("Node SaveConfig:", newNode.SaveConfig)
 	if err := newNode.Validate(true); err != nil {
 	if err := newNode.Validate(true); err != nil {
 		return err
 		return err
 	}
 	}
 	newNode.SetID()
 	newNode.SetID()
 	if newNode.ID == currentNode.ID {
 	if newNode.ID == currentNode.ID {
+		newNode.Fill(currentNode)
 		if data, err := json.Marshal(newNode); err != nil {
 		if data, err := json.Marshal(newNode); err != nil {
 			return err
 			return err
 		} else {
 		} else {
@@ -183,7 +298,7 @@ func IsIpv4Net(host string) bool {
 }
 }
 
 
 func (node *Node) Validate(isUpdate bool) error {
 func (node *Node) Validate(isUpdate bool) error {
-	log.Println("Node SaveConfig:",node.SaveConfig)
+	log.Println("Node SaveConfig:", node.SaveConfig)
 	v := validator.New()
 	v := validator.New()
 	_ = v.RegisterValidation("macaddress_unique", func(fl validator.FieldLevel) bool {
 	_ = v.RegisterValidation("macaddress_unique", func(fl validator.FieldLevel) bool {
 		if isUpdate {
 		if isUpdate {
@@ -247,3 +362,29 @@ func GetAllNodes() ([]Node, error) {
 
 
 	return nodes, nil
 	return nodes, nil
 }
 }
+
+func GetNode(macaddress string, network string) (Node, error) {
+
+	var node Node
+
+	key, err := GetID(macaddress, network)
+	if err != nil {
+		return node, err
+	}
+	data, err := database.FetchRecord(database.NODES_TABLE_NAME, key)
+	if err != nil {
+		return node, err
+	}
+	if err = json.Unmarshal([]byte(data), &node); err != nil {
+		return node, err
+	}
+
+	return node, err
+}
+
+func GetID(macaddress string, network string) (string, error) {
+	if macaddress == "" || network == "" {
+		return "", errors.New("unable to get record key")
+	}
+	return macaddress + "###" + network, nil
+}