Newer
Older
package api
import (
"context"
"net"
"os"
"testing"
"code.fbi.h-da.de/danet/gosdn/api/go/gosdn/csbi"
mnepb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/networkelement"
rpb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/plugin-registry"
ppb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/pnd"
apb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/rbac"
tpb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/transport"
Andre Sterba
committed
"code.fbi.h-da.de/danet/gosdn/controller/app"
"code.fbi.h-da.de/danet/gosdn/controller/config"
"code.fbi.h-da.de/danet/gosdn/controller/conflict"
Fabian Seidl
committed
eventservice "code.fbi.h-da.de/danet/gosdn/controller/eventService"
"code.fbi.h-da.de/danet/gosdn/controller/interfaces/networkdomain"
"code.fbi.h-da.de/danet/gosdn/controller/interfaces/networkelement"
"code.fbi.h-da.de/danet/gosdn/controller/interfaces/plugin"
"code.fbi.h-da.de/danet/gosdn/controller/interfaces/rbac"
"code.fbi.h-da.de/danet/gosdn/controller/mocks"
nbi "code.fbi.h-da.de/danet/gosdn/controller/northbound/server"
"code.fbi.h-da.de/danet/gosdn/controller/nucleus"
"code.fbi.h-da.de/danet/gosdn/controller/nucleus/util/proto"
rbacImpl "code.fbi.h-da.de/danet/gosdn/controller/rbac"
"code.fbi.h-da.de/danet/gosdn/controller/store"
"code.fbi.h-da.de/danet/gosdn/controller/topology"
"code.fbi.h-da.de/danet/gosdn/controller/topology/links"
"code.fbi.h-da.de/danet/gosdn/controller/topology/nodes"
"code.fbi.h-da.de/danet/gosdn/controller/topology/ports"
Andre Sterba
committed
routingtables "code.fbi.h-da.de/danet/gosdn/controller/topology/routing-tables"
topoStore "code.fbi.h-da.de/danet/gosdn/controller/topology/store"
"code.fbi.h-da.de/danet/gosdn/models/generated/openconfig"
"github.com/google/uuid"
log "github.com/sirupsen/logrus"
"github.com/stretchr/testify/mock"
"google.golang.org/grpc/test/bufconn"
gpb "github.com/openconfig/gnmi/proto/gnmi"
pb "google.golang.org/protobuf/proto"
)
/*
Based on this StackOverflow answer: https://stackoverflow.com/a/52080545/4378176
*/
const bufSize = 1024 * 1024
const bufnet = "bufnet"
const pndID = "2043519e-46d1-4963-9a8e-d99007e104b8"
const changeID = "0992d600-f7d4-4906-9559-409b04d59a5f"
const sbiID = "f6fd4b35-f039-4111-9156-5e4501bb8a5a"
const mneID = "7e0ed8cc-ebf5-46fa-9794-741494914883"
var pndStore networkdomain.PndStore
var userService rbac.UserService
var roleService rbac.RoleService
var pluginStore plugin.Store
var lis *bufconn.Listener
var pndUUID uuid.UUID
var sbiUUID uuid.UUID
func bootstrapUnitTest() {
dialOptions = []grpc.DialOption{
grpc.WithContextDialer(bufDialer),
grpc.WithTransportCredentials(insecure.NewCredentials()),
}
lis = bufconn.Listen(bufSize)
s := grpc.NewServer()
changeUUID, err := uuid.Parse(changeID)
if err != nil {
log.Fatal(err)
}
pndUUID, err = uuid.Parse(pndID)
if err != nil {
log.Fatal(err)
}
sbiUUID, err = uuid.Parse(sbiID)
if err != nil {
log.Fatal(err)
}
mneUUID, err := uuid.Parse(mneID)
Fabian Seidl
committed
eventService := eventservice.NewMockEventService()
pndStore = nucleus.NewMemoryPndStore()
Fabian Seidl
committed
userService = rbacImpl.NewUserService(rbacImpl.NewMemoryUserStore(), eventService)
roleService = rbacImpl.NewRoleService(rbacImpl.NewMemoryRoleStore(), eventService)
if err := clearAndCreateAuthTestSetup(); err != nil {
log.Fatal(err)
}
previousHostname := "previousHostname"
intendedHostname := "intendedHostname"
mockChange := &mocks.Change{}
mockChange.On("ID").Return(uuid.MustParse(changeID))
mockChange.On("Age").Return(time.Hour)
mockChange.On("Commit").Return(nil)
mockChange.On("Confirm").Return(nil)
mockChange.On("State").Return(mnepb.ChangeState_CHANGE_STATE_INCONSISTENT)
mockChange.On("PreviousState").Return(&openconfig.Device{
System: &openconfig.OpenconfigSystem_System{
Config: &openconfig.OpenconfigSystem_System_Config{
Hostname: &previousHostname,
},
},
})
mockChange.On("IntendedState").Return(&openconfig.Device{
System: &openconfig.OpenconfigSystem_System{
Config: &openconfig.OpenconfigSystem_System_Config{
Hostname: &intendedHostname,
},
},
})
defaultPluginID, err := uuid.Parse("b70c8425-68c7-4d4b-bb5e-5586572bd64b")
if err != nil {
log.Fatal(err)
}
Malte Bauch
committed
pluginMock := &mocks.Plugin{}
pluginMock.On("ID").Return(defaultPluginID)
pluginMock.On("Unmarshal", mock.Anything, mock.Anything).Return(nil)
pluginMock.On("GetNode", mock.Anything).Return([]*gpb.Notification{}, nil)
pluginMock.On("Model", mock.Anything).Return([]byte(
"{\n\t\"Acl\": null,\n\t\"Bfd\": null,\n\t\"Components\": null,\n\t\"Interfaces\": null,\n\t\"Keychains\": null,\n\t\"Lldp\": null,\n\t\"Messages\": null,\n\t\"NetworkInstances\": null,\n\t\"RoutingPolicy\": null,\n\t\"System\": null\n}"),
nil,
)
mockNetworkElement := &mocks.NetworkElement{}
mockNetworkElement.On("Plugin").Return(pluginMock)
mockNetworkElement.On("ID").Return(mneUUID)
mockNetworkElement.On("GetModel").Return(pluginMock.Model(false))
mockNetworkElement.On("Name").Return("openconfig")
mockNetworkElement.On("GetPlugin").Return(pluginMock)
mockNetworkElement.On("TransportAddress").Return("127.0.0.1:6030")
mockNetworkElement.On("GetMetadata").Return(conflict.Metadata{ResourceVersion: 0})
Malte Bauch
committed
mockPnd.On("ID").Return(pndUUID)
mockPnd.On("GetName").Return("test")
mockPnd.On("GetDescription").Return("test")
mockPnd.On("PendingChanges").Return([]uuid.UUID{changeUUID})
mockPnd.On("CommittedChanges").Return([]uuid.UUID{changeUUID})
mockPnd.On("GetChange", mock.Anything).Return(mockChange, nil)
mockPnd.On("AddNetworkElement", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, nil)
mockPnd.On("GetNetworkElement", mock.Anything).Return(mockNetworkElement, nil)
mockPnd.On("Commit", mock.Anything).Return(nil)
mockPnd.On("Confirm", mock.Anything).Return(nil)
mockPnd.On("NetworkElements").Return([]networkelement.NetworkElement{
&nucleus.CommonNetworkElement{
UUID: mneUUID,
Plugin: &mocks.Plugin{},
},
})
mockPnd.On("ChangeMNE", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(uuid.Nil, nil)
if err := pndStore.Add(context.TODO(), &mockPnd); err != nil {
jwtManager := rbacImpl.NewJWTManager("", (10000 * time.Hour))
Andre Sterba
committed
appService := app.NewMockAppService()
nodeStore := topoStore.NewGenericStore[nodes.Node]()
nodeService := nodes.NewNodeService(nodeStore, eventService)
portStore := topoStore.NewGenericStore[ports.Port]()
portService := ports.NewPortService(portStore, eventService)
topoloyStore := topoStore.NewGenericStore[links.Link]()
topologyService := topology.NewTopologyService(topoloyStore, nodeService, portService, eventService)
routeStore := topoStore.NewGenericStore[routingtables.RoutingTable]()
Andre Sterba
committed
routeService := routingtables.NewRoutingTableService(routeStore, nodeService, portService, eventService)
pluginStore = nucleus.NewMemoryPluginStore()
pluginService := nucleus.NewPluginService(pluginStore, eventService, nucleus.NewPluginThroughReattachConfig, rpb.NewPluginRegistryServiceClient(&grpc.ClientConn{}))
networkElementStore := nucleus.NewNetworkElementStore(&mongo.Database{}, pndUUID)
networkElementService := nucleus.NewNetworkElementService(networkElementStore, pluginService, eventService)
mne, _ := nucleus.NewNetworkElement("test", mneUUID, &tpb.TransportOption{
Address: "test",
Username: "test",
Password: "test",
TransportOption: &tpb.TransportOption_GnmiTransportOption{
GnmiTransportOption: &tpb.GnmiTransportOption{},
},
},
pndUUID,
pluginMock,
Fabian Seidl
committed
[][]string{},
conflict.Metadata{ResourceVersion: 0})
_ = networkElementService.Add(mne)
networkElementWatcher := nucleus.NewNetworkElementWatcher(networkElementService, eventService)
pndService := &mocks.PndService{}
pndService.On("GetAll").Return([]networkdomain.NetworkDomain{}, nil)
pndService.On("Add", mock.Anything).Return(nil)
pndService.On("Get", mock.Anything).Return(nucleus.NewPND(pndUUID, "test", "test"), nil)
changeStore := *store.NewChangeStore()
err = changeStore.Add(mockChange)
if err != nil {
log.Fatal(err)
}
northbound := nbi.NewNBI(
pndStore,
pndService,
networkElementService,
changeStore,
userService,
roleService,
*jwtManager,
topologyService,
nodeService,
portService,
Andre Sterba
committed
routeService,
appService,
pluginService,
rpb.NewPluginRegistryServiceClient(&grpc.ClientConn{}),
csbi.NewCsbiServiceClient(&grpc.ClientConn{}),
func(u uuid.UUID, c chan networkelement.Details) {},
networkElementWatcher,
apb.RegisterAuthServiceServer(s, northbound.Auth)
apb.RegisterUserServiceServer(s, northbound.User)
apb.RegisterRoleServiceServer(s, northbound.Role)
mnepb.RegisterNetworkElementServiceServer(s, northbound.NetworkElement)
go func() {
if err := s.Serve(lis); err != nil {
log.Fatalf("Server exited with error: %v", err)
}
}()
}
func bufDialer(context.Context, string) (net.Conn, error) {
return lis.Dial()
}
var testAddress = "10.254.254.105:6030"
var testAPIEndpoint = "gosdn-latest.apps.ocp.fbi.h-da.de"
var testUsername = "admin"
var testPassword = "arista"
var opt *tpb.TransportOption
var gnmiMessages map[string]pb.Message
func TestMain(m *testing.M) {
bootstrapUnitTest()
bootstrapIntegrationTest()
os.Exit(m.Run())
}
func bootstrapIntegrationTest() {
log.SetLevel(config.LogLevel)
log.Infof("CEOS_TEST_ENDPOINT set to %v", testAddress)
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
}
api := os.Getenv("GOSDN_TEST_API_ENDPOINT")
if api != "" {
testAPIEndpoint = api
log.Infof("GOSDN_TEST_API_ENDPOINT set to %v", testAPIEndpoint)
}
u := os.Getenv("GOSDN_TEST_USER")
if u != "" {
testUsername = u
log.Infof("GOSDN_TEST_USER set to %v", testUsername)
}
p := os.Getenv("GOSDN_TEST_PASSWORD")
if p != "" {
testPassword = p
log.Infof("GOSDN_TEST_PASSWORD set to %v", testPassword)
}
gnmiMessages = map[string]pb.Message{
"../test/proto/cap-resp-arista-ceos": &gpb.CapabilityResponse{},
"../test/proto/req-full-node": &gpb.GetRequest{},
"../test/proto/req-full-node-arista-ceos": &gpb.GetRequest{},
"../test/proto/req-interfaces-arista-ceos": &gpb.GetRequest{},
"../test/proto/req-interfaces-interface-arista-ceos": &gpb.GetRequest{},
"../test/proto/req-interfaces-wildcard": &gpb.GetRequest{},
"../test/proto/resp-full-node": &gpb.GetResponse{},
"../test/proto/resp-full-node-arista-ceos": &gpb.GetResponse{},
"../test/proto/resp-interfaces-arista-ceos": &gpb.GetResponse{},
"../test/proto/resp-interfaces-interface-arista-ceos": &gpb.GetResponse{},
"../test/proto/resp-interfaces-wildcard": &gpb.GetResponse{},
"../test/proto/resp-set-system-config-hostname": &gpb.SetResponse{},
}
for k, v := range gnmiMessages {
if err := proto.Read(k, v); err != nil {
log.Fatalf("error parsing %v: %v", k, err)
}
}
opt = &tpb.TransportOption{
Address: testAddress,
Username: testUsername,
Password: testPassword,
}
}