diff --git a/cmd/api/main.go b/cmd/api/main.go index b4e757d..76fcab1 100644 --- a/cmd/api/main.go +++ b/cmd/api/main.go @@ -13,5 +13,5 @@ func main() { log.Fatal(err.Error()) } - apiServer.Run(":8080") + apiServer.Run(":40000") } diff --git a/cmd/wg-mesh/main.go b/cmd/wg-mesh/main.go index 2eab14b..dbd58e2 100644 --- a/cmd/wg-mesh/main.go +++ b/cmd/wg-mesh/main.go @@ -185,6 +185,37 @@ func putAlias(client *ipcRpc.Client, alias string) { fmt.Println(reply) } +func setService(client *ipcRpc.Client, service, value string) { + var reply string + + serviceArgs := &ipc.PutServiceArgs{ + Service: service, + Value: value, + } + + err := client.Call("IpcHandler.PutService", serviceArgs, &reply) + + if err != nil { + fmt.Println(err.Error()) + return + } + + fmt.Println(reply) +} + +func deleteService(client *ipcRpc.Client, service string) { + var reply string + + err := client.Call("IpcHandler.PutService", &service, &reply) + + if err != nil { + fmt.Println(err.Error()) + return + } + + fmt.Println(reply) +} + func main() { parser := argparse.NewParser("wg-mesh", "wg-mesh Manipulate WireGuard meshes") @@ -199,6 +230,8 @@ func main() { queryMeshCmd := parser.NewCommand("query-mesh", "Query a mesh network using JMESPath") putDescriptionCmd := parser.NewCommand("put-description", "Place a description for the node") putAliasCmd := parser.NewCommand("put-alias", "Place an alias for the node") + setServiceCmd := parser.NewCommand("set-service", "Place a service into your advertisements") + deleteServiceCmd := parser.NewCommand("delete-service", "Remove a service from your advertisements") var newMeshIfName *string = newMeshCmd.String("f", "ifname", &argparse.Options{Required: true}) var newMeshPort *int = newMeshCmd.Int("p", "wgport", &argparse.Options{Required: true}) @@ -210,8 +243,6 @@ func main() { var joinMeshPort *int = joinMeshCmd.Int("p", "wgport", &argparse.Options{Required: true}) var joinMeshEndpoint *string = joinMeshCmd.String("e", "endpoint", &argparse.Options{}) - // var getMeshId *string = getMeshCmd.String("m", "mesh", &argparse.Options{Required: true}) - var enableInterfaceMeshId *string = enableInterfaceCmd.String("m", "mesh", &argparse.Options{Required: true}) var getGraphMeshId *string = getGraphCmd.String("m", "mesh", &argparse.Options{Required: true}) @@ -225,6 +256,11 @@ func main() { var alias *string = putAliasCmd.String("a", "alias", &argparse.Options{Required: true}) + var serviceKey *string = setServiceCmd.String("s", "service", &argparse.Options{Required: true}) + var serviceValue *string = setServiceCmd.String("v", "value", &argparse.Options{Required: true}) + + var deleteServiceKey *string = deleteServiceCmd.String("s", "service", &argparse.Options{Required: true}) + err := parser.Parse(os.Args) if err != nil { @@ -285,4 +321,12 @@ func main() { if putAliasCmd.Happened() { putAlias(client, *alias) } + + if setServiceCmd.Happened() { + setService(client, *serviceKey, *serviceValue) + } + + if deleteServiceCmd.Happened() { + deleteService(client, *deleteServiceKey) + } } diff --git a/pkg/api/apiserver.go b/pkg/api/apiserver.go index bf074b4..f5ee232 100644 --- a/pkg/api/apiserver.go +++ b/pkg/api/apiserver.go @@ -37,6 +37,8 @@ func meshNodeToAPIMeshNode(meshNode ctrlserver.MeshNode) *SmegNode { Description: meshNode.Description, Routes: meshNode.Routes, PublicKey: meshNode.PublicKey, + Alias: meshNode.Alias, + Services: meshNode.Services, } } diff --git a/pkg/api/types.go b/pkg/api/types.go index b99aa4a..5429fed 100644 --- a/pkg/api/types.go +++ b/pkg/api/types.go @@ -1,13 +1,15 @@ package api type SmegNode struct { - WgHost string `json:"wgHost"` - WgEndpoint string `json:"wgEndpoint"` - Endpoint string `json:"endpoint"` - Timestamp int `json:"timestamp"` - Description string `json:"description"` - PublicKey string `json:"publicKey"` - Routes []string `json:"routes"` + Alias string `json:"alias"` + WgHost string `json:"wgHost"` + WgEndpoint string `json:"wgEndpoint"` + Endpoint string `json:"endpoint"` + Timestamp int `json:"timestamp"` + Description string `json:"description"` + PublicKey string `json:"publicKey"` + Routes []string `json:"routes"` + Services map[string]string `json:"services"` } type SmegMesh struct { diff --git a/pkg/automerge/automerge.go b/pkg/automerge/automerge.go index f6ee57d..8406d6a 100644 --- a/pkg/automerge/automerge.go +++ b/pkg/automerge/automerge.go @@ -20,7 +20,6 @@ import ( type CrdtMeshManager struct { MeshId string IfName string - NodeId string Client *wgctrl.Client doc *automerge.Doc LastHash automerge.ChangeHash @@ -35,8 +34,9 @@ func (c *CrdtMeshManager) AddNode(node mesh.MeshNode) { } crdt.Routes = make(map[string]interface{}) - + crdt.Services = make(map[string]string) crdt.Timestamp = time.Now().Unix() + c.doc.Path("nodes").Map().Set(crdt.HostEndpoint, crdt) } @@ -198,6 +198,52 @@ func (m *CrdtMeshManager) SetAlias(nodeId string, alias string) error { return err } +func (m *CrdtMeshManager) AddService(nodeId, key, value string) error { + node, err := m.doc.Path("nodes").Map().Get(nodeId) + + if err != nil || node.Kind() != automerge.KindMap { + return fmt.Errorf("AddService: node %s does not exist", nodeId) + } + + service, err := node.Map().Get("services") + + if err != nil { + return err + } + + if service.Kind() != automerge.KindMap { + return fmt.Errorf("AddService: services property does not exist in node") + } + + return service.Map().Set(key, value) +} + +func (m *CrdtMeshManager) RemoveService(nodeId, key string) error { + node, err := m.doc.Path("nodes").Map().Get(nodeId) + + if err != nil || node.Kind() != automerge.KindMap { + return fmt.Errorf("RemoveService: node %s does not exist", nodeId) + } + + service, err := node.Map().Get("services") + + if err != nil { + return err + } + + if service.Kind() != automerge.KindMap { + return fmt.Errorf("services property does not exist") + } + + err = service.Map().Delete(key) + + if err != nil { + return fmt.Errorf("service %s does not exist", key) + } + + return nil +} + // AddRoutes: adds routes to the specific nodeId func (m *CrdtMeshManager) AddRoutes(nodeId string, routes ...string) error { nodeVal, err := m.doc.Path("nodes").Map().Get(nodeId) @@ -360,6 +406,16 @@ func (m *MeshNodeCrdt) GetAlias() string { return m.Alias } +func (m *MeshNodeCrdt) GetServices() map[string]string { + services := make(map[string]string) + + for key, service := range m.Services { + services[key] = service + } + + return services +} + func (m *MeshCrdt) GetNodes() map[string]mesh.MeshNode { nodes := make(map[string]mesh.MeshNode) @@ -373,6 +429,7 @@ func (m *MeshCrdt) GetNodes() map[string]mesh.MeshNode { Routes: node.Routes, Description: node.Description, Alias: node.Alias, + Services: node.GetServices(), } } diff --git a/pkg/automerge/types.go b/pkg/automerge/types.go index 01b6b69..2888b50 100644 --- a/pkg/automerge/types.go +++ b/pkg/automerge/types.go @@ -10,6 +10,7 @@ type MeshNodeCrdt struct { Routes map[string]interface{} `automerge:"routes"` Alias string `automerge:"alias"` Description string `automerge:"description"` + Services map[string]string `automerge:"services"` } // MeshCrdt: Represents the mesh network as a whole diff --git a/pkg/ctrlserver/ctrltypes.go b/pkg/ctrlserver/ctrltypes.go index 6f290db..4215ad4 100644 --- a/pkg/ctrlserver/ctrltypes.go +++ b/pkg/ctrlserver/ctrltypes.go @@ -18,6 +18,8 @@ type MeshNode struct { Timestamp int64 Routes []string Description string + Alias string + Services map[string]string } // Represents a WireGuard Mesh diff --git a/pkg/hosts/hosts.go b/pkg/hosts/hosts.go index 735b91c..259baf6 100644 --- a/pkg/hosts/hosts.go +++ b/pkg/hosts/hosts.go @@ -17,34 +17,55 @@ const HOSTS_FILE = "/etc/hosts" const DOMAIN_HEADER = "#WG AUTO GENERATED HOSTS" const DOMAIN_TRAILER = "#WG AUTO GENERATED HOSTS END" +type HostsEntry struct { + Alias string + Ip net.IP +} + // Generic interface to manipulate /etc/hosts file type HostsManipulator interface { // AddrAddr associates an aliasd with a given IP address - AddAddr(ipAddr net.IP, alias string) + AddAddr(hosts ...HostsEntry) // Remove deletes the entry from /etc/hosts - Remove(alias string) + Remove(hosts ...HostsEntry) // Writes the changes to /etc/hosts file Write() error } type HostsManipulatorImpl struct { - hosts map[string]net.IP - meshid string + hosts map[string]HostsEntry } // AddAddr implements HostsManipulator. -func (m *HostsManipulatorImpl) AddAddr(ipAddr net.IP, alias string) { - m.hosts[alias] = ipAddr +func (m *HostsManipulatorImpl) AddAddr(hosts ...HostsEntry) { + changed := false + + for _, host := range hosts { + prev, ok := m.hosts[host.Ip.String()] + + if !ok || prev.Alias != host.Alias { + changed = true + } + + m.hosts[host.Ip.String()] = host + } + + if changed { + m.Write() + } } // Remove implements HostsManipulator. -func (m *HostsManipulatorImpl) Remove(alias string) { - delete(m.hosts, alias) -} +func (m *HostsManipulatorImpl) Remove(hosts ...HostsEntry) { + lenBefore := len(m.hosts) -type HostsEntry struct { - Alias string - Ip net.IP + for _, host := range hosts { + delete(m.hosts, host.Alias) + } + + if lenBefore != len(m.hosts) { + m.Write() + } } func (m *HostsManipulatorImpl) removeHosts() string { @@ -69,7 +90,7 @@ func (m *HostsManipulatorImpl) removeHosts() string { return "" } - if !hostsSection && strings.Contains(line, DOMAIN_HEADER+m.meshid) { + if !hostsSection && strings.Contains(line, DOMAIN_HEADER) { hostsSection = true } @@ -77,7 +98,7 @@ func (m *HostsManipulatorImpl) removeHosts() string { contents.WriteString(line + "\n") } - if hostsSection && strings.Contains(line, DOMAIN_TRAILER+m.meshid) { + if hostsSection && strings.Contains(line, DOMAIN_TRAILER) { hostsSection = false } } @@ -96,36 +117,16 @@ func (m *HostsManipulatorImpl) Write() error { var nextHosts strings.Builder nextHosts.WriteString(contents) - nextHosts.WriteString(DOMAIN_HEADER + m.meshid + "\n") + nextHosts.WriteString(DOMAIN_HEADER + "\n") - for alias, ip := range m.hosts { - nextHosts.WriteString(fmt.Sprintf("%s\t%s\n", ip.String(), alias)) + for _, host := range m.hosts { + nextHosts.WriteString(fmt.Sprintf("%s\t%s\n", host.Ip.String(), host.Alias)) } - nextHosts.WriteString(DOMAIN_TRAILER + m.meshid + "\n") + nextHosts.WriteString(DOMAIN_TRAILER + "\n") return os.WriteFile(HOSTS_FILE, []byte(nextHosts.String()), 0644) } -// parseLine parses a line in the /etc/hosts file -func parseLine(line string) (*HostsEntry, error) { - fields := strings.Fields(line) - - if len(fields) != 2 { - return nil, fmt.Errorf("expected entry length of 2 was %d", len(fields)) - } - - ipAddr := fields[0] - alias := fields[1] - - ip := net.ParseIP(ipAddr) - - if ip == nil { - return nil, fmt.Errorf("failed to parse ip for %s", alias) - } - - return &HostsEntry{Ip: ip, Alias: alias}, nil -} - -func NewHostsManipulator(meshId string) HostsManipulator { - return &HostsManipulatorImpl{hosts: make(map[string]net.IP), meshid: meshId} +func NewHostsManipulator() HostsManipulator { + return &HostsManipulatorImpl{hosts: make(map[string]HostsEntry)} } diff --git a/pkg/ipc/ipc.go b/pkg/ipc/ipc.go index 54d6b0f..8115a3c 100644 --- a/pkg/ipc/ipc.go +++ b/pkg/ipc/ipc.go @@ -34,6 +34,11 @@ type JoinMeshArgs struct { Endpoint string } +type PutServiceArgs struct { + Service string + Value string +} + type GetMeshReply struct { Nodes []ctrlserver.MeshNode } @@ -58,6 +63,8 @@ type MeshIpc interface { Query(query QueryMesh, reply *string) error PutDescription(description string, reply *string) error PutAlias(alias string, reply *string) error + PutService(args PutServiceArgs, reply *string) error + DeleteService(service string, reply *string) error } const SockAddr = "/tmp/wgmesh_ipc.sock" diff --git a/pkg/mesh/alias.go b/pkg/mesh/alias.go index f54324d..5227597 100644 --- a/pkg/mesh/alias.go +++ b/pkg/mesh/alias.go @@ -1,15 +1,46 @@ package mesh -import "github.com/tim-beatham/wgmesh/pkg/hosts" +import ( + "fmt" -func AddAliases(meshid string, snapshot MeshSnapshot) { - hosts := hosts.NewHostsManipulator(meshid) + "github.com/tim-beatham/wgmesh/pkg/hosts" +) - for _, node := range snapshot.GetNodes() { +type MeshAliasManager interface { + AddAliases(nodes []MeshNode) + RemoveAliases(node []MeshNode) +} + +type AliasManager struct { + hosts hosts.HostsManipulator +} + +// AddAliases: on node update or change add aliases to the hosts file +func (a *AliasManager) AddAliases(nodes []MeshNode) { + for _, node := range nodes { if node.GetAlias() != "" { - hosts.AddAddr(node.GetWgHost().IP, node.GetAlias()) + a.hosts.AddAddr(hosts.HostsEntry{ + Alias: fmt.Sprintf("%s.smeg", node.GetAlias()), + Ip: node.GetWgHost().IP, + }) } } - - hosts.Write() +} + +// RemoveAliases: on node remove remove aliases from the hosts file +func (a *AliasManager) RemoveAliases(nodes []MeshNode) { + for _, node := range nodes { + if node.GetAlias() != "" { + a.hosts.Remove(hosts.HostsEntry{ + Alias: fmt.Sprintf("%s.smeg", node.GetAlias()), + Ip: node.GetWgHost().IP, + }) + } + } +} + +func NewAliasManager() MeshAliasManager { + return &AliasManager{ + hosts: hosts.NewHostsManipulator(), + } } diff --git a/pkg/mesh/manager.go b/pkg/mesh/manager.go index d0ae9a7..5dc86c3 100644 --- a/pkg/mesh/manager.go +++ b/pkg/mesh/manager.go @@ -26,6 +26,8 @@ type MeshManager interface { ApplyConfig() error SetDescription(description string) error SetAlias(alias string) error + SetService(service string, value string) error + RemoveService(service string) error UpdateTimeStamp() error GetClient() *wgctrl.Client GetMeshes() map[string]MeshProvider @@ -51,6 +53,32 @@ type MeshManagerImpl struct { Monitor MeshMonitor } +// RemoveService implements MeshManager. +func (m *MeshManagerImpl) RemoveService(service string) error { + for _, mesh := range m.Meshes { + err := mesh.RemoveService(m.HostParameters.HostEndpoint, service) + + if err != nil { + return err + } + } + + return nil +} + +// SetService implements MeshManager. +func (m *MeshManagerImpl) SetService(service string, value string) error { + for _, mesh := range m.Meshes { + err := mesh.AddService(m.HostParameters.HostEndpoint, service, value) + + if err != nil { + return err + } + } + + return nil +} + // GetMonitor implements MeshManager. func (m *MeshManagerImpl) GetMonitor() MeshMonitor { return m.Monitor @@ -411,7 +439,10 @@ func NewMeshManager(params *NewMeshManagerParams) MeshManager { m.ipAllocator = params.IPAllocator m.interfaceManipulator = params.InterfaceManipulator - m.Monitor = NewMeshMonitor() - m.Monitor.AddCallback(AddAliases) + m.Monitor = NewMeshMonitor(m) + + aliasManager := NewAliasManager() + m.Monitor.AddUpdateCallback(aliasManager.AddAliases) + m.Monitor.AddRemoveCallback(aliasManager.RemoveAliases) return m } diff --git a/pkg/mesh/monitor.go b/pkg/mesh/monitor.go index a0a098c..62946b3 100644 --- a/pkg/mesh/monitor.go +++ b/pkg/mesh/monitor.go @@ -1,28 +1,81 @@ package mesh -type OnChange = func(string, MeshSnapshot) +type OnChange = func([]MeshNode) type MeshMonitor interface { - AddCallback(cb OnChange) - Trigger(meshid string, m MeshSnapshot) + AddUpdateCallback(cb OnChange) + AddRemoveCallback(cb OnChange) + Trigger() error } type MeshMonitorImpl struct { - callbacks []OnChange + updateCbs []OnChange + removeCbs []OnChange + nodes map[string]MeshNode + manager MeshManager } -func (m *MeshMonitorImpl) Trigger(meshid string, snapshot MeshSnapshot) { - for _, cb := range m.callbacks { - cb(meshid, snapshot) +// Trigger causes the mesh monitor to trigger all of +// the callbacks. +func (m *MeshMonitorImpl) Trigger() error { + changedNodes := make([]MeshNode, 0) + removedNodes := make([]MeshNode, 0) + + nodes := make(map[string]MeshNode) + + for _, mesh := range m.manager.GetMeshes() { + snapshot, err := mesh.GetMesh() + + if err != nil { + return err + } + + for _, node := range snapshot.GetNodes() { + previous, exists := m.nodes[node.GetWgHost().String()] + + if !exists || !NodeEquals(previous, node) { + changedNodes = append(changedNodes, node) + } + + nodes[node.GetWgHost().String()] = node + } } + + for _, previous := range m.nodes { + _, ok := nodes[previous.GetWgHost().String()] + + if !ok { + removedNodes = append(removedNodes, previous) + } + } + + if len(removedNodes) > 0 { + for _, cb := range m.removeCbs { + cb(removedNodes) + } + } + + if len(changedNodes) > 0 { + for _, cb := range m.updateCbs { + cb(changedNodes) + } + } + + return nil } -func (m *MeshMonitorImpl) AddCallback(cb OnChange) { - m.callbacks = append(m.callbacks, cb) +func (m *MeshMonitorImpl) AddUpdateCallback(cb OnChange) { + m.updateCbs = append(m.updateCbs, cb) } -func NewMeshMonitor() MeshMonitor { +func (m *MeshMonitorImpl) AddRemoveCallback(cb OnChange) { + m.removeCbs = append(m.removeCbs, cb) +} + +func NewMeshMonitor(manager MeshManager) MeshMonitor { return &MeshMonitorImpl{ - callbacks: make([]OnChange, 0), + updateCbs: make([]OnChange, 0), + nodes: make(map[string]MeshNode), + manager: manager, } } diff --git a/pkg/mesh/stub_types.go b/pkg/mesh/stub_types.go index 49b3900..74fe859 100644 --- a/pkg/mesh/stub_types.go +++ b/pkg/mesh/stub_types.go @@ -21,9 +21,14 @@ type MeshNodeStub struct { description string } +// GetServices implements MeshNode. +func (*MeshNodeStub) GetServices() map[string]string { + return make(map[string]string) +} + // GetAlias implements MeshNode. func (*MeshNodeStub) GetAlias() string { - panic("unimplemented") + return "" } func (m *MeshNodeStub) GetHostEndpoint() string { @@ -71,6 +76,16 @@ type MeshProviderStub struct { snapshot *MeshSnapshotStub } +// AddService implements MeshProvider. +func (*MeshProviderStub) AddService(nodeId string, key string, value string) error { + panic("unimplemented") +} + +// RemoveService implements MeshProvider. +func (*MeshProviderStub) RemoveService(nodeId string, key string) error { + panic("unimplemented") +} + // SetAlias implements MeshProvider. func (*MeshProviderStub) SetAlias(nodeId string, alias string) error { panic("unimplemented") @@ -181,6 +196,16 @@ type MeshManagerStub struct { meshes map[string]MeshProvider } +// RemoveService implements MeshManager. +func (*MeshManagerStub) RemoveService(service string) error { + panic("unimplemented") +} + +// SetService implements MeshManager. +func (*MeshManagerStub) SetService(service string, value string) error { + panic("unimplemented") +} + // GetMonitor implements MeshManager. func (*MeshManagerStub) GetMonitor() MeshMonitor { panic("unimplemented") diff --git a/pkg/mesh/types.go b/pkg/mesh/types.go index 6ab174d..8013c7a 100644 --- a/pkg/mesh/types.go +++ b/pkg/mesh/types.go @@ -4,6 +4,7 @@ package mesh import ( "net" + "slices" "github.com/tim-beatham/wgmesh/pkg/conf" "golang.zx2c4.com/wireguard/wgctrl" @@ -31,6 +32,48 @@ type MeshNode interface { // GetAlias: associates the node with an alias. Potentially used // for DNS and so forth. GetAlias() string + // GetServices: returns a list of services offered by the node + GetServices() map[string]string +} + +// NodeEquals: determines if two mesh nodes are equivalent to one another +func NodeEquals(node1, node2 MeshNode) bool { + if node1.GetHostEndpoint() != node2.GetHostEndpoint() { + return false + } + + node1Pub, _ := node1.GetPublicKey() + node2Pub, _ := node2.GetPublicKey() + + if node1Pub != node2Pub { + return false + } + + if node1.GetWgEndpoint() != node2.GetWgEndpoint() { + return false + } + + if node1.GetWgHost() != node2.GetWgHost() { + return false + } + + if !slices.Equal(node1.GetRoutes(), node2.GetRoutes()) { + return false + } + + if node1.GetIdentifier() != node2.GetIdentifier() { + return false + } + + if node1.GetDescription() != node2.GetDescription() { + return false + } + + if node1.GetAlias() != node2.GetAlias() { + return false + } + + return true } type MeshSnapshot interface { @@ -75,6 +118,10 @@ type MeshProvider interface { SetDescription(nodeId string, description string) error // SetAlias: set the alias of the nodeId SetAlias(nodeId string, alias string) error + // AddService: adds the service to the given node + AddService(nodeId, key, value string) error + // RemoveService: removes the service form the node. throws an error if the service does not exist + RemoveService(nodeId, key string) error // Prune: prunes all nodes that have not updated their timestamp in // pruneAmount seconds Prune(pruneAmount int) error diff --git a/pkg/query/query.go b/pkg/query/query.go index 16bdc00..5f06d96 100644 --- a/pkg/query/query.go +++ b/pkg/query/query.go @@ -24,14 +24,15 @@ type QueryError struct { } type QueryNode struct { - HostEndpoint string `json:"hostEndpoint"` - PublicKey string `json:"publicKey"` - WgEndpoint string `json:"wgEndpoint"` - WgHost string `json:"wgHost"` - Timestamp int64 `json:"timestmap"` - Description string `json:"description"` - Routes []string `json:"routes"` - Alias string `json:"alias"` + HostEndpoint string `json:"hostEndpoint"` + PublicKey string `json:"publicKey"` + WgEndpoint string `json:"wgEndpoint"` + WgHost string `json:"wgHost"` + Timestamp int64 `json:"timestmap"` + Description string `json:"description"` + Routes []string `json:"routes"` + Alias string `json:"alias"` + Services map[string]string `json:"services"` } func (m *QueryError) Error() string { @@ -78,6 +79,7 @@ func meshNodeToQueryNode(node mesh.MeshNode) *QueryNode { queryNode.Routes = node.GetRoutes() queryNode.Description = node.GetDescription() queryNode.Alias = node.GetAlias() + queryNode.Services = node.GetServices() return queryNode } diff --git a/pkg/robin/requester.go b/pkg/robin/requester.go index 337cac3..c201152 100644 --- a/pkg/robin/requester.go +++ b/pkg/robin/requester.go @@ -117,6 +117,11 @@ func (n *IpcHandler) LeaveMesh(meshId string, reply *string) error { func (n *IpcHandler) GetMesh(meshId string, reply *ipc.GetMeshReply) error { mesh := n.Server.GetMeshManager().GetMesh(meshId) + + if mesh == nil { + return fmt.Errorf("mesh %s does not exist", meshId) + } + meshSnapshot, err := mesh.GetMesh() if err != nil { @@ -145,6 +150,8 @@ func (n *IpcHandler) GetMesh(meshId string, reply *ipc.GetMeshReply) error { Timestamp: node.GetTimeStamp(), Routes: node.GetRoutes(), Description: node.GetDescription(), + Alias: node.GetAlias(), + Services: node.GetServices(), } nodes[i] = node @@ -213,6 +220,28 @@ func (n *IpcHandler) PutAlias(alias string, reply *string) error { return nil } +func (n *IpcHandler) PutService(service ipc.PutServiceArgs, reply *string) error { + err := n.Server.GetMeshManager().SetService(service.Service, service.Value) + + if err != nil { + return err + } + + *reply = "success" + return nil +} + +func (n *IpcHandler) DeleteService(service string, reply *string) error { + err := n.Server.GetMeshManager().RemoveService(service) + + if err != nil { + return err + } + + *reply = "success" + return nil +} + type RobinIpcParams struct { CtrlServer ctrlserver.CtrlServer } diff --git a/pkg/sync/syncer.go b/pkg/sync/syncer.go index 040d13a..155c1ed 100644 --- a/pkg/sync/syncer.go +++ b/pkg/sync/syncer.go @@ -48,14 +48,7 @@ func (s *SyncerImpl) Sync(meshId string) error { return errors.New("the provided mesh does not exist") } - snapshot, err := theMesh.GetMesh() - - s.manager.GetMonitor().Trigger(meshId, snapshot) - - if err != nil { - return err - } - + snapshot, _ := theMesh.GetMesh() nodes := snapshot.GetNodes() if len(nodes) <= 1 { @@ -109,24 +102,19 @@ func (s *SyncerImpl) Sync(meshId string) error { waitGroup.Wait() s.syncCount++ - logging.Log.WriteInfof("SYNC TIME: %v", time.Now().Sub(before)) + logging.Log.WriteInfof("SYNC TIME: %v", time.Since(before)) logging.Log.WriteInfof("SYNC COUNT: %d", s.syncCount) s.infectionCount = ((s.conf.InfectionCount + s.infectionCount - 1) % s.conf.InfectionCount) - newMesh := s.manager.GetMesh(meshId) - snapshot, err = newMesh.GetMesh() - - if err != nil { - return err - } - - return nil + // Check if any changes have occurred and trigger callbacks + // if changes have occurred. + return s.manager.GetMonitor().Trigger() } // SyncMeshes: Sync all meshes func (s *SyncerImpl) SyncMeshes() error { - for meshId, _ := range s.manager.GetMeshes() { + for meshId := range s.manager.GetMeshes() { err := s.Sync(meshId) if err != nil {