github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/internal/domain/subscription/service_test.go (about) 1 package subscription_test 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "regexp" 8 "testing" 9 10 "github.com/DATA-DOG/go-sqlmock" 11 "github.com/kyma-incubator/compass/components/director/internal/domain/subscription" 12 "github.com/kyma-incubator/compass/components/director/internal/repo" 13 "github.com/kyma-incubator/compass/components/director/internal/repo/testdb" 14 "github.com/kyma-incubator/compass/components/director/pkg/graphql" 15 "github.com/kyma-incubator/compass/components/director/pkg/persistence" 16 17 "github.com/kyma-incubator/compass/components/director/internal/domain/subscription/automock" 18 19 "github.com/stretchr/testify/assert" 20 "github.com/stretchr/testify/mock" 21 22 "github.com/kyma-incubator/compass/components/director/internal/domain/tenant" 23 "github.com/kyma-incubator/compass/components/director/internal/labelfilter" 24 "github.com/kyma-incubator/compass/components/director/internal/model" 25 "github.com/kyma-incubator/compass/components/director/pkg/apperrors" 26 "github.com/kyma-incubator/compass/components/director/pkg/resource" 27 ) 28 29 const ( 30 uuid = "647af599-7f2d-485c-a63b-615b5ff6daf1" 31 tenantRegion = "eu-1" 32 tenantRegionWithPrefix = subscription.RegionPrefix + tenantRegion 33 subscriptionAppName = "subscription-app-name-value" 34 35 regionalTenantSubdomain = "myregionaltenant" 36 subaccountTenantExtID = "32468d6e-f4cc-453c-beca-28c7bf55e0dd" 37 subaccountTenantInternalID = "b6fe5f45-d8ba-4aa8-a949-5f8edb00d4a3" 38 subscriptionProviderID = "id-value!t12345" 39 providerSubaccountID = "9cdbe10c-778c-432e-bf0e-e9686d04c679" 40 providerInternalID = "aa6301aa-7cf5-4335-82ae-35d078f8a2ed" 41 consumerTenantID = "ddf290d5-31c2-457e-a14d-461d3df95ac9" 42 runtimeCtxID = "cf226ea8-31f8-475d-bd28-5cba3df9c199" 43 providerRuntimeID = "96c85d13-22ee-4555-9b41-f5e364070c20" 44 instancesLabelID = "123-123" 45 runtimeM2MTableName = "tenant_runtimes" 46 47 subscriptionProviderIDLabelKey = "subscriptionProviderId" 48 consumerSubaccountLabelKey = "global_subaccount_id" 49 subscriptionLabelKey = "subscription" 50 subscriptionAppNameLabelKey = "runtimeType" 51 tntSubdomain = "subdomain1" 52 ) 53 54 var ( 55 testError = errors.New("test error") 56 notFoundErr = apperrors.NewNotFoundErrorWithType(resource.Runtime) 57 notFoundLabelErr = apperrors.NewNotFoundErrorWithType(resource.Label) 58 notFoundAppTemplateErr = apperrors.NewNotFoundErrorWithType(resource.ApplicationTemplate) 59 60 regionalAndSubscriptionFiltersWithPrefix = []*labelfilter.LabelFilter{ 61 labelfilter.NewForKeyWithQuery(subscriptionProviderIDLabelKey, fmt.Sprintf("\"%s\"", subscriptionProviderID)), 62 labelfilter.NewForKeyWithQuery(tenant.RegionLabelKey, fmt.Sprintf("\"%s\"", tenantRegionWithPrefix)), 63 } 64 regionalAndSubscriptionFilters = []*labelfilter.LabelFilter{ 65 labelfilter.NewForKeyWithQuery(subscriptionProviderIDLabelKey, fmt.Sprintf("\"%s\"", subscriptionProviderID)), 66 labelfilter.NewForKeyWithQuery(tenant.RegionLabelKey, fmt.Sprintf("\"%s\"", tenantRegion)), 67 } 68 69 providerRuntime = &model.Runtime{ID: providerRuntimeID, Name: "provider-runtime-1"} 70 71 providerAppNameLabelInput = &model.LabelInput{ 72 Key: subscriptionAppNameLabelKey, 73 Value: subscriptionAppName, 74 ObjectType: model.RuntimeLabelableObject, 75 ObjectID: providerRuntimeID, 76 } 77 78 runtimeCtxInput = model.RuntimeContextInput{ 79 Key: subscriptionLabelKey, 80 Value: consumerTenantID, 81 RuntimeID: providerRuntimeID, 82 } 83 84 consumerSubaccountLabelInput = &model.LabelInput{ 85 Key: consumerSubaccountLabelKey, 86 Value: subaccountTenantExtID, 87 ObjectID: runtimeCtxID, 88 ObjectType: model.RuntimeContextLabelableObject, 89 } 90 91 subdomainLabel = &model.Label{ 92 Key: subscription.SubdomainLabelKey, 93 Value: tntSubdomain, 94 ObjectType: model.TenantLabelableObject, 95 } 96 97 instancesLabelWithValueOne = &model.Label{ 98 ID: instancesLabelID, 99 Key: subscription.InstancesLabelKey, 100 Value: float64(1), 101 } 102 103 instancesLabelWithValueTwo = &model.Label{ 104 ID: instancesLabelID, 105 Key: subscription.InstancesLabelKey, 106 Value: float64(2), 107 } 108 109 instancesLabelInputWithValueOne = &model.LabelInput{ 110 Key: subscription.InstancesLabelKey, 111 Value: float64(1), 112 } 113 114 instancesLabelInputWithValueTwo = &model.LabelInput{ 115 Key: subscription.InstancesLabelKey, 116 Value: float64(2), 117 } 118 ) 119 120 func TestSubscribeRegionalTenant(t *testing.T) { 121 // GIVEN 122 db, DBMock := testdb.MockDatabase(t) 123 ctx := persistence.SaveToContext(context.TODO(), db) 124 providerCtx := tenant.SaveToContext(ctx, providerInternalID, providerSubaccountID) 125 consumerCtx := tenant.SaveToContext(providerCtx, subaccountTenantInternalID, subaccountTenantExtID) 126 127 // Subscribe flow 128 testCases := []struct { 129 Name string 130 Region string 131 RuntimeServiceFn func() *automock.RuntimeService 132 RuntimeCtxServiceFn func() *automock.RuntimeCtxService 133 LabelServiceFn func() *automock.LabelService 134 UIDServiceFn func() *automock.UidService 135 TenantSvcFn func() *automock.TenantService 136 TenantAccessMock func(DBMock testdb.DBMock) 137 ExpectedErrorOutput string 138 IsSuccessful bool 139 }{ 140 { 141 Name: "Succeeds", 142 Region: tenantRegion, 143 RuntimeServiceFn: func() *automock.RuntimeService { 144 provisioner := &automock.RuntimeService{} 145 provisioner.On("GetByFilters", providerCtx, regionalAndSubscriptionFilters).Return(providerRuntime, nil).Once() 146 return provisioner 147 }, 148 RuntimeCtxServiceFn: func() *automock.RuntimeCtxService { 149 rtmCtxSvc := &automock.RuntimeCtxService{} 150 rtmCtxSvc.On("Create", consumerCtx, runtimeCtxInput).Return(runtimeCtxID, nil).Once() 151 rtmCtxSvc.On("ListByFilter", consumerCtx, providerRuntimeID, []*labelfilter.LabelFilter{labelfilter.NewForKeyWithQuery(consumerSubaccountLabelKey, fmt.Sprintf("\"%s\"", subaccountTenantExtID))}, 100, "").Return(&model.RuntimeContextPage{}, nil).Once() 152 return rtmCtxSvc 153 }, 154 TenantSvcFn: func() *automock.TenantService { 155 tenantSvc := &automock.TenantService{} 156 tenantSvc.On("GetInternalTenant", ctx, providerSubaccountID).Return(providerInternalID, nil).Once() 157 tenantSvc.On("GetLowestOwnerForResource", providerCtx, resource.Runtime, providerRuntimeID).Return(providerSubaccountID, nil).Once() 158 tenantSvc.On("GetInternalTenant", providerCtx, subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 159 return tenantSvc 160 }, 161 LabelServiceFn: func() *automock.LabelService { 162 labelInput := &model.LabelInput{ 163 ObjectType: model.RuntimeContextLabelableObject, 164 ObjectID: runtimeCtxID, 165 Key: subscription.InstancesLabelKey, 166 Value: 1, 167 } 168 labelSvc := &automock.LabelService{} 169 labelSvc.On("UpsertLabel", providerCtx, providerSubaccountID, providerAppNameLabelInput).Return(nil).Once() 170 labelSvc.On("CreateLabel", consumerCtx, subaccountTenantInternalID, uuid, consumerSubaccountLabelInput).Return(nil).Once() 171 labelSvc.On("CreateLabel", consumerCtx, subaccountTenantInternalID, uuid, labelInput).Return(nil).Once() 172 return labelSvc 173 }, 174 UIDServiceFn: func() *automock.UidService { 175 uidSvc := &automock.UidService{} 176 uidSvc.On("Generate").Return(uuid).Twice() 177 return uidSvc 178 }, 179 TenantAccessMock: func(dbMock testdb.DBMock) { 180 dbMock.ExpectExec(regexp.QuoteMeta(fmt.Sprintf("WITH RECURSIVE parents AS (SELECT t1.id, t1.parent FROM business_tenant_mappings t1 WHERE id = ? UNION ALL SELECT t2.id, t2.parent FROM business_tenant_mappings t2 INNER JOIN parents t on t2.id = t.parent) INSERT INTO %s ( %s, %s, %s ) (SELECT parents.id AS tenant_id, ? as id, ? AS owner FROM parents) ON CONFLICT ( tenant_id, id ) DO NOTHING", runtimeM2MTableName, repo.M2MTenantIDColumn, repo.M2MResourceIDColumn, repo.M2MOwnerColumn))). 181 WithArgs(subaccountTenantInternalID, providerRuntimeID, false).WillReturnResult(sqlmock.NewResult(1, 1)) 182 }, 183 IsSuccessful: true, 184 }, 185 { 186 Name: "Succeeds when consumer is already subscribed", 187 Region: tenantRegion, 188 RuntimeServiceFn: func() *automock.RuntimeService { 189 provisioner := &automock.RuntimeService{} 190 provisioner.On("GetByFilters", providerCtx, regionalAndSubscriptionFilters).Return(providerRuntime, nil).Once() 191 return provisioner 192 }, 193 RuntimeCtxServiceFn: func() *automock.RuntimeCtxService { 194 rtmCtxSvc := &automock.RuntimeCtxService{} 195 rtmCtxSvc.On("ListByFilter", consumerCtx, providerRuntimeID, []*labelfilter.LabelFilter{labelfilter.NewForKeyWithQuery(consumerSubaccountLabelKey, fmt.Sprintf("\"%s\"", subaccountTenantExtID))}, 100, "").Return(&model.RuntimeContextPage{ 196 Data: []*model.RuntimeContext{{ 197 ID: "id", 198 RuntimeID: providerRuntimeID, 199 Key: consumerSubaccountLabelKey, 200 Value: consumerTenantID, 201 }}, 202 PageInfo: nil, 203 TotalCount: 1, 204 }, nil).Once() 205 return rtmCtxSvc 206 }, 207 TenantSvcFn: func() *automock.TenantService { 208 tenantSvc := &automock.TenantService{} 209 tenantSvc.On("GetInternalTenant", ctx, providerSubaccountID).Return(providerInternalID, nil).Once() 210 tenantSvc.On("GetInternalTenant", providerCtx, subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 211 return tenantSvc 212 }, 213 LabelServiceFn: func() *automock.LabelService { 214 lblSvc := &automock.LabelService{} 215 lblSvc.On("GetByKey", mock.Anything, subaccountTenantInternalID, model.RuntimeContextLabelableObject, "id", subscription.InstancesLabelKey).Return(instancesLabelWithValueOne, nil) 216 lblSvc.On("UpdateLabel", mock.Anything, subaccountTenantInternalID, instancesLabelID, instancesLabelInputWithValueTwo).Return(nil) 217 218 return lblSvc 219 }, 220 UIDServiceFn: unusedUUIDSvc, 221 IsSuccessful: true, 222 }, 223 { 224 Name: "Succeeds when consumer is already subscribed - missing instances label", 225 Region: tenantRegion, 226 RuntimeServiceFn: func() *automock.RuntimeService { 227 provisioner := &automock.RuntimeService{} 228 provisioner.On("GetByFilters", providerCtx, regionalAndSubscriptionFilters).Return(providerRuntime, nil).Once() 229 return provisioner 230 }, 231 RuntimeCtxServiceFn: func() *automock.RuntimeCtxService { 232 rtmCtxSvc := &automock.RuntimeCtxService{} 233 rtmCtxSvc.On("ListByFilter", consumerCtx, providerRuntimeID, []*labelfilter.LabelFilter{labelfilter.NewForKeyWithQuery(consumerSubaccountLabelKey, fmt.Sprintf("\"%s\"", subaccountTenantExtID))}, 100, "").Return(&model.RuntimeContextPage{ 234 Data: []*model.RuntimeContext{{ 235 ID: "id", 236 RuntimeID: providerRuntimeID, 237 Key: consumerSubaccountLabelKey, 238 Value: consumerTenantID, 239 }}, 240 PageInfo: nil, 241 TotalCount: 1, 242 }, nil).Once() 243 return rtmCtxSvc 244 }, 245 TenantSvcFn: func() *automock.TenantService { 246 tenantSvc := &automock.TenantService{} 247 tenantSvc.On("GetInternalTenant", ctx, providerSubaccountID).Return(providerInternalID, nil).Once() 248 tenantSvc.On("GetInternalTenant", providerCtx, subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 249 return tenantSvc 250 }, 251 LabelServiceFn: func() *automock.LabelService { 252 lblSvc := &automock.LabelService{} 253 labelInput := &model.LabelInput{ 254 Key: subscription.InstancesLabelKey, 255 ObjectID: "id", 256 ObjectType: model.RuntimeContextLabelableObject, 257 Value: 2, 258 } 259 lblSvc.On("GetByKey", mock.Anything, subaccountTenantInternalID, model.RuntimeContextLabelableObject, "id", subscription.InstancesLabelKey).Return(nil, notFoundLabelErr) 260 lblSvc.On("CreateLabel", mock.Anything, subaccountTenantInternalID, uuid, labelInput).Return(nil) 261 262 return lblSvc 263 }, 264 UIDServiceFn: func() *automock.UidService { 265 uidSvc := &automock.UidService{} 266 uidSvc.On("Generate").Return(uuid).Once() 267 return uidSvc 268 }, 269 IsSuccessful: true, 270 }, 271 { 272 Name: "Returns error when consumer listing runtime contexts by filter fails", 273 Region: tenantRegion, 274 RuntimeServiceFn: func() *automock.RuntimeService { 275 provisioner := &automock.RuntimeService{} 276 provisioner.On("GetByFilters", providerCtx, regionalAndSubscriptionFilters).Return(providerRuntime, nil).Once() 277 return provisioner 278 }, 279 RuntimeCtxServiceFn: func() *automock.RuntimeCtxService { 280 rtmCtxSvc := &automock.RuntimeCtxService{} 281 rtmCtxSvc.On("ListByFilter", consumerCtx, providerRuntimeID, []*labelfilter.LabelFilter{labelfilter.NewForKeyWithQuery(consumerSubaccountLabelKey, fmt.Sprintf("\"%s\"", subaccountTenantExtID))}, 100, "").Return(nil, testError).Once() 282 return rtmCtxSvc 283 }, 284 TenantSvcFn: func() *automock.TenantService { 285 tenantSvc := &automock.TenantService{} 286 tenantSvc.On("GetInternalTenant", ctx, providerSubaccountID).Return(providerInternalID, nil).Once() 287 tenantSvc.On("GetInternalTenant", providerCtx, subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 288 return tenantSvc 289 }, 290 LabelServiceFn: unusedLabelSvc, 291 UIDServiceFn: unusedUUIDSvc, 292 ExpectedErrorOutput: testError.Error(), 293 IsSuccessful: false, 294 }, 295 { 296 Name: "Returns an error when getting internal provider tenant", 297 Region: tenantRegion, 298 RuntimeServiceFn: unusedRuntimeSvc, 299 RuntimeCtxServiceFn: unusedRuntimeContextSvc, 300 TenantSvcFn: func() *automock.TenantService { 301 tenantSvc := &automock.TenantService{} 302 tenantSvc.On("GetInternalTenant", ctx, providerSubaccountID).Return("", testError).Once() 303 return tenantSvc 304 }, 305 LabelServiceFn: unusedLabelSvc, 306 UIDServiceFn: unusedUUIDSvc, 307 ExpectedErrorOutput: testError.Error(), 308 IsSuccessful: false, 309 }, 310 { 311 Name: "Returns an error when can't find runtimes", 312 Region: tenantRegion, 313 RuntimeServiceFn: func() *automock.RuntimeService { 314 provisioner := &automock.RuntimeService{} 315 provisioner.On("GetByFilters", providerCtx, regionalAndSubscriptionFilters).Return(nil, notFoundErr).Once() 316 return provisioner 317 }, 318 RuntimeCtxServiceFn: unusedRuntimeContextSvc, 319 TenantSvcFn: func() *automock.TenantService { 320 tenantSvc := &automock.TenantService{} 321 tenantSvc.On("GetInternalTenant", ctx, providerSubaccountID).Return(providerInternalID, nil).Once() 322 return tenantSvc 323 }, 324 LabelServiceFn: unusedLabelSvc, 325 UIDServiceFn: unusedUUIDSvc, 326 IsSuccessful: false, 327 }, 328 { 329 Name: "Returns an error when could not get runtime", 330 Region: tenantRegion, 331 RuntimeServiceFn: func() *automock.RuntimeService { 332 provisioner := &automock.RuntimeService{} 333 provisioner.On("GetByFilters", providerCtx, regionalAndSubscriptionFilters).Return(nil, testError).Once() 334 return provisioner 335 }, 336 RuntimeCtxServiceFn: unusedRuntimeContextSvc, 337 TenantSvcFn: func() *automock.TenantService { 338 tenantSvc := &automock.TenantService{} 339 tenantSvc.On("GetInternalTenant", ctx, providerSubaccountID).Return(providerInternalID, nil).Once() 340 return tenantSvc 341 }, 342 LabelServiceFn: unusedLabelSvc, 343 UIDServiceFn: unusedUUIDSvc, 344 ExpectedErrorOutput: testError.Error(), 345 IsSuccessful: false, 346 }, 347 { 348 Name: "Returns an error when could not get lowest owner of the runtime", 349 Region: tenantRegion, 350 RuntimeServiceFn: func() *automock.RuntimeService { 351 provisioner := &automock.RuntimeService{} 352 provisioner.On("GetByFilters", providerCtx, regionalAndSubscriptionFilters).Return(providerRuntime, nil).Once() 353 return provisioner 354 }, 355 RuntimeCtxServiceFn: func() *automock.RuntimeCtxService { 356 svc := &automock.RuntimeCtxService{} 357 svc.On("ListByFilter", consumerCtx, providerRuntimeID, []*labelfilter.LabelFilter{labelfilter.NewForKeyWithQuery(consumerSubaccountLabelKey, fmt.Sprintf("\"%s\"", subaccountTenantExtID))}, 100, "").Return(&model.RuntimeContextPage{}, nil).Once() 358 return svc 359 }, 360 TenantSvcFn: func() *automock.TenantService { 361 tenantSvc := &automock.TenantService{} 362 tenantSvc.On("GetInternalTenant", ctx, providerSubaccountID).Return(providerInternalID, nil).Once() 363 tenantSvc.On("GetInternalTenant", providerCtx, subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 364 tenantSvc.On("GetLowestOwnerForResource", providerCtx, resource.Runtime, providerRuntimeID).Return("", testError).Once() 365 return tenantSvc 366 }, 367 LabelServiceFn: unusedLabelSvc, 368 UIDServiceFn: unusedUUIDSvc, 369 ExpectedErrorOutput: testError.Error(), 370 IsSuccessful: false, 371 }, 372 { 373 Name: "Returns an error when could not upsert provider app name label", 374 Region: tenantRegion, 375 RuntimeServiceFn: func() *automock.RuntimeService { 376 provisioner := &automock.RuntimeService{} 377 provisioner.On("GetByFilters", providerCtx, regionalAndSubscriptionFilters).Return(providerRuntime, nil).Once() 378 return provisioner 379 }, 380 RuntimeCtxServiceFn: func() *automock.RuntimeCtxService { 381 svc := &automock.RuntimeCtxService{} 382 svc.On("ListByFilter", consumerCtx, providerRuntimeID, []*labelfilter.LabelFilter{labelfilter.NewForKeyWithQuery(consumerSubaccountLabelKey, fmt.Sprintf("\"%s\"", subaccountTenantExtID))}, 100, "").Return(&model.RuntimeContextPage{}, nil).Once() 383 return svc 384 }, 385 TenantSvcFn: func() *automock.TenantService { 386 tenantSvc := &automock.TenantService{} 387 tenantSvc.On("GetInternalTenant", ctx, providerSubaccountID).Return(providerInternalID, nil).Once() 388 tenantSvc.On("GetInternalTenant", providerCtx, subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 389 tenantSvc.On("GetLowestOwnerForResource", providerCtx, resource.Runtime, providerRuntimeID).Return(providerSubaccountID, nil).Once() 390 return tenantSvc 391 }, 392 393 LabelServiceFn: func() *automock.LabelService { 394 labelSvc := &automock.LabelService{} 395 labelSvc.On("UpsertLabel", providerCtx, providerSubaccountID, providerAppNameLabelInput).Return(testError).Once() 396 return labelSvc 397 }, 398 UIDServiceFn: unusedUUIDSvc, 399 ExpectedErrorOutput: testError.Error(), 400 IsSuccessful: false, 401 }, 402 { 403 Name: "Returns an error when getting consumer tenant", 404 Region: tenantRegion, 405 RuntimeServiceFn: func() *automock.RuntimeService { 406 provisioner := &automock.RuntimeService{} 407 provisioner.On("GetByFilters", providerCtx, regionalAndSubscriptionFilters).Return(providerRuntime, nil).Once() 408 return provisioner 409 }, 410 RuntimeCtxServiceFn: unusedRuntimeContextSvc, 411 TenantSvcFn: func() *automock.TenantService { 412 tenantSvc := &automock.TenantService{} 413 tenantSvc.On("GetInternalTenant", ctx, providerSubaccountID).Return(providerInternalID, nil).Once() 414 tenantSvc.On("GetInternalTenant", providerCtx, subaccountTenantExtID).Return("", testError).Once() 415 return tenantSvc 416 }, 417 418 LabelServiceFn: unusedLabelSvc, 419 UIDServiceFn: unusedUUIDSvc, 420 ExpectedErrorOutput: testError.Error(), 421 IsSuccessful: false, 422 }, 423 { 424 Name: "Returns an error when creating runtime context", 425 Region: tenantRegion, 426 RuntimeServiceFn: func() *automock.RuntimeService { 427 provisioner := &automock.RuntimeService{} 428 provisioner.On("GetByFilters", providerCtx, regionalAndSubscriptionFilters).Return(providerRuntime, nil).Once() 429 return provisioner 430 }, 431 RuntimeCtxServiceFn: func() *automock.RuntimeCtxService { 432 rtmCtxSvc := &automock.RuntimeCtxService{} 433 rtmCtxSvc.On("Create", consumerCtx, runtimeCtxInput).Return("", testError).Once() 434 rtmCtxSvc.On("ListByFilter", consumerCtx, providerRuntimeID, []*labelfilter.LabelFilter{labelfilter.NewForKeyWithQuery(consumerSubaccountLabelKey, fmt.Sprintf("\"%s\"", subaccountTenantExtID))}, 100, "").Return(&model.RuntimeContextPage{}, nil).Once() 435 return rtmCtxSvc 436 }, 437 TenantSvcFn: func() *automock.TenantService { 438 tenantSvc := &automock.TenantService{} 439 tenantSvc.On("GetInternalTenant", ctx, providerSubaccountID).Return(providerInternalID, nil).Once() 440 tenantSvc.On("GetLowestOwnerForResource", providerCtx, resource.Runtime, providerRuntimeID).Return(providerSubaccountID, nil).Once() 441 tenantSvc.On("GetInternalTenant", providerCtx, subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 442 return tenantSvc 443 }, 444 LabelServiceFn: func() *automock.LabelService { 445 labelSvc := &automock.LabelService{} 446 labelSvc.On("UpsertLabel", providerCtx, providerSubaccountID, providerAppNameLabelInput).Return(nil).Once() 447 return labelSvc 448 }, 449 TenantAccessMock: func(dbMock testdb.DBMock) { 450 dbMock.ExpectExec(regexp.QuoteMeta(fmt.Sprintf("WITH RECURSIVE parents AS (SELECT t1.id, t1.parent FROM business_tenant_mappings t1 WHERE id = ? UNION ALL SELECT t2.id, t2.parent FROM business_tenant_mappings t2 INNER JOIN parents t on t2.id = t.parent) INSERT INTO %s ( %s, %s, %s ) (SELECT parents.id AS tenant_id, ? as id, ? AS owner FROM parents) ON CONFLICT ( tenant_id, id ) DO NOTHING", runtimeM2MTableName, repo.M2MTenantIDColumn, repo.M2MResourceIDColumn, repo.M2MOwnerColumn))). 451 WithArgs(subaccountTenantInternalID, providerRuntimeID, false).WillReturnResult(sqlmock.NewResult(1, 1)) 452 }, 453 UIDServiceFn: unusedUUIDSvc, 454 ExpectedErrorOutput: testError.Error(), 455 IsSuccessful: false, 456 }, 457 { 458 Name: "Error when getting instances label", 459 Region: tenantRegion, 460 RuntimeServiceFn: func() *automock.RuntimeService { 461 provisioner := &automock.RuntimeService{} 462 provisioner.On("GetByFilters", providerCtx, regionalAndSubscriptionFilters).Return(providerRuntime, nil).Once() 463 return provisioner 464 }, 465 RuntimeCtxServiceFn: func() *automock.RuntimeCtxService { 466 rtmCtxSvc := &automock.RuntimeCtxService{} 467 rtmCtxSvc.On("ListByFilter", consumerCtx, providerRuntimeID, []*labelfilter.LabelFilter{labelfilter.NewForKeyWithQuery(consumerSubaccountLabelKey, fmt.Sprintf("\"%s\"", subaccountTenantExtID))}, 100, "").Return(&model.RuntimeContextPage{ 468 Data: []*model.RuntimeContext{{ 469 ID: "id", 470 RuntimeID: providerRuntimeID, 471 Key: consumerSubaccountLabelKey, 472 Value: consumerTenantID, 473 }}, 474 PageInfo: nil, 475 TotalCount: 1, 476 }, nil).Once() 477 return rtmCtxSvc 478 }, 479 TenantSvcFn: func() *automock.TenantService { 480 tenantSvc := &automock.TenantService{} 481 tenantSvc.On("GetInternalTenant", ctx, providerSubaccountID).Return(providerInternalID, nil).Once() 482 tenantSvc.On("GetInternalTenant", providerCtx, subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 483 return tenantSvc 484 }, 485 LabelServiceFn: func() *automock.LabelService { 486 lblSvc := &automock.LabelService{} 487 lblSvc.On("GetByKey", mock.Anything, subaccountTenantInternalID, model.RuntimeContextLabelableObject, "id", subscription.InstancesLabelKey).Return(nil, testError) 488 return lblSvc 489 }, 490 UIDServiceFn: unusedUUIDSvc, 491 IsSuccessful: false, 492 ExpectedErrorOutput: testError.Error(), 493 }, 494 { 495 Name: "Error when updating instances label", 496 Region: tenantRegion, 497 RuntimeServiceFn: func() *automock.RuntimeService { 498 provisioner := &automock.RuntimeService{} 499 provisioner.On("GetByFilters", providerCtx, regionalAndSubscriptionFilters).Return(providerRuntime, nil).Once() 500 return provisioner 501 }, 502 RuntimeCtxServiceFn: func() *automock.RuntimeCtxService { 503 rtmCtxSvc := &automock.RuntimeCtxService{} 504 rtmCtxSvc.On("ListByFilter", consumerCtx, providerRuntimeID, []*labelfilter.LabelFilter{labelfilter.NewForKeyWithQuery(consumerSubaccountLabelKey, fmt.Sprintf("\"%s\"", subaccountTenantExtID))}, 100, "").Return(&model.RuntimeContextPage{ 505 Data: []*model.RuntimeContext{{ 506 ID: "id", 507 RuntimeID: providerRuntimeID, 508 Key: consumerSubaccountLabelKey, 509 Value: consumerTenantID, 510 }}, 511 PageInfo: nil, 512 TotalCount: 1, 513 }, nil).Once() 514 return rtmCtxSvc 515 }, 516 TenantSvcFn: func() *automock.TenantService { 517 tenantSvc := &automock.TenantService{} 518 tenantSvc.On("GetInternalTenant", ctx, providerSubaccountID).Return(providerInternalID, nil).Once() 519 tenantSvc.On("GetInternalTenant", providerCtx, subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 520 return tenantSvc 521 }, 522 LabelServiceFn: func() *automock.LabelService { 523 lblSvc := &automock.LabelService{} 524 lblSvc.On("GetByKey", mock.Anything, subaccountTenantInternalID, model.RuntimeContextLabelableObject, "id", subscription.InstancesLabelKey).Return(instancesLabelWithValueOne, nil) 525 lblSvc.On("UpdateLabel", mock.Anything, subaccountTenantInternalID, instancesLabelID, instancesLabelInputWithValueTwo).Return(testError) 526 527 return lblSvc 528 }, 529 UIDServiceFn: unusedUUIDSvc, 530 IsSuccessful: false, 531 ExpectedErrorOutput: testError.Error(), 532 }, 533 { 534 Name: "Error when casting instances label value", 535 Region: tenantRegion, 536 RuntimeServiceFn: func() *automock.RuntimeService { 537 provisioner := &automock.RuntimeService{} 538 provisioner.On("GetByFilters", providerCtx, regionalAndSubscriptionFilters).Return(providerRuntime, nil).Once() 539 return provisioner 540 }, 541 RuntimeCtxServiceFn: func() *automock.RuntimeCtxService { 542 rtmCtxSvc := &automock.RuntimeCtxService{} 543 rtmCtxSvc.On("ListByFilter", consumerCtx, providerRuntimeID, []*labelfilter.LabelFilter{labelfilter.NewForKeyWithQuery(consumerSubaccountLabelKey, fmt.Sprintf("\"%s\"", subaccountTenantExtID))}, 100, "").Return(&model.RuntimeContextPage{ 544 Data: []*model.RuntimeContext{{ 545 ID: "id", 546 RuntimeID: providerRuntimeID, 547 Key: consumerSubaccountLabelKey, 548 Value: consumerTenantID, 549 }}, 550 PageInfo: nil, 551 TotalCount: 1, 552 }, nil).Once() 553 return rtmCtxSvc 554 }, 555 TenantSvcFn: func() *automock.TenantService { 556 tenantSvc := &automock.TenantService{} 557 tenantSvc.On("GetInternalTenant", ctx, providerSubaccountID).Return(providerInternalID, nil).Once() 558 tenantSvc.On("GetInternalTenant", providerCtx, subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 559 return tenantSvc 560 }, 561 LabelServiceFn: func() *automock.LabelService { 562 lblSvc := &automock.LabelService{} 563 instancesLabel := &model.Label{ 564 ID: instancesLabelID, 565 Key: subscription.InstancesLabelKey, 566 Value: "invalid-value", 567 } 568 lblSvc.On("GetByKey", mock.Anything, subaccountTenantInternalID, model.RuntimeContextLabelableObject, "id", subscription.InstancesLabelKey).Return(instancesLabel, nil) 569 return lblSvc 570 }, 571 UIDServiceFn: unusedUUIDSvc, 572 IsSuccessful: false, 573 ExpectedErrorOutput: errors.New("cannot cast \"instances\" label value").Error(), 574 }, 575 { 576 Name: "Error when creating instances label", 577 Region: tenantRegion, 578 RuntimeServiceFn: func() *automock.RuntimeService { 579 provisioner := &automock.RuntimeService{} 580 provisioner.On("GetByFilters", providerCtx, regionalAndSubscriptionFilters).Return(providerRuntime, nil).Once() 581 return provisioner 582 }, 583 RuntimeCtxServiceFn: func() *automock.RuntimeCtxService { 584 rtmCtxSvc := &automock.RuntimeCtxService{} 585 rtmCtxSvc.On("ListByFilter", consumerCtx, providerRuntimeID, []*labelfilter.LabelFilter{labelfilter.NewForKeyWithQuery(consumerSubaccountLabelKey, fmt.Sprintf("\"%s\"", subaccountTenantExtID))}, 100, "").Return(&model.RuntimeContextPage{ 586 Data: []*model.RuntimeContext{{ 587 ID: "id", 588 RuntimeID: providerRuntimeID, 589 Key: consumerSubaccountLabelKey, 590 Value: consumerTenantID, 591 }}, 592 PageInfo: nil, 593 TotalCount: 1, 594 }, nil).Once() 595 return rtmCtxSvc 596 }, 597 TenantSvcFn: func() *automock.TenantService { 598 tenantSvc := &automock.TenantService{} 599 tenantSvc.On("GetInternalTenant", ctx, providerSubaccountID).Return(providerInternalID, nil).Once() 600 tenantSvc.On("GetInternalTenant", providerCtx, subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 601 return tenantSvc 602 }, 603 LabelServiceFn: func() *automock.LabelService { 604 lblSvc := &automock.LabelService{} 605 labelInput := &model.LabelInput{ 606 Key: subscription.InstancesLabelKey, 607 ObjectID: "id", 608 ObjectType: model.RuntimeContextLabelableObject, 609 Value: 2, 610 } 611 lblSvc.On("GetByKey", mock.Anything, subaccountTenantInternalID, model.RuntimeContextLabelableObject, "id", subscription.InstancesLabelKey).Return(nil, notFoundLabelErr) 612 lblSvc.On("CreateLabel", mock.Anything, subaccountTenantInternalID, uuid, labelInput).Return(testError) 613 614 return lblSvc 615 }, 616 UIDServiceFn: func() *automock.UidService { 617 uidSvc := &automock.UidService{} 618 uidSvc.On("Generate").Return(uuid).Once() 619 return uidSvc 620 }, 621 IsSuccessful: false, 622 ExpectedErrorOutput: testError.Error(), 623 }, 624 { 625 Name: "Returns an error when creating tenant access recursively", 626 Region: tenantRegion, 627 RuntimeServiceFn: func() *automock.RuntimeService { 628 provisioner := &automock.RuntimeService{} 629 provisioner.On("GetByFilters", providerCtx, regionalAndSubscriptionFilters).Return(providerRuntime, nil).Once() 630 return provisioner 631 }, 632 RuntimeCtxServiceFn: func() *automock.RuntimeCtxService { 633 rtmCtxSvc := &automock.RuntimeCtxService{} 634 rtmCtxSvc.On("ListByFilter", consumerCtx, providerRuntimeID, []*labelfilter.LabelFilter{labelfilter.NewForKeyWithQuery(consumerSubaccountLabelKey, fmt.Sprintf("\"%s\"", subaccountTenantExtID))}, 100, "").Return(&model.RuntimeContextPage{}, nil).Once() 635 return rtmCtxSvc 636 }, 637 TenantSvcFn: func() *automock.TenantService { 638 tenantSvc := &automock.TenantService{} 639 tenantSvc.On("GetInternalTenant", ctx, providerSubaccountID).Return(providerInternalID, nil).Once() 640 tenantSvc.On("GetLowestOwnerForResource", providerCtx, resource.Runtime, providerRuntimeID).Return(providerSubaccountID, nil).Once() 641 tenantSvc.On("GetInternalTenant", providerCtx, subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 642 return tenantSvc 643 }, 644 LabelServiceFn: func() *automock.LabelService { 645 labelSvc := &automock.LabelService{} 646 labelSvc.On("UpsertLabel", providerCtx, providerSubaccountID, providerAppNameLabelInput).Return(nil).Once() 647 return labelSvc 648 }, 649 UIDServiceFn: unusedUUIDSvc, 650 TenantAccessMock: func(dbMock testdb.DBMock) { 651 dbMock.ExpectExec(regexp.QuoteMeta(fmt.Sprintf("WITH RECURSIVE parents AS (SELECT t1.id, t1.parent FROM business_tenant_mappings t1 WHERE id = ? UNION ALL SELECT t2.id, t2.parent FROM business_tenant_mappings t2 INNER JOIN parents t on t2.id = t.parent) INSERT INTO %s ( %s, %s, %s ) (SELECT parents.id AS tenant_id, ? as id, ? AS owner FROM parents) ON CONFLICT ( tenant_id, id ) DO NOTHING", runtimeM2MTableName, repo.M2MTenantIDColumn, repo.M2MResourceIDColumn, repo.M2MOwnerColumn))). 652 WithArgs(subaccountTenantInternalID, providerRuntimeID, false).WillReturnError(testError) 653 }, 654 ExpectedErrorOutput: "Unexpected error while executing SQL query", 655 IsSuccessful: false, 656 }, 657 { 658 Name: "Returns an error when creating consumer subaccount label", 659 Region: tenantRegion, 660 RuntimeServiceFn: func() *automock.RuntimeService { 661 provisioner := &automock.RuntimeService{} 662 provisioner.On("GetByFilters", providerCtx, regionalAndSubscriptionFilters).Return(providerRuntime, nil).Once() 663 return provisioner 664 }, 665 RuntimeCtxServiceFn: func() *automock.RuntimeCtxService { 666 rtmCtxSvc := &automock.RuntimeCtxService{} 667 rtmCtxSvc.On("Create", consumerCtx, runtimeCtxInput).Return(runtimeCtxID, nil).Once() 668 rtmCtxSvc.On("ListByFilter", consumerCtx, providerRuntimeID, []*labelfilter.LabelFilter{labelfilter.NewForKeyWithQuery(consumerSubaccountLabelKey, fmt.Sprintf("\"%s\"", subaccountTenantExtID))}, 100, "").Return(&model.RuntimeContextPage{}, nil).Once() 669 return rtmCtxSvc 670 }, 671 TenantSvcFn: func() *automock.TenantService { 672 tenantSvc := &automock.TenantService{} 673 tenantSvc.On("GetInternalTenant", ctx, providerSubaccountID).Return(providerInternalID, nil).Once() 674 tenantSvc.On("GetLowestOwnerForResource", providerCtx, resource.Runtime, providerRuntimeID).Return(providerSubaccountID, nil).Once() 675 tenantSvc.On("GetInternalTenant", providerCtx, subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 676 return tenantSvc 677 }, 678 LabelServiceFn: func() *automock.LabelService { 679 labelSvc := &automock.LabelService{} 680 labelSvc.On("UpsertLabel", providerCtx, providerSubaccountID, providerAppNameLabelInput).Return(nil).Once() 681 labelSvc.On("CreateLabel", consumerCtx, subaccountTenantInternalID, uuid, consumerSubaccountLabelInput).Return(testError).Once() 682 return labelSvc 683 }, 684 UIDServiceFn: func() *automock.UidService { 685 uidSvc := &automock.UidService{} 686 uidSvc.On("Generate").Return(uuid).Once() 687 return uidSvc 688 }, 689 TenantAccessMock: func(dbMock testdb.DBMock) { 690 dbMock.ExpectExec(regexp.QuoteMeta(fmt.Sprintf("WITH RECURSIVE parents AS (SELECT t1.id, t1.parent FROM business_tenant_mappings t1 WHERE id = ? UNION ALL SELECT t2.id, t2.parent FROM business_tenant_mappings t2 INNER JOIN parents t on t2.id = t.parent) INSERT INTO %s ( %s, %s, %s ) (SELECT parents.id AS tenant_id, ? as id, ? AS owner FROM parents) ON CONFLICT ( tenant_id, id ) DO NOTHING", runtimeM2MTableName, repo.M2MTenantIDColumn, repo.M2MResourceIDColumn, repo.M2MOwnerColumn))). 691 WithArgs(subaccountTenantInternalID, providerRuntimeID, false).WillReturnResult(sqlmock.NewResult(1, 1)) 692 }, 693 ExpectedErrorOutput: testError.Error(), 694 IsSuccessful: false, 695 }, 696 { 697 Name: "Returns an error when creating instances label", 698 Region: tenantRegion, 699 RuntimeServiceFn: func() *automock.RuntimeService { 700 provisioner := &automock.RuntimeService{} 701 provisioner.On("GetByFilters", providerCtx, regionalAndSubscriptionFilters).Return(providerRuntime, nil).Once() 702 return provisioner 703 }, 704 RuntimeCtxServiceFn: func() *automock.RuntimeCtxService { 705 rtmCtxSvc := &automock.RuntimeCtxService{} 706 rtmCtxSvc.On("Create", consumerCtx, runtimeCtxInput).Return(runtimeCtxID, nil).Once() 707 rtmCtxSvc.On("ListByFilter", consumerCtx, providerRuntimeID, []*labelfilter.LabelFilter{labelfilter.NewForKeyWithQuery(consumerSubaccountLabelKey, fmt.Sprintf("\"%s\"", subaccountTenantExtID))}, 100, "").Return(&model.RuntimeContextPage{}, nil).Once() 708 return rtmCtxSvc 709 }, 710 TenantSvcFn: func() *automock.TenantService { 711 tenantSvc := &automock.TenantService{} 712 tenantSvc.On("GetInternalTenant", ctx, providerSubaccountID).Return(providerInternalID, nil).Once() 713 tenantSvc.On("GetLowestOwnerForResource", providerCtx, resource.Runtime, providerRuntimeID).Return(providerSubaccountID, nil).Once() 714 tenantSvc.On("GetInternalTenant", providerCtx, subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 715 return tenantSvc 716 }, 717 LabelServiceFn: func() *automock.LabelService { 718 labelInput := &model.LabelInput{ 719 ObjectType: model.RuntimeContextLabelableObject, 720 ObjectID: runtimeCtxID, 721 Key: subscription.InstancesLabelKey, 722 Value: 1, 723 } 724 labelSvc := &automock.LabelService{} 725 labelSvc.On("UpsertLabel", providerCtx, providerSubaccountID, providerAppNameLabelInput).Return(nil).Once() 726 labelSvc.On("CreateLabel", consumerCtx, subaccountTenantInternalID, uuid, consumerSubaccountLabelInput).Return(nil).Once() 727 labelSvc.On("CreateLabel", consumerCtx, subaccountTenantInternalID, uuid, labelInput).Return(testError).Once() 728 return labelSvc 729 }, 730 UIDServiceFn: func() *automock.UidService { 731 uidSvc := &automock.UidService{} 732 uidSvc.On("Generate").Return(uuid).Twice() 733 return uidSvc 734 }, 735 TenantAccessMock: func(dbMock testdb.DBMock) { 736 dbMock.ExpectExec(regexp.QuoteMeta(fmt.Sprintf("WITH RECURSIVE parents AS (SELECT t1.id, t1.parent FROM business_tenant_mappings t1 WHERE id = ? UNION ALL SELECT t2.id, t2.parent FROM business_tenant_mappings t2 INNER JOIN parents t on t2.id = t.parent) INSERT INTO %s ( %s, %s, %s ) (SELECT parents.id AS tenant_id, ? as id, ? AS owner FROM parents) ON CONFLICT ( tenant_id, id ) DO NOTHING", runtimeM2MTableName, repo.M2MTenantIDColumn, repo.M2MResourceIDColumn, repo.M2MOwnerColumn))). 737 WithArgs(subaccountTenantInternalID, providerRuntimeID, false).WillReturnResult(sqlmock.NewResult(1, 1)) 738 }, 739 ExpectedErrorOutput: testError.Error(), 740 IsSuccessful: false, 741 }, 742 } 743 744 for _, testCase := range testCases { 745 t.Run(testCase.Name, func(t *testing.T) { 746 runtimeSvc := testCase.RuntimeServiceFn() 747 runtimeCtxSvc := testCase.RuntimeCtxServiceFn() 748 labelSvc := testCase.LabelServiceFn() 749 uuidSvc := testCase.UIDServiceFn() 750 tenantSvc := &automock.TenantService{} 751 if testCase.TenantSvcFn != nil { 752 tenantSvc = testCase.TenantSvcFn() 753 } 754 755 if testCase.TenantAccessMock != nil { 756 testCase.TenantAccessMock(DBMock) 757 defer DBMock.AssertExpectations(t) 758 } 759 760 service := subscription.NewService(runtimeSvc, runtimeCtxSvc, tenantSvc, labelSvc, nil, nil, nil, nil, uuidSvc, consumerSubaccountLabelKey, subscriptionLabelKey, subscriptionAppNameLabelKey, subscriptionProviderIDLabelKey) 761 762 // WHEN 763 isSubscribeSuccessful, err := service.SubscribeTenantToRuntime(ctx, subscriptionProviderID, subaccountTenantExtID, providerSubaccountID, consumerTenantID, testCase.Region, subscriptionAppName) 764 765 // THEN 766 if len(testCase.ExpectedErrorOutput) > 0 { 767 assert.Error(t, err) 768 assert.Contains(t, err.Error(), testCase.ExpectedErrorOutput) 769 } else { 770 assert.NoError(t, err) 771 } 772 773 assert.Equal(t, testCase.IsSuccessful, isSubscribeSuccessful) 774 775 mock.AssertExpectationsForObjects(t, runtimeSvc, runtimeCtxSvc, tenantSvc, labelSvc, uuidSvc) 776 }) 777 } 778 } 779 780 func TestUnSubscribeRegionalTenant(t *testing.T) { 781 // GIVEN 782 ctx := context.TODO() 783 providerCtx := tenant.SaveToContext(ctx, providerInternalID, providerSubaccountID) 784 consumerCtx := tenant.SaveToContext(providerCtx, subaccountTenantInternalID, subaccountTenantExtID) 785 786 runtimeCtxPage := &model.RuntimeContextPage{ 787 Data: []*model.RuntimeContext{ 788 { 789 ID: runtimeCtxID, 790 RuntimeID: providerRuntimeID, 791 Key: subscriptionLabelKey, 792 Value: consumerTenantID, 793 }, 794 }, 795 } 796 797 runtimeCtxFilter := []*labelfilter.LabelFilter{ 798 labelfilter.NewForKeyWithQuery(consumerSubaccountLabelKey, fmt.Sprintf("\"%s\"", subaccountTenantExtID)), 799 } 800 801 testCases := []struct { 802 Name string 803 Region string 804 RuntimeServiceFn func() *automock.RuntimeService 805 RuntimeCtxServiceFn func() *automock.RuntimeCtxService 806 LabelServiceFn func() *automock.LabelService 807 UIDServiceFn func() *automock.UidService 808 TenantSvcFn func() *automock.TenantService 809 ExpectedErrorOutput string 810 IsSuccessful bool 811 }{ 812 { 813 Name: "Succeeds", 814 Region: tenantRegion, 815 RuntimeServiceFn: func() *automock.RuntimeService { 816 provisioner := &automock.RuntimeService{} 817 provisioner.On("GetByFilters", providerCtx, regionalAndSubscriptionFilters).Return(providerRuntime, nil).Once() 818 return provisioner 819 }, 820 RuntimeCtxServiceFn: func() *automock.RuntimeCtxService { 821 rtmCtxSvc := &automock.RuntimeCtxService{} 822 rtmCtxSvc.On("ListByFilter", consumerCtx, providerRuntimeID, runtimeCtxFilter, 100, "").Return(runtimeCtxPage, nil).Once() 823 rtmCtxSvc.On("Delete", consumerCtx, runtimeCtxID).Return(nil).Once() 824 return rtmCtxSvc 825 }, 826 TenantSvcFn: func() *automock.TenantService { 827 tenantSvc := &automock.TenantService{} 828 tenantSvc.On("GetInternalTenant", ctx, providerSubaccountID).Return(providerInternalID, nil).Once() 829 tenantSvc.On("GetInternalTenant", providerCtx, subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 830 return tenantSvc 831 }, 832 LabelServiceFn: func() *automock.LabelService { 833 lblSvc := &automock.LabelService{} 834 lblSvc.On("GetByKey", mock.Anything, subaccountTenantInternalID, model.RuntimeContextLabelableObject, runtimeCtxID, subscription.InstancesLabelKey).Return(instancesLabelWithValueOne, nil) 835 return lblSvc 836 }, 837 UIDServiceFn: unusedUUIDSvc, 838 IsSuccessful: true, 839 }, 840 { 841 Name: "Succeeds - missing instances label", 842 Region: tenantRegion, 843 RuntimeServiceFn: func() *automock.RuntimeService { 844 provisioner := &automock.RuntimeService{} 845 provisioner.On("GetByFilters", providerCtx, regionalAndSubscriptionFilters).Return(providerRuntime, nil).Once() 846 return provisioner 847 }, 848 RuntimeCtxServiceFn: func() *automock.RuntimeCtxService { 849 rtmCtxSvc := &automock.RuntimeCtxService{} 850 rtmCtxSvc.On("ListByFilter", consumerCtx, providerRuntimeID, runtimeCtxFilter, 100, "").Return(runtimeCtxPage, nil).Once() 851 rtmCtxSvc.On("Delete", consumerCtx, runtimeCtxID).Return(nil).Once() 852 return rtmCtxSvc 853 }, 854 TenantSvcFn: func() *automock.TenantService { 855 tenantSvc := &automock.TenantService{} 856 tenantSvc.On("GetInternalTenant", ctx, providerSubaccountID).Return(providerInternalID, nil).Once() 857 tenantSvc.On("GetInternalTenant", providerCtx, subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 858 return tenantSvc 859 }, 860 LabelServiceFn: func() *automock.LabelService { 861 lblSvc := &automock.LabelService{} 862 lblSvc.On("GetByKey", mock.Anything, subaccountTenantInternalID, model.RuntimeContextLabelableObject, runtimeCtxID, subscription.InstancesLabelKey).Return(nil, notFoundLabelErr) 863 return lblSvc 864 }, 865 UIDServiceFn: unusedUUIDSvc, 866 IsSuccessful: true, 867 }, 868 { 869 Name: "Succeeds - skip deletion because of multiple instance", 870 Region: tenantRegion, 871 RuntimeServiceFn: func() *automock.RuntimeService { 872 provisioner := &automock.RuntimeService{} 873 provisioner.On("GetByFilters", providerCtx, regionalAndSubscriptionFilters).Return(providerRuntime, nil).Once() 874 return provisioner 875 }, 876 RuntimeCtxServiceFn: func() *automock.RuntimeCtxService { 877 rtmCtxSvc := &automock.RuntimeCtxService{} 878 rtmCtxSvc.On("ListByFilter", consumerCtx, providerRuntimeID, runtimeCtxFilter, 100, "").Return(runtimeCtxPage, nil).Once() 879 return rtmCtxSvc 880 }, 881 TenantSvcFn: func() *automock.TenantService { 882 tenantSvc := &automock.TenantService{} 883 tenantSvc.On("GetInternalTenant", ctx, providerSubaccountID).Return(providerInternalID, nil).Once() 884 tenantSvc.On("GetInternalTenant", providerCtx, subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 885 return tenantSvc 886 }, 887 LabelServiceFn: func() *automock.LabelService { 888 lblSvc := &automock.LabelService{} 889 lblSvc.On("GetByKey", mock.Anything, subaccountTenantInternalID, model.RuntimeContextLabelableObject, runtimeCtxID, subscription.InstancesLabelKey).Return(instancesLabelWithValueTwo, nil) 890 lblSvc.On("UpdateLabel", mock.Anything, subaccountTenantInternalID, instancesLabelID, instancesLabelInputWithValueOne).Return(nil) 891 892 return lblSvc 893 }, 894 UIDServiceFn: unusedUUIDSvc, 895 IsSuccessful: true, 896 }, 897 { 898 Name: "Returns an error when getting internal provider tenant", 899 Region: tenantRegion, 900 RuntimeServiceFn: unusedRuntimeSvc, 901 RuntimeCtxServiceFn: unusedRuntimeContextSvc, 902 TenantSvcFn: func() *automock.TenantService { 903 tenantSvc := &automock.TenantService{} 904 tenantSvc.On("GetInternalTenant", ctx, providerSubaccountID).Return("", testError).Once() 905 return tenantSvc 906 }, 907 LabelServiceFn: unusedLabelSvc, 908 UIDServiceFn: unusedUUIDSvc, 909 ExpectedErrorOutput: testError.Error(), 910 IsSuccessful: false, 911 }, 912 { 913 Name: "Returns an error when can't find runtimes", 914 Region: tenantRegion, 915 RuntimeServiceFn: func() *automock.RuntimeService { 916 provisioner := &automock.RuntimeService{} 917 provisioner.On("GetByFilters", providerCtx, regionalAndSubscriptionFilters).Return(nil, notFoundErr).Once() 918 return provisioner 919 }, 920 RuntimeCtxServiceFn: unusedRuntimeContextSvc, 921 TenantSvcFn: func() *automock.TenantService { 922 tenantSvc := &automock.TenantService{} 923 tenantSvc.On("GetInternalTenant", ctx, providerSubaccountID).Return(providerInternalID, nil).Once() 924 return tenantSvc 925 }, 926 LabelServiceFn: unusedLabelSvc, 927 UIDServiceFn: unusedUUIDSvc, 928 IsSuccessful: false, 929 }, 930 { 931 Name: "Returns an error when could not get runtime", 932 Region: tenantRegion, 933 RuntimeServiceFn: func() *automock.RuntimeService { 934 provisioner := &automock.RuntimeService{} 935 provisioner.On("GetByFilters", providerCtx, regionalAndSubscriptionFilters).Return(nil, testError).Once() 936 return provisioner 937 }, 938 RuntimeCtxServiceFn: unusedRuntimeContextSvc, 939 TenantSvcFn: func() *automock.TenantService { 940 tenantSvc := &automock.TenantService{} 941 tenantSvc.On("GetInternalTenant", ctx, providerSubaccountID).Return(providerInternalID, nil).Once() 942 return tenantSvc 943 }, 944 LabelServiceFn: unusedLabelSvc, 945 UIDServiceFn: unusedUUIDSvc, 946 ExpectedErrorOutput: testError.Error(), 947 IsSuccessful: false, 948 }, 949 { 950 Name: "Returns an error when could not list runtime contexts", 951 Region: tenantRegion, 952 RuntimeServiceFn: func() *automock.RuntimeService { 953 provisioner := &automock.RuntimeService{} 954 provisioner.On("GetByFilters", providerCtx, regionalAndSubscriptionFilters).Return(providerRuntime, nil).Once() 955 return provisioner 956 }, 957 RuntimeCtxServiceFn: func() *automock.RuntimeCtxService { 958 rtmCtxSvc := &automock.RuntimeCtxService{} 959 rtmCtxSvc.On("ListByFilter", consumerCtx, providerRuntimeID, runtimeCtxFilter, 100, "").Return(nil, testError).Once() 960 return rtmCtxSvc 961 }, 962 TenantSvcFn: func() *automock.TenantService { 963 tenantSvc := &automock.TenantService{} 964 tenantSvc.On("GetInternalTenant", ctx, providerSubaccountID).Return(providerInternalID, nil).Once() 965 tenantSvc.On("GetInternalTenant", providerCtx, subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 966 return tenantSvc 967 }, 968 LabelServiceFn: unusedLabelSvc, 969 UIDServiceFn: unusedUUIDSvc, 970 ExpectedErrorOutput: testError.Error(), 971 IsSuccessful: false, 972 }, 973 { 974 Name: "Returns an error when getting consumer tenant", 975 Region: tenantRegion, 976 RuntimeServiceFn: func() *automock.RuntimeService { 977 provisioner := &automock.RuntimeService{} 978 provisioner.On("GetByFilters", providerCtx, regionalAndSubscriptionFilters).Return(providerRuntime, nil).Once() 979 return provisioner 980 }, 981 RuntimeCtxServiceFn: unusedRuntimeContextSvc, 982 TenantSvcFn: func() *automock.TenantService { 983 tenantSvc := &automock.TenantService{} 984 tenantSvc.On("GetInternalTenant", ctx, providerSubaccountID).Return(providerInternalID, nil).Once() 985 tenantSvc.On("GetInternalTenant", providerCtx, subaccountTenantExtID).Return("", testError).Once() 986 return tenantSvc 987 }, 988 LabelServiceFn: unusedLabelSvc, 989 UIDServiceFn: unusedUUIDSvc, 990 ExpectedErrorOutput: testError.Error(), 991 IsSuccessful: false, 992 }, 993 { 994 Name: "Returns an error when deleting runtime context", 995 Region: tenantRegion, 996 RuntimeServiceFn: func() *automock.RuntimeService { 997 provisioner := &automock.RuntimeService{} 998 provisioner.On("GetByFilters", providerCtx, regionalAndSubscriptionFilters).Return(providerRuntime, nil).Once() 999 return provisioner 1000 }, 1001 RuntimeCtxServiceFn: func() *automock.RuntimeCtxService { 1002 rtmCtxSvc := &automock.RuntimeCtxService{} 1003 rtmCtxSvc.On("ListByFilter", consumerCtx, providerRuntimeID, runtimeCtxFilter, 100, "").Return(runtimeCtxPage, nil).Once() 1004 rtmCtxSvc.On("Delete", consumerCtx, runtimeCtxID).Return(testError).Once() 1005 return rtmCtxSvc 1006 }, 1007 TenantSvcFn: func() *automock.TenantService { 1008 tenantSvc := &automock.TenantService{} 1009 tenantSvc.On("GetInternalTenant", ctx, providerSubaccountID).Return(providerInternalID, nil).Once() 1010 tenantSvc.On("GetInternalTenant", providerCtx, subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 1011 return tenantSvc 1012 }, 1013 LabelServiceFn: func() *automock.LabelService { 1014 lblSvc := &automock.LabelService{} 1015 lblSvc.On("GetByKey", mock.Anything, subaccountTenantInternalID, model.RuntimeContextLabelableObject, runtimeCtxID, subscription.InstancesLabelKey).Return(instancesLabelWithValueOne, nil) 1016 return lblSvc 1017 }, 1018 UIDServiceFn: unusedUUIDSvc, 1019 ExpectedErrorOutput: testError.Error(), 1020 IsSuccessful: false, 1021 }, 1022 { 1023 Name: "Returns an error when deleting runtime context with missing instances label", 1024 Region: tenantRegion, 1025 RuntimeServiceFn: func() *automock.RuntimeService { 1026 provisioner := &automock.RuntimeService{} 1027 provisioner.On("GetByFilters", providerCtx, regionalAndSubscriptionFilters).Return(providerRuntime, nil).Once() 1028 return provisioner 1029 }, 1030 RuntimeCtxServiceFn: func() *automock.RuntimeCtxService { 1031 rtmCtxSvc := &automock.RuntimeCtxService{} 1032 rtmCtxSvc.On("ListByFilter", consumerCtx, providerRuntimeID, runtimeCtxFilter, 100, "").Return(runtimeCtxPage, nil).Once() 1033 rtmCtxSvc.On("Delete", consumerCtx, runtimeCtxID).Return(testError).Once() 1034 return rtmCtxSvc 1035 }, 1036 TenantSvcFn: func() *automock.TenantService { 1037 tenantSvc := &automock.TenantService{} 1038 tenantSvc.On("GetInternalTenant", ctx, providerSubaccountID).Return(providerInternalID, nil).Once() 1039 tenantSvc.On("GetInternalTenant", providerCtx, subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 1040 return tenantSvc 1041 }, 1042 LabelServiceFn: func() *automock.LabelService { 1043 lblSvc := &automock.LabelService{} 1044 lblSvc.On("GetByKey", mock.Anything, subaccountTenantInternalID, model.RuntimeContextLabelableObject, runtimeCtxID, subscription.InstancesLabelKey).Return(nil, notFoundLabelErr) 1045 return lblSvc 1046 }, 1047 UIDServiceFn: unusedUUIDSvc, 1048 ExpectedErrorOutput: testError.Error(), 1049 IsSuccessful: false, 1050 }, 1051 { 1052 Name: "Error when getting instances label", 1053 Region: tenantRegion, 1054 RuntimeServiceFn: func() *automock.RuntimeService { 1055 provisioner := &automock.RuntimeService{} 1056 provisioner.On("GetByFilters", providerCtx, regionalAndSubscriptionFilters).Return(providerRuntime, nil).Once() 1057 return provisioner 1058 }, 1059 RuntimeCtxServiceFn: func() *automock.RuntimeCtxService { 1060 rtmCtxSvc := &automock.RuntimeCtxService{} 1061 rtmCtxSvc.On("ListByFilter", consumerCtx, providerRuntimeID, runtimeCtxFilter, 100, "").Return(runtimeCtxPage, nil).Once() 1062 return rtmCtxSvc 1063 }, 1064 TenantSvcFn: func() *automock.TenantService { 1065 tenantSvc := &automock.TenantService{} 1066 tenantSvc.On("GetInternalTenant", ctx, providerSubaccountID).Return(providerInternalID, nil).Once() 1067 tenantSvc.On("GetInternalTenant", providerCtx, subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 1068 return tenantSvc 1069 }, 1070 LabelServiceFn: func() *automock.LabelService { 1071 lblSvc := &automock.LabelService{} 1072 lblSvc.On("GetByKey", mock.Anything, subaccountTenantInternalID, model.RuntimeContextLabelableObject, runtimeCtxID, subscription.InstancesLabelKey).Return(nil, testError) 1073 return lblSvc 1074 }, 1075 UIDServiceFn: unusedUUIDSvc, 1076 IsSuccessful: false, 1077 ExpectedErrorOutput: testError.Error(), 1078 }, 1079 { 1080 Name: "error when casting instances label value", 1081 Region: tenantRegion, 1082 RuntimeServiceFn: func() *automock.RuntimeService { 1083 provisioner := &automock.RuntimeService{} 1084 provisioner.On("GetByFilters", providerCtx, regionalAndSubscriptionFilters).Return(providerRuntime, nil).Once() 1085 return provisioner 1086 }, 1087 RuntimeCtxServiceFn: func() *automock.RuntimeCtxService { 1088 rtmCtxSvc := &automock.RuntimeCtxService{} 1089 rtmCtxSvc.On("ListByFilter", consumerCtx, providerRuntimeID, runtimeCtxFilter, 100, "").Return(runtimeCtxPage, nil).Once() 1090 return rtmCtxSvc 1091 }, 1092 TenantSvcFn: func() *automock.TenantService { 1093 tenantSvc := &automock.TenantService{} 1094 tenantSvc.On("GetInternalTenant", ctx, providerSubaccountID).Return(providerInternalID, nil).Once() 1095 tenantSvc.On("GetInternalTenant", providerCtx, subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 1096 return tenantSvc 1097 }, 1098 LabelServiceFn: func() *automock.LabelService { 1099 instancesLabel := &model.Label{ 1100 ID: instancesLabelID, 1101 Key: subscription.InstancesLabelKey, 1102 Value: "invalid-value", 1103 } 1104 lblSvc := &automock.LabelService{} 1105 lblSvc.On("GetByKey", mock.Anything, subaccountTenantInternalID, model.RuntimeContextLabelableObject, runtimeCtxID, subscription.InstancesLabelKey).Return(instancesLabel, nil) 1106 return lblSvc 1107 }, 1108 UIDServiceFn: unusedUUIDSvc, 1109 IsSuccessful: false, 1110 ExpectedErrorOutput: "cannot cast \"instances\" label value", 1111 }, 1112 { 1113 Name: "error while updating instances label", 1114 Region: tenantRegion, 1115 RuntimeServiceFn: func() *automock.RuntimeService { 1116 provisioner := &automock.RuntimeService{} 1117 provisioner.On("GetByFilters", providerCtx, regionalAndSubscriptionFilters).Return(providerRuntime, nil).Once() 1118 return provisioner 1119 }, 1120 RuntimeCtxServiceFn: func() *automock.RuntimeCtxService { 1121 rtmCtxSvc := &automock.RuntimeCtxService{} 1122 rtmCtxSvc.On("ListByFilter", consumerCtx, providerRuntimeID, runtimeCtxFilter, 100, "").Return(runtimeCtxPage, nil).Once() 1123 return rtmCtxSvc 1124 }, 1125 TenantSvcFn: func() *automock.TenantService { 1126 tenantSvc := &automock.TenantService{} 1127 tenantSvc.On("GetInternalTenant", ctx, providerSubaccountID).Return(providerInternalID, nil).Once() 1128 tenantSvc.On("GetInternalTenant", providerCtx, subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 1129 return tenantSvc 1130 }, 1131 LabelServiceFn: func() *automock.LabelService { 1132 lblSvc := &automock.LabelService{} 1133 lblSvc.On("GetByKey", mock.Anything, subaccountTenantInternalID, model.RuntimeContextLabelableObject, runtimeCtxID, subscription.InstancesLabelKey).Return(instancesLabelWithValueTwo, nil) 1134 lblSvc.On("UpdateLabel", mock.Anything, subaccountTenantInternalID, instancesLabelID, instancesLabelInputWithValueOne).Return(testError) 1135 1136 return lblSvc 1137 }, 1138 UIDServiceFn: unusedUUIDSvc, 1139 IsSuccessful: false, 1140 ExpectedErrorOutput: testError.Error(), 1141 }, 1142 } 1143 1144 for _, testCase := range testCases { 1145 t.Run(testCase.Name, func(t *testing.T) { 1146 runtimeSvc := testCase.RuntimeServiceFn() 1147 runtimeCtxSvc := testCase.RuntimeCtxServiceFn() 1148 labelSvc := testCase.LabelServiceFn() 1149 uidSvc := testCase.UIDServiceFn() 1150 tenantSvc := &automock.TenantService{} 1151 if testCase.TenantSvcFn != nil { 1152 tenantSvc = testCase.TenantSvcFn() 1153 } 1154 defer mock.AssertExpectationsForObjects(t, runtimeSvc, labelSvc, uidSvc, tenantSvc) 1155 1156 service := subscription.NewService(runtimeSvc, runtimeCtxSvc, tenantSvc, labelSvc, nil, nil, nil, nil, uidSvc, consumerSubaccountLabelKey, subscriptionLabelKey, subscriptionAppNameLabelKey, subscriptionProviderIDLabelKey) 1157 1158 // WHEN 1159 isUnsubscribeSuccessful, err := service.UnsubscribeTenantFromRuntime(ctx, subscriptionProviderID, subaccountTenantExtID, providerSubaccountID, consumerTenantID, testCase.Region) 1160 1161 // THEN 1162 if len(testCase.ExpectedErrorOutput) > 0 { 1163 assert.Error(t, err) 1164 assert.Contains(t, err.Error(), testCase.ExpectedErrorOutput) 1165 } else { 1166 assert.NoError(t, err) 1167 } 1168 1169 assert.Equal(t, testCase.IsSuccessful, isUnsubscribeSuccessful) 1170 mock.AssertExpectationsForObjects(t, runtimeSvc, runtimeCtxSvc, tenantSvc, labelSvc, uidSvc) 1171 }) 1172 } 1173 } 1174 1175 func TestSubscribeTenantToApplication(t *testing.T) { 1176 appTmplName := "test-app-tmpl" 1177 appTmplAppName := "{{name}}" 1178 appTmplID := "123-456-789" 1179 repeats := 5 1180 subscriptionPayload := `{"name":"subscription-app-name-value", "display-name":"subscription-app-name-value"}` 1181 1182 jsonAppCreateInput := fixJSONApplicationCreateInput(appTmplAppName) 1183 modelAppTemplate := fixModelAppTemplateWithAppInputJSON(appTmplID, appTmplName, jsonAppCreateInput) 1184 modelAppTemplateWithPlaceholders := fixModelAppTemplateWithPlaceholdersWithAppInputJSON(appTmplID, appTmplName, jsonAppCreateInput) 1185 modelAppFromTemplateInput := fixModelApplicationFromTemplateInput(appTmplName, subscriptionAppName, tntSubdomain, tenantRegion) 1186 modelAppFromTemplateSimplifiedInput := fixModelApplicationFromTemplateSimplifiedInput(appTmplName, subscriptionAppName, tntSubdomain, tenantRegion) 1187 gqlAppFromTemplateInput := fixGQLApplicationFromTemplateWithPayloadInput(appTmplName, subscriptionAppName, tntSubdomain, tenantRegion) 1188 gqlAppFromTemplateWithPayloadInput := fixGQLApplicationFromTemplateWithPayloadInput(appTmplName, subscriptionAppName, tntSubdomain, tenantRegion) 1189 modelAppFromTemplateInputWithPlaceholders := fixModelApplicationFromTemplateInputWithPlaceholders(appTmplName, subscriptionAppName, tntSubdomain, tenantRegion) 1190 modelAppFromTemplateInputWithEmptySubdomain := fixModelApplicationFromTemplateInput(appTmplName, subscriptionAppName, "", tenantRegion) 1191 gqlAppCreateInput := fixGQLApplicationCreateInput(appTmplName) 1192 modelAppCreateInput := fixModelApplicationCreateInput(appTmplName) 1193 modelAppCreateInputWithLabels := fixModelApplicationCreateInputWithLabels(appTmplName, subaccountTenantExtID) 1194 modelApps := []*model.Application{ 1195 fixModelApplication(appTmplID, appTmplName, appTmplID), 1196 } 1197 1198 testCases := []struct { 1199 Name string 1200 Region string 1201 SubscriptionAppName string 1202 SubscriptionProviderID string 1203 SubscriptionPayload string 1204 AppTemplateServiceFn func() *automock.ApplicationTemplateService 1205 LabelServiceFn func() *automock.LabelService 1206 UIDServiceFn func() *automock.UidService 1207 TenantSvcFn func() *automock.TenantService 1208 AppConverterFn func() *automock.ApplicationConverter 1209 AppTemplConverterFn func() *automock.ApplicationTemplateConverter 1210 AppSvcFn func() *automock.ApplicationService 1211 ExpectedErrorOutput string 1212 IsSuccessful bool 1213 Repeats int 1214 }{ 1215 { 1216 Name: "Succeeds", 1217 Region: tenantRegionWithPrefix, 1218 SubscriptionPayload: subscriptionPayload, 1219 AppTemplateServiceFn: func() *automock.ApplicationTemplateService { 1220 appTemplateSvc := &automock.ApplicationTemplateService{} 1221 appTemplateSvc.On("GetByFilters", context.TODO(), regionalAndSubscriptionFiltersWithPrefix).Return(modelAppTemplate, nil).Once() 1222 appTemplateSvc.On("PrepareApplicationCreateInputJSON", modelAppTemplate, modelAppFromTemplateInput.Values).Return(jsonAppCreateInput, nil).Once() 1223 return appTemplateSvc 1224 }, 1225 TenantSvcFn: func() *automock.TenantService { 1226 tenantSvc := &automock.TenantService{} 1227 tenantSvc.On("GetInternalTenant", context.TODO(), subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 1228 return tenantSvc 1229 }, 1230 AppConverterFn: func() *automock.ApplicationConverter { 1231 appConv := &automock.ApplicationConverter{} 1232 appConv.On("CreateRegisterInputJSONToGQL", jsonAppCreateInput).Return(gqlAppCreateInput, nil).Once() 1233 appConv.On("CreateInputFromGraphQL", mock.Anything, gqlAppCreateInput).Return(modelAppCreateInput, nil).Once() 1234 1235 return appConv 1236 }, 1237 AppTemplConverterFn: func() *automock.ApplicationTemplateConverter { 1238 appTemplateConv := &automock.ApplicationTemplateConverter{} 1239 appTemplateConv.On("ApplicationFromTemplateInputFromGraphQL", modelAppTemplate, gqlAppFromTemplateInput).Return(modelAppFromTemplateSimplifiedInput, nil).Once() 1240 1241 return appTemplateConv 1242 }, 1243 AppSvcFn: func() *automock.ApplicationService { 1244 appSvc := &automock.ApplicationService{} 1245 appSvc.On("ListAll", ctxWithTenantMatcher(subaccountTenantInternalID)).Return([]*model.Application{}, nil).Once() 1246 appSvc.On("CreateFromTemplate", ctxWithTenantMatcher(subaccountTenantInternalID), modelAppCreateInputWithLabels, &appTmplID).Return(appTmplID, nil).Once() 1247 1248 return appSvc 1249 }, 1250 LabelServiceFn: func() *automock.LabelService { 1251 lblSvc := &automock.LabelService{} 1252 lblSvc.On("GetByKey", ctxWithTenantMatcher(subaccountTenantInternalID), subaccountTenantInternalID, model.TenantLabelableObject, subaccountTenantInternalID, subscription.SubdomainLabelKey).Return(subdomainLabel, nil).Once() 1253 1254 return lblSvc 1255 }, 1256 UIDServiceFn: unusedUUIDSvc, 1257 IsSuccessful: true, 1258 Repeats: 1, 1259 }, 1260 { 1261 Name: "Succeeds with subscription payload", 1262 Region: tenantRegionWithPrefix, 1263 SubscriptionPayload: subscriptionPayload, 1264 AppTemplateServiceFn: func() *automock.ApplicationTemplateService { 1265 appTemplateSvc := &automock.ApplicationTemplateService{} 1266 appTemplateSvc.On("GetByFilters", context.TODO(), regionalAndSubscriptionFiltersWithPrefix).Return(modelAppTemplateWithPlaceholders, nil).Once() 1267 appTemplateSvc.On("PrepareApplicationCreateInputJSON", modelAppTemplateWithPlaceholders, modelAppFromTemplateInputWithPlaceholders.Values).Return(jsonAppCreateInput, nil).Once() 1268 return appTemplateSvc 1269 }, 1270 TenantSvcFn: func() *automock.TenantService { 1271 tenantSvc := &automock.TenantService{} 1272 tenantSvc.On("GetInternalTenant", context.TODO(), subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 1273 return tenantSvc 1274 }, 1275 AppConverterFn: func() *automock.ApplicationConverter { 1276 appConv := &automock.ApplicationConverter{} 1277 appConv.On("CreateRegisterInputJSONToGQL", jsonAppCreateInput).Return(gqlAppCreateInput, nil).Once() 1278 appConv.On("CreateInputFromGraphQL", mock.Anything, gqlAppCreateInput).Return(modelAppCreateInput, nil).Once() 1279 1280 return appConv 1281 }, 1282 AppSvcFn: func() *automock.ApplicationService { 1283 appSvc := &automock.ApplicationService{} 1284 appSvc.On("ListAll", ctxWithTenantMatcher(subaccountTenantInternalID)).Return([]*model.Application{}, nil).Once() 1285 appSvc.On("CreateFromTemplate", ctxWithTenantMatcher(subaccountTenantInternalID), modelAppCreateInputWithLabels, &appTmplID).Return(appTmplID, nil).Once() 1286 1287 return appSvc 1288 }, 1289 AppTemplConverterFn: func() *automock.ApplicationTemplateConverter { 1290 appTemplateConv := &automock.ApplicationTemplateConverter{} 1291 appTemplateConv.On("ApplicationFromTemplateInputFromGraphQL", modelAppTemplateWithPlaceholders, gqlAppFromTemplateWithPayloadInput).Return(modelAppFromTemplateSimplifiedInput, nil).Once() 1292 1293 return appTemplateConv 1294 }, 1295 LabelServiceFn: func() *automock.LabelService { 1296 lblSvc := &automock.LabelService{} 1297 lblSvc.On("GetByKey", ctxWithTenantMatcher(subaccountTenantInternalID), subaccountTenantInternalID, model.TenantLabelableObject, subaccountTenantInternalID, subscription.SubdomainLabelKey).Return(subdomainLabel, nil).Once() 1298 1299 return lblSvc 1300 }, 1301 UIDServiceFn: unusedUUIDSvc, 1302 IsSuccessful: true, 1303 Repeats: 1, 1304 }, 1305 { 1306 Name: "Returns an error when can't find internal consumer tenant", 1307 Region: tenantRegion, 1308 SubscriptionPayload: subscriptionPayload, 1309 AppTemplateServiceFn: func() *automock.ApplicationTemplateService { 1310 appTemplateSvc := &automock.ApplicationTemplateService{} 1311 appTemplateSvc.On("GetByFilters", context.TODO(), regionalAndSubscriptionFilters).Return(modelAppTemplate, nil).Once() 1312 appTemplateSvc.AssertNotCalled(t, "PrepareApplicationCreateInputJSON") 1313 return appTemplateSvc 1314 }, 1315 TenantSvcFn: func() *automock.TenantService { 1316 tenantSvc := &automock.TenantService{} 1317 tenantSvc.On("GetInternalTenant", context.TODO(), subaccountTenantExtID).Return("", testError).Once() 1318 return tenantSvc 1319 }, 1320 AppConverterFn: func() *automock.ApplicationConverter { 1321 appConv := &automock.ApplicationConverter{} 1322 appConv.AssertNotCalled(t, "CreateRegisterInputJSONToGQL") 1323 appConv.AssertNotCalled(t, "CreateInputFromGraphQL") 1324 1325 return appConv 1326 }, 1327 AppTemplConverterFn: func() *automock.ApplicationTemplateConverter { 1328 appTemplateConv := &automock.ApplicationTemplateConverter{} 1329 appTemplateConv.On("ApplicationFromTemplateInputFromGraphQL", modelAppTemplateWithPlaceholders, gqlAppFromTemplateWithPayloadInput).Return(modelAppFromTemplateSimplifiedInput, nil).Once() 1330 1331 return appTemplateConv 1332 }, 1333 AppSvcFn: func() *automock.ApplicationService { 1334 appSvc := &automock.ApplicationService{} 1335 appSvc.AssertNotCalled(t, "ListAll") 1336 appSvc.AssertNotCalled(t, "CreateFromTemplate") 1337 1338 return appSvc 1339 }, 1340 LabelServiceFn: unusedLabelSvc, 1341 UIDServiceFn: unusedUUIDSvc, 1342 ExpectedErrorOutput: testError.Error(), 1343 IsSuccessful: false, 1344 Repeats: 1, 1345 }, 1346 { 1347 Name: "Returns an error when can't find app template", 1348 Region: tenantRegion, 1349 SubscriptionPayload: subscriptionPayload, 1350 AppTemplateServiceFn: func() *automock.ApplicationTemplateService { 1351 appTemplateSvc := &automock.ApplicationTemplateService{} 1352 appTemplateSvc.On("GetByFilters", context.TODO(), regionalAndSubscriptionFilters).Return(nil, notFoundErr).Once() 1353 appTemplateSvc.AssertNotCalled(t, "PrepareApplicationCreateInputJSON") 1354 return appTemplateSvc 1355 }, 1356 TenantSvcFn: func() *automock.TenantService { 1357 tenantSvc := &automock.TenantService{} 1358 tenantSvc.AssertNotCalled(t, "GetInternalTenant") 1359 return tenantSvc 1360 }, 1361 AppConverterFn: func() *automock.ApplicationConverter { 1362 appConv := &automock.ApplicationConverter{} 1363 appConv.AssertNotCalled(t, "CreateRegisterInputJSONToGQL") 1364 appConv.AssertNotCalled(t, "CreateInputFromGraphQL") 1365 1366 return appConv 1367 }, 1368 AppTemplConverterFn: func() *automock.ApplicationTemplateConverter { 1369 appTemplateConv := &automock.ApplicationTemplateConverter{} 1370 appTemplateConv.On("ApplicationFromTemplateInputFromGraphQL", modelAppTemplateWithPlaceholders, gqlAppFromTemplateWithPayloadInput).Return(modelAppFromTemplateSimplifiedInput, nil).Once() 1371 1372 return appTemplateConv 1373 }, 1374 AppSvcFn: func() *automock.ApplicationService { 1375 appSvc := &automock.ApplicationService{} 1376 appSvc.AssertNotCalled(t, "ListAll") 1377 appSvc.AssertNotCalled(t, "CreateFromTemplate") 1378 1379 return appSvc 1380 }, 1381 LabelServiceFn: unusedLabelSvc, 1382 UIDServiceFn: unusedUUIDSvc, 1383 IsSuccessful: false, 1384 Repeats: 1, 1385 }, 1386 { 1387 Name: "Returns an error when fails to find an app template", 1388 Region: tenantRegion, 1389 SubscriptionPayload: subscriptionPayload, 1390 AppTemplateServiceFn: func() *automock.ApplicationTemplateService { 1391 appTemplateSvc := &automock.ApplicationTemplateService{} 1392 appTemplateSvc.On("GetByFilters", context.TODO(), regionalAndSubscriptionFilters).Return(nil, testError).Once() 1393 appTemplateSvc.AssertNotCalled(t, "PrepareApplicationCreateInputJSON") 1394 return appTemplateSvc 1395 }, 1396 TenantSvcFn: func() *automock.TenantService { 1397 tenantSvc := &automock.TenantService{} 1398 tenantSvc.AssertNotCalled(t, "GetInternalTenant") 1399 return tenantSvc 1400 }, 1401 AppConverterFn: func() *automock.ApplicationConverter { 1402 appConv := &automock.ApplicationConverter{} 1403 appConv.AssertNotCalled(t, "CreateRegisterInputJSONToGQL") 1404 appConv.AssertNotCalled(t, "CreateInputFromGraphQL") 1405 1406 return appConv 1407 }, 1408 AppTemplConverterFn: func() *automock.ApplicationTemplateConverter { 1409 appTemplateConv := &automock.ApplicationTemplateConverter{} 1410 appTemplateConv.On("ApplicationFromTemplateInputFromGraphQL", modelAppTemplateWithPlaceholders, gqlAppFromTemplateWithPayloadInput).Return(modelAppFromTemplateSimplifiedInput, nil).Once() 1411 1412 return appTemplateConv 1413 }, 1414 AppSvcFn: func() *automock.ApplicationService { 1415 appSvc := &automock.ApplicationService{} 1416 appSvc.AssertNotCalled(t, "ListAll") 1417 appSvc.AssertNotCalled(t, "CreateFromTemplate") 1418 1419 return appSvc 1420 }, 1421 LabelServiceFn: unusedLabelSvc, 1422 UIDServiceFn: unusedUUIDSvc, 1423 ExpectedErrorOutput: testError.Error(), 1424 IsSuccessful: false, 1425 Repeats: 1, 1426 }, 1427 { 1428 Name: "Returns an error when fails to get subdomain label", 1429 Region: tenantRegion, 1430 SubscriptionPayload: subscriptionPayload, 1431 AppTemplateServiceFn: func() *automock.ApplicationTemplateService { 1432 appTemplateSvc := &automock.ApplicationTemplateService{} 1433 appTemplateSvc.On("GetByFilters", context.TODO(), regionalAndSubscriptionFilters).Return(modelAppTemplate, nil).Once() 1434 appTemplateSvc.AssertNotCalled(t, "PrepareApplicationCreateInputJSON") 1435 return appTemplateSvc 1436 }, 1437 TenantSvcFn: func() *automock.TenantService { 1438 tenantSvc := &automock.TenantService{} 1439 tenantSvc.On("GetInternalTenant", context.TODO(), subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 1440 return tenantSvc 1441 }, 1442 AppConverterFn: func() *automock.ApplicationConverter { 1443 appConv := &automock.ApplicationConverter{} 1444 appConv.AssertNotCalled(t, "CreateRegisterInputJSONToGQL") 1445 appConv.AssertNotCalled(t, "CreateInputFromGraphQL") 1446 1447 return appConv 1448 }, 1449 AppTemplConverterFn: func() *automock.ApplicationTemplateConverter { 1450 appTemplateConv := &automock.ApplicationTemplateConverter{} 1451 appTemplateConv.On("ApplicationFromTemplateInputFromGraphQL", modelAppTemplateWithPlaceholders, gqlAppFromTemplateWithPayloadInput).Return(modelAppFromTemplateSimplifiedInput, nil).Once() 1452 1453 return appTemplateConv 1454 }, 1455 AppSvcFn: func() *automock.ApplicationService { 1456 appSvc := &automock.ApplicationService{} 1457 appSvc.On("ListAll", ctxWithTenantMatcher(subaccountTenantInternalID)).Return([]*model.Application{}, nil).Once() 1458 appSvc.AssertNotCalled(t, "CreateFromTemplate") 1459 1460 return appSvc 1461 }, 1462 LabelServiceFn: func() *automock.LabelService { 1463 lblSvc := &automock.LabelService{} 1464 lblSvc.On("GetByKey", ctxWithTenantMatcher(subaccountTenantInternalID), subaccountTenantInternalID, model.TenantLabelableObject, subaccountTenantInternalID, subscription.SubdomainLabelKey).Return(nil, testError).Once() 1465 1466 return lblSvc 1467 }, 1468 UIDServiceFn: unusedUUIDSvc, 1469 ExpectedErrorOutput: testError.Error(), 1470 IsSuccessful: false, 1471 Repeats: 1, 1472 }, 1473 { 1474 Name: "Success with empty subdomain value when it is missing", 1475 Region: tenantRegionWithPrefix, 1476 SubscriptionPayload: subscriptionPayload, 1477 AppTemplateServiceFn: func() *automock.ApplicationTemplateService { 1478 appTemplateSvc := &automock.ApplicationTemplateService{} 1479 appTemplateSvc.On("GetByFilters", context.TODO(), regionalAndSubscriptionFiltersWithPrefix).Return(modelAppTemplate, nil).Once() 1480 appTemplateSvc.On("PrepareApplicationCreateInputJSON", modelAppTemplate, modelAppFromTemplateInputWithEmptySubdomain.Values).Return(jsonAppCreateInput, nil).Once() 1481 return appTemplateSvc 1482 }, 1483 TenantSvcFn: func() *automock.TenantService { 1484 tenantSvc := &automock.TenantService{} 1485 tenantSvc.On("GetInternalTenant", context.TODO(), subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 1486 return tenantSvc 1487 }, 1488 AppConverterFn: func() *automock.ApplicationConverter { 1489 appConv := &automock.ApplicationConverter{} 1490 appConv.On("CreateRegisterInputJSONToGQL", jsonAppCreateInput).Return(gqlAppCreateInput, nil).Once() 1491 appConv.On("CreateInputFromGraphQL", mock.Anything, gqlAppCreateInput).Return(modelAppCreateInput, nil).Once() 1492 1493 return appConv 1494 }, 1495 AppTemplConverterFn: func() *automock.ApplicationTemplateConverter { 1496 appTemplateConv := &automock.ApplicationTemplateConverter{} 1497 appTemplateConv.On("ApplicationFromTemplateInputFromGraphQL", modelAppTemplate, gqlAppFromTemplateInput).Return(modelAppFromTemplateSimplifiedInput, nil).Once() 1498 1499 return appTemplateConv 1500 }, 1501 AppSvcFn: func() *automock.ApplicationService { 1502 appSvc := &automock.ApplicationService{} 1503 appSvc.On("ListAll", ctxWithTenantMatcher(subaccountTenantInternalID)).Return([]*model.Application{}, nil).Once() 1504 appSvc.On("CreateFromTemplate", ctxWithTenantMatcher(subaccountTenantInternalID), modelAppCreateInputWithLabels, &appTmplID).Return(appTmplID, nil).Once() 1505 1506 return appSvc 1507 }, 1508 LabelServiceFn: func() *automock.LabelService { 1509 lblSvc := &automock.LabelService{} 1510 lblSvc.On("GetByKey", ctxWithTenantMatcher(subaccountTenantInternalID), subaccountTenantInternalID, model.TenantLabelableObject, subaccountTenantInternalID, subscription.SubdomainLabelKey).Return(nil, notFoundLabelErr).Once() 1511 1512 return lblSvc 1513 }, 1514 UIDServiceFn: unusedUUIDSvc, 1515 IsSuccessful: true, 1516 Repeats: 1, 1517 }, 1518 { 1519 Name: "Returns an error when preparing application input json", 1520 Region: tenantRegion, 1521 SubscriptionPayload: subscriptionPayload, 1522 AppTemplateServiceFn: func() *automock.ApplicationTemplateService { 1523 appTemplateSvc := &automock.ApplicationTemplateService{} 1524 appTemplateSvc.On("GetByFilters", context.TODO(), regionalAndSubscriptionFilters).Return(modelAppTemplate, nil).Once() 1525 appTemplateSvc.On("PrepareApplicationCreateInputJSON", modelAppTemplate, modelAppFromTemplateInput.Values).Return("", testError).Once() 1526 1527 return appTemplateSvc 1528 }, 1529 TenantSvcFn: func() *automock.TenantService { 1530 tenantSvc := &automock.TenantService{} 1531 tenantSvc.On("GetInternalTenant", context.TODO(), subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 1532 return tenantSvc 1533 }, 1534 AppConverterFn: func() *automock.ApplicationConverter { 1535 appConv := &automock.ApplicationConverter{} 1536 appConv.AssertNotCalled(t, "CreateRegisterInputJSONToGQL") 1537 appConv.AssertNotCalled(t, "CreateInputFromGraphQL") 1538 1539 return appConv 1540 }, 1541 AppTemplConverterFn: func() *automock.ApplicationTemplateConverter { 1542 appTemplateConv := &automock.ApplicationTemplateConverter{} 1543 appTemplateConv.On("ApplicationFromTemplateInputFromGraphQL", modelAppTemplate, gqlAppFromTemplateInput).Return(modelAppFromTemplateSimplifiedInput, nil).Once() 1544 1545 return appTemplateConv 1546 }, 1547 AppSvcFn: func() *automock.ApplicationService { 1548 appSvc := &automock.ApplicationService{} 1549 appSvc.On("ListAll", ctxWithTenantMatcher(subaccountTenantInternalID)).Return([]*model.Application{}, nil).Once() 1550 appSvc.AssertNotCalled(t, "CreateFromTemplate") 1551 1552 return appSvc 1553 }, 1554 LabelServiceFn: func() *automock.LabelService { 1555 lblSvc := &automock.LabelService{} 1556 lblSvc.On("GetByKey", ctxWithTenantMatcher(subaccountTenantInternalID), subaccountTenantInternalID, model.TenantLabelableObject, subaccountTenantInternalID, subscription.SubdomainLabelKey).Return(subdomainLabel, nil).Once() 1557 1558 return lblSvc 1559 }, 1560 UIDServiceFn: unusedUUIDSvc, 1561 ExpectedErrorOutput: testError.Error(), 1562 IsSuccessful: false, 1563 Repeats: 1, 1564 }, 1565 { 1566 Name: "Returns an error when creating graphql input from json", 1567 Region: tenantRegion, 1568 SubscriptionPayload: subscriptionPayload, 1569 AppTemplateServiceFn: func() *automock.ApplicationTemplateService { 1570 appTemplateSvc := &automock.ApplicationTemplateService{} 1571 appTemplateSvc.On("GetByFilters", context.TODO(), regionalAndSubscriptionFilters).Return(modelAppTemplate, nil).Once() 1572 appTemplateSvc.On("PrepareApplicationCreateInputJSON", modelAppTemplate, modelAppFromTemplateInput.Values).Return(jsonAppCreateInput, nil).Once() 1573 1574 return appTemplateSvc 1575 }, 1576 TenantSvcFn: func() *automock.TenantService { 1577 tenantSvc := &automock.TenantService{} 1578 tenantSvc.On("GetInternalTenant", context.TODO(), subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 1579 return tenantSvc 1580 }, 1581 AppConverterFn: func() *automock.ApplicationConverter { 1582 appConv := &automock.ApplicationConverter{} 1583 appConv.On("CreateRegisterInputJSONToGQL", jsonAppCreateInput).Return(graphql.ApplicationRegisterInput{}, testError).Once() 1584 appConv.AssertNotCalled(t, "CreateInputFromGraphQL") 1585 1586 return appConv 1587 }, 1588 AppTemplConverterFn: func() *automock.ApplicationTemplateConverter { 1589 appTemplateConv := &automock.ApplicationTemplateConverter{} 1590 appTemplateConv.On("ApplicationFromTemplateInputFromGraphQL", modelAppTemplate, gqlAppFromTemplateInput).Return(modelAppFromTemplateSimplifiedInput, nil).Once() 1591 1592 return appTemplateConv 1593 }, 1594 AppSvcFn: func() *automock.ApplicationService { 1595 appSvc := &automock.ApplicationService{} 1596 appSvc.On("ListAll", ctxWithTenantMatcher(subaccountTenantInternalID)).Return([]*model.Application{}, nil).Once() 1597 appSvc.AssertNotCalled(t, "CreateFromTemplate") 1598 1599 return appSvc 1600 }, 1601 LabelServiceFn: func() *automock.LabelService { 1602 lblSvc := &automock.LabelService{} 1603 lblSvc.On("GetByKey", ctxWithTenantMatcher(subaccountTenantInternalID), subaccountTenantInternalID, model.TenantLabelableObject, subaccountTenantInternalID, subscription.SubdomainLabelKey).Return(subdomainLabel, nil).Once() 1604 1605 return lblSvc 1606 }, 1607 UIDServiceFn: unusedUUIDSvc, 1608 ExpectedErrorOutput: testError.Error(), 1609 IsSuccessful: false, 1610 Repeats: 1, 1611 }, 1612 { 1613 Name: "Returns an error when creating input from graphql", 1614 Region: tenantRegion, 1615 SubscriptionPayload: subscriptionPayload, 1616 AppTemplateServiceFn: func() *automock.ApplicationTemplateService { 1617 appTemplateSvc := &automock.ApplicationTemplateService{} 1618 appTemplateSvc.On("GetByFilters", context.TODO(), regionalAndSubscriptionFilters).Return(modelAppTemplate, nil).Once() 1619 appTemplateSvc.On("PrepareApplicationCreateInputJSON", modelAppTemplate, modelAppFromTemplateInput.Values).Return(jsonAppCreateInput, nil).Once() 1620 return appTemplateSvc 1621 }, 1622 TenantSvcFn: func() *automock.TenantService { 1623 tenantSvc := &automock.TenantService{} 1624 tenantSvc.On("GetInternalTenant", context.TODO(), subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 1625 return tenantSvc 1626 }, 1627 AppConverterFn: func() *automock.ApplicationConverter { 1628 appConv := &automock.ApplicationConverter{} 1629 appConv.On("CreateRegisterInputJSONToGQL", jsonAppCreateInput).Return(gqlAppCreateInput, nil).Once() 1630 appConv.On("CreateInputFromGraphQL", ctxWithTenantMatcher(subaccountTenantInternalID), gqlAppCreateInput).Return(model.ApplicationRegisterInput{}, testError).Once() 1631 return appConv 1632 }, 1633 AppTemplConverterFn: func() *automock.ApplicationTemplateConverter { 1634 appTemplateConv := &automock.ApplicationTemplateConverter{} 1635 appTemplateConv.On("ApplicationFromTemplateInputFromGraphQL", modelAppTemplate, gqlAppFromTemplateInput).Return(modelAppFromTemplateSimplifiedInput, nil).Once() 1636 1637 return appTemplateConv 1638 }, 1639 AppSvcFn: func() *automock.ApplicationService { 1640 appSvc := &automock.ApplicationService{} 1641 appSvc.On("ListAll", ctxWithTenantMatcher(subaccountTenantInternalID)).Return([]*model.Application{}, nil).Once() 1642 appSvc.AssertNotCalled(t, "CreateFromTemplate") 1643 return appSvc 1644 }, 1645 LabelServiceFn: func() *automock.LabelService { 1646 lblSvc := &automock.LabelService{} 1647 lblSvc.On("GetByKey", ctxWithTenantMatcher(subaccountTenantInternalID), subaccountTenantInternalID, model.TenantLabelableObject, subaccountTenantInternalID, subscription.SubdomainLabelKey).Return(subdomainLabel, nil).Once() 1648 1649 return lblSvc 1650 }, 1651 UIDServiceFn: unusedUUIDSvc, 1652 ExpectedErrorOutput: testError.Error(), 1653 IsSuccessful: false, 1654 Repeats: 1, 1655 }, 1656 { 1657 Name: "Returns an error when creating app from app template", 1658 Region: tenantRegion, 1659 SubscriptionPayload: subscriptionPayload, 1660 AppTemplateServiceFn: func() *automock.ApplicationTemplateService { 1661 appTemplateSvc := &automock.ApplicationTemplateService{} 1662 appTemplateSvc.On("GetByFilters", context.TODO(), regionalAndSubscriptionFilters).Return(modelAppTemplate, nil).Once() 1663 appTemplateSvc.On("PrepareApplicationCreateInputJSON", modelAppTemplate, modelAppFromTemplateInput.Values).Return(jsonAppCreateInput, nil).Once() 1664 return appTemplateSvc 1665 }, 1666 TenantSvcFn: func() *automock.TenantService { 1667 tenantSvc := &automock.TenantService{} 1668 tenantSvc.On("GetInternalTenant", context.TODO(), subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 1669 return tenantSvc 1670 }, 1671 AppConverterFn: func() *automock.ApplicationConverter { 1672 appConv := &automock.ApplicationConverter{} 1673 appConv.On("CreateRegisterInputJSONToGQL", jsonAppCreateInput).Return(gqlAppCreateInput, nil).Once() 1674 appConv.On("CreateInputFromGraphQL", ctxWithTenantMatcher(subaccountTenantInternalID), gqlAppCreateInput).Return(modelAppCreateInput, nil).Once() 1675 return appConv 1676 }, 1677 AppTemplConverterFn: func() *automock.ApplicationTemplateConverter { 1678 appTemplateConv := &automock.ApplicationTemplateConverter{} 1679 appTemplateConv.On("ApplicationFromTemplateInputFromGraphQL", modelAppTemplate, gqlAppFromTemplateInput).Return(modelAppFromTemplateSimplifiedInput, nil).Once() 1680 1681 return appTemplateConv 1682 }, 1683 AppSvcFn: func() *automock.ApplicationService { 1684 appSvc := &automock.ApplicationService{} 1685 appSvc.On("ListAll", ctxWithTenantMatcher(subaccountTenantInternalID)).Return([]*model.Application{}, nil).Once() 1686 appSvc.On("CreateFromTemplate", ctxWithTenantMatcher(subaccountTenantInternalID), modelAppCreateInputWithLabels, &appTmplID).Return("", testError).Once() 1687 return appSvc 1688 }, 1689 LabelServiceFn: func() *automock.LabelService { 1690 lblSvc := &automock.LabelService{} 1691 lblSvc.On("GetByKey", ctxWithTenantMatcher(subaccountTenantInternalID), subaccountTenantInternalID, model.TenantLabelableObject, subaccountTenantInternalID, subscription.SubdomainLabelKey).Return(subdomainLabel, nil).Once() 1692 1693 return lblSvc 1694 }, 1695 UIDServiceFn: unusedUUIDSvc, 1696 ExpectedErrorOutput: testError.Error(), 1697 IsSuccessful: false, 1698 Repeats: 1, 1699 }, 1700 { 1701 Name: "Succeeds on on multiple calls", 1702 Region: tenantRegion, 1703 SubscriptionPayload: subscriptionPayload, 1704 AppTemplateServiceFn: func() *automock.ApplicationTemplateService { 1705 appTemplateSvc := &automock.ApplicationTemplateService{} 1706 appTemplateSvc.On("GetByFilters", context.TODO(), regionalAndSubscriptionFilters).Return(modelAppTemplate, nil).Times(repeats) 1707 appTemplateSvc.AssertNotCalled(t, "PrepareApplicationCreateInputJSON") 1708 1709 return appTemplateSvc 1710 }, 1711 TenantSvcFn: func() *automock.TenantService { 1712 tenantSvc := &automock.TenantService{} 1713 tenantSvc.On("GetInternalTenant", context.TODO(), subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Times(repeats) 1714 return tenantSvc 1715 }, 1716 AppConverterFn: func() *automock.ApplicationConverter { 1717 appConv := &automock.ApplicationConverter{} 1718 appConv.AssertNotCalled(t, "CreateRegisterInputJSONToGQL") 1719 appConv.AssertNotCalled(t, "CreateInputFromGraphQL") 1720 1721 return appConv 1722 }, 1723 AppTemplConverterFn: func() *automock.ApplicationTemplateConverter { 1724 appTemplateConv := &automock.ApplicationTemplateConverter{} 1725 appTemplateConv.On("ApplicationFromTemplateInputFromGraphQL", modelAppTemplate, gqlAppFromTemplateInput).Return(modelAppFromTemplateSimplifiedInput, nil).Times(repeats) 1726 1727 return appTemplateConv 1728 }, 1729 AppSvcFn: func() *automock.ApplicationService { 1730 appSvc := &automock.ApplicationService{} 1731 appSvc.On("ListAll", ctxWithTenantMatcher(subaccountTenantInternalID)).Return(modelApps, nil).Times(repeats) 1732 appSvc.AssertNotCalled(t, "CreateFromTemplate") 1733 1734 return appSvc 1735 }, 1736 LabelServiceFn: func() *automock.LabelService { 1737 lblSvc := &automock.LabelService{} 1738 lblSvc.On("GetByKey", ctxWithTenantMatcher(subaccountTenantInternalID), subaccountTenantInternalID, model.ApplicationLabelableObject, appTmplID, subscription.InstancesLabelKey).Return(instancesLabelWithValueOne, nil) 1739 lblSvc.On("UpdateLabel", ctxWithTenantMatcher(subaccountTenantInternalID), subaccountTenantInternalID, instancesLabelID, instancesLabelInputWithValueTwo).Return(nil) 1740 1741 return lblSvc 1742 }, 1743 UIDServiceFn: unusedUUIDSvc, 1744 IsSuccessful: true, 1745 Repeats: repeats, 1746 }, 1747 { 1748 Name: "Succeeds on on multiple calls - instances label not found", 1749 Region: tenantRegion, 1750 SubscriptionPayload: subscriptionPayload, 1751 AppTemplateServiceFn: func() *automock.ApplicationTemplateService { 1752 appTemplateSvc := &automock.ApplicationTemplateService{} 1753 appTemplateSvc.On("GetByFilters", context.TODO(), regionalAndSubscriptionFilters).Return(modelAppTemplate, nil).Times(repeats) 1754 appTemplateSvc.AssertNotCalled(t, "PrepareApplicationCreateInputJSON") 1755 1756 return appTemplateSvc 1757 }, 1758 TenantSvcFn: func() *automock.TenantService { 1759 tenantSvc := &automock.TenantService{} 1760 tenantSvc.On("GetInternalTenant", context.TODO(), subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Times(repeats) 1761 return tenantSvc 1762 }, 1763 AppConverterFn: func() *automock.ApplicationConverter { 1764 appConv := &automock.ApplicationConverter{} 1765 appConv.AssertNotCalled(t, "CreateRegisterInputJSONToGQL") 1766 appConv.AssertNotCalled(t, "CreateInputFromGraphQL") 1767 1768 return appConv 1769 }, 1770 AppTemplConverterFn: func() *automock.ApplicationTemplateConverter { 1771 appTemplateConv := &automock.ApplicationTemplateConverter{} 1772 appTemplateConv.On("ApplicationFromTemplateInputFromGraphQL", modelAppTemplate, gqlAppFromTemplateInput).Return(modelAppFromTemplateSimplifiedInput, nil).Times(repeats) 1773 1774 return appTemplateConv 1775 }, 1776 AppSvcFn: func() *automock.ApplicationService { 1777 appSvc := &automock.ApplicationService{} 1778 appSvc.On("ListAll", ctxWithTenantMatcher(subaccountTenantInternalID)).Return(modelApps, nil).Times(repeats) 1779 appSvc.AssertNotCalled(t, "CreateFromTemplate") 1780 1781 return appSvc 1782 }, 1783 LabelServiceFn: func() *automock.LabelService { 1784 labelInput := &model.LabelInput{ 1785 Key: subscription.InstancesLabelKey, 1786 ObjectID: appTmplID, 1787 ObjectType: model.ApplicationLabelableObject, 1788 Value: 2, 1789 } 1790 lblSvc := &automock.LabelService{} 1791 lblSvc.On("GetByKey", ctxWithTenantMatcher(subaccountTenantInternalID), subaccountTenantInternalID, model.ApplicationLabelableObject, appTmplID, subscription.InstancesLabelKey).Return(nil, notFoundLabelErr) 1792 lblSvc.On("CreateLabel", ctxWithTenantMatcher(subaccountTenantInternalID), subaccountTenantInternalID, uuid, labelInput).Return(nil) 1793 1794 return lblSvc 1795 }, 1796 UIDServiceFn: func() *automock.UidService { 1797 uidSvc := &automock.UidService{} 1798 uidSvc.On("Generate").Return(uuid).Times(repeats) 1799 return uidSvc 1800 }, 1801 IsSuccessful: true, 1802 Repeats: repeats, 1803 }, 1804 { 1805 Name: "Error when getting instances label", 1806 Region: tenantRegion, 1807 SubscriptionPayload: subscriptionPayload, 1808 AppTemplateServiceFn: func() *automock.ApplicationTemplateService { 1809 appTemplateSvc := &automock.ApplicationTemplateService{} 1810 appTemplateSvc.On("GetByFilters", context.TODO(), regionalAndSubscriptionFilters).Return(modelAppTemplate, nil).Twice() 1811 appTemplateSvc.AssertNotCalled(t, "PrepareApplicationCreateInputJSON") 1812 1813 return appTemplateSvc 1814 }, 1815 TenantSvcFn: func() *automock.TenantService { 1816 tenantSvc := &automock.TenantService{} 1817 tenantSvc.On("GetInternalTenant", context.TODO(), subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Twice() 1818 return tenantSvc 1819 }, 1820 AppConverterFn: func() *automock.ApplicationConverter { 1821 appConv := &automock.ApplicationConverter{} 1822 appConv.AssertNotCalled(t, "CreateRegisterInputJSONToGQL") 1823 appConv.AssertNotCalled(t, "CreateInputFromGraphQL") 1824 1825 return appConv 1826 }, 1827 AppTemplConverterFn: func() *automock.ApplicationTemplateConverter { 1828 appTemplateConv := &automock.ApplicationTemplateConverter{} 1829 appTemplateConv.On("ApplicationFromTemplateInputFromGraphQL", modelAppTemplate, gqlAppFromTemplateInput).Return(modelAppFromTemplateSimplifiedInput, nil).Twice() 1830 1831 return appTemplateConv 1832 }, 1833 AppSvcFn: func() *automock.ApplicationService { 1834 appSvc := &automock.ApplicationService{} 1835 appSvc.On("ListAll", ctxWithTenantMatcher(subaccountTenantInternalID)).Return(modelApps, nil).Twice() 1836 appSvc.AssertNotCalled(t, "CreateFromTemplate") 1837 1838 return appSvc 1839 }, 1840 LabelServiceFn: func() *automock.LabelService { 1841 lblSvc := &automock.LabelService{} 1842 lblSvc.On("GetByKey", ctxWithTenantMatcher(subaccountTenantInternalID), subaccountTenantInternalID, model.ApplicationLabelableObject, appTmplID, subscription.InstancesLabelKey).Return(nil, testError) 1843 return lblSvc 1844 }, 1845 UIDServiceFn: unusedUUIDSvc, 1846 IsSuccessful: false, 1847 ExpectedErrorOutput: testError.Error(), 1848 Repeats: 2, 1849 }, 1850 { 1851 Name: "Error when creating instances label", 1852 Region: tenantRegion, 1853 SubscriptionPayload: subscriptionPayload, 1854 AppTemplateServiceFn: func() *automock.ApplicationTemplateService { 1855 appTemplateSvc := &automock.ApplicationTemplateService{} 1856 appTemplateSvc.On("GetByFilters", context.TODO(), regionalAndSubscriptionFilters).Return(modelAppTemplate, nil).Twice() 1857 appTemplateSvc.AssertNotCalled(t, "PrepareApplicationCreateInputJSON") 1858 1859 return appTemplateSvc 1860 }, 1861 TenantSvcFn: func() *automock.TenantService { 1862 tenantSvc := &automock.TenantService{} 1863 tenantSvc.On("GetInternalTenant", context.TODO(), subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Twice() 1864 return tenantSvc 1865 }, 1866 AppConverterFn: func() *automock.ApplicationConverter { 1867 appConv := &automock.ApplicationConverter{} 1868 appConv.AssertNotCalled(t, "CreateRegisterInputJSONToGQL") 1869 appConv.AssertNotCalled(t, "CreateInputFromGraphQL") 1870 1871 return appConv 1872 }, 1873 AppTemplConverterFn: func() *automock.ApplicationTemplateConverter { 1874 appTemplateConv := &automock.ApplicationTemplateConverter{} 1875 appTemplateConv.On("ApplicationFromTemplateInputFromGraphQL", modelAppTemplate, gqlAppFromTemplateInput).Return(modelAppFromTemplateSimplifiedInput, nil).Twice() 1876 1877 return appTemplateConv 1878 }, 1879 AppSvcFn: func() *automock.ApplicationService { 1880 appSvc := &automock.ApplicationService{} 1881 appSvc.On("ListAll", ctxWithTenantMatcher(subaccountTenantInternalID)).Return(modelApps, nil).Twice() 1882 appSvc.AssertNotCalled(t, "CreateFromTemplate") 1883 1884 return appSvc 1885 }, 1886 LabelServiceFn: func() *automock.LabelService { 1887 labelInput := &model.LabelInput{ 1888 Key: subscription.InstancesLabelKey, 1889 ObjectID: appTmplID, 1890 ObjectType: model.ApplicationLabelableObject, 1891 Value: 2, 1892 } 1893 lblSvc := &automock.LabelService{} 1894 lblSvc.On("GetByKey", ctxWithTenantMatcher(subaccountTenantInternalID), subaccountTenantInternalID, model.ApplicationLabelableObject, appTmplID, subscription.InstancesLabelKey).Return(nil, notFoundLabelErr) 1895 lblSvc.On("CreateLabel", ctxWithTenantMatcher(subaccountTenantInternalID), subaccountTenantInternalID, uuid, labelInput).Return(testError) 1896 1897 return lblSvc 1898 }, 1899 UIDServiceFn: func() *automock.UidService { 1900 uidSvc := &automock.UidService{} 1901 uidSvc.On("Generate").Return(uuid).Twice() 1902 return uidSvc 1903 }, 1904 IsSuccessful: false, 1905 ExpectedErrorOutput: testError.Error(), 1906 Repeats: 2, 1907 }, 1908 { 1909 Name: "Error when updating instances label", 1910 Region: tenantRegion, 1911 SubscriptionPayload: subscriptionPayload, 1912 AppTemplateServiceFn: func() *automock.ApplicationTemplateService { 1913 appTemplateSvc := &automock.ApplicationTemplateService{} 1914 appTemplateSvc.On("GetByFilters", context.TODO(), regionalAndSubscriptionFilters).Return(modelAppTemplate, nil).Twice() 1915 appTemplateSvc.AssertNotCalled(t, "PrepareApplicationCreateInputJSON") 1916 1917 return appTemplateSvc 1918 }, 1919 TenantSvcFn: func() *automock.TenantService { 1920 tenantSvc := &automock.TenantService{} 1921 tenantSvc.On("GetInternalTenant", context.TODO(), subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Twice() 1922 return tenantSvc 1923 }, 1924 AppConverterFn: func() *automock.ApplicationConverter { 1925 appConv := &automock.ApplicationConverter{} 1926 appConv.AssertNotCalled(t, "CreateRegisterInputJSONToGQL") 1927 appConv.AssertNotCalled(t, "CreateInputFromGraphQL") 1928 1929 return appConv 1930 }, 1931 AppTemplConverterFn: func() *automock.ApplicationTemplateConverter { 1932 appTemplateConv := &automock.ApplicationTemplateConverter{} 1933 appTemplateConv.On("ApplicationFromTemplateInputFromGraphQL", modelAppTemplate, gqlAppFromTemplateInput).Return(modelAppFromTemplateSimplifiedInput, nil).Twice() 1934 1935 return appTemplateConv 1936 }, 1937 AppSvcFn: func() *automock.ApplicationService { 1938 appSvc := &automock.ApplicationService{} 1939 appSvc.On("ListAll", ctxWithTenantMatcher(subaccountTenantInternalID)).Return(modelApps, nil).Twice() 1940 appSvc.AssertNotCalled(t, "CreateFromTemplate") 1941 1942 return appSvc 1943 }, 1944 LabelServiceFn: func() *automock.LabelService { 1945 lblSvc := &automock.LabelService{} 1946 lblSvc.On("GetByKey", ctxWithTenantMatcher(subaccountTenantInternalID), subaccountTenantInternalID, model.ApplicationLabelableObject, appTmplID, subscription.InstancesLabelKey).Return(instancesLabelWithValueOne, nil) 1947 lblSvc.On("UpdateLabel", ctxWithTenantMatcher(subaccountTenantInternalID), subaccountTenantInternalID, instancesLabelID, instancesLabelInputWithValueTwo).Return(testError) 1948 1949 return lblSvc 1950 }, 1951 UIDServiceFn: unusedUUIDSvc, 1952 IsSuccessful: false, 1953 ExpectedErrorOutput: testError.Error(), 1954 Repeats: 2, 1955 }, 1956 { 1957 Name: "Error when casting instances label value", 1958 Region: tenantRegion, 1959 SubscriptionPayload: subscriptionPayload, 1960 AppTemplateServiceFn: func() *automock.ApplicationTemplateService { 1961 appTemplateSvc := &automock.ApplicationTemplateService{} 1962 appTemplateSvc.On("GetByFilters", context.TODO(), regionalAndSubscriptionFilters).Return(modelAppTemplate, nil).Twice() 1963 appTemplateSvc.AssertNotCalled(t, "PrepareApplicationCreateInputJSON") 1964 1965 return appTemplateSvc 1966 }, 1967 TenantSvcFn: func() *automock.TenantService { 1968 tenantSvc := &automock.TenantService{} 1969 tenantSvc.On("GetInternalTenant", context.TODO(), subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Twice() 1970 return tenantSvc 1971 }, 1972 AppConverterFn: func() *automock.ApplicationConverter { 1973 appConv := &automock.ApplicationConverter{} 1974 appConv.AssertNotCalled(t, "CreateRegisterInputJSONToGQL") 1975 appConv.AssertNotCalled(t, "CreateInputFromGraphQL") 1976 1977 return appConv 1978 }, 1979 AppTemplConverterFn: func() *automock.ApplicationTemplateConverter { 1980 appTemplateConv := &automock.ApplicationTemplateConverter{} 1981 appTemplateConv.On("ApplicationFromTemplateInputFromGraphQL", modelAppTemplate, gqlAppFromTemplateInput).Return(modelAppFromTemplateSimplifiedInput, nil).Twice() 1982 1983 return appTemplateConv 1984 }, 1985 AppSvcFn: func() *automock.ApplicationService { 1986 appSvc := &automock.ApplicationService{} 1987 appSvc.On("ListAll", ctxWithTenantMatcher(subaccountTenantInternalID)).Return(modelApps, nil).Twice() 1988 appSvc.AssertNotCalled(t, "CreateFromTemplate") 1989 1990 return appSvc 1991 }, 1992 LabelServiceFn: func() *automock.LabelService { 1993 instancesLabel := &model.Label{ 1994 ID: instancesLabelID, 1995 Key: subscription.InstancesLabelKey, 1996 Value: "invalid-value", 1997 } 1998 lblSvc := &automock.LabelService{} 1999 lblSvc.On("GetByKey", ctxWithTenantMatcher(subaccountTenantInternalID), subaccountTenantInternalID, model.ApplicationLabelableObject, appTmplID, subscription.InstancesLabelKey).Return(instancesLabel, nil) 2000 2001 return lblSvc 2002 }, 2003 UIDServiceFn: unusedUUIDSvc, 2004 IsSuccessful: false, 2005 ExpectedErrorOutput: errors.New("cannot cast \"instances\" label value").Error(), 2006 Repeats: 2, 2007 }, 2008 } 2009 2010 for _, testCase := range testCases { 2011 t.Run(testCase.Name, func(t *testing.T) { 2012 appTemplateSvc := testCase.AppTemplateServiceFn() 2013 labelSvc := testCase.LabelServiceFn() 2014 appConv := testCase.AppConverterFn() 2015 appTemplConv := testCase.AppTemplConverterFn() 2016 appSvc := testCase.AppSvcFn() 2017 uuidSvc := testCase.UIDServiceFn() 2018 tenantSvc := &automock.TenantService{} 2019 if testCase.TenantSvcFn != nil { 2020 tenantSvc = testCase.TenantSvcFn() 2021 } 2022 2023 service := subscription.NewService(nil, nil, tenantSvc, labelSvc, appTemplateSvc, appConv, appTemplConv, appSvc, uuidSvc, consumerSubaccountLabelKey, subscriptionLabelKey, subscriptionAppNameLabelKey, subscriptionProviderIDLabelKey) 2024 2025 for count := 0; count < testCase.Repeats; count++ { 2026 // WHEN 2027 isSubscribeSuccessful, err := service.SubscribeTenantToApplication(context.TODO(), subscriptionProviderID, subaccountTenantExtID, consumerTenantID, testCase.Region, subscriptionAppName, testCase.SubscriptionPayload) 2028 2029 // THEN 2030 if len(testCase.ExpectedErrorOutput) > 0 { 2031 assert.Error(t, err) 2032 assert.Contains(t, err.Error(), testCase.ExpectedErrorOutput) 2033 } else { 2034 assert.NoError(t, err) 2035 } 2036 2037 assert.Equal(t, testCase.IsSuccessful, isSubscribeSuccessful) 2038 } 2039 2040 mock.AssertExpectationsForObjects(t, appTemplateSvc, labelSvc, uuidSvc, tenantSvc, appConv, appSvc) 2041 }) 2042 } 2043 } 2044 2045 func TestUnsubscribeTenantFromApplication(t *testing.T) { 2046 appTmplAppName := "app-name" 2047 appTmplName := "app-tmpl-name" 2048 appTmplID := "b91b59f7-2563-40b2-aba9-fef726037aa3" 2049 appFirstID := "b91b59f7-2563-40b2-aba9-fef726037bb4" 2050 appSecondID := "b91b59e6-2563-40b2-aba9-fef726037cc5" 2051 jsonAppCreateInput := fixJSONApplicationCreateInput(appTmplAppName) 2052 modelAppTemplate := fixModelAppTemplateWithAppInputJSON(appTmplID, appTmplName, jsonAppCreateInput) 2053 modelApps := []*model.Application{ 2054 fixModelApplication(appFirstID, "first", appTmplID), 2055 fixModelApplication(appSecondID, "second", appTmplID), 2056 } 2057 testCases := []struct { 2058 Name string 2059 AppTemplateServiceFn func() *automock.ApplicationTemplateService 2060 AppSvcFn func() *automock.ApplicationService 2061 TenantSvcFn func() *automock.TenantService 2062 LabelServiceFn func() *automock.LabelService 2063 ExpectedErrorOutput string 2064 IsSuccessful bool 2065 }{ 2066 { 2067 Name: "Success", 2068 AppTemplateServiceFn: func() *automock.ApplicationTemplateService { 2069 svc := &automock.ApplicationTemplateService{} 2070 svc.On("GetByFilters", context.TODO(), regionalAndSubscriptionFilters).Return(modelAppTemplate, nil).Once() 2071 return svc 2072 }, 2073 AppSvcFn: func() *automock.ApplicationService { 2074 svc := &automock.ApplicationService{} 2075 svc.On("ListAll", ctxWithTenantMatcher(subaccountTenantInternalID)).Return(modelApps, nil).Once() 2076 svc.On("Delete", ctxWithTenantMatcher(subaccountTenantInternalID), appFirstID).Return(nil).Once() 2077 svc.On("Delete", ctxWithTenantMatcher(subaccountTenantInternalID), appSecondID).Return(nil).Once() 2078 return svc 2079 }, 2080 TenantSvcFn: func() *automock.TenantService { 2081 tenantSvc := &automock.TenantService{} 2082 tenantSvc.On("GetInternalTenant", context.TODO(), subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 2083 return tenantSvc 2084 }, 2085 LabelServiceFn: func() *automock.LabelService { 2086 lblSvc := &automock.LabelService{} 2087 lblSvc.On("GetByKey", mock.Anything, subaccountTenantInternalID, model.ApplicationLabelableObject, appFirstID, subscription.InstancesLabelKey).Return(instancesLabelWithValueOne, nil) 2088 lblSvc.On("GetByKey", mock.Anything, subaccountTenantInternalID, model.ApplicationLabelableObject, appSecondID, subscription.InstancesLabelKey).Return(instancesLabelWithValueOne, nil) 2089 return lblSvc 2090 }, 2091 IsSuccessful: true, 2092 }, 2093 { 2094 Name: "Success - missing instances label", 2095 AppTemplateServiceFn: func() *automock.ApplicationTemplateService { 2096 svc := &automock.ApplicationTemplateService{} 2097 svc.On("GetByFilters", context.TODO(), regionalAndSubscriptionFilters).Return(modelAppTemplate, nil).Once() 2098 return svc 2099 }, 2100 AppSvcFn: func() *automock.ApplicationService { 2101 svc := &automock.ApplicationService{} 2102 svc.On("ListAll", ctxWithTenantMatcher(subaccountTenantInternalID)).Return(modelApps, nil).Once() 2103 svc.On("Delete", ctxWithTenantMatcher(subaccountTenantInternalID), appFirstID).Return(nil).Once() 2104 svc.On("Delete", ctxWithTenantMatcher(subaccountTenantInternalID), appSecondID).Return(nil).Once() 2105 return svc 2106 }, 2107 TenantSvcFn: func() *automock.TenantService { 2108 tenantSvc := &automock.TenantService{} 2109 tenantSvc.On("GetInternalTenant", context.TODO(), subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 2110 return tenantSvc 2111 }, 2112 LabelServiceFn: func() *automock.LabelService { 2113 lblSvc := &automock.LabelService{} 2114 lblSvc.On("GetByKey", mock.Anything, subaccountTenantInternalID, model.ApplicationLabelableObject, appFirstID, subscription.InstancesLabelKey).Return(nil, notFoundLabelErr) 2115 lblSvc.On("GetByKey", mock.Anything, subaccountTenantInternalID, model.ApplicationLabelableObject, appSecondID, subscription.InstancesLabelKey).Return(nil, notFoundLabelErr) 2116 return lblSvc 2117 }, 2118 IsSuccessful: true, 2119 }, 2120 { 2121 Name: "Success - skipping deletion because of more than one instances", 2122 AppTemplateServiceFn: func() *automock.ApplicationTemplateService { 2123 svc := &automock.ApplicationTemplateService{} 2124 svc.On("GetByFilters", context.TODO(), regionalAndSubscriptionFilters).Return(modelAppTemplate, nil).Once() 2125 return svc 2126 }, 2127 AppSvcFn: func() *automock.ApplicationService { 2128 svc := &automock.ApplicationService{} 2129 svc.On("ListAll", ctxWithTenantMatcher(subaccountTenantInternalID)).Return(modelApps, nil).Once() 2130 return svc 2131 }, 2132 TenantSvcFn: func() *automock.TenantService { 2133 tenantSvc := &automock.TenantService{} 2134 tenantSvc.On("GetInternalTenant", context.TODO(), subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 2135 return tenantSvc 2136 }, 2137 LabelServiceFn: func() *automock.LabelService { 2138 lblSvc := &automock.LabelService{} 2139 lblSvc.On("GetByKey", mock.Anything, subaccountTenantInternalID, model.ApplicationLabelableObject, appFirstID, subscription.InstancesLabelKey).Return(instancesLabelWithValueTwo, nil) 2140 lblSvc.On("GetByKey", mock.Anything, subaccountTenantInternalID, model.ApplicationLabelableObject, appSecondID, subscription.InstancesLabelKey).Return(instancesLabelWithValueTwo, nil) 2141 lblSvc.On("UpdateLabel", mock.Anything, subaccountTenantInternalID, instancesLabelID, instancesLabelInputWithValueOne).Return(nil).Twice() 2142 return lblSvc 2143 }, 2144 IsSuccessful: true, 2145 }, 2146 { 2147 Name: "Error when fails to get internal tenant", 2148 AppTemplateServiceFn: func() *automock.ApplicationTemplateService { 2149 svc := &automock.ApplicationTemplateService{} 2150 svc.On("GetByFilters", context.TODO(), regionalAndSubscriptionFilters).Return(modelAppTemplate, nil).Once() 2151 return svc 2152 }, 2153 AppSvcFn: func() *automock.ApplicationService { 2154 svc := &automock.ApplicationService{} 2155 svc.AssertNotCalled(t, "ListAll") 2156 svc.AssertNotCalled(t, "Delete") 2157 return svc 2158 }, 2159 TenantSvcFn: func() *automock.TenantService { 2160 tenantSvc := &automock.TenantService{} 2161 tenantSvc.On("GetInternalTenant", context.TODO(), subaccountTenantExtID).Return("", testError).Once() 2162 return tenantSvc 2163 }, 2164 LabelServiceFn: func() *automock.LabelService { 2165 lblSvc := &automock.LabelService{} 2166 return lblSvc 2167 }, 2168 IsSuccessful: false, 2169 ExpectedErrorOutput: testError.Error(), 2170 }, 2171 { 2172 Name: "Error when getting app template by filters", 2173 AppTemplateServiceFn: func() *automock.ApplicationTemplateService { 2174 svc := &automock.ApplicationTemplateService{} 2175 svc.On("GetByFilters", context.TODO(), regionalAndSubscriptionFilters).Return(nil, testError).Once() 2176 return svc 2177 }, 2178 AppSvcFn: func() *automock.ApplicationService { 2179 svc := &automock.ApplicationService{} 2180 svc.AssertNotCalled(t, "ListAll") 2181 svc.AssertNotCalled(t, "Delete") 2182 return svc 2183 }, 2184 TenantSvcFn: func() *automock.TenantService { 2185 tenantSvc := &automock.TenantService{} 2186 tenantSvc.AssertNotCalled(t, "GetInternalTenant") 2187 return tenantSvc 2188 }, 2189 LabelServiceFn: func() *automock.LabelService { 2190 lblSvc := &automock.LabelService{} 2191 return lblSvc 2192 }, 2193 IsSuccessful: false, 2194 ExpectedErrorOutput: testError.Error(), 2195 }, 2196 { 2197 Name: "Error when app template by filters is not found", 2198 AppTemplateServiceFn: func() *automock.ApplicationTemplateService { 2199 svc := &automock.ApplicationTemplateService{} 2200 svc.On("GetByFilters", context.TODO(), regionalAndSubscriptionFilters).Return(nil, notFoundAppTemplateErr).Once() 2201 return svc 2202 }, 2203 AppSvcFn: func() *automock.ApplicationService { 2204 svc := &automock.ApplicationService{} 2205 svc.AssertNotCalled(t, "ListAll") 2206 svc.AssertNotCalled(t, "Delete") 2207 return svc 2208 }, 2209 TenantSvcFn: func() *automock.TenantService { 2210 tenantSvc := &automock.TenantService{} 2211 tenantSvc.AssertNotCalled(t, "GetInternalTenant") 2212 return tenantSvc 2213 }, 2214 LabelServiceFn: func() *automock.LabelService { 2215 lblSvc := &automock.LabelService{} 2216 return lblSvc 2217 }, 2218 IsSuccessful: false, 2219 }, 2220 { 2221 Name: "Error when listing applications", 2222 AppTemplateServiceFn: func() *automock.ApplicationTemplateService { 2223 svc := &automock.ApplicationTemplateService{} 2224 svc.On("GetByFilters", context.TODO(), regionalAndSubscriptionFilters).Return(modelAppTemplate, nil).Once() 2225 return svc 2226 }, 2227 AppSvcFn: func() *automock.ApplicationService { 2228 svc := &automock.ApplicationService{} 2229 svc.On("ListAll", ctxWithTenantMatcher(subaccountTenantInternalID)).Return(nil, testError).Once() 2230 svc.AssertNotCalled(t, "Delete") 2231 return svc 2232 }, 2233 TenantSvcFn: func() *automock.TenantService { 2234 tenantSvc := &automock.TenantService{} 2235 tenantSvc.On("GetInternalTenant", context.TODO(), subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 2236 return tenantSvc 2237 }, 2238 LabelServiceFn: func() *automock.LabelService { 2239 lblSvc := &automock.LabelService{} 2240 return lblSvc 2241 }, 2242 IsSuccessful: false, 2243 ExpectedErrorOutput: testError.Error(), 2244 }, 2245 { 2246 Name: "Error when deleting application", 2247 AppTemplateServiceFn: func() *automock.ApplicationTemplateService { 2248 svc := &automock.ApplicationTemplateService{} 2249 svc.On("GetByFilters", context.TODO(), regionalAndSubscriptionFilters).Return(modelAppTemplate, nil).Once() 2250 return svc 2251 }, 2252 AppSvcFn: func() *automock.ApplicationService { 2253 svc := &automock.ApplicationService{} 2254 svc.On("ListAll", ctxWithTenantMatcher(subaccountTenantInternalID)).Return(modelApps, nil).Once() 2255 svc.On("Delete", ctxWithTenantMatcher(subaccountTenantInternalID), appFirstID).Return(nil).Once() 2256 svc.On("Delete", ctxWithTenantMatcher(subaccountTenantInternalID), appSecondID).Return(testError).Once() 2257 return svc 2258 }, 2259 TenantSvcFn: func() *automock.TenantService { 2260 tenantSvc := &automock.TenantService{} 2261 tenantSvc.On("GetInternalTenant", context.TODO(), subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 2262 return tenantSvc 2263 }, 2264 LabelServiceFn: func() *automock.LabelService { 2265 lblSvc := &automock.LabelService{} 2266 lblSvc.On("GetByKey", mock.Anything, subaccountTenantInternalID, model.ApplicationLabelableObject, appFirstID, subscription.InstancesLabelKey).Return(instancesLabelWithValueOne, nil) 2267 lblSvc.On("GetByKey", mock.Anything, subaccountTenantInternalID, model.ApplicationLabelableObject, appSecondID, subscription.InstancesLabelKey).Return(instancesLabelWithValueOne, nil) 2268 return lblSvc 2269 }, 2270 IsSuccessful: false, 2271 ExpectedErrorOutput: testError.Error(), 2272 }, 2273 { 2274 Name: "Error when deleting application - missing instances label", 2275 AppTemplateServiceFn: func() *automock.ApplicationTemplateService { 2276 svc := &automock.ApplicationTemplateService{} 2277 svc.On("GetByFilters", context.TODO(), regionalAndSubscriptionFilters).Return(modelAppTemplate, nil).Once() 2278 return svc 2279 }, 2280 AppSvcFn: func() *automock.ApplicationService { 2281 svc := &automock.ApplicationService{} 2282 svc.On("ListAll", ctxWithTenantMatcher(subaccountTenantInternalID)).Return(modelApps, nil).Once() 2283 svc.On("Delete", ctxWithTenantMatcher(subaccountTenantInternalID), appFirstID).Return(nil).Once() 2284 svc.On("Delete", ctxWithTenantMatcher(subaccountTenantInternalID), appSecondID).Return(testError).Once() 2285 return svc 2286 }, 2287 TenantSvcFn: func() *automock.TenantService { 2288 tenantSvc := &automock.TenantService{} 2289 tenantSvc.On("GetInternalTenant", context.TODO(), subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 2290 return tenantSvc 2291 }, 2292 LabelServiceFn: func() *automock.LabelService { 2293 lblSvc := &automock.LabelService{} 2294 lblSvc.On("GetByKey", mock.Anything, subaccountTenantInternalID, model.ApplicationLabelableObject, appFirstID, subscription.InstancesLabelKey).Return(instancesLabelWithValueOne, notFoundLabelErr) 2295 lblSvc.On("GetByKey", mock.Anything, subaccountTenantInternalID, model.ApplicationLabelableObject, appSecondID, subscription.InstancesLabelKey).Return(instancesLabelWithValueOne, notFoundLabelErr) 2296 return lblSvc 2297 }, 2298 IsSuccessful: false, 2299 ExpectedErrorOutput: testError.Error(), 2300 }, 2301 { 2302 Name: "Error when getting instances label", 2303 AppTemplateServiceFn: func() *automock.ApplicationTemplateService { 2304 svc := &automock.ApplicationTemplateService{} 2305 svc.On("GetByFilters", context.TODO(), regionalAndSubscriptionFilters).Return(modelAppTemplate, nil).Once() 2306 return svc 2307 }, 2308 AppSvcFn: func() *automock.ApplicationService { 2309 svc := &automock.ApplicationService{} 2310 svc.On("ListAll", ctxWithTenantMatcher(subaccountTenantInternalID)).Return(modelApps, nil).Once() 2311 return svc 2312 }, 2313 TenantSvcFn: func() *automock.TenantService { 2314 tenantSvc := &automock.TenantService{} 2315 tenantSvc.On("GetInternalTenant", context.TODO(), subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 2316 return tenantSvc 2317 }, 2318 LabelServiceFn: func() *automock.LabelService { 2319 lblSvc := &automock.LabelService{} 2320 lblSvc.On("GetByKey", mock.Anything, subaccountTenantInternalID, model.ApplicationLabelableObject, appFirstID, subscription.InstancesLabelKey).Return(nil, testError) 2321 return lblSvc 2322 }, 2323 IsSuccessful: false, 2324 ExpectedErrorOutput: testError.Error(), 2325 }, 2326 { 2327 Name: "Error when casting instances label", 2328 AppTemplateServiceFn: func() *automock.ApplicationTemplateService { 2329 svc := &automock.ApplicationTemplateService{} 2330 svc.On("GetByFilters", context.TODO(), regionalAndSubscriptionFilters).Return(modelAppTemplate, nil).Once() 2331 return svc 2332 }, 2333 AppSvcFn: func() *automock.ApplicationService { 2334 svc := &automock.ApplicationService{} 2335 svc.On("ListAll", ctxWithTenantMatcher(subaccountTenantInternalID)).Return(modelApps, nil).Once() 2336 return svc 2337 }, 2338 TenantSvcFn: func() *automock.TenantService { 2339 tenantSvc := &automock.TenantService{} 2340 tenantSvc.On("GetInternalTenant", context.TODO(), subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 2341 return tenantSvc 2342 }, 2343 LabelServiceFn: func() *automock.LabelService { 2344 instancesLabel := &model.Label{ 2345 ID: instancesLabelID, 2346 Key: subscription.InstancesLabelKey, 2347 Value: "invalid-value", 2348 } 2349 lblSvc := &automock.LabelService{} 2350 lblSvc.On("GetByKey", mock.Anything, subaccountTenantInternalID, model.ApplicationLabelableObject, appFirstID, subscription.InstancesLabelKey).Return(instancesLabel, nil) 2351 return lblSvc 2352 }, 2353 IsSuccessful: false, 2354 ExpectedErrorOutput: errors.New("cannot cast \"instances\" label value").Error(), 2355 }, 2356 { 2357 Name: "Error when updating instances label", 2358 AppTemplateServiceFn: func() *automock.ApplicationTemplateService { 2359 svc := &automock.ApplicationTemplateService{} 2360 svc.On("GetByFilters", context.TODO(), regionalAndSubscriptionFilters).Return(modelAppTemplate, nil).Once() 2361 return svc 2362 }, 2363 AppSvcFn: func() *automock.ApplicationService { 2364 svc := &automock.ApplicationService{} 2365 svc.On("ListAll", ctxWithTenantMatcher(subaccountTenantInternalID)).Return(modelApps, nil).Once() 2366 return svc 2367 }, 2368 TenantSvcFn: func() *automock.TenantService { 2369 tenantSvc := &automock.TenantService{} 2370 tenantSvc.On("GetInternalTenant", context.TODO(), subaccountTenantExtID).Return(subaccountTenantInternalID, nil).Once() 2371 return tenantSvc 2372 }, 2373 LabelServiceFn: func() *automock.LabelService { 2374 lblSvc := &automock.LabelService{} 2375 lblSvc.On("GetByKey", mock.Anything, subaccountTenantInternalID, model.ApplicationLabelableObject, appFirstID, subscription.InstancesLabelKey).Return(instancesLabelWithValueTwo, nil) 2376 lblSvc.On("UpdateLabel", mock.Anything, subaccountTenantInternalID, instancesLabelID, instancesLabelInputWithValueOne).Return(testError) 2377 return lblSvc 2378 }, 2379 IsSuccessful: false, 2380 ExpectedErrorOutput: testError.Error(), 2381 }, 2382 } 2383 2384 for _, testCase := range testCases { 2385 t.Run(testCase.Name, func(t *testing.T) { 2386 appTemplateSvc := testCase.AppTemplateServiceFn() 2387 appSvc := testCase.AppSvcFn() 2388 tenantSvc := testCase.TenantSvcFn() 2389 lblSvc := testCase.LabelServiceFn() 2390 service := subscription.NewService(nil, nil, tenantSvc, lblSvc, appTemplateSvc, nil, nil, appSvc, nil, consumerSubaccountLabelKey, subscriptionLabelKey, subscriptionAppNameLabelKey, subscriptionProviderIDLabelKey) 2391 2392 // WHEN 2393 successful, err := service.UnsubscribeTenantFromApplication(context.TODO(), subscriptionProviderID, subaccountTenantExtID, tenantRegion) 2394 2395 // THEN 2396 if len(testCase.ExpectedErrorOutput) > 0 { 2397 assert.Error(t, err) 2398 assert.Contains(t, err.Error(), testCase.ExpectedErrorOutput) 2399 } else { 2400 assert.NoError(t, err) 2401 } 2402 2403 assert.Equal(t, testCase.IsSuccessful, successful) 2404 2405 mock.AssertExpectationsForObjects(t, appTemplateSvc, tenantSvc, appSvc, lblSvc) 2406 }) 2407 } 2408 } 2409 2410 func TestDetermineSubscriptionFlow(t *testing.T) { 2411 filters := []*labelfilter.LabelFilter{ 2412 labelfilter.NewForKeyWithQuery("subscriptionProviderId", fmt.Sprintf("\"%s\"", providerSubaccountID)), 2413 labelfilter.NewForKeyWithQuery(tenant.RegionLabelKey, fmt.Sprintf("\"%s\"", regionalTenantSubdomain)), 2414 } 2415 appTemplateID := "app-tmpl-ID" 2416 appTemplateName := "app-tmpl-name" 2417 rtmName := "rtm-name" 2418 modelAppTemplate := fixModelApplicationTemplate(appTemplateID, appTemplateName) 2419 modelRuntime := fixModelRuntime(rtmName) 2420 2421 testCases := []struct { 2422 Name string 2423 AppTemplateFn func() *automock.ApplicationTemplateService 2424 RuntimeFn func() *automock.RuntimeService 2425 Output resource.Type 2426 ExpectedErrorOutput string 2427 }{ 2428 { 2429 Name: "Success for runtime", 2430 AppTemplateFn: func() *automock.ApplicationTemplateService { 2431 appTemplateSvc := &automock.ApplicationTemplateService{} 2432 appTemplateSvc.On("GetByFilters", context.TODO(), filters).Return(nil, nil).Once() 2433 return appTemplateSvc 2434 }, 2435 RuntimeFn: func() *automock.RuntimeService { 2436 runtimeSvc := &automock.RuntimeService{} 2437 runtimeSvc.On("GetByFiltersGlobal", context.TODO(), filters).Return(modelRuntime, nil).Once() 2438 return runtimeSvc 2439 }, 2440 Output: resource.Runtime, 2441 }, 2442 { 2443 Name: "Success for application template", 2444 AppTemplateFn: func() *automock.ApplicationTemplateService { 2445 appTemplateSvc := &automock.ApplicationTemplateService{} 2446 appTemplateSvc.On("GetByFilters", context.TODO(), filters).Return(modelAppTemplate, nil).Once() 2447 return appTemplateSvc 2448 }, 2449 RuntimeFn: func() *automock.RuntimeService { 2450 runtimeSvc := &automock.RuntimeService{} 2451 runtimeSvc.On("GetByFiltersGlobal", context.TODO(), filters).Return(nil, nil).Once() 2452 return runtimeSvc 2453 }, 2454 Output: resource.ApplicationTemplate, 2455 }, 2456 { 2457 Name: "Error for runtime fetch by filters", 2458 AppTemplateFn: func() *automock.ApplicationTemplateService { 2459 appTemplateSvc := &automock.ApplicationTemplateService{} 2460 appTemplateSvc.AssertNotCalled(t, "GetByFilters") 2461 return appTemplateSvc 2462 }, 2463 RuntimeFn: func() *automock.RuntimeService { 2464 runtimeSvc := &automock.RuntimeService{} 2465 runtimeSvc.On("GetByFiltersGlobal", context.TODO(), filters).Return(nil, testError).Once() 2466 return runtimeSvc 2467 }, 2468 Output: "", 2469 ExpectedErrorOutput: testError.Error(), 2470 }, 2471 { 2472 Name: "Error for application template fetch by filters", 2473 AppTemplateFn: func() *automock.ApplicationTemplateService { 2474 appTemplateSvc := &automock.ApplicationTemplateService{} 2475 appTemplateSvc.On("GetByFilters", context.TODO(), filters).Return(nil, testError).Once() 2476 return appTemplateSvc 2477 }, 2478 RuntimeFn: func() *automock.RuntimeService { 2479 runtimeSvc := &automock.RuntimeService{} 2480 runtimeSvc.On("GetByFiltersGlobal", context.TODO(), filters).Return(nil, nil).Once() 2481 return runtimeSvc 2482 }, 2483 Output: "", 2484 ExpectedErrorOutput: testError.Error(), 2485 }, 2486 { 2487 Name: "Error when a runtime and app template exist", 2488 AppTemplateFn: func() *automock.ApplicationTemplateService { 2489 appTemplateSvc := &automock.ApplicationTemplateService{} 2490 appTemplateSvc.On("GetByFilters", context.TODO(), filters).Return(modelAppTemplate, nil).Once() 2491 return appTemplateSvc 2492 }, 2493 RuntimeFn: func() *automock.RuntimeService { 2494 runtimeSvc := &automock.RuntimeService{} 2495 runtimeSvc.On("GetByFiltersGlobal", context.TODO(), filters).Return(modelRuntime, nil).Once() 2496 return runtimeSvc 2497 }, 2498 Output: "", 2499 ExpectedErrorOutput: fmt.Sprintf("both a runtime (%+v) and application template (%+v) exist with filter labels provider (%q) and region (%q)", modelRuntime, modelAppTemplate, providerSubaccountID, regionalTenantSubdomain), 2500 }, 2501 { 2502 Name: "Success when no runtime and app template exists", 2503 AppTemplateFn: func() *automock.ApplicationTemplateService { 2504 appTemplateSvc := &automock.ApplicationTemplateService{} 2505 appTemplateSvc.On("GetByFilters", context.TODO(), filters).Return(nil, nil).Once() 2506 return appTemplateSvc 2507 }, 2508 RuntimeFn: func() *automock.RuntimeService { 2509 runtimeSvc := &automock.RuntimeService{} 2510 runtimeSvc.On("GetByFiltersGlobal", context.TODO(), filters).Return(nil, nil).Once() 2511 return runtimeSvc 2512 }, 2513 Output: "", 2514 }, 2515 } 2516 2517 for _, testCase := range testCases { 2518 t.Run(testCase.Name, func(t *testing.T) { 2519 appTemplateSvc := testCase.AppTemplateFn() 2520 rtmService := testCase.RuntimeFn() 2521 defer mock.AssertExpectationsForObjects(t, appTemplateSvc, rtmService) 2522 2523 service := subscription.NewService(rtmService, nil, nil, nil, appTemplateSvc, nil, nil, nil, nil, consumerSubaccountLabelKey, subscriptionLabelKey, subscriptionAppNameLabelKey, subscriptionProviderIDLabelKey) 2524 2525 output, err := service.DetermineSubscriptionFlow(context.TODO(), providerSubaccountID, regionalTenantSubdomain) 2526 if len(testCase.ExpectedErrorOutput) > 0 { 2527 assert.Error(t, err) 2528 assert.Contains(t, err.Error(), testCase.ExpectedErrorOutput) 2529 } else { 2530 assert.NoError(t, err) 2531 } 2532 2533 assert.Equal(t, testCase.Output, output) 2534 }) 2535 } 2536 } 2537 2538 func ctxWithTenantMatcher(expectedTenantID string) interface{} { 2539 return mock.MatchedBy(func(ctx context.Context) bool { 2540 tenantID, err := tenant.LoadFromContext(ctx) 2541 return err == nil && tenantID == expectedTenantID 2542 }) 2543 }