diff --git a/controller.go b/controller.go index da943ff1256ceb4701dccf4b98a1bfe87a630b10..f286874790320c61744951965ac6891a329105e4 100644 --- a/controller.go +++ b/controller.go @@ -9,6 +9,8 @@ import ( "sync" "time" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/southbound" + "github.com/google/uuid" log "github.com/sirupsen/logrus" "github.com/spf13/viper" @@ -88,7 +90,7 @@ func createSouthboundInterfaces() error { } // createPrincipalNetworkDomain initializes the controller with an initial PND -func createPrincipalNetworkDomain(s nucleus.SouthboundInterface) error { +func createPrincipalNetworkDomain(s southbound.SouthboundInterface) error { pnd, err := nucleus.NewPND("base", "gosdn base pnd", uuid.New(), s) if err != nil { return err diff --git a/initialise_test.go b/initialise_test.go index 6994a752f978424529d604a7d823ed6be0f9ea9c..984cf81ec228f76245892538aab838209ac981c1 100644 --- a/initialise_test.go +++ b/initialise_test.go @@ -5,7 +5,10 @@ import ( "os" "testing" - "code.fbi.h-da.de/cocsn/gosdn/nucleus" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/device" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/networkdomain" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/southbound" + "code.fbi.h-da.de/cocsn/gosdn/nucleus/util/proto" "github.com/google/uuid" gpb "github.com/openconfig/gnmi/proto/gnmi" @@ -22,10 +25,10 @@ var defaultSbiID uuid.UUID var defaultPndID uuid.UUID var cuid uuid.UUID -var sbi nucleus.SouthboundInterface -var httpTestPND nucleus.PrincipalNetworkDomain +var sbi southbound.SouthboundInterface +var httpTestPND networkdomain.NetworkDomain var gnmiMessages map[string]pb.Message -var httpTestDevice nucleus.Device +var httpTestDevice device.Device var args string var argsNotFound string diff --git a/interfaces/change/change.go b/interfaces/change/change.go new file mode 100644 index 0000000000000000000000000000000000000000..9c861b44ad34de54f177e91f2b0eed2a590d6558 --- /dev/null +++ b/interfaces/change/change.go @@ -0,0 +1,13 @@ +package change + +import "github.com/google/uuid" + +// Change is an intended change to an OND. It is unique and immutable. +// It has a cuid, a timestamp, and holds both the previous and the new +// state. It keeps track if the state is committed and confirmed. A callback +// exists to acess the proper transport for the changed OND +type Change interface { + ID() uuid.UUID + Commit() error + Confirm() error +} diff --git a/interfaces/device/device.go b/interfaces/device/device.go new file mode 100644 index 0000000000000000000000000000000000000000..ca233d357a2fa26688eb2e63f1ee7b6213ccbea0 --- /dev/null +++ b/interfaces/device/device.go @@ -0,0 +1,20 @@ +package device + +import ( + "code.fbi.h-da.de/cocsn/gosdn/interfaces/southbound" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/transport" + "github.com/google/uuid" + "github.com/openconfig/ygot/ygot" + "google.golang.org/protobuf/proto" +) + +// Device represents an Orchestrated Network Device (OND) which is managed by +// nucleus +type Device interface { + ID() uuid.UUID + Model() ygot.GoStruct + Transport() transport.Transport + Name() string + SBI() southbound.SouthboundInterface + ProcessResponse(proto.Message) error +} diff --git a/interfaces/networkdomain/pnd.go b/interfaces/networkdomain/pnd.go new file mode 100644 index 0000000000000000000000000000000000000000..ce032d856f5d3ff64705593d7c2e2cef5c6b7b58 --- /dev/null +++ b/interfaces/networkdomain/pnd.go @@ -0,0 +1,37 @@ +package networkdomain + +import ( + ppb "code.fbi.h-da.de/cocsn/api/go/gosdn/pnd" + tpb "code.fbi.h-da.de/cocsn/api/go/gosdn/transport" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/change" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/device" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/southbound" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/store" + "github.com/google/uuid" +) + +// NetworkDomain provides an interface for network domain implementations +// like principal network domain or logical network domain. +type NetworkDomain interface { + Destroy() error + AddSbi(s southbound.SouthboundInterface) error + RemoveSbi(uuid.UUID) error + AddDevice(name string, opts *tpb.TransportOption, sid uuid.UUID) error + GetDevice(identifier string) (device.Device, error) + RemoveDevice(uuid.UUID) error + Devices() []uuid.UUID + ChangeOND(uuid uuid.UUID, operation ppb.ApiOperation, path string, value ...string) error + Request(uuid.UUID, string) error + RequestAll(string) error + GetName() string + GetDescription() string + MarshalDevice(string) (string, error) + ContainsDevice(uuid.UUID) bool + GetSBIs() store.Store + ID() uuid.UUID + PendingChanges() []uuid.UUID + CommittedChanges() []uuid.UUID + GetChange(uuid.UUID, ...int) (change.Change, error) + Commit(uuid.UUID) error + Confirm(uuid.UUID) error +} diff --git a/interfaces/southbound/sbi.go b/interfaces/southbound/sbi.go new file mode 100644 index 0000000000000000000000000000000000000000..0d4cdb56fd5290a849e33bd107a2ef55e31e3748 --- /dev/null +++ b/interfaces/southbound/sbi.go @@ -0,0 +1,25 @@ +package southbound + +import ( + spb "code.fbi.h-da.de/cocsn/api/go/gosdn/southbound" + + "github.com/google/uuid" + gpb "github.com/openconfig/gnmi/proto/gnmi" + "github.com/openconfig/goyang/pkg/yang" + "github.com/openconfig/ygot/ytypes" +) + +// SouthboundInterface provides an +// interface for SBI implementations +type SouthboundInterface interface { // nolint + // deprecated + SbiIdentifier() string + + // SetNode injects SBI specific model + // representation to the transport. + // Needed for type assertion. + SetNode() func(schema *yang.Entry, root interface{}, path *gpb.Path, val interface{}, opts ...ytypes.SetNodeOpt) error + Schema() *ytypes.Schema + ID() uuid.UUID + Type() spb.Type +} diff --git a/interfaces/store/store.go b/interfaces/store/store.go new file mode 100644 index 0000000000000000000000000000000000000000..7d4d4a6a7f51c1cbeb3f60b55587fd9fc205f858 --- /dev/null +++ b/interfaces/store/store.go @@ -0,0 +1,17 @@ +package store + +import "github.com/google/uuid" + +// Storable provides an interface for the controller's storage architecture. +type Storable interface { + ID() uuid.UUID +} + +// Store describes an interface for store implementations. +type Store interface { + Exists(id uuid.UUID) bool + Add(item Storable) error + Get(id uuid.UUID) (Storable, error) + Delete(id uuid.UUID) error + UUIDs() []uuid.UUID +} diff --git a/interfaces/transport/transport.go b/interfaces/transport/transport.go new file mode 100644 index 0000000000000000000000000000000000000000..24bc2ab02884dbb6fd8fe446e0cfca2aa0ce3bc4 --- /dev/null +++ b/interfaces/transport/transport.go @@ -0,0 +1,17 @@ +package transport + +import ( + "context" + + "github.com/openconfig/ygot/ytypes" +) + +// Transport provides an interface for Transport implementations +// like RESTCONF or gnmi +type Transport interface { + Get(ctx context.Context, params ...string) (interface{}, error) + Set(ctx context.Context, params ...interface{}) error + Subscribe(ctx context.Context, params ...string) error + Type() string + ProcessResponse(resp interface{}, root interface{}, models *ytypes.Schema) error +} diff --git a/mocks/Change.go b/mocks/Change.go new file mode 100644 index 0000000000000000000000000000000000000000..f59f4749d421b8e6dab4388044cd4c9feb3d6b8a --- /dev/null +++ b/mocks/Change.go @@ -0,0 +1,57 @@ +// Code generated by mockery 2.7.5. DO NOT EDIT. + +package mocks + +import ( + uuid "github.com/google/uuid" + mock "github.com/stretchr/testify/mock" +) + +// Change is an autogenerated mock type for the Change type +type Change struct { + mock.Mock +} + +// Commit provides a mock function with given fields: +func (_m *Change) Commit() error { + ret := _m.Called() + + var r0 error + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Confirm provides a mock function with given fields: +func (_m *Change) Confirm() error { + ret := _m.Called() + + var r0 error + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ID provides a mock function with given fields: +func (_m *Change) ID() uuid.UUID { + ret := _m.Called() + + var r0 uuid.UUID + if rf, ok := ret.Get(0).(func() uuid.UUID); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(uuid.UUID) + } + } + + return r0 +} diff --git a/mocks/ConfigCallback.go b/mocks/ConfigCallback.go deleted file mode 100644 index 36173a9d7ae5bafba95cff07a023db983ab80db0..0000000000000000000000000000000000000000 --- a/mocks/ConfigCallback.go +++ /dev/null @@ -1,27 +0,0 @@ -// Code generated by mockery v2.6.0. DO NOT EDIT. - -package mocks - -import ( - ygot "github.com/openconfig/ygot/ygot" - mock "github.com/stretchr/testify/mock" -) - -// ConfigCallback is an autogenerated mock type for the ConfigCallback type -type ConfigCallback struct { - mock.Mock -} - -// Execute provides a mock function with given fields: _a0 -func (_m *ConfigCallback) Execute(_a0 ygot.ValidatedGoStruct) error { - ret := _m.Called(_a0) - - var r0 error - if rf, ok := ret.Get(0).(func(ygot.ValidatedGoStruct) error); ok { - r0 = rf(_a0) - } else { - r0 = ret.Error(0) - } - - return r0 -} diff --git a/mocks/Device.go b/mocks/Device.go new file mode 100644 index 0000000000000000000000000000000000000000..f3e7d900d1dcda30c253341be4f48517b1b00c41 --- /dev/null +++ b/mocks/Device.go @@ -0,0 +1,112 @@ +// Code generated by mockery 2.7.5. DO NOT EDIT. + +package mocks + +import ( + southbound "code.fbi.h-da.de/cocsn/gosdn/interfaces/southbound" + mock "github.com/stretchr/testify/mock" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + + transport "code.fbi.h-da.de/cocsn/gosdn/interfaces/transport" + + uuid "github.com/google/uuid" + + ygot "github.com/openconfig/ygot/ygot" +) + +// Device is an autogenerated mock type for the Device type +type Device struct { + mock.Mock +} + +// ID provides a mock function with given fields: +func (_m *Device) ID() uuid.UUID { + ret := _m.Called() + + var r0 uuid.UUID + if rf, ok := ret.Get(0).(func() uuid.UUID); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(uuid.UUID) + } + } + + return r0 +} + +// Model provides a mock function with given fields: +func (_m *Device) Model() ygot.GoStruct { + ret := _m.Called() + + var r0 ygot.GoStruct + if rf, ok := ret.Get(0).(func() ygot.GoStruct); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(ygot.GoStruct) + } + } + + return r0 +} + +// Name provides a mock function with given fields: +func (_m *Device) Name() string { + ret := _m.Called() + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} + +// ProcessResponse provides a mock function with given fields: _a0 +func (_m *Device) ProcessResponse(_a0 protoreflect.ProtoMessage) error { + ret := _m.Called(_a0) + + var r0 error + if rf, ok := ret.Get(0).(func(protoreflect.ProtoMessage) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// SBI provides a mock function with given fields: +func (_m *Device) SBI() southbound.SouthboundInterface { + ret := _m.Called() + + var r0 southbound.SouthboundInterface + if rf, ok := ret.Get(0).(func() southbound.SouthboundInterface); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(southbound.SouthboundInterface) + } + } + + return r0 +} + +// Transport provides a mock function with given fields: +func (_m *Device) Transport() transport.Transport { + ret := _m.Called() + + var r0 transport.Transport + if rf, ok := ret.Get(0).(func() transport.Transport); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(transport.Transport) + } + } + + return r0 +} diff --git a/mocks/EscapeFunc.go b/mocks/EscapeFunc.go deleted file mode 100644 index 3ab84b3e650e7bad1fb3e88f2f0f7d02bee2abb1..0000000000000000000000000000000000000000 --- a/mocks/EscapeFunc.go +++ /dev/null @@ -1,24 +0,0 @@ -// Code generated by mockery v2.6.0. DO NOT EDIT. - -package mocks - -import mock "github.com/stretchr/testify/mock" - -// EscapeFunc is an autogenerated mock type for the EscapeFunc type -type EscapeFunc struct { - mock.Mock -} - -// Execute provides a mock function with given fields: k -func (_m *EscapeFunc) Execute(k string) string { - ret := _m.Called(k) - - var r0 string - if rf, ok := ret.Get(0).(func(string) string); ok { - r0 = rf(k) - } else { - r0 = ret.Get(0).(string) - } - - return r0 -} diff --git a/mocks/GNMIClient.go b/mocks/GNMIClient.go index 255d4a40d68513d1b1125101f8e9cdc12f139dc2..556bb65df2d7dd1a1605a16b984ba39cbe5e08ab 100644 --- a/mocks/GNMIClient.go +++ b/mocks/GNMIClient.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.6.0. DO NOT EDIT. +// Code generated by mockery 2.7.5. DO NOT EDIT. package mocks diff --git a/mocks/GNMIServer.go b/mocks/GNMIServer.go index 0628c5b31fe2c971810f5a2c9f7be3a8326ee40c..47dfbd15510c27896f0cb201999992816dfdeb59 100644 --- a/mocks/GNMIServer.go +++ b/mocks/GNMIServer.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.6.0. DO NOT EDIT. +// Code generated by mockery 2.7.5. DO NOT EDIT. package mocks diff --git a/mocks/GNMI_SubscribeClient.go b/mocks/GNMI_SubscribeClient.go index 456be898e5d92171a26add0d03e863f08f302d24..0d58afc80bc054a8c8f94dd8b27e5864e86239a4 100644 --- a/mocks/GNMI_SubscribeClient.go +++ b/mocks/GNMI_SubscribeClient.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.6.0. DO NOT EDIT. +// Code generated by mockery 2.7.5. DO NOT EDIT. package mocks diff --git a/mocks/GNMI_SubscribeServer.go b/mocks/GNMI_SubscribeServer.go index e19a9379ffc57345b30141b757dbd5d57327a82a..f663f552a3acb72cf00e011c0d557450bcca45a3 100644 --- a/mocks/GNMI_SubscribeServer.go +++ b/mocks/GNMI_SubscribeServer.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.6.0. DO NOT EDIT. +// Code generated by mockery 2.7.5. DO NOT EDIT. package mocks diff --git a/mocks/JSONUnmarshaler.go b/mocks/JSONUnmarshaler.go deleted file mode 100644 index 15dd0529058297459efe0de40d6264846bb03586..0000000000000000000000000000000000000000 --- a/mocks/JSONUnmarshaler.go +++ /dev/null @@ -1,36 +0,0 @@ -// Code generated by mockery v2.6.0. DO NOT EDIT. - -package mocks - -import ( - ygot "github.com/openconfig/ygot/ygot" - mock "github.com/stretchr/testify/mock" - - ytypes "github.com/openconfig/ygot/ytypes" -) - -// JSONUnmarshaler is an autogenerated mock type for the JSONUnmarshaler type -type JSONUnmarshaler struct { - mock.Mock -} - -// Execute provides a mock function with given fields: _a0, _a1, _a2 -func (_m *JSONUnmarshaler) Execute(_a0 []byte, _a1 ygot.GoStruct, _a2 ...ytypes.UnmarshalOpt) error { - _va := make([]interface{}, len(_a2)) - for _i := range _a2 { - _va[_i] = _a2[_i] - } - var _ca []interface{} - _ca = append(_ca, _a0, _a1) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) - - var r0 error - if rf, ok := ret.Get(0).(func([]byte, ygot.GoStruct, ...ytypes.UnmarshalOpt) error); ok { - r0 = rf(_a0, _a1, _a2...) - } else { - r0 = ret.Error(0) - } - - return r0 -} diff --git a/mocks/PrincipalNetworkDomain.go b/mocks/NetworkDomain.go similarity index 71% rename from mocks/PrincipalNetworkDomain.go rename to mocks/NetworkDomain.go index ed11f411beeff2f5f7e44d7e49550f2d2d937476..c43edae6837df98034f87947c4457ec1c7de7465 100644 --- a/mocks/PrincipalNetworkDomain.go +++ b/mocks/NetworkDomain.go @@ -3,22 +3,29 @@ package mocks import ( + change "code.fbi.h-da.de/cocsn/gosdn/interfaces/change" + device "code.fbi.h-da.de/cocsn/gosdn/interfaces/device" + mock "github.com/stretchr/testify/mock" pnd "code.fbi.h-da.de/cocsn/api/go/gosdn/pnd" + southbound "code.fbi.h-da.de/cocsn/gosdn/interfaces/southbound" + + store "code.fbi.h-da.de/cocsn/gosdn/interfaces/store" + transport "code.fbi.h-da.de/cocsn/api/go/gosdn/transport" uuid "github.com/google/uuid" ) -// PrincipalNetworkDomain is an autogenerated mock type for the PrincipalNetworkDomain type -type PrincipalNetworkDomain struct { +// NetworkDomain is an autogenerated mock type for the NetworkDomain type +type NetworkDomain struct { mock.Mock } // AddDevice provides a mock function with given fields: name, opts, sid -func (_m *PrincipalNetworkDomain) AddDevice(name string, opts *transport.TransportOption, sid uuid.UUID) error { +func (_m *NetworkDomain) AddDevice(name string, opts *transport.TransportOption, sid uuid.UUID) error { ret := _m.Called(name, opts, sid) var r0 error @@ -31,13 +38,13 @@ func (_m *PrincipalNetworkDomain) AddDevice(name string, opts *transport.Transpo return r0 } -// AddSbi provides a mock function with given fields: _a0 -func (_m *PrincipalNetworkDomain) AddSbi(_a0 interface{}) error { - ret := _m.Called(_a0) +// AddSbi provides a mock function with given fields: s +func (_m *NetworkDomain) AddSbi(s southbound.SouthboundInterface) error { + ret := _m.Called(s) var r0 error - if rf, ok := ret.Get(0).(func(interface{}) error); ok { - r0 = rf(_a0) + if rf, ok := ret.Get(0).(func(southbound.SouthboundInterface) error); ok { + r0 = rf(s) } else { r0 = ret.Error(0) } @@ -46,7 +53,7 @@ func (_m *PrincipalNetworkDomain) AddSbi(_a0 interface{}) error { } // ChangeOND provides a mock function with given fields: _a0, operation, path, value -func (_m *PrincipalNetworkDomain) ChangeOND(_a0 uuid.UUID, operation pnd.ApiOperation, path string, value ...string) error { +func (_m *NetworkDomain) ChangeOND(_a0 uuid.UUID, operation pnd.ApiOperation, path string, value ...string) error { _va := make([]interface{}, len(value)) for _i := range value { _va[_i] = value[_i] @@ -67,7 +74,7 @@ func (_m *PrincipalNetworkDomain) ChangeOND(_a0 uuid.UUID, operation pnd.ApiOper } // Commit provides a mock function with given fields: _a0 -func (_m *PrincipalNetworkDomain) Commit(_a0 uuid.UUID) error { +func (_m *NetworkDomain) Commit(_a0 uuid.UUID) error { ret := _m.Called(_a0) var r0 error @@ -81,7 +88,7 @@ func (_m *PrincipalNetworkDomain) Commit(_a0 uuid.UUID) error { } // CommittedChanges provides a mock function with given fields: -func (_m *PrincipalNetworkDomain) CommittedChanges() []uuid.UUID { +func (_m *NetworkDomain) CommittedChanges() []uuid.UUID { ret := _m.Called() var r0 []uuid.UUID @@ -97,7 +104,7 @@ func (_m *PrincipalNetworkDomain) CommittedChanges() []uuid.UUID { } // Confirm provides a mock function with given fields: _a0 -func (_m *PrincipalNetworkDomain) Confirm(_a0 uuid.UUID) error { +func (_m *NetworkDomain) Confirm(_a0 uuid.UUID) error { ret := _m.Called(_a0) var r0 error @@ -111,7 +118,7 @@ func (_m *PrincipalNetworkDomain) Confirm(_a0 uuid.UUID) error { } // ContainsDevice provides a mock function with given fields: _a0 -func (_m *PrincipalNetworkDomain) ContainsDevice(_a0 uuid.UUID) bool { +func (_m *NetworkDomain) ContainsDevice(_a0 uuid.UUID) bool { ret := _m.Called(_a0) var r0 bool @@ -125,7 +132,7 @@ func (_m *PrincipalNetworkDomain) ContainsDevice(_a0 uuid.UUID) bool { } // Destroy provides a mock function with given fields: -func (_m *PrincipalNetworkDomain) Destroy() error { +func (_m *NetworkDomain) Destroy() error { ret := _m.Called() var r0 error @@ -139,7 +146,7 @@ func (_m *PrincipalNetworkDomain) Destroy() error { } // Devices provides a mock function with given fields: -func (_m *PrincipalNetworkDomain) Devices() []uuid.UUID { +func (_m *NetworkDomain) Devices() []uuid.UUID { ret := _m.Called() var r0 []uuid.UUID @@ -155,7 +162,7 @@ func (_m *PrincipalNetworkDomain) Devices() []uuid.UUID { } // GetChange provides a mock function with given fields: _a0, _a1 -func (_m *PrincipalNetworkDomain) GetChange(_a0 uuid.UUID, _a1 ...int) (interface{}, error) { +func (_m *NetworkDomain) GetChange(_a0 uuid.UUID, _a1 ...int) (change.Change, error) { _va := make([]interface{}, len(_a1)) for _i := range _a1 { _va[_i] = _a1[_i] @@ -165,12 +172,12 @@ func (_m *PrincipalNetworkDomain) GetChange(_a0 uuid.UUID, _a1 ...int) (interfac _ca = append(_ca, _va...) ret := _m.Called(_ca...) - var r0 interface{} - if rf, ok := ret.Get(0).(func(uuid.UUID, ...int) interface{}); ok { + var r0 change.Change + if rf, ok := ret.Get(0).(func(uuid.UUID, ...int) change.Change); ok { r0 = rf(_a0, _a1...) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(interface{}) + r0 = ret.Get(0).(change.Change) } } @@ -185,7 +192,7 @@ func (_m *PrincipalNetworkDomain) GetChange(_a0 uuid.UUID, _a1 ...int) (interfac } // GetDescription provides a mock function with given fields: -func (_m *PrincipalNetworkDomain) GetDescription() string { +func (_m *NetworkDomain) GetDescription() string { ret := _m.Called() var r0 string @@ -199,15 +206,15 @@ func (_m *PrincipalNetworkDomain) GetDescription() string { } // GetDevice provides a mock function with given fields: identifier -func (_m *PrincipalNetworkDomain) GetDevice(identifier string) (interface{}, error) { +func (_m *NetworkDomain) GetDevice(identifier string) (device.Device, error) { ret := _m.Called(identifier) - var r0 interface{} - if rf, ok := ret.Get(0).(func(string) interface{}); ok { + var r0 device.Device + if rf, ok := ret.Get(0).(func(string) device.Device); ok { r0 = rf(identifier) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(interface{}) + r0 = ret.Get(0).(device.Device) } } @@ -222,7 +229,7 @@ func (_m *PrincipalNetworkDomain) GetDevice(identifier string) (interface{}, err } // GetName provides a mock function with given fields: -func (_m *PrincipalNetworkDomain) GetName() string { +func (_m *NetworkDomain) GetName() string { ret := _m.Called() var r0 string @@ -236,15 +243,15 @@ func (_m *PrincipalNetworkDomain) GetName() string { } // GetSBIs provides a mock function with given fields: -func (_m *PrincipalNetworkDomain) GetSBIs() interface{} { +func (_m *NetworkDomain) GetSBIs() store.Store { ret := _m.Called() - var r0 interface{} - if rf, ok := ret.Get(0).(func() interface{}); ok { + var r0 store.Store + if rf, ok := ret.Get(0).(func() store.Store); ok { r0 = rf() } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(interface{}) + r0 = ret.Get(0).(store.Store) } } @@ -252,7 +259,7 @@ func (_m *PrincipalNetworkDomain) GetSBIs() interface{} { } // ID provides a mock function with given fields: -func (_m *PrincipalNetworkDomain) ID() uuid.UUID { +func (_m *NetworkDomain) ID() uuid.UUID { ret := _m.Called() var r0 uuid.UUID @@ -268,7 +275,7 @@ func (_m *PrincipalNetworkDomain) ID() uuid.UUID { } // MarshalDevice provides a mock function with given fields: _a0 -func (_m *PrincipalNetworkDomain) MarshalDevice(_a0 string) (string, error) { +func (_m *NetworkDomain) MarshalDevice(_a0 string) (string, error) { ret := _m.Called(_a0) var r0 string @@ -289,7 +296,7 @@ func (_m *PrincipalNetworkDomain) MarshalDevice(_a0 string) (string, error) { } // PendingChanges provides a mock function with given fields: -func (_m *PrincipalNetworkDomain) PendingChanges() []uuid.UUID { +func (_m *NetworkDomain) PendingChanges() []uuid.UUID { ret := _m.Called() var r0 []uuid.UUID @@ -305,7 +312,7 @@ func (_m *PrincipalNetworkDomain) PendingChanges() []uuid.UUID { } // RemoveDevice provides a mock function with given fields: _a0 -func (_m *PrincipalNetworkDomain) RemoveDevice(_a0 uuid.UUID) error { +func (_m *NetworkDomain) RemoveDevice(_a0 uuid.UUID) error { ret := _m.Called(_a0) var r0 error @@ -319,7 +326,7 @@ func (_m *PrincipalNetworkDomain) RemoveDevice(_a0 uuid.UUID) error { } // RemoveSbi provides a mock function with given fields: _a0 -func (_m *PrincipalNetworkDomain) RemoveSbi(_a0 uuid.UUID) error { +func (_m *NetworkDomain) RemoveSbi(_a0 uuid.UUID) error { ret := _m.Called(_a0) var r0 error @@ -333,7 +340,7 @@ func (_m *PrincipalNetworkDomain) RemoveSbi(_a0 uuid.UUID) error { } // Request provides a mock function with given fields: _a0, _a1 -func (_m *PrincipalNetworkDomain) Request(_a0 uuid.UUID, _a1 string) error { +func (_m *NetworkDomain) Request(_a0 uuid.UUID, _a1 string) error { ret := _m.Called(_a0, _a1) var r0 error @@ -347,7 +354,7 @@ func (_m *PrincipalNetworkDomain) Request(_a0 uuid.UUID, _a1 string) error { } // RequestAll provides a mock function with given fields: _a0 -func (_m *PrincipalNetworkDomain) RequestAll(_a0 string) error { +func (_m *NetworkDomain) RequestAll(_a0 string) error { ret := _m.Called(_a0) var r0 error diff --git a/mocks/PublishFunc.go b/mocks/PublishFunc.go deleted file mode 100644 index 9bafd22090b46cd8a0b9d9aedcb5d502b340911b..0000000000000000000000000000000000000000 --- a/mocks/PublishFunc.go +++ /dev/null @@ -1,18 +0,0 @@ -// Code generated by mockery v2.6.0. DO NOT EDIT. - -package mocks - -import ( - mock "github.com/stretchr/testify/mock" - protoiface "google.golang.org/protobuf/runtime/protoiface" -) - -// PublishFunc is an autogenerated mock type for the PublishFunc type -type PublishFunc struct { - mock.Mock -} - -// Execute provides a mock function with given fields: addr, message -func (_m *PublishFunc) Execute(addr string, message protoiface.MessageV1) { - _m.Called(addr, message) -} diff --git a/mocks/SBIGreeter.go b/mocks/SBIGreeter.go deleted file mode 100644 index 7b7c999166b64bdf711da1b7ddb8e5801e9330fc..0000000000000000000000000000000000000000 --- a/mocks/SBIGreeter.go +++ /dev/null @@ -1,15 +0,0 @@ -// Code generated by mockery v2.6.0. DO NOT EDIT. - -package mocks - -import mock "github.com/stretchr/testify/mock" - -// SBIGreeter is an autogenerated mock type for the SBIGreeter type -type SBIGreeter struct { - mock.Mock -} - -// SBIHello provides a mock function with given fields: -func (_m *SBIGreeter) SBIHello() { - _m.Called() -} diff --git a/mocks/SouthboundInterface.go b/mocks/SouthboundInterface.go index 560db283ced93dfae4790ac5d934e132feb5d92f..c7936b27df0f42f4c6331711b357635badb1a05b 100644 --- a/mocks/SouthboundInterface.go +++ b/mocks/SouthboundInterface.go @@ -3,10 +3,10 @@ package mocks import ( + gosdnsouthbound "code.fbi.h-da.de/cocsn/api/go/gosdn/southbound" gnmi "github.com/openconfig/gnmi/proto/gnmi" - mock "github.com/stretchr/testify/mock" - southbound "code.fbi.h-da.de/cocsn/api/go/gosdn/southbound" + mock "github.com/stretchr/testify/mock" uuid "github.com/google/uuid" @@ -83,14 +83,14 @@ func (_m *SouthboundInterface) SetNode() func(*yang.Entry, interface{}, *gnmi.Pa } // Type provides a mock function with given fields: -func (_m *SouthboundInterface) Type() southbound.Type { +func (_m *SouthboundInterface) Type() gosdnsouthbound.Type { ret := _m.Called() - var r0 southbound.Type - if rf, ok := ret.Get(0).(func() southbound.Type); ok { + var r0 gosdnsouthbound.Type + if rf, ok := ret.Get(0).(func() gosdnsouthbound.Type); ok { r0 = rf() } else { - r0 = ret.Get(0).(southbound.Type) + r0 = ret.Get(0).(gosdnsouthbound.Type) } return r0 diff --git a/mocks/Store.go b/mocks/Store.go new file mode 100644 index 0000000000000000000000000000000000000000..d964f824e8d29aa7d851e7553bcaaf0804167a13 --- /dev/null +++ b/mocks/Store.go @@ -0,0 +1,95 @@ +// Code generated by mockery 2.7.5. DO NOT EDIT. + +package mocks + +import ( + store "code.fbi.h-da.de/cocsn/gosdn/interfaces/store" + uuid "github.com/google/uuid" + mock "github.com/stretchr/testify/mock" +) + +// Store is an autogenerated mock type for the Store type +type Store struct { + mock.Mock +} + +// Add provides a mock function with given fields: item +func (_m *Store) Add(item store.Storable) error { + ret := _m.Called(item) + + var r0 error + if rf, ok := ret.Get(0).(func(store.Storable) error); ok { + r0 = rf(item) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Delete provides a mock function with given fields: id +func (_m *Store) Delete(id uuid.UUID) error { + ret := _m.Called(id) + + var r0 error + if rf, ok := ret.Get(0).(func(uuid.UUID) error); ok { + r0 = rf(id) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Exists provides a mock function with given fields: id +func (_m *Store) Exists(id uuid.UUID) bool { + ret := _m.Called(id) + + var r0 bool + if rf, ok := ret.Get(0).(func(uuid.UUID) bool); ok { + r0 = rf(id) + } else { + r0 = ret.Get(0).(bool) + } + + return r0 +} + +// Get provides a mock function with given fields: id +func (_m *Store) Get(id uuid.UUID) (store.Storable, error) { + ret := _m.Called(id) + + var r0 store.Storable + if rf, ok := ret.Get(0).(func(uuid.UUID) store.Storable); ok { + r0 = rf(id) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(store.Storable) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(uuid.UUID) error); ok { + r1 = rf(id) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// UUIDs provides a mock function with given fields: +func (_m *Store) UUIDs() []uuid.UUID { + ret := _m.Called() + + var r0 []uuid.UUID + if rf, ok := ret.Get(0).(func() []uuid.UUID); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]uuid.UUID) + } + } + + return r0 +} diff --git a/mocks/TransportOptions.go b/mocks/TransportOptions.go deleted file mode 100644 index b969fdb60e490658017a191dfb2bae818408b83a..0000000000000000000000000000000000000000 --- a/mocks/TransportOptions.go +++ /dev/null @@ -1,57 +0,0 @@ -// Code generated by mockery 2.7.4. DO NOT EDIT. - -package mocks - -import mock "github.com/stretchr/testify/mock" - -// TransportOptions is an autogenerated mock type for the TransportOptions type -type TransportOptions struct { - mock.Mock -} - -// GetAddress provides a mock function with given fields: -func (_m *TransportOptions) GetAddress() string { - ret := _m.Called() - - var r0 string - if rf, ok := ret.Get(0).(func() string); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(string) - } - - return r0 -} - -// GetPassword provides a mock function with given fields: -func (_m *TransportOptions) GetPassword() string { - ret := _m.Called() - - var r0 string - if rf, ok := ret.Get(0).(func() string); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(string) - } - - return r0 -} - -// GetUsername provides a mock function with given fields: -func (_m *TransportOptions) GetUsername() string { - ret := _m.Called() - - var r0 string - if rf, ok := ret.Get(0).(func() string); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(string) - } - - return r0 -} - -// IsTransportOption provides a mock function with given fields: -func (_m *TransportOptions) IsTransportOption() { - _m.Called() -} diff --git a/mocks/UnsafeGNMIServer.go b/mocks/UnsafeGNMIServer.go new file mode 100644 index 0000000000000000000000000000000000000000..377e2d1cdda4eff9764adc784825237c7f2f4356 --- /dev/null +++ b/mocks/UnsafeGNMIServer.go @@ -0,0 +1,15 @@ +// Code generated by mockery 2.7.5. DO NOT EDIT. + +package mocks + +import mock "github.com/stretchr/testify/mock" + +// UnsafeGNMIServer is an autogenerated mock type for the UnsafeGNMIServer type +type UnsafeGNMIServer struct { + mock.Mock +} + +// mustEmbedUnimplementedGNMIServer provides a mock function with given fields: +func (_m *UnsafeGNMIServer) mustEmbedUnimplementedGNMIServer() { + _m.Called() +} diff --git a/mocks/isSubscribeRequest_Request.go b/mocks/isSubscribeRequest_Request.go index 73f763981ed7bd4586787e88694c844885b2b843..b1b09e55db8d7b31bbd4b02d383bb45e786b1de6 100644 --- a/mocks/isSubscribeRequest_Request.go +++ b/mocks/isSubscribeRequest_Request.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.6.0. DO NOT EDIT. +// Code generated by mockery 2.7.5. DO NOT EDIT. package mocks diff --git a/mocks/isSubscribeResponse_Response.go b/mocks/isSubscribeResponse_Response.go index ba10966e2703113f5fc03233883022efb7843b4b..0f38e4ee6d5ccc28a7e13943de6434d6647e811f 100644 --- a/mocks/isSubscribeResponse_Response.go +++ b/mocks/isSubscribeResponse_Response.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.6.0. DO NOT EDIT. +// Code generated by mockery 2.7.5. DO NOT EDIT. package mocks diff --git a/mocks/isTypedValue_Value.go b/mocks/isTypedValue_Value.go index a49fc787f9dbe7f24023258d180371a5bcd42c7b..bc9ac6962403f9d2251accafaf295ad63ca36303 100644 --- a/mocks/isTypedValue_Value.go +++ b/mocks/isTypedValue_Value.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.6.0. DO NOT EDIT. +// Code generated by mockery 2.7.5. DO NOT EDIT. package mocks diff --git a/northbound/server/core.go b/northbound/server/core.go index a655ef4d21889974240ecf6607fbcfbc3b59721c..0bc9415fae5eace64856a30683ed71bf01c872df 100644 --- a/northbound/server/core.go +++ b/northbound/server/core.go @@ -32,7 +32,7 @@ func (s core) Get(ctx context.Context, request *pb.GetRequest) (*pb.GetResponse, pnds := make([]*ppb.PrincipalNetworkDomain, len(pndList)) for i, id := range pndList { - pnd, err := pndc.Get(id) + pnd, err := pndc.GetPND(id) if err != nil { return nil, err } diff --git a/northbound/server/nbi.go b/northbound/server/nbi.go index 2e17223c969be515b278f07e6c02775b4e761dc7..931dc4795f1c073ea6693f838726cf40e51675aa 100644 --- a/northbound/server/nbi.go +++ b/northbound/server/nbi.go @@ -9,7 +9,7 @@ var pndc *nucleus.PndStore // NorthboundInterface is the representation of the // gRPC services used provided. type NorthboundInterface struct { - Pnd *pnd + Pnd *pndServer Core *core } @@ -17,7 +17,7 @@ type NorthboundInterface struct { func NewNBI(pnds *nucleus.PndStore) *NorthboundInterface { pndc = pnds return &NorthboundInterface{ - Pnd: &pnd{}, + Pnd: &pndServer{}, Core: &core{}, } } diff --git a/northbound/server/pnd.go b/northbound/server/pnd.go index 00a334b8808a6877ab4129bfdb865934edde9f4f..9b46337668225aa4508aada51c44c388ca955d28 100644 --- a/northbound/server/pnd.go +++ b/northbound/server/pnd.go @@ -5,19 +5,22 @@ import ( "reflect" "time" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/device" + ppb "code.fbi.h-da.de/cocsn/api/go/gosdn/pnd" spb "code.fbi.h-da.de/cocsn/api/go/gosdn/southbound" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/networkdomain" "code.fbi.h-da.de/cocsn/gosdn/nucleus" "code.fbi.h-da.de/cocsn/gosdn/nucleus/errors" "github.com/google/uuid" "github.com/openconfig/ygot/ygot" ) -type pnd struct { +type pndServer struct { ppb.UnimplementedPndServer } -func (p pnd) Get(ctx context.Context, request *ppb.GetRequest) (*ppb.GetResponse, error) { +func (p pndServer) Get(ctx context.Context, request *ppb.GetRequest) (*ppb.GetResponse, error) { pid, err := uuid.Parse(request.Pid) if err != nil { return nil, err @@ -37,7 +40,7 @@ func (p pnd) Get(ctx context.Context, request *ppb.GetRequest) (*ppb.GetResponse } func handleGetPnd(pid uuid.UUID) (*ppb.GetResponse, error) { - pnd, err := pndc.Get(pid) + pnd, err := pndc.GetPND(pid) if err != nil { return nil, err } @@ -68,7 +71,7 @@ func handleGetPnd(pid uuid.UUID) (*ppb.GetResponse, error) { } func handleGetSbi(pid uuid.UUID, req *ppb.GetRequest_Sbi) (*ppb.GetResponse, error) { - pnd, err := pndc.Get(pid) + pnd, err := pndc.GetPND(pid) if err != nil { return nil, err } @@ -95,7 +98,7 @@ func stringToUUID(sid []string) ([]uuid.UUID, error) { } func handleGetOnd(pid uuid.UUID, req *ppb.GetRequest_Ond) (*ppb.GetResponse, error) { - pnd, err := pndc.Get(pid) + pnd, err := pndc.GetPND(pid) if err != nil { return nil, err } @@ -110,7 +113,7 @@ func handleGetOnd(pid uuid.UUID, req *ppb.GetRequest_Ond) (*ppb.GetResponse, err } func handleGetChange(pid uuid.UUID, req *ppb.GetRequest_Change) (*ppb.GetResponse, error) { - pnd, err := pndc.Get(pid) + pnd, err := pndc.GetPND(pid) if err != nil { return nil, err } @@ -124,7 +127,7 @@ func handleGetChange(pid uuid.UUID, req *ppb.GetRequest_Change) (*ppb.GetRespons }, nil } -func fillSbis(pnd nucleus.PrincipalNetworkDomain, all bool, sid ...string) ([]*spb.SouthboundInterface, error) { +func fillSbis(pnd networkdomain.NetworkDomain, all bool, sid ...string) ([]*spb.SouthboundInterface, error) { var sbiList []uuid.UUID sbiStore := pnd.GetSBIs().(*nucleus.SbiStore) @@ -146,7 +149,7 @@ func fillSbis(pnd nucleus.PrincipalNetworkDomain, all bool, sid ...string) ([]*s } sbis := make([]*spb.SouthboundInterface, len(sbiList)) for i, id := range sbiList { - sbi, err := sbiStore.Get(id) + sbi, err := sbiStore.GetSBI(id) if err != nil { return nil, err } @@ -158,7 +161,7 @@ func fillSbis(pnd nucleus.PrincipalNetworkDomain, all bool, sid ...string) ([]*s return sbis, nil } -func fillOnds(pnd nucleus.PrincipalNetworkDomain, all bool, did ...string) ([]*ppb.OrchestratedNetworkingDevice, error) { +func fillOnds(pnd networkdomain.NetworkDomain, all bool, did ...string) ([]*ppb.OrchestratedNetworkingDevice, error) { var ondList []uuid.UUID switch all { @@ -185,7 +188,7 @@ func fillOnds(pnd nucleus.PrincipalNetworkDomain, all bool, did ...string) ([]*p return nil, err } cfg := ygot.GNMINotificationsConfig{} - dev, err := ygot.TogNMINotifications(d.(nucleus.Device).Model(), time.Now().UnixNano(), cfg) + dev, err := ygot.TogNMINotifications(d.(device.Device).Model(), time.Now().UnixNano(), cfg) if err != nil { return nil, err } @@ -198,7 +201,7 @@ func fillOnds(pnd nucleus.PrincipalNetworkDomain, all bool, did ...string) ([]*p return onds, nil } -func fillChanges(pnd nucleus.PrincipalNetworkDomain, all bool, cuid ...string) ([]*ppb.Change, error) { +func fillChanges(pnd networkdomain.NetworkDomain, all bool, cuid ...string) ([]*ppb.Change, error) { var changeList []uuid.UUID switch all { @@ -242,13 +245,13 @@ func fillChanges(pnd nucleus.PrincipalNetworkDomain, all bool, cuid ...string) ( return changes, nil } -func (p pnd) Set(ctx context.Context, request *ppb.SetRequest) (*ppb.SetResponse, error) { +func (p pndServer) Set(ctx context.Context, request *ppb.SetRequest) (*ppb.SetResponse, error) { pid, err := uuid.Parse(request.Pid) if err != nil { return nil, err } - pnd, err := pndc.Get(pid) + pnd, err := pndc.GetPND(pid) if err != nil { return nil, err } @@ -276,7 +279,7 @@ func (p pnd) Set(ctx context.Context, request *ppb.SetRequest) (*ppb.SetResponse }, nil } -func handleSetOnd(pnd nucleus.PrincipalNetworkDomain, req []*ppb.SetOnd) (*ppb.SetResponse, error) { +func handleSetOnd(pnd networkdomain.NetworkDomain, req []*ppb.SetOnd) (*ppb.SetResponse, error) { for _, r := range req { sid, err := uuid.Parse(r.Sbi.Id) if err != nil { @@ -292,14 +295,14 @@ func handleSetOnd(pnd nucleus.PrincipalNetworkDomain, req []*ppb.SetOnd) (*ppb.S }, nil } -func handleSetSbi(pnd nucleus.PrincipalNetworkDomain, req []*ppb.SetSbi) (*ppb.SetResponse, error) { +func handleSetSbi(pnd networkdomain.NetworkDomain, req []*ppb.SetSbi) (*ppb.SetResponse, error) { return &ppb.SetResponse{ Timestamp: time.Now().UnixNano(), Status: ppb.SetResponse_ERROR, }, nil } -func handleSetChange(pnd nucleus.PrincipalNetworkDomain, req []*ppb.SetChange) (*ppb.SetResponse, error) { +func handleSetChange(pnd networkdomain.NetworkDomain, req []*ppb.SetChange) (*ppb.SetResponse, error) { for _, r := range req { cuid, err := uuid.Parse(r.Cuid) if err != nil { @@ -327,7 +330,7 @@ func handleSetChange(pnd nucleus.PrincipalNetworkDomain, req []*ppb.SetChange) ( }, nil } -func handleChangeRequest(pnd nucleus.PrincipalNetworkDomain, req []*ppb.ChangeRequest) (*ppb.SetResponse, error) { +func handleChangeRequest(pnd networkdomain.NetworkDomain, req []*ppb.ChangeRequest) (*ppb.SetResponse, error) { for _, r := range req { did, err := uuid.Parse(r.Id) if err != nil { diff --git a/northbound/server/pnd_test.go b/northbound/server/pnd_test.go index e5fea39f2c9b22d3f6469e23e10ace2ef152e8b4..0d25e79ca28e1b778b452ad2781e7a0c8169f6a1 100644 --- a/northbound/server/pnd_test.go +++ b/northbound/server/pnd_test.go @@ -9,6 +9,7 @@ import ( ppb "code.fbi.h-da.de/cocsn/api/go/gosdn/pnd" spb "code.fbi.h-da.de/cocsn/api/go/gosdn/southbound" "code.fbi.h-da.de/cocsn/api/go/gosdn/transport" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/device" "code.fbi.h-da.de/cocsn/gosdn/mocks" "code.fbi.h-da.de/cocsn/gosdn/nucleus" "code.fbi.h-da.de/cocsn/yang-models/generated/openconfig" @@ -28,8 +29,8 @@ var pndUUID uuid.UUID var pendingChangeUUID uuid.UUID var committedChangeUUID uuid.UUID var deviceUUID uuid.UUID -var mockPnd *mocks.PrincipalNetworkDomain -var mockDevice nucleus.Device +var mockPnd *mocks.NetworkDomain +var mockDevice device.Device var sbiStore *nucleus.SbiStore func TestMain(m *testing.M) { @@ -74,7 +75,7 @@ func TestMain(m *testing.M) { log.Fatal(err) } - mockPnd = &mocks.PrincipalNetworkDomain{} + mockPnd = &mocks.NetworkDomain{} mockPnd.On("ID").Return(pndUUID) mockPnd.On("GetName").Return("test") mockPnd.On("GetDescription").Return("test") @@ -130,7 +131,7 @@ func Test_pnd_Get(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - p := pnd{ + p := pndServer{ UnimplementedPndServer: ppb.UnimplementedPndServer{}, } resp, err := p.Get(tt.args.ctx, tt.args.request) @@ -241,7 +242,7 @@ func Test_pnd_Set(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - p := pnd{ + p := pndServer{ UnimplementedPndServer: ppb.UnimplementedPndServer{}, } resp, err := p.Set(tt.args.ctx, tt.args.request) diff --git a/nucleus/device.go b/nucleus/device.go index fc74f50e3f845c66f61287a892b064229a202a3c..716deb687c90fe26d5d68bf6e0e607236dbaef3a 100644 --- a/nucleus/device.go +++ b/nucleus/device.go @@ -2,23 +2,33 @@ package nucleus import ( tpb "code.fbi.h-da.de/cocsn/api/go/gosdn/transport" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/device" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/southbound" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/transport" "github.com/docker/docker/pkg/namesgenerator" "github.com/google/uuid" "github.com/openconfig/ygot/ygot" "google.golang.org/protobuf/proto" ) -// Device represents an Orchestrated Network Device (OND) which is managed by -// nucleus -type Device interface { - ID() uuid.UUID - Model() ygot.GoStruct - Transport() Transport - Name() string - SBI() SouthboundInterface - ProcessResponse(proto.Message) error +// NewDevice creates a Device +func NewDevice(name string, opt *tpb.TransportOption, sbi southbound.SouthboundInterface) (device.Device, error) { + t, err := NewTransport(opt, sbi) + if err != nil { + return nil, err + } - isDevice() + if name == "" { + name = namesgenerator.GetRandomName(0) + } + + return &CommonDevice{ + UUID: uuid.New(), + GoStruct: sbi.Schema().Root, + sbi: sbi, + transport: t, + name: name, + }, nil } // CommonDevice represents an OND @@ -30,35 +40,15 @@ type CommonDevice struct { ygot.GoStruct // SBI is the device's southbound interface implementation - sbi SouthboundInterface + sbi southbound.SouthboundInterface // Transport is the device's Transport implementation - transport Transport + transport transport.Transport // Name is the device's human readable name name string } -// NewDevice creates a Device -func NewDevice(name string, opt *tpb.TransportOption, sbi SouthboundInterface) (Device, error) { - transport, err := NewTransport(opt, sbi) - if err != nil { - return nil, err - } - - if name == "" { - name = namesgenerator.GetRandomName(0) - } - - return &CommonDevice{ - UUID: uuid.New(), - GoStruct: sbi.Schema().Root, - sbi: sbi, - transport: transport, - name: name, - }, nil -} - // ID returns the UUID of the Device func (d *CommonDevice) ID() uuid.UUID { return d.UUID @@ -70,7 +60,7 @@ func (d *CommonDevice) Model() ygot.GoStruct { } // Transport returns the Transport of the device -func (d *CommonDevice) Transport() Transport { +func (d *CommonDevice) Transport() transport.Transport { return d.transport } @@ -80,12 +70,12 @@ func (d *CommonDevice) Name() string { } // SBI returns the sbi of the Device -func (d *CommonDevice) SBI() SouthboundInterface { +func (d *CommonDevice) SBI() southbound.SouthboundInterface { return d.sbi } // SetTransport sets the Device's Transport -func (d *CommonDevice) SetTransport(t Transport) { +func (d *CommonDevice) SetTransport(t transport.Transport) { d.transport = t } @@ -95,7 +85,7 @@ func (d *CommonDevice) SetName(n string) { } // SetSBI sets the Device's SBI -func (d *CommonDevice) SetSBI(sbi SouthboundInterface) { +func (d *CommonDevice) SetSBI(sbi southbound.SouthboundInterface) { d.sbi = sbi } @@ -104,8 +94,6 @@ func (d *CommonDevice) ProcessResponse(resp proto.Message) error { return d.transport.ProcessResponse(resp, d.GoStruct, d.sbi.Schema()) } -func (d *CommonDevice) isDevice() {} - type csbiDevice struct { CommonDevice } @@ -119,20 +107,18 @@ func (d *csbiDevice) Model() ygot.GoStruct { return d.GoStruct } -func (d *csbiDevice) Transport() Transport { - return d.Transport() +func (d *csbiDevice) Transport() transport.Transport { + return d.transport } func (d *csbiDevice) Name() string { - return d.Name() + return d.name } -func (d *csbiDevice) SBI() SouthboundInterface { - return d.SBI() +func (d *csbiDevice) SBI() southbound.SouthboundInterface { + return d.sbi } func (d *csbiDevice) ProcessResponse(resp proto.Message) error { return d.transport.ProcessResponse(resp, d.GoStruct, d.sbi.Schema()) } - -func (d *csbiDevice) isDevice() {} diff --git a/nucleus/device_test.go b/nucleus/device_test.go index 1efa756817f6db9fc5a7e2e5bd54a9353e2ec48a..9290231c1235bf8b05f0aac7ca5cd1145e87ebaa 100644 --- a/nucleus/device_test.go +++ b/nucleus/device_test.go @@ -4,6 +4,9 @@ import ( "reflect" "testing" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/southbound" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/transport" + tpb "code.fbi.h-da.de/cocsn/api/go/gosdn/transport" "code.fbi.h-da.de/cocsn/yang-models/generated/openconfig" @@ -14,8 +17,8 @@ import ( func TestDevice_Id(t *testing.T) { type fields struct { GoStruct ygot.GoStruct - SBI SouthboundInterface - Transport Transport + SBI southbound.SouthboundInterface + Transport transport.Transport UUID uuid.UUID Name string } @@ -51,7 +54,7 @@ func TestDevice_Id(t *testing.T) { func TestNewDevice(t *testing.T) { sbi := &OpenConfig{} type args struct { - sbi SouthboundInterface + sbi southbound.SouthboundInterface opts *tpb.TransportOption name string } diff --git a/nucleus/gnmi_transport.go b/nucleus/gnmi_transport.go index 6e8318e382e80df2885feefb22a5b35d11a20784..1185107479694aae1b22f77ee9e2d9ea26035169 100644 --- a/nucleus/gnmi_transport.go +++ b/nucleus/gnmi_transport.go @@ -4,6 +4,8 @@ import ( "context" "reflect" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/southbound" + "google.golang.org/grpc" ppb "code.fbi.h-da.de/cocsn/api/go/gosdn/pnd" @@ -41,7 +43,7 @@ type Gnmi struct { // NewGnmiTransport takes a struct of GnmiTransportOptions and returns a Gnmi // transport based on the values of it. -func NewGnmiTransport(opts *tpb.TransportOption, sbi SouthboundInterface) (*Gnmi, error) { +func NewGnmiTransport(opts *tpb.TransportOption, sbi southbound.SouthboundInterface) (*Gnmi, error) { gnmiConfig := &gnmi.Config{ Addr: opts.Address, Password: opts.Password, diff --git a/nucleus/gnmi_transport_test.go b/nucleus/gnmi_transport_test.go index d4d89bd10b886ca4481c02dc75256dca1ab01a35..597cecd8ff954aa2b623df9f339115014ce08266 100644 --- a/nucleus/gnmi_transport_test.go +++ b/nucleus/gnmi_transport_test.go @@ -6,6 +6,8 @@ import ( "reflect" "testing" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/southbound" + spb "code.fbi.h-da.de/cocsn/api/go/gosdn/southbound" tpb "code.fbi.h-da.de/cocsn/api/go/gosdn/transport" @@ -212,7 +214,7 @@ func TestGnmi_Get(t *testing.T) { func TestGnmi_ProcessResponse(t *testing.T) { type fields struct { - Sbi SouthboundInterface + Sbi southbound.SouthboundInterface } type args struct { path string diff --git a/nucleus/initialise_test.go b/nucleus/initialise_test.go index e3b589fe4cf4c846996484edcabd6ecf2147bd38..ffa4fa64a19b9fd44929c0287ef846127618f067 100644 --- a/nucleus/initialise_test.go +++ b/nucleus/initialise_test.go @@ -5,6 +5,8 @@ import ( "os" "testing" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/device" + tpb "code.fbi.h-da.de/cocsn/api/go/gosdn/transport" "code.fbi.h-da.de/cocsn/gosdn/forks/goarista/gnmi" @@ -115,7 +117,7 @@ func readTestUUIDs() { } } -func mockDevice() Device { +func mockDevice() device.Device { sbi := &OpenConfig{} return &CommonDevice{ UUID: mdid, @@ -129,11 +131,11 @@ func newPnd() pndImplementation { return pndImplementation{ name: "default", description: "default test pnd", - sbic: SbiStore{store{}}, + sbic: SbiStore{genericStore{}}, devices: NewDeviceStore(), - pendingChanges: ChangeStore{store{}}, - committedChanges: ChangeStore{store{}}, - confirmedChanges: ChangeStore{store{}}, + pendingChanges: ChangeStore{genericStore{}}, + committedChanges: ChangeStore{genericStore{}}, + confirmedChanges: ChangeStore{genericStore{}}, id: defaultPndID, errChans: make(map[uuid.UUID]chan error), } diff --git a/nucleus/principalNetworkDomain.go b/nucleus/principalNetworkDomain.go index 7192878c39b172d92200c88b2d1290eebd1eb2c1..2a25b7bdd1b259353d66ad1001e72b3363494281 100644 --- a/nucleus/principalNetworkDomain.go +++ b/nucleus/principalNetworkDomain.go @@ -7,53 +7,32 @@ import ( ppb "code.fbi.h-da.de/cocsn/api/go/gosdn/pnd" tpb "code.fbi.h-da.de/cocsn/api/go/gosdn/transport" + "google.golang.org/protobuf/proto" "code.fbi.h-da.de/cocsn/gosdn/forks/goarista/gnmi" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/change" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/device" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/networkdomain" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/southbound" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/store" "code.fbi.h-da.de/cocsn/gosdn/nucleus/errors" "github.com/google/uuid" "github.com/openconfig/ygot/ygot" "github.com/openconfig/ygot/ytypes" log "github.com/sirupsen/logrus" - "google.golang.org/protobuf/proto" ) -// PrincipalNetworkDomain provides an -// interface for PND implementations -type PrincipalNetworkDomain interface { - Destroy() error - AddSbi(interface{}) error - RemoveSbi(uuid.UUID) error - AddDevice(name string, opts *tpb.TransportOption, sid uuid.UUID) error - GetDevice(identifier string) (interface{}, error) - RemoveDevice(uuid.UUID) error - Devices() []uuid.UUID - ChangeOND(uuid uuid.UUID, operation ppb.ApiOperation, path string, value ...string) error - Request(uuid.UUID, string) error - RequestAll(string) error - GetName() string - GetDescription() string - MarshalDevice(string) (string, error) - ContainsDevice(uuid.UUID) bool - GetSBIs() interface{} - ID() uuid.UUID - PendingChanges() []uuid.UUID - CommittedChanges() []uuid.UUID - GetChange(uuid.UUID, ...int) (interface{}, error) - Commit(uuid.UUID) error - Confirm(uuid.UUID) error -} - // NewPND creates a Principle Network Domain -func NewPND(name, description string, id uuid.UUID, sbi SouthboundInterface) (PrincipalNetworkDomain, error) { +func NewPND(name, description string, id uuid.UUID, sbi southbound.SouthboundInterface) (networkdomain.NetworkDomain, error) { pnd := &pndImplementation{ name: name, description: description, - sbic: SbiStore{store{}}, + sbic: SbiStore{genericStore{}}, devices: NewDeviceStore(), - pendingChanges: ChangeStore{store{}}, - committedChanges: ChangeStore{store{}}, - confirmedChanges: ChangeStore{store{}}, + pendingChanges: ChangeStore{genericStore{}}, + committedChanges: ChangeStore{genericStore{}}, + confirmedChanges: ChangeStore{genericStore{}}, id: id, errChans: make(map[uuid.UUID]chan error), } @@ -83,7 +62,7 @@ func (pnd *pndImplementation) CommittedChanges() []uuid.UUID { return pnd.committedChanges.UUIDs() } -func (pnd *pndImplementation) GetChange(cuid uuid.UUID, i ...int) (interface{}, error) { +func (pnd *pndImplementation) GetChange(cuid uuid.UUID, i ...int) (change.Change, error) { var index int if len(i) == 1 { index = i[0] @@ -98,7 +77,7 @@ func (pnd *pndImplementation) GetChange(cuid uuid.UUID, i ...int) (interface{}, &pnd.committedChanges, &pnd.confirmedChanges, } - ch, err := stores[index].Get(cuid) + ch, err := stores[index].GetChange(cuid) index++ if err != nil { switch err.(type) { @@ -124,11 +103,11 @@ func (pnd *pndImplementation) GetChange(cuid uuid.UUID, i ...int) (interface{}, } func (pnd *pndImplementation) Commit(u uuid.UUID) error { - change, err := pnd.pendingChanges.Get(u) + ch, err := pnd.pendingChanges.GetChange(u) if err != nil { return err } - if err := change.Commit(); err != nil { + if err := ch.Commit(); err != nil { return err } go func() { @@ -136,27 +115,27 @@ func (pnd *pndImplementation) Commit(u uuid.UUID) error { select { case err := <-pnd.errChans[u]: if err != nil { - handleRollbackError(change.ID(), err) + handleRollbackError(ch.ID(), err) } - case <-change.done: + case <-ch.done: } } }() - if err := pnd.committedChanges.Add(change); err != nil { + if err := pnd.committedChanges.Add(ch); err != nil { return err } return pnd.pendingChanges.Delete(u) } func (pnd *pndImplementation) Confirm(u uuid.UUID) error { - change, err := pnd.committedChanges.Get(u) + ch, err := pnd.committedChanges.GetChange(u) if err != nil { return err } - if err := change.Confirm(); err != nil { + if err := ch.Confirm(); err != nil { return err } - if err := pnd.confirmedChanges.Add(change); err != nil { + if err := pnd.confirmedChanges.Add(ch); err != nil { return err } return pnd.committedChanges.Delete(u) @@ -186,7 +165,7 @@ func (pnd *pndImplementation) GetDescription() string { } // GetSBIs returns the registered SBIs -func (pnd *pndImplementation) GetSBIs() interface{} { +func (pnd *pndImplementation) GetSBIs() store.Store { return &pnd.sbic } @@ -196,14 +175,7 @@ func (pnd *pndImplementation) Destroy() error { } // AddSbi adds a SBI to the PND which will be supported -func (pnd *pndImplementation) AddSbi(sbi interface{}) error { - s, ok := sbi.(SouthboundInterface) - if !ok { - return &errors.ErrInvalidTypeAssertion{ - Value: sbi, - Type: "Device", - } - } +func (pnd *pndImplementation) AddSbi(s southbound.SouthboundInterface) error { return pnd.addSbi(s) } @@ -217,7 +189,7 @@ func (pnd *pndImplementation) RemoveSbi(id uuid.UUID) error { //AddDevice adds a new device to the PND func (pnd *pndImplementation) AddDevice(name string, opt *tpb.TransportOption, sid uuid.UUID) error { - sbi, err := pnd.sbic.Get(sid) + sbi, err := pnd.sbic.GetSBI(sid) if err != nil { return err } @@ -229,8 +201,8 @@ func (pnd *pndImplementation) AddDevice(name string, opt *tpb.TransportOption, s return pnd.addDevice(d) } -func (pnd *pndImplementation) GetDevice(identifier string) (interface{}, error) { - d, err := pnd.devices.Get(FromString(identifier)) +func (pnd *pndImplementation) GetDevice(identifier string) (device.Device, error) { + d, err := pnd.devices.GetDevice(FromString(identifier)) if err != nil { return nil, err } @@ -256,7 +228,7 @@ func destroy() error { return nil } -func (pnd *pndImplementation) addSbi(sbi SouthboundInterface) error { +func (pnd *pndImplementation) addSbi(sbi southbound.SouthboundInterface) error { return pnd.sbic.Add(sbi) } @@ -264,7 +236,7 @@ func (pnd *pndImplementation) removeSbi(id uuid.UUID) error { return pnd.sbic.Delete(id) } -func (pnd *pndImplementation) addDevice(device Device) error { +func (pnd *pndImplementation) addDevice(device device.Device) error { err := pnd.devices.Add(device, device.Name()) if err != nil { return err @@ -278,7 +250,7 @@ func (pnd *pndImplementation) removeDevice(id uuid.UUID) error { } func (pnd *pndImplementation) MarshalDevice(identifier string) (string, error) { - foundDevice, err := pnd.devices.Get(FromString(identifier)) + foundDevice, err := pnd.devices.GetDevice(FromString(identifier)) if err != nil { return "", err } @@ -298,7 +270,7 @@ func (pnd *pndImplementation) MarshalDevice(identifier string) (string, error) { // Request sends a get request to a specific device func (pnd *pndImplementation) Request(uuid uuid.UUID, path string) error { - d, err := pnd.devices.Get(FromString(uuid.String())) + d, err := pnd.devices.GetDevice(FromString(uuid.String())) if err != nil { return err } @@ -330,7 +302,7 @@ func (pnd *pndImplementation) RequestAll(path string) error { // ChangeOND creates a change from the provided Operation, path and value. The Change is Pending and func (pnd *pndImplementation) ChangeOND(uuid uuid.UUID, operation ppb.ApiOperation, path string, value ...string) error { - d, err := pnd.devices.Get(uuid) + d, err := pnd.devices.GetDevice(uuid) if err != nil { return err } @@ -372,10 +344,10 @@ func (pnd *pndImplementation) ChangeOND(uuid uuid.UUID, operation ppb.ApiOperati } errChan := make(chan error) - change := NewChange(uuid, d.Model(), cpy, callback, errChan) - pnd.errChans[change.ID()] = errChan + ch := NewChange(uuid, d.Model(), cpy, callback, errChan) + pnd.errChans[ch.ID()] = errChan - return pnd.pendingChanges.Add(change) + return pnd.pendingChanges.Add(ch) } func handleRollbackError(id uuid.UUID, err error) { diff --git a/nucleus/principalNetworkDomain_test.go b/nucleus/principalNetworkDomain_test.go index 5e6e5ec43e6c9463447aed72f703df0a398d7d5e..7e7a4e252997f1e14964f8b66c12873d0cf4dd01 100644 --- a/nucleus/principalNetworkDomain_test.go +++ b/nucleus/principalNetworkDomain_test.go @@ -9,6 +9,9 @@ import ( spb "code.fbi.h-da.de/cocsn/api/go/gosdn/southbound" tpb "code.fbi.h-da.de/cocsn/api/go/gosdn/transport" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/device" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/networkdomain" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/southbound" "code.fbi.h-da.de/cocsn/gosdn/mocks" "code.fbi.h-da.de/cocsn/yang-models/generated/openconfig" "github.com/google/uuid" @@ -18,20 +21,20 @@ import ( ) func TestNewPND(t *testing.T) { - pnd := newPnd() - if err := pnd.addSbi(&OpenConfig{id: defaultSbiID}); err != nil { + p := newPnd() + if err := p.addSbi(&OpenConfig{id: defaultSbiID}); err != nil { t.Error(err) } type args struct { name string description string - sbi SouthboundInterface + sbi southbound.SouthboundInterface pid uuid.UUID } tests := []struct { name string args args - want PrincipalNetworkDomain + want networkdomain.NetworkDomain wantErr bool }{ { @@ -42,7 +45,7 @@ func TestNewPND(t *testing.T) { sbi: &OpenConfig{id: defaultSbiID}, pid: defaultPndID, }, - want: &pnd, + want: &p, wantErr: false, }, } @@ -123,7 +126,7 @@ func Test_pndImplementation_AddDevice(t *testing.T) { t.Error(err) } if tt.name == "already exists" { - pnd.devices.store[did] = tt.args.device.(Device) + pnd.devices.genericStore[did] = tt.args.device.(device.Device) } err := pnd.AddDevice(tt.args.name, tt.args.opts, defaultSbiID) if (err != nil) != tt.wantErr { @@ -131,7 +134,7 @@ func Test_pndImplementation_AddDevice(t *testing.T) { } if tt.name != "fails wrong type" { if err == nil { - d, err := pnd.devices.Get(FromString(tt.args.name)) + d, err := pnd.devices.GetDevice(FromString(tt.args.name)) if err != nil { t.Errorf("AddDevice() error = %v", err) return @@ -150,7 +153,7 @@ func Test_pndImplementation_AddDevice(t *testing.T) { func Test_pndImplementation_AddSbi(t *testing.T) { type args struct { - sbi interface{} + sbi southbound.SouthboundInterface } tests := []struct { name string @@ -175,21 +178,12 @@ func Test_pndImplementation_AddSbi(t *testing.T) { }, wantErr: true, }, - { - name: "fails wrong type", - args: args{ - sbi: &pndImplementation{ - id: defaultSbiID, - }, - }, - wantErr: true, - }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { pnd := newPnd() if tt.name == "already exists" { - pnd.sbic.store[defaultSbiID] = tt.args.sbi.(*OpenConfig) + pnd.sbic.genericStore[defaultSbiID] = tt.args.sbi } err := pnd.AddSbi(tt.args.sbi) if (err != nil) != tt.wantErr { @@ -197,7 +191,7 @@ func Test_pndImplementation_AddSbi(t *testing.T) { } if tt.name != "fails wrong type" { if err == nil { - _, ok := pnd.sbic.store[defaultSbiID] + _, ok := pnd.sbic.genericStore[defaultSbiID] if !ok { t.Errorf("AddSbi() SBI %v not in device store %v", tt.args.sbi, pnd.GetSBIs()) @@ -214,7 +208,7 @@ func Test_pndImplementation_AddSbi(t *testing.T) { func Test_pndImplementation_ContainsDevice(t *testing.T) { type args struct { uuid uuid.UUID - device Device + device device.Device } tests := []struct { name string @@ -426,7 +420,7 @@ func Test_pndImplementation_RemoveSbi(t *testing.T) { pnd := &pndImplementation{ name: "test-remove-sbi", description: "test-remove-sbi", - sbic: SbiStore{store{}}, + sbic: SbiStore{genericStore{}}, devices: NewDeviceStore(), id: defaultPndID, } @@ -657,8 +651,8 @@ func Test_pndImplementation_ChangeOND(t *testing.T) { return } if !tt.wantErr { - if len(pnd.pendingChanges.store) != 1 { - t.Errorf("ChangeOND() unexpected change count. got %v, want 1", len(pnd.pendingChanges.store)) + if len(pnd.pendingChanges.genericStore) != 1 { + t.Errorf("ChangeOND() unexpected change count. got %v, want 1", len(pnd.pendingChanges.genericStore)) } } }) @@ -707,8 +701,8 @@ func Test_pndImplementation_GetDevice(t *testing.T) { return } if foundDevice != nil { - if !reflect.DeepEqual(foundDevice.(Device).Model(), tt.want) { - t.Errorf("GetDevice() got = %v, want %v", foundDevice.(Device).Model(), tt.want) + if !reflect.DeepEqual(foundDevice.(device.Device).Model(), tt.want) { + t.Errorf("GetDevice() got = %v, want %v", foundDevice.(device.Device).Model(), tt.want) } } @@ -758,8 +752,8 @@ func Test_pndImplementation_GetDeviceByName(t *testing.T) { return } if foundDevice != nil { - if !reflect.DeepEqual(foundDevice.(Device).Model(), tt.want) { - t.Errorf("GetDeviceByName() got = %v, want %v", foundDevice.(Device).Model(), tt.want) + if !reflect.DeepEqual(foundDevice.(device.Device).Model(), tt.want) { + t.Errorf("GetDeviceByName() got = %v, want %v", foundDevice.(device.Device).Model(), tt.want) } } diff --git a/nucleus/southbound.go b/nucleus/southbound.go index 11d63ddb6e537c78d6e0d9ecb29652efd53df77f..0f2eda136b167053125b66d67890f6657b39699c 100644 --- a/nucleus/southbound.go +++ b/nucleus/southbound.go @@ -4,6 +4,7 @@ import ( "reflect" spb "code.fbi.h-da.de/cocsn/api/go/gosdn/southbound" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/southbound" "code.fbi.h-da.de/cocsn/gosdn/nucleus/errors" "code.fbi.h-da.de/cocsn/yang-models/generated/openconfig" @@ -16,23 +17,8 @@ import ( log "github.com/sirupsen/logrus" ) -// SouthboundInterface provides an -// interface for SBI implementations -type SouthboundInterface interface { - // deprecated - SbiIdentifier() string - - // SetNode injects SBI specific model - // representation to the transport. - // Needed for type assertion. - SetNode() func(schema *yang.Entry, root interface{}, path *gpb.Path, val interface{}, opts ...ytypes.SetNodeOpt) error - Schema() *ytypes.Schema - ID() uuid.UUID - Type() spb.Type -} - // NewSBI creates a SouthboundInterface of a given type. -func NewSBI(southbound spb.Type) SouthboundInterface { +func NewSBI(southbound spb.Type) southbound.SouthboundInterface { switch southbound { case spb.Type_OPENCONFIG: return &OpenConfig{id: uuid.New()} diff --git a/nucleus/southbound_test.go b/nucleus/southbound_test.go index 0bdaa18ec4c481c532f0eebd2de810c373acd89b..65f9d4b2faa87d3d0c319e8185036042a0eccab4 100644 --- a/nucleus/southbound_test.go +++ b/nucleus/southbound_test.go @@ -4,6 +4,8 @@ import ( "reflect" "testing" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/transport" + "code.fbi.h-da.de/cocsn/gosdn/nucleus/util/path" "code.fbi.h-da.de/cocsn/gosdn/nucleus/util/proto" "code.fbi.h-da.de/cocsn/yang-models/generated/openconfig" @@ -14,7 +16,7 @@ import ( func TestOpenConfig_Id(t *testing.T) { type fields struct { - transport Transport + transport transport.Transport schema *ytypes.Schema id uuid.UUID } diff --git a/nucleus/store.go b/nucleus/store.go index 911ae31129a32358660e52afb9a14d4125983d84..94a741bc69e395b833e0267fecd3452774a49b6b 100644 --- a/nucleus/store.go +++ b/nucleus/store.go @@ -5,6 +5,10 @@ import ( "reflect" "sync" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/device" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/networkdomain" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/southbound" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/store" "code.fbi.h-da.de/cocsn/gosdn/nucleus/errors" "github.com/google/uuid" @@ -13,49 +17,35 @@ import ( var storeLock sync.RWMutex -// Storable provides an interface for the controller's storage architecture. -type Storable interface { - ID() uuid.UUID -} - -// Store describes an interface for store implementations. -type Store interface { - Exists(id uuid.UUID) bool - Add(item Storable) error - Get(id uuid.UUID) (Storable, error) - Delete(id uuid.UUID) error - UUIDs() []uuid.UUID -} - // NewStore returns a generic Store -func NewStore() Store { - return store{} +func NewStore() store.Store { + return genericStore{} } // NewPndStore returns a PndStore func NewPndStore() *PndStore { - return &PndStore{store{}} + return &PndStore{genericStore{}} } // NewSbiStore returns a SbiStore func NewSbiStore() *SbiStore { - return &SbiStore{store{}} + return &SbiStore{genericStore{}} } // NewDeviceStore returns a DeviceStore func NewDeviceStore() *DeviceStore { - return &DeviceStore{store: store{}, deviceNameToUUIDLookup: make(map[string]uuid.UUID)} + return &DeviceStore{genericStore: genericStore{}, deviceNameToUUIDLookup: make(map[string]uuid.UUID)} } // NewChangeStore returns a ChangeStore func NewChangeStore() *ChangeStore { - return &ChangeStore{store{}} + return &ChangeStore{genericStore{}} } -type store map[uuid.UUID]Storable +type genericStore map[uuid.UUID]store.Storable // Exists takes a Storable's UUID and checks its existence in the store. -func (s store) Exists(id uuid.UUID) bool { +func (s genericStore) Exists(id uuid.UUID) bool { storeLock.RLock() defer storeLock.RUnlock() _, ok := s[id] @@ -63,7 +53,7 @@ func (s store) Exists(id uuid.UUID) bool { } // Add adds a Storable to the Store -func (s store) Add(item Storable) error { +func (s genericStore) Add(item store.Storable) error { if s.Exists(item.ID()) { return &errors.ErrAlreadyExists{Item: item} } @@ -79,7 +69,7 @@ func (s store) Add(item Storable) error { // Get takes a Storable's UUID and returns the Storable. If the requested // Storable does not exist an error is returned. -func (s store) Get(id uuid.UUID) (Storable, error) { +func (s genericStore) Get(id uuid.UUID) (store.Storable, error) { if !s.Exists(id) { return nil, &errors.ErrNotFound{ID: id} } @@ -93,7 +83,7 @@ func (s store) Get(id uuid.UUID) (Storable, error) { // Delete takes a Storable's UUID and deletes it. If the specified UUID does not // exist in the Store an error is returned. -func (s store) Delete(id uuid.UUID) error { +func (s genericStore) Delete(id uuid.UUID) error { if !s.Exists(id) { return &errors.ErrNotFound{ID: id} } @@ -107,7 +97,7 @@ func (s store) Delete(id uuid.UUID) error { } // UUIDs returns all UUIDs in the store. -func (s store) UUIDs() []uuid.UUID { +func (s genericStore) UUIDs() []uuid.UUID { storeLock.RLock() defer storeLock.RUnlock() keys := make([]uuid.UUID, len(s)) @@ -121,17 +111,17 @@ func (s store) UUIDs() []uuid.UUID { // SbiStore is used to store SouthboundInterfaces type SbiStore struct { - store + genericStore } -// Get takes a SouthboundInterface's UUID and returns the SouthboundInterface. If the requested +// GetSBI takes a SouthboundInterface's UUID and returns the SouthboundInterface. If the requested // SouthboundInterface does not exist an error is returned. -func (s SbiStore) Get(id uuid.UUID) (SouthboundInterface, error) { - item, err := s.store.Get(id) +func (s SbiStore) GetSBI(id uuid.UUID) (southbound.SouthboundInterface, error) { + item, err := s.genericStore.Get(id) if err != nil { return nil, err } - sbi, ok := item.(SouthboundInterface) + sbi, ok := item.(southbound.SouthboundInterface) if !ok { return nil, &errors.ErrInvalidTypeAssertion{ Value: sbi, @@ -146,17 +136,17 @@ func (s SbiStore) Get(id uuid.UUID) (SouthboundInterface, error) { // PndStore is used to store PrincipalNetworkDomains type PndStore struct { - store + genericStore } -// Get takes a PrincipalNetworkDomain's UUID and returns the PrincipalNetworkDomain. If the requested +// GetPND takes a PrincipalNetworkDomain's UUID and returns the PrincipalNetworkDomain. If the requested // PrincipalNetworkDomain does not exist an error is returned. -func (s PndStore) Get(id uuid.UUID) (PrincipalNetworkDomain, error) { - item, err := s.store.Get(id) +func (s PndStore) GetPND(id uuid.UUID) (networkdomain.NetworkDomain, error) { + item, err := s.genericStore.Get(id) if err != nil { return nil, err } - pnd, ok := item.(PrincipalNetworkDomain) + pnd, ok := item.(networkdomain.NetworkDomain) if !ok { return nil, &errors.ErrInvalidTypeAssertion{ Value: pnd, @@ -172,12 +162,12 @@ func (s PndStore) Get(id uuid.UUID) (PrincipalNetworkDomain, error) { // DeviceStore is used to store Devices type DeviceStore struct { deviceNameToUUIDLookup map[string]uuid.UUID - store + genericStore } -// Get takes a Device's UUID and returns the Device. If the requested +// GetDevice takes a Device's UUID and returns the Device. If the requested // Device does not exist an error is returned. -func (s DeviceStore) Get(id uuid.UUID, parseErrors ...error) (Device, error) { +func (s DeviceStore) GetDevice(id uuid.UUID, parseErrors ...error) (device.Device, error) { var foundID uuid.UUID foundID = id @@ -197,23 +187,23 @@ func (s DeviceStore) Get(id uuid.UUID, parseErrors ...error) (Device, error) { } } - item, err := s.store.Get(foundID) + item, err := s.genericStore.Get(foundID) if err != nil { return nil, err } - device, ok := item.(Device) + d, ok := item.(device.Device) if !ok { return nil, &errors.ErrInvalidTypeAssertion{ - Value: device, - Type: reflect.TypeOf((Device)(nil)), + Value: d, + Type: reflect.TypeOf((device.Device)(nil)), } } log.WithFields(log.Fields{ "uuid": id, - "name": device.Name, + "name": d.Name, }).Debug("device was accessed") - return device, nil + return d, nil } // FromString is a helper to check if a provided string as a valid UUID or a name. @@ -234,7 +224,7 @@ func FromString(id string) (uuid.UUID, error) { // Add adds a device to the device store. // It also adds the name of the device to the lookup table. -func (s DeviceStore) Add(item Storable, name string) error { +func (s DeviceStore) Add(item store.Storable, name string) error { if s.Exists(item.ID()) { return &errors.ErrAlreadyExists{Item: item} } @@ -242,7 +232,7 @@ func (s DeviceStore) Add(item Storable, name string) error { s.deviceNameToUUIDLookup[name] = item.ID() storeLock.Lock() - s.store[item.ID()] = item + s.genericStore[item.ID()] = item storeLock.Unlock() log.WithFields(log.Fields{ @@ -260,7 +250,7 @@ func (s DeviceStore) Delete(id uuid.UUID) error { } storeLock.Lock() - delete(s.store, id) + delete(s.genericStore, id) storeLock.Unlock() for key, value := range s.deviceNameToUUIDLookup { @@ -278,13 +268,13 @@ func (s DeviceStore) Delete(id uuid.UUID) error { // ChangeStore is used to store Changes type ChangeStore struct { - store + genericStore } -// Get takes a Change's UUID and returns the Change. If the requested +// GetChange takes a Change's UUID and returns the Change. If the requested // Change does not exist an error is returned. -func (s ChangeStore) Get(id uuid.UUID) (*Change, error) { - item, err := s.store.Get(id) +func (s ChangeStore) GetChange(id uuid.UUID) (*Change, error) { + item, err := s.genericStore.Get(id) if err != nil { return nil, err } diff --git a/nucleus/store_test.go b/nucleus/store_test.go index 69bbd6282f2e9bf7946d851e9c9bef2ba98b3949..abba8efcc2153e642bca10c222ea629aa3834eb3 100644 --- a/nucleus/store_test.go +++ b/nucleus/store_test.go @@ -5,30 +5,35 @@ import ( "sort" "testing" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/device" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/networkdomain" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/southbound" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/store" + "code.fbi.h-da.de/cocsn/gosdn/mocks" "github.com/google/uuid" ) -func Test_store_add(t *testing.T) { +func Test_Store_add(t *testing.T) { type args struct { - item Storable + item store.Storable } tests := []struct { name string - s store + s genericStore args args wantErr bool }{ { name: "default", - s: store{}, + s: genericStore{}, args: args{ item: &mocks.Storable{}, }, }, { name: "already exists", - s: store{ + s: genericStore{ iid: &mocks.Storable{}, }, args: args{ @@ -52,19 +57,19 @@ func Test_store_add(t *testing.T) { } } -func Test_store_delete(t *testing.T) { +func Test_Store_delete(t *testing.T) { type args struct { id uuid.UUID } tests := []struct { name string - s store + s genericStore args args wantErr bool }{ { name: "default", - s: store{ + s: genericStore{ iid: &mocks.Storable{}, }, args: args{id: iid}, @@ -72,13 +77,13 @@ func Test_store_delete(t *testing.T) { }, { name: "not found empty", - s: store{}, + s: genericStore{}, args: args{id: iid}, wantErr: true, }, { name: "not found", - s: store{ + s: genericStore{ iid: &mocks.Storable{}, }, args: args{id: altIid}, @@ -93,26 +98,26 @@ func Test_store_delete(t *testing.T) { if tt.name == "default" { item, ok := tt.s[iid] if ok { - t.Errorf("delete() item %v still in store %v", item, tt.s) + t.Errorf("delete() item %v still in genericStore %v", item, tt.s) } } }) } } -func Test_store_exists(t *testing.T) { +func Test_Store_exists(t *testing.T) { type args struct { id uuid.UUID } tests := []struct { name string - s store + s genericStore args args want bool }{ { name: "default", - s: store{ + s: genericStore{ iid: &mocks.Storable{}, }, args: args{id: iid}, @@ -120,13 +125,13 @@ func Test_store_exists(t *testing.T) { }, { name: "not found empty", - s: store{}, + s: genericStore{}, args: args{id: iid}, want: false, }, { name: "not found", - s: store{ + s: genericStore{ iid: &mocks.Storable{}, }, args: args{id: altIid}, @@ -142,20 +147,20 @@ func Test_store_exists(t *testing.T) { } } -func Test_store_get(t *testing.T) { +func Test_Store_get(t *testing.T) { type args struct { id uuid.UUID } tests := []struct { name string - s store + s genericStore args args - want Storable + want store.Storable wantErr bool }{ { name: "exists", - s: store{ + s: genericStore{ iid: &mocks.Storable{}, }, args: args{id: iid}, @@ -164,7 +169,7 @@ func Test_store_get(t *testing.T) { }, { name: "not found", - s: store{ + s: genericStore{ iid: &mocks.Storable{}, }, args: args{id: altIid}, @@ -173,7 +178,7 @@ func Test_store_get(t *testing.T) { }, { name: "not found empty", - s: store{}, + s: genericStore{}, args: args{id: iid}, want: nil, wantErr: true, @@ -193,15 +198,15 @@ func Test_store_get(t *testing.T) { } } -func Test_store_UUIDs(t *testing.T) { +func Test_Store_UUIDs(t *testing.T) { tests := []struct { name string - s store + s genericStore want []uuid.UUID }{ { name: "default", - s: store{ + s: genericStore{ iid: &mocks.Storable{}, altIid: &mocks.Storable{}, }, @@ -226,7 +231,7 @@ func Test_store_UUIDs(t *testing.T) { func Test_sbiStore_get(t *testing.T) { type fields struct { - store store + genericStore genericStore } type args struct { id uuid.UUID @@ -235,13 +240,13 @@ func Test_sbiStore_get(t *testing.T) { name string fields fields args args - want SouthboundInterface + want southbound.SouthboundInterface wantErr bool }{ { name: "exists", fields: fields{ - store: store{ + genericStore: genericStore{ defaultSbiID: &OpenConfig{id: defaultSbiID}, }, }, @@ -252,7 +257,7 @@ func Test_sbiStore_get(t *testing.T) { { name: "fails", fields: fields{ - store: store{ + genericStore: genericStore{ defaultSbiID: &OpenConfig{id: defaultSbiID}, }, }, @@ -262,7 +267,7 @@ func Test_sbiStore_get(t *testing.T) { { name: "fails empty", fields: fields{ - store: store{}, + genericStore: genericStore{}, }, args: args{id: defaultSbiID}, wantErr: true, @@ -270,7 +275,7 @@ func Test_sbiStore_get(t *testing.T) { { name: "fails wrong type", fields: fields{ - store: store{ + genericStore: genericStore{ did: &CommonDevice{ UUID: did, }, @@ -283,7 +288,7 @@ func Test_sbiStore_get(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { s := SbiStore{ - store: tt.fields.store, + genericStore: tt.fields.genericStore, } got, err := s.Get(tt.args.id) if (err != nil) != tt.wantErr { @@ -299,7 +304,7 @@ func Test_sbiStore_get(t *testing.T) { func Test_pndStore_get(t *testing.T) { type fields struct { - store store + genericStore genericStore } type args struct { id uuid.UUID @@ -308,13 +313,13 @@ func Test_pndStore_get(t *testing.T) { name string fields fields args args - want PrincipalNetworkDomain + want networkdomain.NetworkDomain wantErr bool }{ { name: "exists", fields: fields{ - store: store{ + genericStore: genericStore{ defaultPndID: &pndImplementation{id: defaultPndID}, }, }, @@ -325,7 +330,7 @@ func Test_pndStore_get(t *testing.T) { { name: "fails", fields: fields{ - store: store{ + genericStore: genericStore{ defaultPndID: &pndImplementation{id: defaultPndID}, }, }, @@ -335,7 +340,7 @@ func Test_pndStore_get(t *testing.T) { { name: "fails empty", fields: fields{ - store: store{}, + genericStore: genericStore{}, }, args: args{id: defaultPndID}, wantErr: true, @@ -343,7 +348,7 @@ func Test_pndStore_get(t *testing.T) { { name: "fails wrong type", fields: fields{ - store: store{ + genericStore: genericStore{ did: &CommonDevice{ UUID: did, }, @@ -356,7 +361,7 @@ func Test_pndStore_get(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { s := PndStore{ - store: tt.fields.store, + genericStore: tt.fields.genericStore, } got, err := s.Get(tt.args.id) if (err != nil) != tt.wantErr { @@ -372,7 +377,7 @@ func Test_pndStore_get(t *testing.T) { func Test_deviceStore_get(t *testing.T) { type fields struct { - store store + genericStore genericStore } type args struct { id uuid.UUID @@ -381,13 +386,13 @@ func Test_deviceStore_get(t *testing.T) { name string fields fields args args - want Device + want device.Device wantErr bool }{ { name: "exists", fields: fields{ - store: store{ + genericStore: genericStore{ defaultPndID: &CommonDevice{UUID: did}}}, args: args{id: defaultPndID}, want: &CommonDevice{ @@ -398,7 +403,7 @@ func Test_deviceStore_get(t *testing.T) { { name: "fails", fields: fields{ - store: store{ + genericStore: genericStore{ defaultPndID: &CommonDevice{UUID: did}}}, args: args{id: iid}, wantErr: true, @@ -406,7 +411,7 @@ func Test_deviceStore_get(t *testing.T) { { name: "fails empty", fields: fields{ - store: store{}, + genericStore: genericStore{}, }, args: args{id: defaultPndID}, wantErr: true, @@ -414,7 +419,7 @@ func Test_deviceStore_get(t *testing.T) { { name: "fails wrong type", fields: fields{ - store: store{ + genericStore: genericStore{ defaultPndID: &pndImplementation{id: defaultPndID}}}, args: args{id: defaultPndID}, wantErr: true, @@ -423,11 +428,11 @@ func Test_deviceStore_get(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { s := DeviceStore{ - store: tt.fields.store, + genericStore: tt.fields.genericStore, deviceNameToUUIDLookup: make(map[string]uuid.UUID), } - got, err := s.Get(FromString(tt.args.id.String())) + got, err := s.GetDevice(FromString(tt.args.id.String())) if (err != nil) != tt.wantErr { t.Errorf("get() error = %v, wantErr %v", err, tt.wantErr) return diff --git a/nucleus/transport.go b/nucleus/transport.go index dded3c4b299dcf9e9046b52e9c18c5f52dfe737e..3d8523e954d448a9fa461b42bacf56bf8b83e668 100644 --- a/nucleus/transport.go +++ b/nucleus/transport.go @@ -1,27 +1,15 @@ package nucleus import ( - "context" - tpb "code.fbi.h-da.de/cocsn/api/go/gosdn/transport" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/southbound" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/transport" "code.fbi.h-da.de/cocsn/gosdn/nucleus/errors" - - "github.com/openconfig/ygot/ytypes" ) -// Transport provides an interface for Transport implementations -// like RESTCONF or gnmi -type Transport interface { - Get(ctx context.Context, params ...string) (interface{}, error) - Set(ctx context.Context, params ...interface{}) error - Subscribe(ctx context.Context, params ...string) error - Type() string - ProcessResponse(resp interface{}, root interface{}, models *ytypes.Schema) error -} - // NewTransport receives TransportOptions and returns an appropriate Transport // implementation -func NewTransport(opts *tpb.TransportOption, sbi SouthboundInterface) (Transport, error) { +func NewTransport(opts *tpb.TransportOption, sbi southbound.SouthboundInterface) (transport.Transport, error) { if opts == nil { return nil, &errors.ErrInvalidParameters{ Func: NewTransport, diff --git a/nucleus/transport_test.go b/nucleus/transport_test.go index 0fa4ffa903a1f894325aaf5211341e19a2df754a..787c12a36021b1efe304a388b49092dd8515910d 100644 --- a/nucleus/transport_test.go +++ b/nucleus/transport_test.go @@ -1 +1,37 @@ package nucleus + +import ( + "reflect" + "testing" + + tpb "code.fbi.h-da.de/cocsn/api/go/gosdn/transport" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/southbound" + "code.fbi.h-da.de/cocsn/gosdn/interfaces/transport" +) + +func TestNewTransport(t *testing.T) { + type args struct { + opts *tpb.TransportOption + sbi southbound.SouthboundInterface + } + tests := []struct { + name string + args args + want transport.Transport + wantErr bool + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := NewTransport(tt.args.opts, tt.args.sbi) + if (err != nil) != tt.wantErr { + t.Errorf("NewTransport() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("NewTransport() got = %v, want %v", got, tt.want) + } + }) + } +}