Skip to content
Snippets Groups Projects
initialise_test.go 11 KiB
Newer Older
  • Learn to ignore specific revisions
  • Manuel Kieweg's avatar
    Manuel Kieweg committed
    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"
    
    	"code.fbi.h-da.de/danet/gosdn/controller/config"
    
    	"code.fbi.h-da.de/danet/gosdn/controller/conflict"
    
    	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"
    
    	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"
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	"github.com/google/uuid"
    	log "github.com/sirupsen/logrus"
    	"github.com/stretchr/testify/mock"
    
    	"go.mongodb.org/mongo-driver/mongo"
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	"google.golang.org/grpc"
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	"google.golang.org/grpc/credentials/insecure"
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	"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
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    var lis *bufconn.Listener
    var pndUUID uuid.UUID
    var sbiUUID uuid.UUID
    
    func bootstrapUnitTest() {
    	dialOptions = []grpc.DialOption{
    		grpc.WithContextDialer(bufDialer),
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    		grpc.WithTransportCredentials(insecure.NewCredentials()),
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	}
    	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)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	if err != nil {
    		log.Fatal(err)
    	}
    
    
    	eventService := eventservice.NewMockEventService()
    
    
    	pndStore = nucleus.NewMemoryPndStore()
    
    	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)
    	}
    
    	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})
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	mockPnd := mocks.NetworkDomain{}
    
    Manuel Kieweg's avatar
    Manuel Kieweg 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)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	mockPnd.On("Commit", mock.Anything).Return(nil)
    	mockPnd.On("Confirm", mock.Anything).Return(nil)
    
    	mockPnd.On("NetworkElements").Return([]networkelement.NetworkElement{
    		&nucleus.CommonNetworkElement{
    
    	mockPnd.On("ChangeMNE", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(uuid.Nil, nil)
    
    	if err := pndStore.Add(context.TODO(), &mockPnd); err != nil {
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		log.Fatal(err)
    	}
    
    
    	jwtManager := rbacImpl.NewJWTManager("", (10000 * time.Hour))
    
    	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]()
    
    	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,
    
    		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,
    
    		pluginService,
    		rpb.NewPluginRegistryServiceClient(&grpc.ClientConn{}),
    		csbi.NewCsbiServiceClient(&grpc.ClientConn{}),
    		func(u uuid.UUID, c chan networkelement.Details) {},
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	ppb.RegisterPndServiceServer(s, northbound.Pnd)
    
    	apb.RegisterAuthServiceServer(s, northbound.Auth)
    	apb.RegisterUserServiceServer(s, northbound.User)
    	apb.RegisterRoleServiceServer(s, northbound.Role)
    
    	mnepb.RegisterNetworkElementServiceServer(s, northbound.NetworkElement)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	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"
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    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)
    
    	addr := os.Getenv("CEOS_TEST_ENDPOINT")
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	if addr != "" {
    		testAddress = addr
    
    		log.Infof("CEOS_TEST_ENDPOINT set to %v", testAddress)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	}
    	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,
    	}
    }