diff --git a/.gitlab/ci/.test.yml b/.gitlab/ci/.test.yml index f66da72706c2bc6d549ee0fa0f82428e38e54cc4..2b291b8f4d32e65f9701ce46d4e051df14622357 100644 --- a/.gitlab/ci/.test.yml +++ b/.gitlab/ci/.test.yml @@ -10,6 +10,7 @@ integration-test-gosdn: MONGO_INITDB_ROOT_USERNAME: root MONGO_INITDB_ROOT_PASSWORD: example INTEGRATION_TEST_TARGET_A: gnmi-target_A:7030 + INTEGRATION_TEST_TARGET_B: gnmi-target_B:7030 services: - name: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/mongo:5 alias: mongo diff --git a/dev_env_data/docker-compose/integration-test_docker-compose.yml b/dev_env_data/docker-compose/integration-test_docker-compose.yml index 3d355431e435558556165abddd7e6b05cb4cc2e0..9d5ba0cb0ba554b36eee75c90f0196f9daab3e1c 100644 --- a/dev_env_data/docker-compose/integration-test_docker-compose.yml +++ b/dev_env_data/docker-compose/integration-test_docker-compose.yml @@ -65,6 +65,8 @@ services: gnmi-target_B: privileged: true image: registry.code.fbi.h-da.de/danet/gnmi-target/debian:master + ports: + - 3920:7030 volumes: - ../../artifacts/ssl/gnmi-target:/etc/gnmi-target/ssl command: diff --git a/integration-tests/example_tests/example_test.go b/integration-tests/example_tests/example_test.go index f88f8be2877577749f40b6b87731a9c4d6a9747f..b97e86fa85c09004d7dd6167e880a8e9a5c9b51e 100644 --- a/integration-tests/example_tests/example_test.go +++ b/integration-tests/example_tests/example_test.go @@ -37,5 +37,5 @@ func TestMain(m *testing.M) { func TestExample(t *testing.T) { defer integration_test_utils.ApplySDNConfig(conn, ctx, defaultSDNConfig) // You can set the environment to a different sdn config like this: - //integration_test_utils.SetEnvironment(connection, ctx, customSDNConfig) + // integration_test_utils.ApplySDNConfig(connection, ctx, customSDNConfig) } diff --git a/integration-tests/integrationTestUtils/integrationTestUtils.go b/integration-tests/integrationTestUtils/integrationTestUtils.go index daf272f74c1cd1d30c9dd68bc76f2bf8a8f5cbef..7f556cb825eb5b9c279be83ba0d3b767c65e15a4 100644 --- a/integration-tests/integrationTestUtils/integrationTestUtils.go +++ b/integration-tests/integrationTestUtils/integrationTestUtils.go @@ -21,6 +21,13 @@ import ( const admin = "admin" +// Default target values. +const DefaultTargetPluginUUID = "d1c269a2-6482-4010-b0d8-679dff73153b" +const DefaultTargetAAdress = "gnmi-target_A:7030" +const DefaultTargetBAdress = "gnmi-target_B:7030" +const DefaultTargetUsername = "admin" +const DefaultTargetPassword = "admin" + func CreateContextWithAuthorization(loginResponse *rbac.LoginResponse) context.Context { md := metadata.Pairs("authorize", loginResponse.Token) return metadata.NewOutgoingContext(context.Background(), md) diff --git a/integration-tests/lab_tests/lab00_test.go b/integration-tests/lab_tests/lab00_test.go new file mode 100644 index 0000000000000000000000000000000000000000..a2c5be7013cc4e91920da6e4a2bd00af0ac6106d --- /dev/null +++ b/integration-tests/lab_tests/lab00_test.go @@ -0,0 +1,157 @@ +package integration_test_labs + +import ( + "context" + "fmt" + "testing" + + mnepb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/networkelement" + integration_test_utils "code.fbi.h-da.de/danet/gosdn/integration-tests/integrationTestUtils" + "github.com/stretchr/testify/assert" + "google.golang.org/grpc" +) + +const pndID = "5f20f34b-cbd0-4511-9ddc-c50cf6a3b49d" + +const ( + targetAName = "gnmi-targetA" + targetAUUID = "e3cc56ad-2a6c-4b76-8315-5f17a6dc25bf" + targetBName = "gnmi-targetB" + targetBUUID = "87c8bcc1-d95c-401e-b447-f02c56abd8b1" +) + +// The connection to the controller to use in each test. +var conn *grpc.ClientConn + +// The context containing the credentials when authenticated. +var ctx context.Context + +// A defaultSDN config with default/empty values. +var defaultSDNConfig string + +func TestMain(m *testing.M) { + localConn, localCtx, err := integration_test_utils.CreateSecureConnection() + if err != nil { + fmt.Println(err.Error()) + } + conn = localConn + ctx = localCtx + + sndConfig, err := integration_test_utils.ExportCurrentSDNConfig(conn, ctx) + defaultSDNConfig = sndConfig + if err != nil { + fmt.Println(err.Error()) + } + + integration_test_utils.ApplySDNConfig(conn, ctx, defaultSDNConfig) + + m.Run() +} + +// The following test describes a chain of commands (see +// https://code.fbi.h-da.de/danet/gosdn/-/wikis/Labs/Lab00-education). + +func TestLab00(t *testing.T) { + defer integration_test_utils.ApplySDNConfig(conn, ctx, defaultSDNConfig) + + managedNetworkElements := []struct { + name string + newHostname string + id string + addr string + username string + password string + }{ + { + name: targetAName, + newHostname: "newHostnameForTargetA", + id: targetAUUID, + addr: integration_test_utils.DefaultTargetAAdress, + }, + { + name: targetBName, + newHostname: "newHostnameForTargetB", + id: targetBUUID, + addr: integration_test_utils.DefaultTargetBAdress, + }, + } + + mneService := mnepb.NewNetworkElementServiceClient(conn) + + // Create the two managed network elements. + for i, mne := range managedNetworkElements { + alr := createAddListRequestSingleMne(mne.addr, mne.name, mne.id, integration_test_utils.DefaultTargetUsername, integration_test_utils.DefaultTargetPassword) + + _, err := mneService.AddList(ctx, alr) + if err != nil { + t.Error(err) + } + + getAllMneRequest := &mnepb.GetAllRequest{ + Timestamp: integration_test_utils.GetTimestamp(), + Pid: pndID, + } + + getAllResponse, err := mneService.GetAll(ctx, getAllMneRequest) + if err != nil { + t.Error(err) + } + + assert.Equal(t, i+1, len(getAllResponse.GetMne()), "Amount of registered managed network elements is not correct.") + } + + // Check the initial hostname of both managed network elements. + for _, mne := range managedNetworkElements { + hostnameRequest := getHostnameSingleMne(mne.id) + resp, err := mneService.GetPath(ctx, hostnameRequest) + if err != nil { + t.Error(err) + } + + assert.Equal(t, 1, len(resp.GetMneNotification()), "The hostname for the managed network element has been requested. Therefore exactly one response is expected.") + assert.NotEmpty(t, resp.MneNotification[0].GetUpdate()[0].GetVal().GetStringVal(), "It is expected, that the hostname of the managed network element is not empty.") + } + + // Change the hostname of both managed network elements. + + for _, mne := range managedNetworkElements { + hostnamePathListRequest, err := setHostnamePathListRequestSingleMne(mne.id, mne.newHostname, mnepb.ApiOperation_API_OPERATION_UPDATE) + if err != nil { + t.Error(err) + } + + setResp, err := mneService.SetPathList(ctx, hostnamePathListRequest) + if err != nil { + t.Error(err) + } + + assert.Equal(t, 1, len(setResp.GetResponses()), "A single path change for the hostname has been requested. Therefore exactly one response is expected.") + + // Commit the change. + commitChange := commitOrConfirmChange(setResp.GetResponses()[0].GetId(), mnepb.Operation_OPERATION_COMMIT) + _, err = mneService.SetChangeList(ctx, commitChange) + if err != nil { + t.Error(err) + } + + // Confirm the change. + confirmChange := commitOrConfirmChange(setResp.GetResponses()[0].GetId(), mnepb.Operation_OPERATION_CONFIRM) + _, err = mneService.SetChangeList(ctx, confirmChange) + if err != nil { + t.Error(err) + } + } + + // Check if the hostname has been changed and is accessible through a + // GetPath request. + for _, mne := range managedNetworkElements { + hostnameRequest := getHostnameSingleMne(mne.id) + resp, err := mneService.GetPath(ctx, hostnameRequest) + if err != nil { + t.Error(err) + } + + assert.Equal(t, 1, len(resp.GetMneNotification()), "The hostname for the managed network element has been requested. Therefore exactly one response is expected.") + assert.Equal(t, mne.newHostname, resp.MneNotification[0].GetUpdate()[0].GetVal().GetStringVal(), "Exptected the new changed hostname.") + } +} diff --git a/integration-tests/lab_tests/labUtility_test.go b/integration-tests/lab_tests/labUtility_test.go new file mode 100644 index 0000000000000000000000000000000000000000..8ef246c3549b254336a8c1cf049d8770d3916570 --- /dev/null +++ b/integration-tests/lab_tests/labUtility_test.go @@ -0,0 +1,85 @@ +package integration_test_labs + +import ( + mnepb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/networkelement" + tpb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/transport" + integration_test_utils "code.fbi.h-da.de/danet/gosdn/integration-tests/integrationTestUtils" + "github.com/openconfig/gnmi/proto/gnmi" + "github.com/openconfig/ygot/ygot" +) + +func getHostnameSingleMne(mneId string) *mnepb.GetPathRequest { + gpr := &mnepb.GetPathRequest{ + Timestamp: integration_test_utils.GetTimestamp(), + Mneid: mneId, + Path: "system/config/hostname", + Pid: pndID, + } + + return gpr +} + +func commitOrConfirmChange(cid string, operation mnepb.Operation) *mnepb.SetChangeListRequest { + sclr := &mnepb.SetChangeListRequest{ + Timestamp: integration_test_utils.GetTimestamp(), + Change: []*mnepb.SetChange{{ + Cuid: cid, + Op: operation, + }}, + Pid: pndID, + } + return sclr +} + +func setHostnamePathListRequestSingleMne(mneId string, newHostname string, operation mnepb.ApiOperation) (*mnepb.SetPathListRequest, error) { + hostnamePath, err := ygot.StringToStructuredPath("/system/config/hostname") + if err != nil { + return nil, err + } + + splr := &mnepb.SetPathListRequest{ + Timestamp: integration_test_utils.GetTimestamp(), + ChangeRequest: []*mnepb.ChangeRequest{ + { + Mneid: mneId, + Path: hostnamePath, + Value: &gnmi.TypedValue{ + Value: &gnmi.TypedValue_StringVal{ + StringVal: newHostname, + }, + }, + ApiOp: operation, + }, + }, + } + return splr, nil +} + +func createAddListRequestSingleMne(addr, name, id, username, password string) *mnepb.AddListRequest { + opt := &tpb.TransportOption{ + Address: addr, + Username: username, + Password: password, + TransportOption: &tpb.TransportOption_GnmiTransportOption{ + GnmiTransportOption: &tpb.GnmiTransportOption{}, + }, + Tls: true, + } + + alr := &mnepb.AddListRequest{ + Timestamp: integration_test_utils.GetTimestamp(), + Mne: []*mnepb.SetMne{ + { + Address: addr, + Pid: pndID, + PluginId: integration_test_utils.DefaultTargetPluginUUID, + TransportOption: opt, + MneName: name, + MneId: id, + }, + }, + Pid: pndID, + } + + return alr +}