mirror of
https://github.com/tim-beatham/smegmesh.git
synced 2025-06-25 14:31:24 +02:00
Adding stubs and writing tests
This commit is contained in:
parent
bb07d35dcb
commit
9454d62417
@ -9,7 +9,6 @@ import (
|
|||||||
ctrlserver "github.com/tim-beatham/wgmesh/pkg/ctrlserver"
|
ctrlserver "github.com/tim-beatham/wgmesh/pkg/ctrlserver"
|
||||||
"github.com/tim-beatham/wgmesh/pkg/ipc"
|
"github.com/tim-beatham/wgmesh/pkg/ipc"
|
||||||
logging "github.com/tim-beatham/wgmesh/pkg/log"
|
logging "github.com/tim-beatham/wgmesh/pkg/log"
|
||||||
"github.com/tim-beatham/wgmesh/pkg/middleware"
|
|
||||||
"github.com/tim-beatham/wgmesh/pkg/robin"
|
"github.com/tim-beatham/wgmesh/pkg/robin"
|
||||||
"github.com/tim-beatham/wgmesh/pkg/sync"
|
"github.com/tim-beatham/wgmesh/pkg/sync"
|
||||||
"github.com/tim-beatham/wgmesh/pkg/timestamp"
|
"github.com/tim-beatham/wgmesh/pkg/timestamp"
|
||||||
@ -37,12 +36,10 @@ func main() {
|
|||||||
|
|
||||||
var robinRpc robin.WgRpc
|
var robinRpc robin.WgRpc
|
||||||
var robinIpc robin.IpcHandler
|
var robinIpc robin.IpcHandler
|
||||||
var authProvider middleware.AuthRpcProvider
|
|
||||||
var syncProvider sync.SyncServiceImpl
|
var syncProvider sync.SyncServiceImpl
|
||||||
|
|
||||||
ctrlServerParams := ctrlserver.NewCtrlServerParams{
|
ctrlServerParams := ctrlserver.NewCtrlServerParams{
|
||||||
Conf: conf,
|
Conf: conf,
|
||||||
AuthProvider: &authProvider,
|
|
||||||
CtrlProvider: &robinRpc,
|
CtrlProvider: &robinRpc,
|
||||||
SyncProvider: &syncProvider,
|
SyncProvider: &syncProvider,
|
||||||
Client: client,
|
Client: client,
|
||||||
|
@ -187,6 +187,10 @@ func (m *CrdtMeshManager) AddRoutes(nodeId string, routes ...string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if nodeVal.Kind() != automerge.KindMap {
|
||||||
|
return fmt.Errorf("node does not exist")
|
||||||
|
}
|
||||||
|
|
||||||
routeMap, err := nodeVal.Map().Get("routes")
|
routeMap, err := nodeVal.Map().Get("routes")
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -85,8 +85,8 @@ func TestAddNodeAddRoute(t *testing.T) {
|
|||||||
|
|
||||||
routes := updatedNode.GetRoutes()
|
routes := updatedNode.GetRoutes()
|
||||||
|
|
||||||
if !slices.Contains(routes, "fdfd:1c64:1d00::/48") {
|
if !slices.Contains(routes, "fd:1c64:1d00::/48") {
|
||||||
t.Fatal("Route node added")
|
t.Fatal("Route node not added")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(routes) != 1 {
|
if len(routes) != 1 {
|
||||||
@ -197,7 +197,7 @@ func TestLength1Node(t *testing.T) {
|
|||||||
func TestLengthMultipleNodes(t *testing.T) {
|
func TestLengthMultipleNodes(t *testing.T) {
|
||||||
testParams := setUpTests()
|
testParams := setUpTests()
|
||||||
node := getTestNode()
|
node := getTestNode()
|
||||||
node1 := getTestNode()
|
node1 := getTestNode2()
|
||||||
|
|
||||||
testParams.manager.AddNode(node)
|
testParams.manager.AddNode(node)
|
||||||
testParams.manager.AddNode(node1)
|
testParams.manager.AddNode(node1)
|
||||||
|
@ -8,6 +8,14 @@ import (
|
|||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type WgMeshConfigurationError struct {
|
||||||
|
msg string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *WgMeshConfigurationError) Error() string {
|
||||||
|
return m.msg
|
||||||
|
}
|
||||||
|
|
||||||
type WgMeshConfiguration struct {
|
type WgMeshConfiguration struct {
|
||||||
// CertificatePath is the path to the certificate to use in mTLS
|
// CertificatePath is the path to the certificate to use in mTLS
|
||||||
CertificatePath string `yaml:"certificatePath"`
|
CertificatePath string `yaml:"certificatePath"`
|
||||||
@ -33,6 +41,70 @@ type WgMeshConfiguration struct {
|
|||||||
KeepAliveRate int `yaml:"keepAliveRate"`
|
KeepAliveRate int `yaml:"keepAliveRate"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ValidateConfiguration(c *WgMeshConfiguration) error {
|
||||||
|
if len(c.CertificatePath) == 0 {
|
||||||
|
return &WgMeshConfigurationError{
|
||||||
|
msg: "A public certificate must be specified for mTLS",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(c.PrivateKeyPath) == 0 {
|
||||||
|
return &WgMeshConfigurationError{
|
||||||
|
msg: "A private key must be specified for mTLS",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(c.CaCertificatePath) == 0 {
|
||||||
|
return &WgMeshConfigurationError{
|
||||||
|
msg: "A ca certificate must be specified for mTLS",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(c.GrpcPort) == 0 {
|
||||||
|
return &WgMeshConfigurationError{
|
||||||
|
msg: "A grpc port must be specified",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.ClusterSize <= 0 {
|
||||||
|
return &WgMeshConfigurationError{
|
||||||
|
msg: "A cluster size must not be 0",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.SyncRate <= 0 {
|
||||||
|
return &WgMeshConfigurationError{
|
||||||
|
msg: "SyncRate cannot be negative",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.BranchRate <= 0 {
|
||||||
|
return &WgMeshConfigurationError{
|
||||||
|
msg: "Branch rate cannot be negative",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.InfectionCount <= 0 {
|
||||||
|
return &WgMeshConfigurationError{
|
||||||
|
msg: "Infection count cannot be less than 1",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.KeepAliveRate <= 0 {
|
||||||
|
return &WgMeshConfigurationError{
|
||||||
|
msg: "KeepAliveRate cannot be less than negative",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.InterClusterChance <= 0 {
|
||||||
|
return &WgMeshConfigurationError{
|
||||||
|
msg: "Intercluster chance cannot be less than 0",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// ParseConfiguration parses the mesh configuration
|
// ParseConfiguration parses the mesh configuration
|
||||||
func ParseConfiguration(filePath string) (*WgMeshConfiguration, error) {
|
func ParseConfiguration(filePath string) (*WgMeshConfiguration, error) {
|
||||||
var conf WgMeshConfiguration
|
var conf WgMeshConfiguration
|
||||||
@ -51,5 +123,5 @@ func ParseConfiguration(filePath string) (*WgMeshConfiguration, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &conf, nil
|
return &conf, ValidateConfiguration(&conf)
|
||||||
}
|
}
|
||||||
|
130
pkg/conf/conf_test.go
Normal file
130
pkg/conf/conf_test.go
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
package conf
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func getExampleConfiguration() *WgMeshConfiguration {
|
||||||
|
return &WgMeshConfiguration{
|
||||||
|
CertificatePath: "./cert/cert.pem",
|
||||||
|
PrivateKeyPath: "./cert/key.pem",
|
||||||
|
CaCertificatePath: "./cert/ca.pems",
|
||||||
|
SkipCertVerification: true,
|
||||||
|
GrpcPort: "8080",
|
||||||
|
AdvertiseRoutes: true,
|
||||||
|
Endpoint: "localhost",
|
||||||
|
ClusterSize: 1,
|
||||||
|
SyncRate: 1,
|
||||||
|
InterClusterChance: 0.1,
|
||||||
|
BranchRate: 2,
|
||||||
|
KeepAliveRate: 1,
|
||||||
|
InfectionCount: 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfigurationCertificatePathEmpty(t *testing.T) {
|
||||||
|
conf := getExampleConfiguration()
|
||||||
|
conf.CertificatePath = ""
|
||||||
|
|
||||||
|
err := ValidateConfiguration(conf)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal(`error should be thrown`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfigurationPrivateKeyPathEmpty(t *testing.T) {
|
||||||
|
conf := getExampleConfiguration()
|
||||||
|
conf.PrivateKeyPath = ""
|
||||||
|
|
||||||
|
err := ValidateConfiguration(conf)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal(`error should be thrown`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfigurationCaCertificatePathEmpty(t *testing.T) {
|
||||||
|
conf := getExampleConfiguration()
|
||||||
|
conf.CaCertificatePath = ""
|
||||||
|
|
||||||
|
err := ValidateConfiguration(conf)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal(`error should be thrown`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfigurationGrpcPortEmpty(t *testing.T) {
|
||||||
|
conf := getExampleConfiguration()
|
||||||
|
conf.GrpcPort = ""
|
||||||
|
|
||||||
|
err := ValidateConfiguration(conf)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal(`error should be thrown`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClusterSizeZero(t *testing.T) {
|
||||||
|
conf := getExampleConfiguration()
|
||||||
|
conf.ClusterSize = 0
|
||||||
|
|
||||||
|
err := ValidateConfiguration(conf)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal(`error should be thrown`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func SyncRateZero(t *testing.T) {
|
||||||
|
conf := getExampleConfiguration()
|
||||||
|
conf.SyncRate = 0
|
||||||
|
|
||||||
|
err := ValidateConfiguration(conf)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal(`error should be thrown`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BranchRateZero(t *testing.T) {
|
||||||
|
conf := getExampleConfiguration()
|
||||||
|
conf.BranchRate = 0
|
||||||
|
|
||||||
|
err := ValidateConfiguration(conf)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal(`error should be thrown`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func InfectionCountZero(t *testing.T) {
|
||||||
|
conf := getExampleConfiguration()
|
||||||
|
conf.InfectionCount = 0
|
||||||
|
|
||||||
|
err := ValidateConfiguration(conf)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal(`error should be thrown`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func KeepAliveRateZero(t *testing.T) {
|
||||||
|
conf := getExampleConfiguration()
|
||||||
|
conf.KeepAliveRate = 0
|
||||||
|
|
||||||
|
err := ValidateConfiguration(conf)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal(`error should be thrown`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValidCOnfiguration(t *testing.T) {
|
||||||
|
conf := getExampleConfiguration()
|
||||||
|
|
||||||
|
err := ValidateConfiguration(conf)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
@ -23,19 +23,21 @@ func binarySearch(global []string, selfId string, groupSize int) (int, int) {
|
|||||||
|
|
||||||
lower := 0
|
lower := 0
|
||||||
higher := len(global) - 1
|
higher := len(global) - 1
|
||||||
mid := lower + (lower+higher)/2
|
mid := (lower + higher) / 2
|
||||||
|
|
||||||
for (higher+1)-lower > groupSize {
|
for (higher+1)-lower > groupSize {
|
||||||
if global[mid] <= selfId {
|
if global[mid] < selfId {
|
||||||
lower = mid
|
lower = mid + 1
|
||||||
|
} else if global[mid] > selfId {
|
||||||
|
higher = mid - 1
|
||||||
} else {
|
} else {
|
||||||
higher = mid
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
mid = lower + (lower+higher)/2
|
mid = (lower + higher) / 2
|
||||||
}
|
}
|
||||||
|
|
||||||
return lower, higher + 1
|
return lower, int(math.Min(float64(lower+groupSize), float64(len(global))))
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNeighbours return the neighbours 'nearest' to you. In this implementation the
|
// GetNeighbours return the neighbours 'nearest' to you. In this implementation the
|
||||||
|
116
pkg/conn/cluster_test.go
Normal file
116
pkg/conn/cluster_test.go
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
package conn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
"slices"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetNeighboursClusterSizeTwo(t *testing.T) {
|
||||||
|
cluster := &ConnClusterImpl{
|
||||||
|
clusterSize: 2,
|
||||||
|
}
|
||||||
|
neighbours := []string{
|
||||||
|
"a",
|
||||||
|
"b",
|
||||||
|
"c",
|
||||||
|
"d",
|
||||||
|
}
|
||||||
|
|
||||||
|
result := cluster.GetNeighbours(neighbours, "b")
|
||||||
|
|
||||||
|
if len(result) != 2 {
|
||||||
|
t.Fatalf(`neighbour length should be 2`)
|
||||||
|
}
|
||||||
|
|
||||||
|
if result[0] != "a" && result[1] != "b" {
|
||||||
|
t.Fatalf(`Expected value b`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetNeighboursGlobalListLessThanClusterSize(t *testing.T) {
|
||||||
|
cluster := &ConnClusterImpl{
|
||||||
|
clusterSize: 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
neighbours := []string{
|
||||||
|
"a",
|
||||||
|
"b",
|
||||||
|
"c",
|
||||||
|
}
|
||||||
|
|
||||||
|
result := cluster.GetNeighbours(neighbours, "a")
|
||||||
|
|
||||||
|
if len(result) != 3 {
|
||||||
|
t.Fatalf(`neighbour length should be 3`)
|
||||||
|
}
|
||||||
|
|
||||||
|
slices.Sort(result)
|
||||||
|
|
||||||
|
if !slices.Equal(result, neighbours) {
|
||||||
|
t.Fatalf(`Cluster and neighbours should be equal`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetNeighboursClusterSize4(t *testing.T) {
|
||||||
|
cluster := &ConnClusterImpl{
|
||||||
|
clusterSize: 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
neighbours := []string{
|
||||||
|
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j",
|
||||||
|
"k", "l", "m", "n", "o",
|
||||||
|
}
|
||||||
|
|
||||||
|
result := cluster.GetNeighbours(neighbours, "k")
|
||||||
|
|
||||||
|
if len(result) != 4 {
|
||||||
|
t.Fatalf(`cluster size must be 4`)
|
||||||
|
}
|
||||||
|
|
||||||
|
slices.Sort(result)
|
||||||
|
|
||||||
|
if !slices.Equal(neighbours[8:12], result) {
|
||||||
|
t.Fatalf(`Cluster should be i, j, k, l`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetNeighboursClusterSize4OneReturned(t *testing.T) {
|
||||||
|
cluster := &ConnClusterImpl{
|
||||||
|
clusterSize: 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
neighbours := []string{
|
||||||
|
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j",
|
||||||
|
"k", "l", "m", "n", "o",
|
||||||
|
}
|
||||||
|
|
||||||
|
result := cluster.GetNeighbours(neighbours, "o")
|
||||||
|
|
||||||
|
if len(result) != 3 {
|
||||||
|
t.Fatalf(`Cluster should be of length 3`)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !slices.Equal(neighbours[12:15], result) {
|
||||||
|
t.Fatalf(`Cluster should be m, n, o`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInterClusterNotInCluster(t *testing.T) {
|
||||||
|
rand.Seed(1)
|
||||||
|
cluster := &ConnClusterImpl{
|
||||||
|
clusterSize: 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
global := []string{
|
||||||
|
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j",
|
||||||
|
"k", "l", "m", "n", "o",
|
||||||
|
}
|
||||||
|
|
||||||
|
neighbours := cluster.GetNeighbours(global, "c")
|
||||||
|
interCluster := cluster.GetInterCluster(global, "c")
|
||||||
|
|
||||||
|
if slices.Contains(neighbours, interCluster) {
|
||||||
|
t.Fatalf(`intercluster cannot be in your cluster`)
|
||||||
|
}
|
||||||
|
}
|
@ -18,6 +18,8 @@ type PeerConnection interface {
|
|||||||
GetClient() (*grpc.ClientConn, error)
|
GetClient() (*grpc.ClientConn, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PeerConnectionFactory = func(clientConfig *tls.Config, server string) (PeerConnection, error)
|
||||||
|
|
||||||
// WgCtrlConnection implements PeerConnection.
|
// WgCtrlConnection implements PeerConnection.
|
||||||
type WgCtrlConnection struct {
|
type WgCtrlConnection struct {
|
||||||
clientConfig *tls.Config
|
clientConfig *tls.Config
|
||||||
@ -26,12 +28,12 @@ type WgCtrlConnection struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewWgCtrlConnection creates a new instance of a WireGuard control connection
|
// NewWgCtrlConnection creates a new instance of a WireGuard control connection
|
||||||
func NewWgCtrlConnection(clientConfig *tls.Config, server string) (*WgCtrlConnection, error) {
|
func NewWgCtrlConnection(clientConfig *tls.Config, server string) (PeerConnection, error) {
|
||||||
var conn WgCtrlConnection
|
var conn WgCtrlConnection
|
||||||
conn.clientConfig = clientConfig
|
conn.clientConfig = clientConfig
|
||||||
conn.endpoint = server
|
conn.endpoint = server
|
||||||
|
|
||||||
if err := conn.createGrpcConn(); err != nil {
|
if err := conn.CreateGrpcConnection(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,7 +41,7 @@ func NewWgCtrlConnection(clientConfig *tls.Config, server string) (*WgCtrlConnec
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ConnectWithToken: Connects to a new gRPC peer given the address of the other server.
|
// ConnectWithToken: Connects to a new gRPC peer given the address of the other server.
|
||||||
func (c *WgCtrlConnection) createGrpcConn() error {
|
func (c *WgCtrlConnection) CreateGrpcConnection() error {
|
||||||
conn, err := grpc.Dial(c.endpoint,
|
conn, err := grpc.Dial(c.endpoint,
|
||||||
grpc.WithTransportCredentials(credentials.NewTLS(c.clientConfig)))
|
grpc.WithTransportCredentials(credentials.NewTLS(c.clientConfig)))
|
||||||
|
|
||||||
@ -62,7 +64,7 @@ func (c *WgCtrlConnection) GetClient() (*grpc.ClientConn, error) {
|
|||||||
var err error = nil
|
var err error = nil
|
||||||
|
|
||||||
if c.conn == nil {
|
if c.conn == nil {
|
||||||
err = errors.New("The client's config does not exist")
|
err = errors.New("the client's config does not exist")
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.conn, err
|
return c.conn, err
|
||||||
|
@ -34,10 +34,11 @@ type ConnectionManagerImpl struct {
|
|||||||
clientConnections map[string]PeerConnection
|
clientConnections map[string]PeerConnection
|
||||||
serverConfig *tls.Config
|
serverConfig *tls.Config
|
||||||
clientConfig *tls.Config
|
clientConfig *tls.Config
|
||||||
|
connFactory PeerConnectionFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new instance of a connection manager.
|
// Create a new instance of a connection manager.
|
||||||
type NewConnectionManageParams struct {
|
type NewConnectionManagerParams struct {
|
||||||
// The path to the certificate
|
// The path to the certificate
|
||||||
CertificatePath string
|
CertificatePath string
|
||||||
// The private key of the node
|
// The private key of the node
|
||||||
@ -45,11 +46,12 @@ type NewConnectionManageParams struct {
|
|||||||
// Whether or not to skip certificate verification
|
// Whether or not to skip certificate verification
|
||||||
SkipCertVerification bool
|
SkipCertVerification bool
|
||||||
CaCert string
|
CaCert string
|
||||||
|
ConnFactory PeerConnectionFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewConnectionManager: Creates a new instance of a ConnectionManager or an error
|
// NewConnectionManager: Creates a new instance of a ConnectionManager or an error
|
||||||
// if something went wrong.
|
// if something went wrong.
|
||||||
func NewConnectionManager(params *NewConnectionManageParams) (ConnectionManager, error) {
|
func NewConnectionManager(params *NewConnectionManagerParams) (ConnectionManager, error) {
|
||||||
cert, err := tls.LoadX509KeyPair(params.CertificatePath, params.PrivateKey)
|
cert, err := tls.LoadX509KeyPair(params.CertificatePath, params.PrivateKey)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -94,10 +96,12 @@ func NewConnectionManager(params *NewConnectionManageParams) (ConnectionManager,
|
|||||||
}
|
}
|
||||||
|
|
||||||
connections := make(map[string]PeerConnection)
|
connections := make(map[string]PeerConnection)
|
||||||
connMgr := ConnectionManagerImpl{sync.RWMutex{},
|
connMgr := ConnectionManagerImpl{
|
||||||
|
sync.RWMutex{},
|
||||||
connections,
|
connections,
|
||||||
serverConfig,
|
serverConfig,
|
||||||
clientConfig,
|
clientConfig,
|
||||||
|
params.ConnFactory,
|
||||||
}
|
}
|
||||||
|
|
||||||
return &connMgr, nil
|
return &connMgr, nil
|
||||||
@ -127,7 +131,7 @@ func (m *ConnectionManagerImpl) AddConnection(endPoint string) (PeerConnection,
|
|||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
connections, err := NewWgCtrlConnection(m.clientConfig, endPoint)
|
connections, err := m.connFactory(m.clientConfig, endPoint)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
145
pkg/conn/connectionmanager_test.go
Normal file
145
pkg/conn/connectionmanager_test.go
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
package conn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"errors"
|
||||||
|
"log"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getConnectionManagerParams() *NewConnectionManagerParams {
|
||||||
|
return &NewConnectionManagerParams{
|
||||||
|
CertificatePath: "./test/cert.pem",
|
||||||
|
PrivateKey: "./test/priv.pem",
|
||||||
|
CaCert: "./test/cacert.pem",
|
||||||
|
SkipCertVerification: false,
|
||||||
|
ConnFactory: MockFactory,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewConnectionManagerCertificatePathDoesNotExist(t *testing.T) {
|
||||||
|
params := getConnectionManagerParams()
|
||||||
|
params.CertificatePath = "./cert/sdfjdskjdsjkd.pem"
|
||||||
|
|
||||||
|
_, err := NewConnectionManager(params)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf(`Expected error as certificate does not exist`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewConnectionManagerPrivateKeyDoesNotExist(t *testing.T) {
|
||||||
|
params := getConnectionManagerParams()
|
||||||
|
params.PrivateKey = "./cert/sdjdjdks.pem"
|
||||||
|
|
||||||
|
_, err := NewConnectionManager(params)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf(`Expected error as private key does not exist`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewConnectionManagerCACertDoesNotExistAndVerify(t *testing.T) {
|
||||||
|
params := getConnectionManagerParams()
|
||||||
|
params.CaCert = "./cert/sdjdsjdksjdks.pem"
|
||||||
|
params.SkipCertVerification = false
|
||||||
|
|
||||||
|
_, err := NewConnectionManager(params)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal(`Expected error as ca cert does not exist and skip is false`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewConnectionManagerCACertDoesNotExistAndNotVerify(t *testing.T) {
|
||||||
|
params := getConnectionManagerParams()
|
||||||
|
params.CaCert = ""
|
||||||
|
params.SkipCertVerification = true
|
||||||
|
|
||||||
|
_, err := NewConnectionManager(params)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(`an error should not be thrown`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetConnectionConnectionDoesNotExistAddsConnection(t *testing.T) {
|
||||||
|
params := getConnectionManagerParams()
|
||||||
|
|
||||||
|
m, _ := NewConnectionManager(params)
|
||||||
|
|
||||||
|
conn, err := m.GetConnection("abc-123.com")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if conn == nil {
|
||||||
|
t.Fatal(`the connection should not be nil`)
|
||||||
|
}
|
||||||
|
|
||||||
|
conn2, _ := m.GetConnection("abc-123.com")
|
||||||
|
|
||||||
|
if conn != conn2 {
|
||||||
|
log.Fatalf(`should return the same connection instance`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddConnectionThrowsAnErrorIfFactoryThrowsError(t *testing.T) {
|
||||||
|
params := getConnectionManagerParams()
|
||||||
|
params.ConnFactory = func(clientConfig *tls.Config, server string) (PeerConnection, error) {
|
||||||
|
return nil, errors.New("this is an error")
|
||||||
|
}
|
||||||
|
|
||||||
|
m, _ := NewConnectionManager(params)
|
||||||
|
|
||||||
|
_, err := m.AddConnection("abc-123.com")
|
||||||
|
|
||||||
|
if err == nil || err.Error() != "this is an error" {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddConnectionConnectionDoesNotExist(t *testing.T) {
|
||||||
|
params := getConnectionManagerParams()
|
||||||
|
|
||||||
|
m, _ := NewConnectionManager(params)
|
||||||
|
|
||||||
|
conn, err := m.AddConnection("abc-123.com")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if conn == nil {
|
||||||
|
t.Fatal(`connection should not be nil`)
|
||||||
|
}
|
||||||
|
|
||||||
|
conn1, _ := m.GetConnection("abc-123.com")
|
||||||
|
|
||||||
|
if conn != conn1 {
|
||||||
|
t.Fatal(`underlying connections should be the same`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHasConnectionConnectionDoesNotExist(t *testing.T) {
|
||||||
|
params := getConnectionManagerParams()
|
||||||
|
|
||||||
|
m, _ := NewConnectionManager(params)
|
||||||
|
|
||||||
|
if m.HasConnection("abc-123.com") {
|
||||||
|
t.Fatal(`should return that the connection does not exist`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHasConnectionConnectionExists(t *testing.T) {
|
||||||
|
params := getConnectionManagerParams()
|
||||||
|
|
||||||
|
m, _ := NewConnectionManager(params)
|
||||||
|
|
||||||
|
m.AddConnection("abc-123.com")
|
||||||
|
|
||||||
|
if !m.HasConnection("abc-123.com") {
|
||||||
|
t.Fatal(`should return that the connection exists`)
|
||||||
|
}
|
||||||
|
}
|
@ -16,9 +16,7 @@ type ConnectionServer struct {
|
|||||||
// tlsConfiguration of the server
|
// tlsConfiguration of the server
|
||||||
serverConfig *tls.Config
|
serverConfig *tls.Config
|
||||||
// server an instance of the grpc server
|
// server an instance of the grpc server
|
||||||
server *grpc.Server
|
server *grpc.Server // the authentication service to authenticate nodes
|
||||||
// the authentication service to authenticate nodes
|
|
||||||
authProvider rpc.AuthenticationServer
|
|
||||||
// the ctrl service to manage node
|
// the ctrl service to manage node
|
||||||
ctrlProvider rpc.MeshCtrlServerServer
|
ctrlProvider rpc.MeshCtrlServerServer
|
||||||
// the sync service to synchronise nodes
|
// the sync service to synchronise nodes
|
||||||
@ -30,7 +28,6 @@ type ConnectionServer struct {
|
|||||||
// NewConnectionServerParams contains params for creating a new connection server
|
// NewConnectionServerParams contains params for creating a new connection server
|
||||||
type NewConnectionServerParams struct {
|
type NewConnectionServerParams struct {
|
||||||
Conf *conf.WgMeshConfiguration
|
Conf *conf.WgMeshConfiguration
|
||||||
AuthProvider rpc.AuthenticationServer
|
|
||||||
CtrlProvider rpc.MeshCtrlServerServer
|
CtrlProvider rpc.MeshCtrlServerServer
|
||||||
SyncProvider rpc.SyncServiceServer
|
SyncProvider rpc.SyncServiceServer
|
||||||
}
|
}
|
||||||
@ -59,14 +56,12 @@ func NewConnectionServer(params *NewConnectionServerParams) (*ConnectionServer,
|
|||||||
grpc.Creds(credentials.NewTLS(serverConfig)),
|
grpc.Creds(credentials.NewTLS(serverConfig)),
|
||||||
)
|
)
|
||||||
|
|
||||||
authProvider := params.AuthProvider
|
|
||||||
ctrlProvider := params.CtrlProvider
|
ctrlProvider := params.CtrlProvider
|
||||||
syncProvider := params.SyncProvider
|
syncProvider := params.SyncProvider
|
||||||
|
|
||||||
connServer := ConnectionServer{
|
connServer := ConnectionServer{
|
||||||
serverConfig: serverConfig,
|
serverConfig: serverConfig,
|
||||||
server: server,
|
server: server,
|
||||||
authProvider: authProvider,
|
|
||||||
ctrlProvider: ctrlProvider,
|
ctrlProvider: ctrlProvider,
|
||||||
syncProvider: syncProvider,
|
syncProvider: syncProvider,
|
||||||
Conf: params.Conf,
|
Conf: params.Conf,
|
||||||
@ -78,7 +73,6 @@ func NewConnectionServer(params *NewConnectionServerParams) (*ConnectionServer,
|
|||||||
// Listen for incoming requests. Returns an error if something went wrong.
|
// Listen for incoming requests. Returns an error if something went wrong.
|
||||||
func (s *ConnectionServer) Listen() error {
|
func (s *ConnectionServer) Listen() error {
|
||||||
rpc.RegisterMeshCtrlServerServer(s.server, s.ctrlProvider)
|
rpc.RegisterMeshCtrlServerServer(s.server, s.ctrlProvider)
|
||||||
rpc.RegisterAuthenticationServer(s.server, s.authProvider)
|
|
||||||
|
|
||||||
rpc.RegisterSyncServiceServer(s.server, s.syncProvider)
|
rpc.RegisterSyncServiceServer(s.server, s.syncProvider)
|
||||||
|
|
||||||
|
51
pkg/conn/stub.go
Normal file
51
pkg/conn/stub.go
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package conn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ConnectionManagerStub struct {
|
||||||
|
Endpoints map[string]PeerConnection
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ConnectionManagerStub) AddConnection(endPoint string) (PeerConnection, error) {
|
||||||
|
mock := &PeerConnectionMock{}
|
||||||
|
s.Endpoints[endPoint] = mock
|
||||||
|
return mock, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ConnectionManagerStub) GetConnection(endPoint string) (PeerConnection, error) {
|
||||||
|
endpoint, ok := s.Endpoints[endPoint]
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
return s.AddConnection(endPoint)
|
||||||
|
}
|
||||||
|
|
||||||
|
return endpoint, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ConnectionManagerStub) HasConnection(endPoint string) bool {
|
||||||
|
_, ok := s.Endpoints[endPoint]
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ConnectionManagerStub) Close() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type PeerConnectionMock struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *PeerConnectionMock) Close() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *PeerConnectionMock) GetClient() (*grpc.ClientConn, error) {
|
||||||
|
return &grpc.ClientConn{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var MockFactory PeerConnectionFactory = func(clientConfig *tls.Config, server string) (PeerConnection, error) {
|
||||||
|
return &PeerConnectionMock{}, nil
|
||||||
|
}
|
@ -18,7 +18,6 @@ import (
|
|||||||
type NewCtrlServerParams struct {
|
type NewCtrlServerParams struct {
|
||||||
Conf *conf.WgMeshConfiguration
|
Conf *conf.WgMeshConfiguration
|
||||||
Client *wgctrl.Client
|
Client *wgctrl.Client
|
||||||
AuthProvider rpc.AuthenticationServer
|
|
||||||
CtrlProvider rpc.MeshCtrlServerServer
|
CtrlProvider rpc.MeshCtrlServerServer
|
||||||
SyncProvider rpc.SyncServiceServer
|
SyncProvider rpc.SyncServiceServer
|
||||||
Querier query.Querier
|
Querier query.Querier
|
||||||
@ -44,16 +43,17 @@ func NewCtrlServer(params *NewCtrlServerParams) (*MeshCtrlServer, error) {
|
|||||||
IdGenerator: idGenerator,
|
IdGenerator: idGenerator,
|
||||||
IPAllocator: ipAllocator,
|
IPAllocator: ipAllocator,
|
||||||
InterfaceManipulator: interfaceManipulator,
|
InterfaceManipulator: interfaceManipulator,
|
||||||
|
ConfigApplyer: mesh.NewWgMeshConfigApplyer(ctrlServer.MeshManager),
|
||||||
}
|
}
|
||||||
|
|
||||||
ctrlServer.MeshManager = mesh.NewMeshManager(meshManagerParams)
|
ctrlServer.MeshManager = mesh.NewMeshManager(meshManagerParams)
|
||||||
|
|
||||||
ctrlServer.Conf = params.Conf
|
ctrlServer.Conf = params.Conf
|
||||||
connManagerParams := conn.NewConnectionManageParams{
|
connManagerParams := conn.NewConnectionManagerParams{
|
||||||
CertificatePath: params.Conf.CertificatePath,
|
CertificatePath: params.Conf.CertificatePath,
|
||||||
PrivateKey: params.Conf.PrivateKeyPath,
|
PrivateKey: params.Conf.PrivateKeyPath,
|
||||||
SkipCertVerification: params.Conf.SkipCertVerification,
|
SkipCertVerification: params.Conf.SkipCertVerification,
|
||||||
CaCert: params.Conf.CaCertificatePath,
|
CaCert: params.Conf.CaCertificatePath,
|
||||||
|
ConnFactory: conn.NewWgCtrlConnection,
|
||||||
}
|
}
|
||||||
|
|
||||||
connMgr, err := conn.NewConnectionManager(&connManagerParams)
|
connMgr, err := conn.NewConnectionManager(&connManagerParams)
|
||||||
@ -65,7 +65,6 @@ func NewCtrlServer(params *NewCtrlServerParams) (*MeshCtrlServer, error) {
|
|||||||
ctrlServer.ConnectionManager = connMgr
|
ctrlServer.ConnectionManager = connMgr
|
||||||
connServerParams := conn.NewConnectionServerParams{
|
connServerParams := conn.NewConnectionServerParams{
|
||||||
Conf: params.Conf,
|
Conf: params.Conf,
|
||||||
AuthProvider: params.AuthProvider,
|
|
||||||
CtrlProvider: params.CtrlProvider,
|
CtrlProvider: params.CtrlProvider,
|
||||||
SyncProvider: params.SyncProvider,
|
SyncProvider: params.SyncProvider,
|
||||||
}
|
}
|
||||||
@ -82,6 +81,26 @@ func NewCtrlServer(params *NewCtrlServerParams) (*MeshCtrlServer, error) {
|
|||||||
return ctrlServer, nil
|
return ctrlServer, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *MeshCtrlServer) GetConfiguration() *conf.WgMeshConfiguration {
|
||||||
|
return s.Conf
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MeshCtrlServer) GetClient() *wgctrl.Client {
|
||||||
|
return s.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MeshCtrlServer) GetQuerier() query.Querier {
|
||||||
|
return s.Querier
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MeshCtrlServer) GetMeshManager() mesh.MeshManager {
|
||||||
|
return s.MeshManager
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MeshCtrlServer) GetConnectionManager() conn.ConnectionManager {
|
||||||
|
return s.ConnectionManager
|
||||||
|
}
|
||||||
|
|
||||||
// Close closes the ctrl server tearing down any connections that exist
|
// Close closes the ctrl server tearing down any connections that exist
|
||||||
func (s *MeshCtrlServer) Close() error {
|
func (s *MeshCtrlServer) Close() error {
|
||||||
if err := s.ConnectionManager.Close(); err != nil {
|
if err := s.ConnectionManager.Close(); err != nil {
|
||||||
|
@ -25,10 +25,19 @@ type Mesh struct {
|
|||||||
Nodes map[string]MeshNode
|
Nodes map[string]MeshNode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CtrlServer interface {
|
||||||
|
GetConfiguration() *conf.WgMeshConfiguration
|
||||||
|
GetClient() *wgctrl.Client
|
||||||
|
GetQuerier() query.Querier
|
||||||
|
GetMeshManager() mesh.MeshManager
|
||||||
|
Close() error
|
||||||
|
GetConnectionManager() conn.ConnectionManager
|
||||||
|
}
|
||||||
|
|
||||||
// Represents a ctrlserver to be used in WireGuard
|
// Represents a ctrlserver to be used in WireGuard
|
||||||
type MeshCtrlServer struct {
|
type MeshCtrlServer struct {
|
||||||
Client *wgctrl.Client
|
Client *wgctrl.Client
|
||||||
MeshManager *mesh.MeshManager
|
MeshManager mesh.MeshManager
|
||||||
ConnectionManager conn.ConnectionManager
|
ConnectionManager conn.ConnectionManager
|
||||||
ConnectionServer *conn.ConnectionServer
|
ConnectionServer *conn.ConnectionServer
|
||||||
Conf *conf.WgMeshConfiguration
|
Conf *conf.WgMeshConfiguration
|
||||||
|
51
pkg/ctrlserver/stub.go
Normal file
51
pkg/ctrlserver/stub.go
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package ctrlserver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/tim-beatham/wgmesh/pkg/conf"
|
||||||
|
"github.com/tim-beatham/wgmesh/pkg/conn"
|
||||||
|
"github.com/tim-beatham/wgmesh/pkg/mesh"
|
||||||
|
"github.com/tim-beatham/wgmesh/pkg/query"
|
||||||
|
"golang.zx2c4.com/wireguard/wgctrl"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CtrlServerStub struct {
|
||||||
|
manager mesh.MeshManager
|
||||||
|
querier query.Querier
|
||||||
|
connectionManager conn.ConnectionManager
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCtrlServerStub() *CtrlServerStub {
|
||||||
|
var manager mesh.MeshManager = mesh.NewMeshManagerStub()
|
||||||
|
return &CtrlServerStub{
|
||||||
|
manager: manager,
|
||||||
|
querier: query.NewJmesQuerier(manager),
|
||||||
|
connectionManager: &conn.ConnectionManagerStub{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CtrlServerStub) GetConfiguration() *conf.WgMeshConfiguration {
|
||||||
|
return &conf.WgMeshConfiguration{
|
||||||
|
GrpcPort: "8080",
|
||||||
|
Endpoint: "abc.com",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CtrlServerStub) GetClient() *wgctrl.Client {
|
||||||
|
return &wgctrl.Client{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CtrlServerStub) GetQuerier() query.Querier {
|
||||||
|
return c.querier
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CtrlServerStub) GetMeshManager() mesh.MeshManager {
|
||||||
|
return c.manager
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CtrlServerStub) Close() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CtrlServerStub) GetConnectionManager() conn.ConnectionManager {
|
||||||
|
return c.connectionManager
|
||||||
|
}
|
@ -16,7 +16,7 @@ type MeshConfigApplyer interface {
|
|||||||
|
|
||||||
// WgMeshConfigApplyer applies WireGuard configuration
|
// WgMeshConfigApplyer applies WireGuard configuration
|
||||||
type WgMeshConfigApplyer struct {
|
type WgMeshConfigApplyer struct {
|
||||||
meshManager *MeshManager
|
meshManager MeshManager
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertMeshNode(node MeshNode) (*wgtypes.PeerConfig, error) {
|
func convertMeshNode(node MeshNode) (*wgtypes.PeerConfig, error) {
|
||||||
@ -82,11 +82,11 @@ func (m *WgMeshConfigApplyer) updateWgConf(mesh MeshProvider) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return m.meshManager.Client.ConfigureDevice(dev.Name, cfg)
|
return m.meshManager.GetClient().ConfigureDevice(dev.Name, cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *WgMeshConfigApplyer) ApplyConfig() error {
|
func (m *WgMeshConfigApplyer) ApplyConfig() error {
|
||||||
for _, mesh := range m.meshManager.Meshes {
|
for _, mesh := range m.meshManager.GetMeshes() {
|
||||||
err := m.updateWgConf(mesh)
|
err := m.updateWgConf(mesh)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -110,7 +110,7 @@ func (m *WgMeshConfigApplyer) RemovePeers(meshId string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
m.meshManager.Client.ConfigureDevice(dev.Name, wgtypes.Config{
|
m.meshManager.GetClient().ConfigureDevice(dev.Name, wgtypes.Config{
|
||||||
ReplacePeers: true,
|
ReplacePeers: true,
|
||||||
Peers: make([]wgtypes.PeerConfig, 1),
|
Peers: make([]wgtypes.PeerConfig, 1),
|
||||||
})
|
})
|
||||||
@ -118,6 +118,6 @@ func (m *WgMeshConfigApplyer) RemovePeers(meshId string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewWgMeshConfigApplyer(manager *MeshManager) MeshConfigApplyer {
|
func NewWgMeshConfigApplyer(manager MeshManager) MeshConfigApplyer {
|
||||||
return &WgMeshConfigApplyer{meshManager: manager}
|
return &WgMeshConfigApplyer{meshManager: manager}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ type MeshGraphConverter interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type MeshDOTConverter struct {
|
type MeshDOTConverter struct {
|
||||||
manager *MeshManager
|
manager MeshManager
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *MeshDOTConverter) Generate(meshId string) (string, error) {
|
func (c *MeshDOTConverter) Generate(meshId string) (string, error) {
|
||||||
@ -34,7 +34,7 @@ func (c *MeshDOTConverter) Generate(meshId string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, node := range snapshot.GetNodes() {
|
for _, node := range snapshot.GetNodes() {
|
||||||
c.graphNode(g, node)
|
c.graphNode(g, node, meshId)
|
||||||
}
|
}
|
||||||
|
|
||||||
nodes := lib.MapValues(snapshot.GetNodes())
|
nodes := lib.MapValues(snapshot.GetNodes())
|
||||||
@ -55,11 +55,13 @@ func (c *MeshDOTConverter) Generate(meshId string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// graphNode: graphs a node within the mesh
|
// graphNode: graphs a node within the mesh
|
||||||
func (c *MeshDOTConverter) graphNode(g *graph.Graph, node MeshNode) {
|
func (c *MeshDOTConverter) graphNode(g *graph.Graph, node MeshNode, meshId string) {
|
||||||
nodeId := fmt.Sprintf("\"%s\"", node.GetIdentifier())
|
nodeId := fmt.Sprintf("\"%s\"", node.GetIdentifier())
|
||||||
g.PutNode(nodeId, graph.CIRCLE)
|
g.PutNode(nodeId, graph.CIRCLE)
|
||||||
|
|
||||||
if node.GetHostEndpoint() == c.manager.HostParameters.HostEndpoint {
|
self, _ := c.manager.GetSelf(meshId)
|
||||||
|
|
||||||
|
if node.GetHostEndpoint() == self.GetHostEndpoint() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,6 +72,6 @@ func (c *MeshDOTConverter) graphNode(g *graph.Graph, node MeshNode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMeshDotConverter(m *MeshManager) MeshGraphConverter {
|
func NewMeshDotConverter(m MeshManager) MeshGraphConverter {
|
||||||
return &MeshDOTConverter{manager: m}
|
return &MeshDOTConverter{manager: m}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,24 @@ import (
|
|||||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MeshManager struct {
|
type MeshManager interface {
|
||||||
|
CreateMesh(devName string, port int) (string, error)
|
||||||
|
AddMesh(params *AddMeshParams) error
|
||||||
|
HasChanges(meshid string) bool
|
||||||
|
GetMesh(meshId string) MeshProvider
|
||||||
|
EnableInterface(meshId string) error
|
||||||
|
GetPublicKey(meshId string) (*wgtypes.Key, error)
|
||||||
|
AddSelf(params *AddSelfParams) error
|
||||||
|
LeaveMesh(meshId string) error
|
||||||
|
GetSelf(meshId string) (MeshNode, error)
|
||||||
|
ApplyConfig() error
|
||||||
|
SetDescription(description string) error
|
||||||
|
UpdateTimeStamp() error
|
||||||
|
GetClient() *wgctrl.Client
|
||||||
|
GetMeshes() map[string]MeshProvider
|
||||||
|
}
|
||||||
|
|
||||||
|
type MeshManagerImpl struct {
|
||||||
Meshes map[string]MeshProvider
|
Meshes map[string]MeshProvider
|
||||||
RouteManager RouteManager
|
RouteManager RouteManager
|
||||||
Client *wgctrl.Client
|
Client *wgctrl.Client
|
||||||
@ -30,7 +47,7 @@ type MeshManager struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateMesh: Creates a new mesh, stores it and returns the mesh id
|
// CreateMesh: Creates a new mesh, stores it and returns the mesh id
|
||||||
func (m *MeshManager) CreateMesh(devName string, port int) (string, error) {
|
func (m *MeshManagerImpl) CreateMesh(devName string, port int) (string, error) {
|
||||||
meshId, err := m.idGenerator.GetId()
|
meshId, err := m.idGenerator.GetId()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -76,7 +93,7 @@ type AddMeshParams struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AddMesh: Add the mesh to the list of meshes
|
// AddMesh: Add the mesh to the list of meshes
|
||||||
func (m *MeshManager) AddMesh(params *AddMeshParams) error {
|
func (m *MeshManagerImpl) AddMesh(params *AddMeshParams) error {
|
||||||
meshProvider, err := m.meshProviderFactory.CreateMesh(&MeshProviderFactoryParams{
|
meshProvider, err := m.meshProviderFactory.CreateMesh(&MeshProviderFactoryParams{
|
||||||
DevName: params.DevName,
|
DevName: params.DevName,
|
||||||
Port: params.WgPort,
|
Port: params.WgPort,
|
||||||
@ -104,18 +121,18 @@ func (m *MeshManager) AddMesh(params *AddMeshParams) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// HasChanges returns true if the mesh has changes
|
// HasChanges returns true if the mesh has changes
|
||||||
func (m *MeshManager) HasChanges(meshId string) bool {
|
func (m *MeshManagerImpl) HasChanges(meshId string) bool {
|
||||||
return m.Meshes[meshId].HasChanges()
|
return m.Meshes[meshId].HasChanges()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetMesh returns the mesh with the given meshid
|
// GetMesh returns the mesh with the given meshid
|
||||||
func (m *MeshManager) GetMesh(meshId string) MeshProvider {
|
func (m *MeshManagerImpl) GetMesh(meshId string) MeshProvider {
|
||||||
theMesh, _ := m.Meshes[meshId]
|
theMesh := m.Meshes[meshId]
|
||||||
return theMesh
|
return theMesh
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnableInterface: Enables the given WireGuard interface.
|
// EnableInterface: Enables the given WireGuard interface.
|
||||||
func (s *MeshManager) EnableInterface(meshId string) error {
|
func (s *MeshManagerImpl) EnableInterface(meshId string) error {
|
||||||
err := s.configApplyer.ApplyConfig()
|
err := s.configApplyer.ApplyConfig()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -144,7 +161,7 @@ func (s *MeshManager) EnableInterface(meshId string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetPublicKey: Gets the public key of the WireGuard mesh
|
// GetPublicKey: Gets the public key of the WireGuard mesh
|
||||||
func (s *MeshManager) GetPublicKey(meshId string) (*wgtypes.Key, error) {
|
func (s *MeshManagerImpl) GetPublicKey(meshId string) (*wgtypes.Key, error) {
|
||||||
mesh, ok := s.Meshes[meshId]
|
mesh, ok := s.Meshes[meshId]
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -171,7 +188,7 @@ type AddSelfParams struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AddSelf adds this host to the mesh
|
// AddSelf adds this host to the mesh
|
||||||
func (s *MeshManager) AddSelf(params *AddSelfParams) error {
|
func (s *MeshManagerImpl) AddSelf(params *AddSelfParams) error {
|
||||||
pubKey, err := s.GetPublicKey(params.MeshId)
|
pubKey, err := s.GetPublicKey(params.MeshId)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -196,7 +213,7 @@ func (s *MeshManager) AddSelf(params *AddSelfParams) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// LeaveMesh leaves the mesh network
|
// LeaveMesh leaves the mesh network
|
||||||
func (s *MeshManager) LeaveMesh(meshId string) error {
|
func (s *MeshManagerImpl) LeaveMesh(meshId string) error {
|
||||||
_, exists := s.Meshes[meshId]
|
_, exists := s.Meshes[meshId]
|
||||||
|
|
||||||
if !exists {
|
if !exists {
|
||||||
@ -208,7 +225,7 @@ func (s *MeshManager) LeaveMesh(meshId string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *MeshManager) GetSelf(meshId string) (MeshNode, error) {
|
func (s *MeshManagerImpl) GetSelf(meshId string) (MeshNode, error) {
|
||||||
meshInstance, ok := s.Meshes[meshId]
|
meshInstance, ok := s.Meshes[meshId]
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -230,11 +247,11 @@ func (s *MeshManager) GetSelf(meshId string) (MeshNode, error) {
|
|||||||
return node, nil
|
return node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *MeshManager) ApplyConfig() error {
|
func (s *MeshManagerImpl) ApplyConfig() error {
|
||||||
return s.configApplyer.ApplyConfig()
|
return s.configApplyer.ApplyConfig()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *MeshManager) SetDescription(description string) error {
|
func (s *MeshManagerImpl) SetDescription(description string) error {
|
||||||
for _, mesh := range s.Meshes {
|
for _, mesh := range s.Meshes {
|
||||||
err := mesh.SetDescription(s.HostParameters.HostEndpoint, description)
|
err := mesh.SetDescription(s.HostParameters.HostEndpoint, description)
|
||||||
|
|
||||||
@ -247,7 +264,7 @@ func (s *MeshManager) SetDescription(description string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateTimeStamp updates the timestamp of this node in all meshes
|
// UpdateTimeStamp updates the timestamp of this node in all meshes
|
||||||
func (s *MeshManager) UpdateTimeStamp() error {
|
func (s *MeshManagerImpl) UpdateTimeStamp() error {
|
||||||
for _, mesh := range s.Meshes {
|
for _, mesh := range s.Meshes {
|
||||||
snapshot, err := mesh.GetMesh()
|
snapshot, err := mesh.GetMesh()
|
||||||
|
|
||||||
@ -269,6 +286,14 @@ func (s *MeshManager) UpdateTimeStamp() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *MeshManagerImpl) GetClient() *wgctrl.Client {
|
||||||
|
return s.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MeshManagerImpl) GetMeshes() map[string]MeshProvider {
|
||||||
|
return s.Meshes
|
||||||
|
}
|
||||||
|
|
||||||
// NewMeshManagerParams params required to create an instance of a mesh manager
|
// NewMeshManagerParams params required to create an instance of a mesh manager
|
||||||
type NewMeshManagerParams struct {
|
type NewMeshManagerParams struct {
|
||||||
Conf conf.WgMeshConfiguration
|
Conf conf.WgMeshConfiguration
|
||||||
@ -278,10 +303,11 @@ type NewMeshManagerParams struct {
|
|||||||
IdGenerator lib.IdGenerator
|
IdGenerator lib.IdGenerator
|
||||||
IPAllocator ip.IPAllocator
|
IPAllocator ip.IPAllocator
|
||||||
InterfaceManipulator wg.WgInterfaceManipulator
|
InterfaceManipulator wg.WgInterfaceManipulator
|
||||||
|
ConfigApplyer MeshConfigApplyer
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a new instance of a mesh manager with the given parameters
|
// Creates a new instance of a mesh manager with the given parameters
|
||||||
func NewMeshManager(params *NewMeshManagerParams) *MeshManager {
|
func NewMeshManager(params *NewMeshManagerParams) *MeshManagerImpl {
|
||||||
hostParams := HostParameters{}
|
hostParams := HostParameters{}
|
||||||
|
|
||||||
switch params.Conf.Endpoint {
|
switch params.Conf.Endpoint {
|
||||||
@ -293,7 +319,7 @@ func NewMeshManager(params *NewMeshManagerParams) *MeshManager {
|
|||||||
|
|
||||||
logging.Log.WriteInfof("Endpoint %s", hostParams.HostEndpoint)
|
logging.Log.WriteInfof("Endpoint %s", hostParams.HostEndpoint)
|
||||||
|
|
||||||
m := &MeshManager{
|
m := &MeshManagerImpl{
|
||||||
Meshes: make(map[string]MeshProvider),
|
Meshes: make(map[string]MeshProvider),
|
||||||
HostParameters: &hostParams,
|
HostParameters: &hostParams,
|
||||||
meshProviderFactory: params.MeshProvider,
|
meshProviderFactory: params.MeshProvider,
|
||||||
@ -301,7 +327,7 @@ func NewMeshManager(params *NewMeshManagerParams) *MeshManager {
|
|||||||
Client: params.Client,
|
Client: params.Client,
|
||||||
conf: ¶ms.Conf,
|
conf: ¶ms.Conf,
|
||||||
}
|
}
|
||||||
m.configApplyer = NewWgMeshConfigApplyer(m)
|
m.configApplyer = params.ConfigApplyer
|
||||||
m.RouteManager = NewRouteManager(m)
|
m.RouteManager = NewRouteManager(m)
|
||||||
m.idGenerator = params.IdGenerator
|
m.idGenerator = params.IdGenerator
|
||||||
m.ipAllocator = params.IPAllocator
|
m.ipAllocator = params.IPAllocator
|
||||||
|
246
pkg/mesh/manager_test.go
Normal file
246
pkg/mesh/manager_test.go
Normal file
@ -0,0 +1,246 @@
|
|||||||
|
package mesh
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/tim-beatham/wgmesh/pkg/conf"
|
||||||
|
"github.com/tim-beatham/wgmesh/pkg/ip"
|
||||||
|
"github.com/tim-beatham/wgmesh/pkg/lib"
|
||||||
|
"github.com/tim-beatham/wgmesh/pkg/wg"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getMeshConfiguration() *conf.WgMeshConfiguration {
|
||||||
|
return &conf.WgMeshConfiguration{
|
||||||
|
GrpcPort: "8080",
|
||||||
|
Endpoint: "abc.com",
|
||||||
|
ClusterSize: 64,
|
||||||
|
SyncRate: 4,
|
||||||
|
BranchRate: 3,
|
||||||
|
InterClusterChance: 0.15,
|
||||||
|
InfectionCount: 2,
|
||||||
|
KeepAliveRate: 60,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getMeshManager() *MeshManagerImpl {
|
||||||
|
manager := NewMeshManager(&NewMeshManagerParams{
|
||||||
|
Conf: *getMeshConfiguration(),
|
||||||
|
Client: nil,
|
||||||
|
MeshProvider: &StubMeshProviderFactory{},
|
||||||
|
NodeFactory: &StubNodeFactory{Config: getMeshConfiguration()},
|
||||||
|
IdGenerator: &lib.UUIDGenerator{},
|
||||||
|
IPAllocator: &ip.ULABuilder{},
|
||||||
|
InterfaceManipulator: &wg.WgInterfaceManipulatorStub{},
|
||||||
|
ConfigApplyer: &MeshConfigApplyerStub{},
|
||||||
|
})
|
||||||
|
|
||||||
|
return manager
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateMeshCreatesANewMeshProvider(t *testing.T) {
|
||||||
|
manager := getMeshManager()
|
||||||
|
|
||||||
|
meshId, err := manager.CreateMesh("wg0", 5000)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(meshId) == 0 {
|
||||||
|
t.Fatal(`meshId should not be empty`)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, exists := manager.Meshes[meshId]
|
||||||
|
|
||||||
|
if !exists {
|
||||||
|
t.Fatal(`mesh was not created when it should be`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddMeshAddsAMesh(t *testing.T) {
|
||||||
|
manager := getMeshManager()
|
||||||
|
meshId := "meshid123"
|
||||||
|
|
||||||
|
manager.AddMesh(&AddMeshParams{
|
||||||
|
MeshId: meshId,
|
||||||
|
DevName: "wg0",
|
||||||
|
WgPort: 6000,
|
||||||
|
MeshBytes: make([]byte, 0),
|
||||||
|
})
|
||||||
|
|
||||||
|
mesh := manager.GetMesh(meshId)
|
||||||
|
|
||||||
|
if mesh == nil || mesh.GetMeshId() != meshId {
|
||||||
|
t.Fatalf(`mesh has not been added to the list of meshes`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddMeshMeshAlreadyExistsReplacesIt(t *testing.T) {
|
||||||
|
manager := getMeshManager()
|
||||||
|
meshId := "meshid123"
|
||||||
|
|
||||||
|
for i := 0; i < 2; i++ {
|
||||||
|
err := manager.AddMesh(&AddMeshParams{
|
||||||
|
MeshId: meshId,
|
||||||
|
DevName: "wg0",
|
||||||
|
WgPort: 6000,
|
||||||
|
MeshBytes: make([]byte, 0),
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mesh := manager.GetMesh(meshId)
|
||||||
|
|
||||||
|
if mesh == nil || mesh.GetMeshId() != meshId {
|
||||||
|
t.Fatalf(`mesh has not been added to the list of meshes`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddSelfAddsSelfToTheMesh(t *testing.T) {
|
||||||
|
manager := getMeshManager()
|
||||||
|
meshId := "meshid123"
|
||||||
|
|
||||||
|
err := manager.AddMesh(&AddMeshParams{
|
||||||
|
MeshId: meshId,
|
||||||
|
DevName: "wg0",
|
||||||
|
WgPort: 6000,
|
||||||
|
MeshBytes: make([]byte, 0),
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = manager.AddSelf(&AddSelfParams{
|
||||||
|
MeshId: meshId,
|
||||||
|
WgPort: 5000,
|
||||||
|
Endpoint: "abc.com",
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
mesh, err := manager.GetMesh(meshId).GetMesh()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, ok := mesh.GetNodes()["abc.com"]
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf(`node has not been added`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddSelfToMeshAlreadyInMesh(t *testing.T) {
|
||||||
|
TestAddSelfAddsSelfToTheMesh(t)
|
||||||
|
TestAddSelfAddsSelfToTheMesh(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddSelfToMeshMeshDoesNotExist(t *testing.T) {
|
||||||
|
manager := getMeshManager()
|
||||||
|
meshId := "meshid123"
|
||||||
|
|
||||||
|
err := manager.AddSelf(&AddSelfParams{
|
||||||
|
MeshId: meshId,
|
||||||
|
WgPort: 5000,
|
||||||
|
Endpoint: "abc.com",
|
||||||
|
})
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf(`Expected error to be thrown`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLeaveMeshMeshDoesNotExist(t *testing.T) {
|
||||||
|
manager := getMeshManager()
|
||||||
|
meshId := "meshid123"
|
||||||
|
|
||||||
|
err := manager.LeaveMesh(meshId)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf(`Expected error to be thrown`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLeaveMeshDeletesMesh(t *testing.T) {
|
||||||
|
manager := getMeshManager()
|
||||||
|
meshId := "meshid123"
|
||||||
|
|
||||||
|
err := manager.AddMesh(&AddMeshParams{
|
||||||
|
MeshId: meshId,
|
||||||
|
DevName: "wg0",
|
||||||
|
WgPort: 6000,
|
||||||
|
MeshBytes: make([]byte, 0),
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = manager.LeaveMesh(meshId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, exists := manager.Meshes[meshId]
|
||||||
|
|
||||||
|
if exists {
|
||||||
|
t.Fatalf(`expected mesh to have been deleted`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetDescription(t *testing.T) {
|
||||||
|
manager := getMeshManager()
|
||||||
|
description := "wooooo"
|
||||||
|
|
||||||
|
meshId1, _ := manager.CreateMesh("wg0", 5000)
|
||||||
|
meshId2, _ := manager.CreateMesh("wg0", 5001)
|
||||||
|
|
||||||
|
manager.AddSelf(&AddSelfParams{
|
||||||
|
MeshId: meshId1,
|
||||||
|
WgPort: 5000,
|
||||||
|
Endpoint: "abc.com:8080",
|
||||||
|
})
|
||||||
|
manager.AddSelf(&AddSelfParams{
|
||||||
|
MeshId: meshId2,
|
||||||
|
WgPort: 5000,
|
||||||
|
Endpoint: "abc.com:8080",
|
||||||
|
})
|
||||||
|
|
||||||
|
err := manager.SetDescription(description)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf(`failed to set the descriptions`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUpdateTimeStampUpdatesAllMeshes(t *testing.T) {
|
||||||
|
manager := getMeshManager()
|
||||||
|
|
||||||
|
meshId1, _ := manager.CreateMesh("wg0", 5000)
|
||||||
|
meshId2, _ := manager.CreateMesh("wg0", 5001)
|
||||||
|
|
||||||
|
manager.AddSelf(&AddSelfParams{
|
||||||
|
MeshId: meshId1,
|
||||||
|
WgPort: 5000,
|
||||||
|
Endpoint: "abc.com:8080",
|
||||||
|
})
|
||||||
|
manager.AddSelf(&AddSelfParams{
|
||||||
|
MeshId: meshId2,
|
||||||
|
WgPort: 5000,
|
||||||
|
Endpoint: "abc.com:8080",
|
||||||
|
})
|
||||||
|
|
||||||
|
err := manager.UpdateTimeStamp()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf(`failed to update the timestamp`)
|
||||||
|
}
|
||||||
|
}
|
@ -11,12 +11,12 @@ type RouteManager interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type RouteManagerImpl struct {
|
type RouteManagerImpl struct {
|
||||||
meshManager *MeshManager
|
meshManager MeshManager
|
||||||
routeInstaller route.RouteInstaller
|
routeInstaller route.RouteInstaller
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RouteManagerImpl) UpdateRoutes() error {
|
func (r *RouteManagerImpl) UpdateRoutes() error {
|
||||||
meshes := r.meshManager.Meshes
|
meshes := r.meshManager.GetMeshes()
|
||||||
ulaBuilder := new(ip.ULABuilder)
|
ulaBuilder := new(ip.ULABuilder)
|
||||||
|
|
||||||
for _, mesh1 := range meshes {
|
for _, mesh1 := range meshes {
|
||||||
@ -32,7 +32,13 @@ func (r *RouteManagerImpl) UpdateRoutes() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = mesh1.AddRoutes(r.meshManager.HostParameters.HostEndpoint, ipNet.String())
|
self, err := r.meshManager.GetSelf(mesh1.GetMeshId())
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = mesh1.AddRoutes(self.GetHostEndpoint(), ipNet.String())
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -43,6 +49,6 @@ func (r *RouteManagerImpl) UpdateRoutes() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRouteManager(m *MeshManager) RouteManager {
|
func NewRouteManager(m MeshManager) RouteManager {
|
||||||
return &RouteManagerImpl{meshManager: m, routeInstaller: route.NewRouteInstaller()}
|
return &RouteManagerImpl{meshManager: m, routeInstaller: route.NewRouteInstaller()}
|
||||||
}
|
}
|
||||||
|
227
pkg/mesh/stub_types.go
Normal file
227
pkg/mesh/stub_types.go
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
package mesh
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/tim-beatham/wgmesh/pkg/conf"
|
||||||
|
"golang.zx2c4.com/wireguard/wgctrl"
|
||||||
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MeshNodeStub struct {
|
||||||
|
hostEndpoint string
|
||||||
|
publicKey wgtypes.Key
|
||||||
|
wgEndpoint string
|
||||||
|
wgHost *net.IPNet
|
||||||
|
timeStamp int64
|
||||||
|
routes []string
|
||||||
|
identifier string
|
||||||
|
description string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MeshNodeStub) GetHostEndpoint() string {
|
||||||
|
return m.hostEndpoint
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MeshNodeStub) GetPublicKey() (wgtypes.Key, error) {
|
||||||
|
return m.publicKey, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MeshNodeStub) GetWgEndpoint() string {
|
||||||
|
return m.wgEndpoint
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MeshNodeStub) GetWgHost() *net.IPNet {
|
||||||
|
return m.wgHost
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MeshNodeStub) GetTimeStamp() int64 {
|
||||||
|
return m.timeStamp
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MeshNodeStub) GetRoutes() []string {
|
||||||
|
return m.routes
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MeshNodeStub) GetIdentifier() string {
|
||||||
|
return m.identifier
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MeshNodeStub) GetDescription() string {
|
||||||
|
return m.description
|
||||||
|
}
|
||||||
|
|
||||||
|
type MeshSnapshotStub struct {
|
||||||
|
nodes map[string]MeshNode
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MeshSnapshotStub) GetNodes() map[string]MeshNode {
|
||||||
|
return s.nodes
|
||||||
|
}
|
||||||
|
|
||||||
|
type MeshProviderStub struct {
|
||||||
|
meshId string
|
||||||
|
snapshot *MeshSnapshotStub
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateTimeStamp implements MeshProvider.
|
||||||
|
func (*MeshProviderStub) UpdateTimeStamp(nodeId string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MeshProviderStub) AddNode(node MeshNode) {
|
||||||
|
s.snapshot.nodes[node.GetHostEndpoint()] = node
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MeshProviderStub) GetMesh() (MeshSnapshot, error) {
|
||||||
|
return s.snapshot, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MeshProviderStub) GetMeshId() string {
|
||||||
|
return s.meshId
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MeshProviderStub) Save() []byte {
|
||||||
|
return make([]byte, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MeshProviderStub) Load(bytes []byte) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MeshProviderStub) GetDevice() (*wgtypes.Device, error) {
|
||||||
|
pubKey, _ := wgtypes.GenerateKey()
|
||||||
|
return &wgtypes.Device{
|
||||||
|
PublicKey: pubKey,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MeshProviderStub) SaveChanges() {}
|
||||||
|
|
||||||
|
func (s *MeshProviderStub) HasChanges() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MeshProviderStub) AddRoutes(nodeId string, route ...string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MeshProviderStub) GetSyncer() MeshSyncer {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MeshProviderStub) SetDescription(nodeId string, description string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type StubMeshProviderFactory struct{}
|
||||||
|
|
||||||
|
func (s *StubMeshProviderFactory) CreateMesh(params *MeshProviderFactoryParams) (MeshProvider, error) {
|
||||||
|
return &MeshProviderStub{
|
||||||
|
meshId: params.MeshId,
|
||||||
|
snapshot: &MeshSnapshotStub{nodes: make(map[string]MeshNode)},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type StubNodeFactory struct {
|
||||||
|
Config *conf.WgMeshConfiguration
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StubNodeFactory) Build(params *MeshNodeFactoryParams) MeshNode {
|
||||||
|
_, wgHost, _ := net.ParseCIDR(fmt.Sprintf("%s/128", params.NodeIP.String()))
|
||||||
|
|
||||||
|
return &MeshNodeStub{
|
||||||
|
hostEndpoint: params.Endpoint,
|
||||||
|
publicKey: *params.PublicKey,
|
||||||
|
wgEndpoint: fmt.Sprintf("%s:%s", params.Endpoint, s.Config.GrpcPort),
|
||||||
|
wgHost: wgHost,
|
||||||
|
timeStamp: time.Now().Unix(),
|
||||||
|
routes: make([]string, 0),
|
||||||
|
identifier: "abc",
|
||||||
|
description: "A Mesh Node Stub",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type MeshConfigApplyerStub struct{}
|
||||||
|
|
||||||
|
func (a *MeshConfigApplyerStub) ApplyConfig() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *MeshConfigApplyerStub) RemovePeers(meshId string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type MeshManagerStub struct {
|
||||||
|
meshes map[string]MeshProvider
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMeshManagerStub() MeshManager {
|
||||||
|
return &MeshManagerStub{meshes: make(map[string]MeshProvider)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MeshManagerStub) CreateMesh(devName string, port int) (string, error) {
|
||||||
|
return "tim123", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MeshManagerStub) AddMesh(params *AddMeshParams) error {
|
||||||
|
m.meshes[params.MeshId] = &MeshProviderStub{
|
||||||
|
params.MeshId,
|
||||||
|
&MeshSnapshotStub{nodes: make(map[string]MeshNode)},
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MeshManagerStub) HasChanges(meshId string) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MeshManagerStub) GetMesh(meshId string) MeshProvider {
|
||||||
|
return &MeshProviderStub{
|
||||||
|
meshId: meshId,
|
||||||
|
snapshot: &MeshSnapshotStub{nodes: make(map[string]MeshNode)}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MeshManagerStub) EnableInterface(meshId string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MeshManagerStub) GetPublicKey(meshId string) (*wgtypes.Key, error) {
|
||||||
|
key, _ := wgtypes.GenerateKey()
|
||||||
|
return &key, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MeshManagerStub) AddSelf(params *AddSelfParams) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MeshManagerStub) GetSelf(meshId string) (MeshNode, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MeshManagerStub) ApplyConfig() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MeshManagerStub) SetDescription(description string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MeshManagerStub) UpdateTimeStamp() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MeshManagerStub) GetClient() *wgctrl.Client {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MeshManagerStub) GetMeshes() map[string]MeshProvider {
|
||||||
|
return m.meshes
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MeshManagerStub) LeaveMesh(meshId string) error {
|
||||||
|
return nil
|
||||||
|
}
|
@ -1,29 +0,0 @@
|
|||||||
package middleware
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
logging "github.com/tim-beatham/wgmesh/pkg/log"
|
|
||||||
"github.com/tim-beatham/wgmesh/pkg/rpc"
|
|
||||||
)
|
|
||||||
|
|
||||||
// AuthRpcProvider implements the AuthRpcProvider service
|
|
||||||
type AuthRpcProvider struct {
|
|
||||||
rpc.UnimplementedAuthenticationServer
|
|
||||||
}
|
|
||||||
|
|
||||||
// JoinMesh handles a JoinMeshRequest. Succeeds by stating the node managed to join the mesh
|
|
||||||
// or returns an error if it failed
|
|
||||||
func (a *AuthRpcProvider) JoinMesh(ctx context.Context, in *rpc.JoinAuthMeshRequest) (*rpc.JoinAuthMeshReply, error) {
|
|
||||||
meshId := in.MeshId
|
|
||||||
|
|
||||||
if meshId == "" {
|
|
||||||
return nil, errors.New("Must specify the meshId")
|
|
||||||
}
|
|
||||||
|
|
||||||
logging.Log.WriteInfof("MeshID: " + in.MeshId)
|
|
||||||
|
|
||||||
var token string = ""
|
|
||||||
return &rpc.JoinAuthMeshReply{Success: true, Token: &token}, nil
|
|
||||||
}
|
|
@ -16,7 +16,7 @@ type Querier interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type JmesQuerier struct {
|
type JmesQuerier struct {
|
||||||
manager *mesh.MeshManager
|
manager mesh.MeshManager
|
||||||
}
|
}
|
||||||
|
|
||||||
type QueryError struct {
|
type QueryError struct {
|
||||||
@ -39,7 +39,7 @@ func (m *QueryError) Error() string {
|
|||||||
|
|
||||||
// Query: queries the data
|
// Query: queries the data
|
||||||
func (j *JmesQuerier) Query(meshId, queryParams string) ([]byte, error) {
|
func (j *JmesQuerier) Query(meshId, queryParams string) ([]byte, error) {
|
||||||
mesh, ok := j.manager.Meshes[meshId]
|
mesh, ok := j.manager.GetMeshes()[meshId]
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, &QueryError{msg: fmt.Sprintf("%s does not exist", meshId)}
|
return nil, &QueryError{msg: fmt.Sprintf("%s does not exist", meshId)}
|
||||||
@ -79,6 +79,6 @@ func meshNodeToQueryNode(node mesh.MeshNode) *QueryNode {
|
|||||||
return queryNode
|
return queryNode
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewJmesQuerier(manager *mesh.MeshManager) Querier {
|
func NewJmesQuerier(manager mesh.MeshManager) Querier {
|
||||||
return &JmesQuerier{manager: manager}
|
return &JmesQuerier{manager: manager}
|
||||||
}
|
}
|
||||||
|
@ -8,25 +8,23 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/tim-beatham/wgmesh/pkg/ctrlserver"
|
"github.com/tim-beatham/wgmesh/pkg/ctrlserver"
|
||||||
"github.com/tim-beatham/wgmesh/pkg/ip"
|
|
||||||
"github.com/tim-beatham/wgmesh/pkg/ipc"
|
"github.com/tim-beatham/wgmesh/pkg/ipc"
|
||||||
"github.com/tim-beatham/wgmesh/pkg/mesh"
|
"github.com/tim-beatham/wgmesh/pkg/mesh"
|
||||||
"github.com/tim-beatham/wgmesh/pkg/rpc"
|
"github.com/tim-beatham/wgmesh/pkg/rpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
type IpcHandler struct {
|
type IpcHandler struct {
|
||||||
Server *ctrlserver.MeshCtrlServer
|
Server ctrlserver.CtrlServer
|
||||||
ipAllocator ip.IPAllocator
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *IpcHandler) CreateMesh(args *ipc.NewMeshArgs, reply *string) error {
|
func (n *IpcHandler) CreateMesh(args *ipc.NewMeshArgs, reply *string) error {
|
||||||
meshId, err := n.Server.MeshManager.CreateMesh(args.IfName, args.WgPort)
|
meshId, err := n.Server.GetMeshManager().CreateMesh(args.IfName, args.WgPort)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = n.Server.MeshManager.AddSelf(&mesh.AddSelfParams{
|
err = n.Server.GetMeshManager().AddSelf(&mesh.AddSelfParams{
|
||||||
MeshId: meshId,
|
MeshId: meshId,
|
||||||
WgPort: args.WgPort,
|
WgPort: args.WgPort,
|
||||||
Endpoint: args.Endpoint,
|
Endpoint: args.Endpoint,
|
||||||
@ -37,10 +35,10 @@ func (n *IpcHandler) CreateMesh(args *ipc.NewMeshArgs, reply *string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (n *IpcHandler) ListMeshes(_ string, reply *ipc.ListMeshReply) error {
|
func (n *IpcHandler) ListMeshes(_ string, reply *ipc.ListMeshReply) error {
|
||||||
meshNames := make([]string, len(n.Server.MeshManager.Meshes))
|
meshNames := make([]string, len(n.Server.GetMeshManager().GetMeshes()))
|
||||||
|
|
||||||
i := 0
|
i := 0
|
||||||
for meshId, _ := range n.Server.MeshManager.Meshes {
|
for meshId, _ := range n.Server.GetMeshManager().GetMeshes() {
|
||||||
meshNames[i] = meshId
|
meshNames[i] = meshId
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
@ -50,7 +48,7 @@ func (n *IpcHandler) ListMeshes(_ string, reply *ipc.ListMeshReply) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (n *IpcHandler) JoinMesh(args ipc.JoinMeshArgs, reply *string) error {
|
func (n *IpcHandler) JoinMesh(args ipc.JoinMeshArgs, reply *string) error {
|
||||||
peerConnection, err := n.Server.ConnectionManager.GetConnection(args.IpAdress)
|
peerConnection, err := n.Server.GetConnectionManager().GetConnection(args.IpAdress)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -77,7 +75,7 @@ func (n *IpcHandler) JoinMesh(args ipc.JoinMeshArgs, reply *string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = n.Server.MeshManager.AddMesh(&mesh.AddMeshParams{
|
err = n.Server.GetMeshManager().AddMesh(&mesh.AddMeshParams{
|
||||||
MeshId: args.MeshId,
|
MeshId: args.MeshId,
|
||||||
DevName: args.IfName,
|
DevName: args.IfName,
|
||||||
WgPort: args.Port,
|
WgPort: args.Port,
|
||||||
@ -88,7 +86,7 @@ func (n *IpcHandler) JoinMesh(args ipc.JoinMeshArgs, reply *string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = n.Server.MeshManager.AddSelf(&mesh.AddSelfParams{
|
err = n.Server.GetMeshManager().AddSelf(&mesh.AddSelfParams{
|
||||||
MeshId: args.MeshId,
|
MeshId: args.MeshId,
|
||||||
WgPort: args.Port,
|
WgPort: args.Port,
|
||||||
Endpoint: args.Endpoint,
|
Endpoint: args.Endpoint,
|
||||||
@ -104,7 +102,7 @@ func (n *IpcHandler) JoinMesh(args ipc.JoinMeshArgs, reply *string) error {
|
|||||||
|
|
||||||
// LeaveMesh leaves a mesh network
|
// LeaveMesh leaves a mesh network
|
||||||
func (n *IpcHandler) LeaveMesh(meshId string, reply *string) error {
|
func (n *IpcHandler) LeaveMesh(meshId string, reply *string) error {
|
||||||
err := n.Server.MeshManager.LeaveMesh(meshId)
|
err := n.Server.GetMeshManager().LeaveMesh(meshId)
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
*reply = fmt.Sprintf("Left Mesh %s", meshId)
|
*reply = fmt.Sprintf("Left Mesh %s", meshId)
|
||||||
@ -114,7 +112,7 @@ func (n *IpcHandler) LeaveMesh(meshId string, reply *string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (n *IpcHandler) GetMesh(meshId string, reply *ipc.GetMeshReply) error {
|
func (n *IpcHandler) GetMesh(meshId string, reply *ipc.GetMeshReply) error {
|
||||||
mesh := n.Server.MeshManager.GetMesh(meshId)
|
mesh := n.Server.GetMeshManager().GetMesh(meshId)
|
||||||
meshSnapshot, err := mesh.GetMesh()
|
meshSnapshot, err := mesh.GetMesh()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -152,7 +150,7 @@ func (n *IpcHandler) GetMesh(meshId string, reply *ipc.GetMeshReply) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (n *IpcHandler) EnableInterface(meshId string, reply *string) error {
|
func (n *IpcHandler) EnableInterface(meshId string, reply *string) error {
|
||||||
err := n.Server.MeshManager.EnableInterface(meshId)
|
err := n.Server.GetMeshManager().EnableInterface(meshId)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
*reply = err.Error()
|
*reply = err.Error()
|
||||||
@ -164,7 +162,7 @@ func (n *IpcHandler) EnableInterface(meshId string, reply *string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (n *IpcHandler) GetDOT(meshId string, reply *string) error {
|
func (n *IpcHandler) GetDOT(meshId string, reply *string) error {
|
||||||
g := mesh.NewMeshDotConverter(n.Server.MeshManager)
|
g := mesh.NewMeshDotConverter(n.Server.GetMeshManager())
|
||||||
|
|
||||||
result, err := g.Generate(meshId)
|
result, err := g.Generate(meshId)
|
||||||
|
|
||||||
@ -177,7 +175,7 @@ func (n *IpcHandler) GetDOT(meshId string, reply *string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (n *IpcHandler) Query(params ipc.QueryMesh, reply *string) error {
|
func (n *IpcHandler) Query(params ipc.QueryMesh, reply *string) error {
|
||||||
queryResponse, err := n.Server.Querier.Query(params.MeshId, params.Query)
|
queryResponse, err := n.Server.GetQuerier().Query(params.MeshId, params.Query)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -188,7 +186,7 @@ func (n *IpcHandler) Query(params ipc.QueryMesh, reply *string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (n *IpcHandler) PutDescription(description string, reply *string) error {
|
func (n *IpcHandler) PutDescription(description string, reply *string) error {
|
||||||
err := n.Server.MeshManager.SetDescription(description)
|
err := n.Server.GetMeshManager().SetDescription(description)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -199,7 +197,7 @@ func (n *IpcHandler) PutDescription(description string, reply *string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type RobinIpcParams struct {
|
type RobinIpcParams struct {
|
||||||
CtrlServer *ctrlserver.MeshCtrlServer
|
CtrlServer ctrlserver.CtrlServer
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRobinIpc(ipcParams RobinIpcParams) IpcHandler {
|
func NewRobinIpc(ipcParams RobinIpcParams) IpcHandler {
|
||||||
|
73
pkg/robin/requester_test.go
Normal file
73
pkg/robin/requester_test.go
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
package robin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/tim-beatham/wgmesh/pkg/ctrlserver"
|
||||||
|
"github.com/tim-beatham/wgmesh/pkg/ipc"
|
||||||
|
"github.com/tim-beatham/wgmesh/pkg/mesh"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getRequester() *IpcHandler {
|
||||||
|
return &IpcHandler{Server: ctrlserver.NewCtrlServerStub()}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateMeshRepliesMeshId(t *testing.T) {
|
||||||
|
var reply string
|
||||||
|
requester := getRequester()
|
||||||
|
|
||||||
|
err := requester.CreateMesh(&ipc.NewMeshArgs{
|
||||||
|
IfName: "wg0",
|
||||||
|
WgPort: 5000,
|
||||||
|
Endpoint: "abc.com",
|
||||||
|
}, &reply)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(reply) == 0 {
|
||||||
|
t.Fatalf(`reply should have been returned`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListMeshesNoMeshesListsEmpty(t *testing.T) {
|
||||||
|
var reply ipc.ListMeshReply
|
||||||
|
requester := getRequester()
|
||||||
|
|
||||||
|
err := requester.ListMeshes("", &reply)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(reply.Meshes) != 0 {
|
||||||
|
t.Fatalf(`meshes should be empty`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListMeshesMeshesNotEmpty(t *testing.T) {
|
||||||
|
var reply ipc.ListMeshReply
|
||||||
|
requester := getRequester()
|
||||||
|
|
||||||
|
requester.Server.GetMeshManager().AddMesh(&mesh.AddMeshParams{
|
||||||
|
MeshId: "tim123",
|
||||||
|
DevName: "wg0",
|
||||||
|
WgPort: 5000,
|
||||||
|
MeshBytes: make([]byte, 0),
|
||||||
|
})
|
||||||
|
|
||||||
|
err := requester.ListMeshes("", &reply)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(reply.Meshes) != 1 {
|
||||||
|
t.Fatalf(`only only mesh exists`)
|
||||||
|
}
|
||||||
|
|
||||||
|
if reply.Meshes[0] != "tim123" {
|
||||||
|
t.Fatalf(`meshId was %s expected %s`, reply.Meshes[0], "tim123")
|
||||||
|
}
|
||||||
|
}
|
@ -13,29 +13,6 @@ type WgRpc struct {
|
|||||||
Server *ctrlserver.MeshCtrlServer
|
Server *ctrlserver.MeshCtrlServer
|
||||||
}
|
}
|
||||||
|
|
||||||
func nodeToRpcNode(node ctrlserver.MeshNode) *rpc.MeshNode {
|
|
||||||
return &rpc.MeshNode{
|
|
||||||
PublicKey: node.PublicKey,
|
|
||||||
WgEndpoint: node.WgEndpoint,
|
|
||||||
WgHost: node.WgHost,
|
|
||||||
Endpoint: node.HostEndpoint,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func nodesToRpcNodes(nodes map[string]ctrlserver.MeshNode) []*rpc.MeshNode {
|
|
||||||
n := len(nodes)
|
|
||||||
meshNodes := make([]*rpc.MeshNode, n)
|
|
||||||
|
|
||||||
var i int = 0
|
|
||||||
|
|
||||||
for _, v := range nodes {
|
|
||||||
meshNodes[i] = nodeToRpcNode(v)
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
|
|
||||||
return meshNodes
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *WgRpc) GetMesh(ctx context.Context, request *rpc.GetMeshRequest) (*rpc.GetMeshReply, error) {
|
func (m *WgRpc) GetMesh(ctx context.Context, request *rpc.GetMeshRequest) (*rpc.GetMeshReply, error) {
|
||||||
mesh := m.Server.MeshManager.GetMesh(request.MeshId)
|
mesh := m.Server.MeshManager.GetMesh(request.MeshId)
|
||||||
|
|
||||||
|
1
pkg/robin/responder_test.go
Normal file
1
pkg/robin/responder_test.go
Normal file
@ -0,0 +1 @@
|
|||||||
|
package robin
|
@ -20,7 +20,7 @@ type Syncer interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SyncerImpl struct {
|
type SyncerImpl struct {
|
||||||
manager *mesh.MeshManager
|
manager mesh.MeshManager
|
||||||
requester SyncRequester
|
requester SyncRequester
|
||||||
infectionCount int
|
infectionCount int
|
||||||
syncCount int
|
syncCount int
|
||||||
@ -56,8 +56,14 @@ func (s *SyncerImpl) Sync(meshId string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self, err := s.manager.GetSelf(meshId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
excludedNodes := map[string]struct{}{
|
excludedNodes := map[string]struct{}{
|
||||||
s.manager.HostParameters.HostEndpoint: {},
|
self.GetHostEndpoint(): {},
|
||||||
}
|
}
|
||||||
meshNodes := lib.MapValuesWithExclude(nodes, excludedNodes)
|
meshNodes := lib.MapValuesWithExclude(nodes, excludedNodes)
|
||||||
|
|
||||||
@ -67,7 +73,7 @@ func (s *SyncerImpl) Sync(meshId string) error {
|
|||||||
|
|
||||||
nodeNames := lib.Map(meshNodes, getNames)
|
nodeNames := lib.Map(meshNodes, getNames)
|
||||||
|
|
||||||
neighbours := s.cluster.GetNeighbours(nodeNames, s.manager.HostParameters.HostEndpoint)
|
neighbours := s.cluster.GetNeighbours(nodeNames, self.GetHostEndpoint())
|
||||||
randomSubset := lib.RandomSubsetOfLength(neighbours, s.conf.BranchRate)
|
randomSubset := lib.RandomSubsetOfLength(neighbours, s.conf.BranchRate)
|
||||||
|
|
||||||
for _, node := range randomSubset {
|
for _, node := range randomSubset {
|
||||||
@ -78,7 +84,7 @@ func (s *SyncerImpl) Sync(meshId string) error {
|
|||||||
|
|
||||||
if len(meshNodes) > s.conf.ClusterSize && rand.Float64() < s.conf.InterClusterChance {
|
if len(meshNodes) > s.conf.ClusterSize && rand.Float64() < s.conf.InterClusterChance {
|
||||||
logging.Log.WriteInfof("Sending to random cluster")
|
logging.Log.WriteInfof("Sending to random cluster")
|
||||||
interCluster := s.cluster.GetInterCluster(nodeNames, s.manager.HostParameters.HostEndpoint)
|
interCluster := s.cluster.GetInterCluster(nodeNames, self.GetHostEndpoint())
|
||||||
randomSubset = append(randomSubset, interCluster)
|
randomSubset = append(randomSubset, interCluster)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,7 +113,7 @@ func (s *SyncerImpl) Sync(meshId string) error {
|
|||||||
|
|
||||||
// SyncMeshes: Sync all meshes
|
// SyncMeshes: Sync all meshes
|
||||||
func (s *SyncerImpl) SyncMeshes() error {
|
func (s *SyncerImpl) SyncMeshes() error {
|
||||||
for meshId, _ := range s.manager.Meshes {
|
for meshId, _ := range s.manager.GetMeshes() {
|
||||||
err := s.Sync(meshId)
|
err := s.Sync(meshId)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -118,7 +124,7 @@ func (s *SyncerImpl) SyncMeshes() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSyncer(m *mesh.MeshManager, conf *conf.WgMeshConfiguration, r SyncRequester) Syncer {
|
func NewSyncer(m mesh.MeshManager, conf *conf.WgMeshConfiguration, r SyncRequester) Syncer {
|
||||||
cluster, _ := conn.NewConnCluster(conf.ClusterSize)
|
cluster, _ := conn.NewConnCluster(conf.ClusterSize)
|
||||||
return &SyncerImpl{
|
return &SyncerImpl{
|
||||||
manager: m,
|
manager: m,
|
||||||
|
@ -14,7 +14,7 @@ type SyncErrorHandler interface {
|
|||||||
|
|
||||||
// SyncErrorHandlerImpl Is an implementation of the SyncErrorHandler
|
// SyncErrorHandlerImpl Is an implementation of the SyncErrorHandler
|
||||||
type SyncErrorHandlerImpl struct {
|
type SyncErrorHandlerImpl struct {
|
||||||
meshManager *mesh.MeshManager
|
meshManager mesh.MeshManager
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SyncErrorHandlerImpl) incrementFailedCount(meshId string, endpoint string) bool {
|
func (s *SyncErrorHandlerImpl) incrementFailedCount(meshId string, endpoint string) bool {
|
||||||
@ -40,6 +40,6 @@ func (s *SyncErrorHandlerImpl) Handle(meshId string, endpoint string, err error)
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSyncErrorHandler(m *mesh.MeshManager) SyncErrorHandler {
|
func NewSyncErrorHandler(m mesh.MeshManager) SyncErrorHandler {
|
||||||
return &SyncErrorHandlerImpl{meshManager: m}
|
return &SyncErrorHandlerImpl{meshManager: m}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ type TimestampScheduler interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type TimeStampSchedulerImpl struct {
|
type TimeStampSchedulerImpl struct {
|
||||||
meshManager *mesh.MeshManager
|
meshManager mesh.MeshManager
|
||||||
updateRate int
|
updateRate int
|
||||||
quit chan struct{}
|
quit chan struct{}
|
||||||
}
|
}
|
||||||
|
11
pkg/wg/stubs.go
Normal file
11
pkg/wg/stubs.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package wg
|
||||||
|
|
||||||
|
type WgInterfaceManipulatorStub struct{}
|
||||||
|
|
||||||
|
func (i *WgInterfaceManipulatorStub) CreateInterface(params *CreateInterfaceParams) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *WgInterfaceManipulatorStub) EnableInterface(ifName string, ip string) error {
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user