package services import ( "context" "errors" "testing" "time" "github.com/DATA-DOG/go-sqlmock" "github.com/google/uuid" "github.com/stretchr/testify/assert" "edge-infra.dev/pkg/edge/api/bsl/types" "edge-infra.dev/pkg/edge/api/graph/model" "edge-infra.dev/pkg/edge/api/middleware" sqlquery "edge-infra.dev/pkg/edge/api/sql" edgetypes "edge-infra.dev/pkg/edge/api/types" "edge-infra.dev/pkg/edge/bsl" "edge-infra.dev/pkg/edge/constants/api/banner" "edge-infra.dev/pkg/edge/controllers/util/edgedb" ) var defaultCfg = &edgetypes.Config{} func TestBannerSQLEntry(t *testing.T) { db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual)) if err != nil { t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) } defer db.Close() mock.MatchExpectationsInOrder(false) mock.ExpectQuery(sqlquery.GetTenantByOrgNameQuery). WithArgs(testOrganization). WillReturnRows(mock.NewRows([]string{"tenant_id"}). AddRow(1)) mock.ExpectExec(sqlquery.BannerInsertQuery). WithArgs("euid", testOrganization, "org", projectID, "1", "uuid", "description"). WillReturnResult(sqlmock.NewResult(1, 1)) mock.ExpectExec(sqlquery.DeleteBannerQuery).WithArgs("uuid"). WillReturnResult(sqlmock.NewResult(1, 1)) bslClient := bsl.NewBSLClient(types.BSPConfig{}) organizationService := NewBannerService(nil, nil, bslClient, "", db, defaultCfg) contextWithAuth := middleware.NewContext(context.Background(), &types.AuthUser{ Username: testUsername, Token: testBSLToken, Organization: testOrganization, }) //projectID, bannerName, bannerType, enterpriseUnitID, bannerUUID, description string err = organizationService.CreateBannerSQLEntry(contextWithAuth, projectID, testOrganization, "org", "euid", "uuid", "description") assert.NoError(t, err) err = organizationService.DeleteBannerSQLEntry(contextWithAuth, "uuid") assert.NoError(t, err) if err := mock.ExpectationsWereMet(); err != nil { t.Errorf("there were unfulfilled expectations: %s", err) } } func TestGetPathEntry(t *testing.T) { db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual)) if err != nil { t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) } defer db.Close() mock.MatchExpectationsInOrder(false) mock.ExpectQuery(sqlquery.GetBannerInfraInfo). WithArgs().WillReturnError(errors.New("bad req")) mock.ExpectQuery(sqlquery.GetBannerInfraInfo). WithArgs(). WillReturnRows(mock.NewRows([]string{"clusterEdgeID", "clusterName", "projectID", "active"}). AddRow("edge_id_path", "&clusterName", "&projectID", true)) organizationService := NewBannerService(nil, nil, nil, "", db, defaultCfg) contextWithAuth := middleware.NewContext(context.Background(), &types.AuthUser{ Username: testUsername, Token: testBSLToken, Organization: testOrganization, }) //projectID, bannerName, bannerType, enterpriseUnitID, bannerUUID, description string path, err := organizationService.GetBannerInfraBucketPath(contextWithAuth) assert.Error(t, err) assert.Equal(t, "", path) path, err = organizationService.GetBannerInfraBucketPath(contextWithAuth) assert.NoError(t, err) assert.Equal(t, "edge_id_path", path) if err := mock.ExpectationsWereMet(); err != nil { t.Errorf("there were unfulfilled expectations: %s", err) } } func TestUpdateBannerSQLEntry(t *testing.T) { db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual)) if err != nil { t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) } defer db.Close() desc := "test-desc" mock.ExpectExec(sqlquery.UpdateBanner).WithArgs("test-name", desc, "test-uuid"). WillReturnResult(sqlmock.NewResult(1, 1)) bslClient := bsl.NewBSLClient(types.BSPConfig{}) organizationService := NewBannerService(nil, nil, bslClient, "", db, defaultCfg) err = organizationService.UpdateBannerSQL(context.Background(), &model.Banner{BannerEdgeID: "test-uuid", Name: "test-name", Description: &desc}) assert.NoError(t, err) if err := mock.ExpectationsWereMet(); err != nil { t.Errorf("there were unfulfilled expectations: %s", err) } } func TestCreateBannerCr(t *testing.T) { bslClient := bsl.NewBSLClient(types.BSPConfig{}) organizationService := NewBannerService(nil, nil, bslClient, "", nil, defaultCfg) contextWithAuth := middleware.NewContext(context.Background(), &types.AuthUser{ Username: testUsername, Token: testBSLToken, Organization: testOrganization, }) caps := []string{"cap1", "cap2"} bannerCRD, err := organizationService.CreateBannerCr(contextWithAuth, uuid.NewString(), projectID, testOrganization, "euid", caps) assert.NoError(t, err) assert.NotEmpty(t, bannerCRD) } func TestBannerProjectID(t *testing.T) { db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual)) if err != nil { t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) } defer db.Close() mock.ExpectQuery(sqlquery.GetProjectIDByBanner). WithArgs(testOrganization). WillReturnRows(mock.NewRows([]string{"project_id"}). AddRow(projectID)) bslClient := bsl.NewBSLClient(types.BSPConfig{}) organizationService := NewBannerService(nil, nil, bslClient, "", db, defaultCfg) p, err := organizationService.GetBannerProjectID(context.Background(), testOrganization) assert.NoError(t, err) assert.Equal(t, p, projectID) } func TestBannerFromEdgeID(t *testing.T) { db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual)) if err != nil { t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) } defer db.Close() mock.ExpectQuery(sqlquery.GetBannerByID). WithArgs(testOrgID). WillReturnRows(mock.NewRows([]string{"banner_edge_id", "banner_bsl_id", "banner_name", "banner_type", "project_id", "tenant_edge_id", "description", "edge_sec_opt_in_compliance"}). AddRow(testOrgID, testOrg, testOrg, "eu", projectID, "tenant", "desc", "true")) bslClient := bsl.NewBSLClient(types.BSPConfig{}) organizationService := NewBannerService(nil, nil, bslClient, "", db, defaultCfg) b, err := organizationService.GetBannerByEdgeID(context.Background(), testOrgID) assert.NoError(t, err) assert.Equal(t, b.BannerEdgeID, testOrgID) assert.Equal(t, b.Name, testOrg) assert.Equal(t, b.BannerType, "eu") assert.Equal(t, b.BannerBSLId, testOrg) assert.Equal(t, *b.Description, "desc") assert.Equal(t, b.TenantEdgeID, "tenant") assert.True(t, b.OptInEdgeSecurityCompliance) } func TestGetBannerTypeFromID(t *testing.T) { db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual)) if err != nil { t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) } defer db.Close() mock.ExpectQuery(sqlquery.GetBannerTypeFromIDQuery). WithArgs(testBannerID). WillReturnRows(mock.NewRows([]string{"banner_type"}). AddRow("eu")) bslClient := bsl.NewBSLClient(types.BSPConfig{}) organizationService := NewBannerService(nil, nil, bslClient, "", db, defaultCfg) bannerType, err := organizationService.GetBannerTypeFromID(context.Background(), testBannerID) assert.NoError(t, err) assert.Equal(t, banner.EU, bannerType) } func TestGetBannerTypeFromUUID(t *testing.T) { db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual)) if err != nil { t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) } defer db.Close() mock.ExpectQuery(sqlquery.GetBannerTypeFromUUIDQuery). WithArgs(testBanner). WillReturnRows(mock.NewRows([]string{"banner_type"}). AddRow("org")) bslClient := bsl.NewBSLClient(types.BSPConfig{}) organizationService := NewBannerService(nil, nil, bslClient, "", db, defaultCfg) bannerType, err := organizationService.GetBannerTypeFromUUID(context.Background(), testBanner) assert.NoError(t, err) assert.Equal(t, banner.Org, bannerType) } func TestGetBannerTenantInfo(t *testing.T) { db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual)) if err != nil { t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) } defer db.Close() mock.ExpectQuery(sqlquery.GetBannerTenantByOrgName). WithArgs("test-org"). WillReturnRows(mock.NewRows([]string{"uuid", "org_id", "org_name"}). AddRow("uuid", "test-org-id", "test-org")) bslClient := bsl.NewBSLClient(types.BSPConfig{}) organizationService := NewBannerService(nil, nil, bslClient, "", db, defaultCfg) tenantInfo, err := organizationService.GetBannerTenantInfo(context.Background(), "test-org") assert.NoError(t, err) assert.Equal(t, tenantInfo.TenantEdgeID, "uuid") assert.Equal(t, tenantInfo.TenantBSLId, "test-org-id") assert.Equal(t, tenantInfo.OrgName, "test-org") } func TestGetBannerInfoNoBanner(t *testing.T) { db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual)) if err != nil { t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) } defer db.Close() mock.ExpectQuery(sqlquery.GetBannerByBSLID). WithArgs("test-bsl-id"). WillReturnRows(mock.NewRows([]string{"banner_edge_id", "banner_bsl_id", "banner_name", "banner_type", "project_id", "tenant_edge_id", "description"})) bslClient := bsl.NewBSLClient(types.BSPConfig{}) organizationService := NewBannerService(nil, nil, bslClient, "", db, defaultCfg) banner := &model.Banner{Name: "test-banner", BannerBSLId: "test-bsl-id"} bannerInfo := organizationService.GetEdgeBannerInfo(context.Background(), []*model.Banner{banner}) assert.Equal(t, bannerInfo, []*model.Banner{}) } func TestGetClusterInfraInfo(t *testing.T) { db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual)) if err != nil { t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) } defer db.Close() active := true mock.ExpectQuery(sqlquery.GetClusterInfraInfo). WithArgs("test-banner-edge-id"). WillReturnRows(mock.NewRows([]string{"cluster_edge_id", "cluster_name", "project_id", "active"}). AddRow("test-cluster-edge-id", "test=cluster", testOrg, &active)) bslClient := bsl.NewBSLClient(types.BSPConfig{}) organizationService := NewBannerService(nil, nil, bslClient, "", db, defaultCfg) cluster, err := organizationService.GetClusterInfraInfo(context.Background(), "test-banner-edge-id") assert.NoError(t, err) assert.Equal(t, cluster.ClusterEdgeID, "test-cluster-edge-id") assert.Equal(t, *cluster.Active, true) assert.Equal(t, cluster.BannerEdgeID, "test-banner-edge-id") } func TestDeleteClusterSQLEntryForBanner(t *testing.T) { db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual)) if err != nil { t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) } defer db.Close() mock.ExpectExec(sqlquery.DeleteClusterQuery).WithArgs("test-cluster-id").WillReturnResult(sqlmock.NewResult(0, 0)) bslClient := bsl.NewBSLClient(types.BSPConfig{}) organizationService := NewBannerService(nil, nil, bslClient, "", db, defaultCfg) err = organizationService.DeleteClusterSQLEntry(context.Background(), "test-cluster-id") assert.NoError(t, err) } func TestDeleteOrgBanner(t *testing.T) { srv := getMockBspServer(t) defer srv.Close() appConfig := edgetypes.Config{ BSP: types.BSPConfig{ Endpoint: srv.URL, }, } bslClient := bsl.NewBSLClient(appConfig.BSP) organizationService := NewBannerService(nil, nil, bslClient, "", nil, defaultCfg) contextWithAuth := middleware.NewContext(context.Background(), &types.AuthUser{ Username: testUsername, Token: testBSLToken, Organization: testOrganization, }) deleted, err := organizationService.DeleteOrgBanner(contextWithAuth, testBannerID) assert.Nil(t, err) assert.Equal(t, deleted, true) } func TestDeleteEUBanner(t *testing.T) { srv := getMockBspServer(t) defer srv.Close() appConfig := edgetypes.Config{ BSP: types.BSPConfig{ Endpoint: srv.URL, }, } bslClient := bsl.NewBSLClient(appConfig.BSP) organizationService := NewBannerService(nil, nil, bslClient, "", nil, defaultCfg) contextWithAuth := middleware.NewContext(context.Background(), &types.AuthUser{ Username: testUsername, Token: testBSLToken, Organization: testOrganization, }) deleted, err := organizationService.DeleteEUBanner(contextWithAuth, testBanner, testBannerID) assert.Nil(t, err) assert.Equal(t, deleted, true) } func TestUpdateOrgBanner(t *testing.T) { srv := getMockBspServer(t) defer srv.Close() appConfig := edgetypes.Config{ BSP: types.BSPConfig{ Endpoint: srv.URL, }, } bslClient := bsl.NewBSLClient(appConfig.BSP) organizationService := NewBannerService(nil, nil, bslClient, "", nil, defaultCfg) contextWithAuth := middleware.NewContext(context.Background(), &types.AuthUser{ Username: testUsername, Token: testBSLToken, Organization: testOrganization, }) desc := "new-description" err := organizationService.UpdateOrgBanner(contextWithAuth, &model.Banner{BannerBSLId: "banner-edge-id", Name: "new-name", Description: &desc}) assert.Nil(t, err) } func TestUpdateEUBanner(t *testing.T) { srv := getMockBspServer(t) defer srv.Close() appConfig := edgetypes.Config{ BSP: types.BSPConfig{ Endpoint: srv.URL, }, } bslClient := bsl.NewBSLClient(appConfig.BSP) organizationService := NewBannerService(nil, nil, bslClient, "", nil, defaultCfg) contextWithAuth := middleware.NewContext(context.Background(), &types.AuthUser{ Username: testUsername, Token: testBSLToken, Organization: testOrganization, }) desc := "new-description" err := organizationService.UpdateEUBanner(contextWithAuth, &model.Banner{BannerBSLId: "test-banner", Name: "new-name", Description: &desc}) assert.Nil(t, err) } func TestGetUserAssignedBanner(t *testing.T) { db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual)) if err != nil { t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) } defer db.Close() mock.ExpectQuery(sqlquery.GetBannerByBSLID).WithArgs("test-org-id"). WillReturnRows(sqlmock.NewRows([]string{"banner_edge_id", "banner_bsl_id", "banner_name", "banner_type", "project_id", "tenant_edge_id", "description", "bsl_data_synced", "bsl_entity_types", "edge_sec_opt_in_compliance"}). AddRow("test-org-id", "test-org-banner", "eu-banner-bsl-id2", "EU", "eu-banner-bsl-id3", "eu-banner-bsl-id4", "eu-banner-bsl-id5", false, nil, true)) mock.ExpectQuery(sqlquery.GetBannerByBSLID).WithArgs("test-org-banner"). WillReturnRows(sqlmock.NewRows([]string{"banner_edge_id", "banner_bsl_id", "banner_name", "banner_type", "project_id", "tenant_edge_id", "description", "bsl_data_synced", "bsl_entity_types", "edge_sec_opt_in_compliance"}). AddRow("test-org-banner", "test-org-banner", "eu-banner-bsl-id2", "EU", "eu-banner-bsl-id3", "eu-banner-bsl-id4", "eu-banner-bsl-id5", false, nil, true)) mock.ExpectQuery(sqlquery.GetBannerByBSLID).WithArgs("eu-banner-bsl-id"). WillReturnRows(sqlmock.NewRows([]string{"banner_edge_id", "banner_bsl_id", "banner_name", "banner_type", "project_id", "tenant_edge_id", "description", "bsl_data_synced", "bsl_entity_types", "edge_sec_opt_in_compliance"}). AddRow("eu-banner-bsl-id", "test-org-banner", "eu-banner-bsl-id2", "EU", "eu-banner-bsl-id3", "eu-banner-bsl-id4", "eu-banner-bsl-id5", false, nil, true)) srv := getMockBspServer(t) defer srv.Close() appConfig := edgetypes.Config{ BSP: types.BSPConfig{ Endpoint: srv.URL, }, } bslClient := bsl.NewBSLClient(appConfig.BSP) organizationService := NewBannerService(nil, nil, bslClient, "", db, defaultCfg) contextWithAuth := middleware.NewContext(context.Background(), &types.AuthUser{ Username: testUsername, Token: testBSLToken, Organization: testOrganization, }) username := "test" _, err = organizationService.GetUserAssignedBanners(contextWithAuth, username) assert.NoError(t, err) } func TestUpdateBannerRemoteAccessIP(t *testing.T) { db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual)) if err != nil { t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) } defer db.Close() remoteAccessIP := "34.123.45.68" bannerEdgeID := "3396a52c-6a22-4049-9593-5a63b596a101" mock.ExpectExec(sqlquery.UpdateBannerRemoteAccessIP). WithArgs(remoteAccessIP, bannerEdgeID). WillReturnResult(sqlmock.NewResult(1, 1)) organizationService := NewBannerService(nil, nil, nil, "", db, defaultCfg) err = organizationService.UpdateBannerRemoteAccessIP(context.Background(), remoteAccessIP, bannerEdgeID) assert.NoError(t, err) assert.NoError(t, mock.ExpectationsWereMet()) } func TestGetBannerInfraStatus(t *testing.T) { db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual)) if err != nil { t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) } defer db.Close() currTime := time.Now().Format(time.RFC3339) testCases := []struct { name string expectedStatusReason string expectedStatusMessage string isReady bool sqlMock func() *sqlmock.ExpectedQuery }{ { name: "READY infra status", expectedStatusReason: ProvisionedStatus, expectedStatusMessage: "ProvisionSucceeded: banner reconciled successfully", isReady: true, sqlMock: func() *sqlmock.ExpectedQuery { return mock.ExpectQuery(sqlquery.GetBannerInfraStatusByBannerEdgeID). WithArgs(testBanner). WillReturnRows(mock.NewRows([]string{"infra_status", "infra_status_details", "infra_status_updated_at"}). AddRow(string(edgedb.InfraStatusReady), "ProvisionSucceeded: banner reconciled successfully", currTime)) }, }, { name: "ERROR infra status", expectedStatusReason: string(edgedb.InfraStatusProvisioning), expectedStatusMessage: "ProjectNotReady: project is not ready: UpdateFailed", isReady: false, sqlMock: func() *sqlmock.ExpectedQuery { return mock.ExpectQuery(sqlquery.GetBannerInfraStatusByBannerEdgeID). WithArgs(testBanner). WillReturnRows(mock.NewRows([]string{"infra_status", "infra_status_details", "infra_status_updated_at"}). AddRow(string(edgedb.InfraStatusError), "ProjectNotReady: project is not ready: UpdateFailed", currTime)) }, }, { name: "PROVISIONING infra status", expectedStatusReason: string(edgedb.InfraStatusProvisioning), expectedStatusMessage: "Ready condition not found", isReady: false, sqlMock: func() *sqlmock.ExpectedQuery { return mock.ExpectQuery(sqlquery.GetBannerInfraStatusByBannerEdgeID). WithArgs(testBanner). WillReturnRows(mock.NewRows([]string{"infra_status", "infra_status_details", "infra_status_updated_at"}). AddRow(string(edgedb.InfraStatusProvisioning), "Ready condition not found", currTime)) }, }, { name: "No/Empty infra status", expectedStatusReason: string(edgedb.InfraStatusProvisioning), expectedStatusMessage: ProvisioningStatusMessage, isReady: false, sqlMock: func() *sqlmock.ExpectedQuery { return mock.ExpectQuery(sqlquery.GetBannerInfraStatusByBannerEdgeID). WithArgs(testBanner). WillReturnRows(mock.NewRows([]string{"infra_status", "infra_status_details", "infra_status_updated_at"}). AddRow("", "", "")) }, }, } bannerService := NewBannerService(nil, nil, nil, "", db, defaultCfg) for _, tc := range testCases { tc := tc t.Run(tc.name, func(t *testing.T) { tc.sqlMock() status, err := bannerService.GetBannerInfraStatus(context.Background(), testBanner) assert.NoError(t, err) assert.NotEmpty(t, status) assert.Equal(t, tc.expectedStatusReason, status.Reason) assert.Equal(t, tc.expectedStatusMessage, status.Message) assert.Equal(t, tc.isReady, status.Ready) assert.NotEmpty(t, status.LastUpdatedAt) _, err = time.Parse(time.RFC3339, status.LastUpdatedAt) assert.NoError(t, err) }) } err = mock.ExpectationsWereMet() assert.NoError(t, err) }