netmaker/controllers/nodeGrpcController.go
2021-08-05 23:38:34 -04:00

201 lines
5.5 KiB
Go

package controller
import (
"context"
"encoding/json"
"errors"
"log"
"strings"
"github.com/gravitl/netmaker/functions"
nodepb "github.com/gravitl/netmaker/grpc"
"github.com/gravitl/netmaker/models"
)
type NodeServiceServer struct {
nodepb.UnimplementedNodeServiceServer
}
func (s *NodeServiceServer) ReadNode(ctx context.Context, req *nodepb.Object) (*nodepb.Object, error) {
// convert string id (from proto) to mongoDB ObjectId
macAndNetwork := strings.Split(req.Data, "###")
if len(macAndNetwork) != 2 {
return nil, errors.New("could not read node, invalid node id given")
}
node, err := GetNode(macAndNetwork[0], macAndNetwork[1])
if err != nil {
log.Println("could not get node "+macAndNetwork[0]+" "+macAndNetwork[1], err)
return nil, err
}
node.SetLastCheckIn()
// Cast to ReadNodeRes type
nodeData, err := json.Marshal(&node)
if err != nil {
return nil, err
}
node.Update(&node)
response := &nodepb.Object{
Data: string(nodeData),
Type: nodepb.NODE_TYPE,
}
return response, nil
}
func (s *NodeServiceServer) CreateNode(ctx context.Context, req *nodepb.Object) (*nodepb.Object, error) {
// Get the protobuf node type from the protobuf request type
// Essentially doing req.Node to access the struct with a nil check
var node models.Node
data := req.GetData()
if err := json.Unmarshal([]byte(data), &node); err != nil {
return nil, err
}
//Check to see if key is valid
//TODO: Triple inefficient!!! This is the third call to the DB we make for networks
validKey := functions.IsKeyValid(node.Network, node.AccessKey)
network, err := functions.GetParentNetwork(node.Network)
if err != nil {
return nil, err
}
if !validKey {
//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.
if network.AllowManualSignUp == "yes" {
node.IsPending = "yes"
} else {
return nil, errors.New("invalid key, and network does not allow no-key signups")
}
}
node, err = CreateNode(node, node.Network)
if err != nil {
log.Println("could not create node on network " + node.Network + " (gRPC controller)")
return nil, err
}
nodeData, err := json.Marshal(&node)
// return the node in a CreateNodeRes type
response := &nodepb.Object{
Data: string(nodeData),
Type: nodepb.NODE_TYPE,
}
err = SetNetworkNodesLastModified(node.Network)
if err != nil {
return nil, err
}
return response, nil
}
func (s *NodeServiceServer) UpdateNode(ctx context.Context, req *nodepb.Object) (*nodepb.Object, error) {
// Get the node data from the request
var newnode models.Node
if err := json.Unmarshal([]byte(req.GetData()), &newnode); err != nil {
return nil, err
}
macaddress := newnode.MacAddress
networkName := newnode.Network
node, err := functions.GetNodeByMacAddress(networkName, macaddress)
if err != nil {
return nil, err
}
err = node.Update(&newnode)
if err != nil {
return nil, err
}
nodeData, err := json.Marshal(&newnode)
if err != nil {
return nil, err
}
return &nodepb.Object{
Data: string(nodeData),
Type: nodepb.NODE_TYPE,
}, nil
}
func (s *NodeServiceServer) DeleteNode(ctx context.Context, req *nodepb.Object) (*nodepb.Object, error) {
nodeID := req.GetData()
err := DeleteNode(nodeID, true)
if err != nil {
log.Println("Error deleting node (gRPC controller).")
return nil, err
}
return &nodepb.Object{
Data: "success",
Type: nodepb.STRING_TYPE,
}, nil
}
func (s *NodeServiceServer) GetPeers(ctx context.Context, req *nodepb.Object) (*nodepb.Object, error) {
macAndNetwork := strings.Split(req.Data, "###")
if len(macAndNetwork) == 2 {
// TODO: Make constant and new variable for isServer
node, err := GetNode(macAndNetwork[0], macAndNetwork[1])
if err != nil {
return nil, err
}
if node.Name == "netmaker" {
SetNetworkServerPeers(macAndNetwork[1])
}
peers, err := GetPeersList(macAndNetwork[1])
if err != nil {
return nil, err
}
peersData, err := json.Marshal(&peers)
return &nodepb.Object{
Data: string(peersData),
Type: nodepb.NODE_TYPE,
}, err
}
return &nodepb.Object{
Data: "",
Type: nodepb.NODE_TYPE,
}, errors.New("could not fetch peers, invalid node id")
}
/**
* Return Ext Peers (clients).NodeCheckIn
* When a gateway node checks in, it pulls these peers to add to peers list in addition to normal network peers.
*/
func (s *NodeServiceServer) GetExtPeers(ctx context.Context, req *nodepb.Object) (*nodepb.Object, error) {
// Initiate a NodeItem type to write decoded data to
//data := &models.PeersResponse{}
// collection.Find returns a cursor for our (empty) query
macAndNetwork := strings.Split(req.Data, "###")
if len(macAndNetwork) != 2 {
return nil, errors.New("did not receive valid node id when fetching ext peers")
}
peers, err := GetExtPeersList(macAndNetwork[0], macAndNetwork[1])
if err != nil {
return nil, err
}
// cursor.Next() returns a boolean, if false there are no more items and loop will break
var extPeers []models.Node
for i := 0; i < len(peers); i++ {
extPeers = append(extPeers, models.Node{
Address: peers[i].Address,
Address6: peers[i].Address6,
Endpoint: peers[i].Endpoint,
PublicKey: peers[i].PublicKey,
PersistentKeepalive: peers[i].KeepAlive,
ListenPort: peers[i].ListenPort,
LocalAddress: peers[i].LocalAddress,
})
}
extData, err := json.Marshal(&extPeers)
if err != nil {
return nil, err
}
return &nodepb.Object{
Data: string(extData),
Type: nodepb.EXT_PEER,
}, nil
}