github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/internal/systemfetcher/service_test.go (about) 1 package systemfetcher_test 2 3 import ( 4 "context" 5 "encoding/json" 6 "errors" 7 "sync" 8 "testing" 9 "time" 10 11 "github.com/tidwall/gjson" 12 13 "github.com/kyma-incubator/compass/components/director/pkg/str" 14 15 "github.com/kyma-incubator/compass/components/director/internal/model" 16 "github.com/kyma-incubator/compass/components/director/internal/systemfetcher" 17 "github.com/kyma-incubator/compass/components/director/internal/systemfetcher/automock" 18 pAutomock "github.com/kyma-incubator/compass/components/director/pkg/persistence/automock" 19 "github.com/kyma-incubator/compass/components/director/pkg/persistence/txtest" 20 tenantEntity "github.com/kyma-incubator/compass/components/director/pkg/tenant" 21 "github.com/stretchr/testify/mock" 22 "github.com/stretchr/testify/require" 23 ) 24 25 const ( 26 appType = "type-1" 27 mainURLKey = "mainUrl" 28 testID = "testID" 29 ) 30 31 func TestSyncSystems(t *testing.T) { 32 const appTemplateID = "appTmp1" 33 testErr := errors.New("testErr") 34 setupSuccessfulTemplateRenderer := func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInput) *automock.TemplateRenderer { 35 svc := &automock.TemplateRenderer{} 36 for i := range appsInputs { 37 svc.On("ApplicationRegisterInputFromTemplate", txtest.CtxWithDBMatcher(), systems[i]).Return(&appsInputs[i], nil).Once() 38 } 39 return svc 40 } 41 42 var mutex sync.Mutex 43 type testCase struct { 44 name string 45 mockTransactioner func() (*pAutomock.PersistenceTx, *pAutomock.Transactioner) 46 fixTestSystems func() []systemfetcher.System 47 fixAppInputs func(systems []systemfetcher.System) []model.ApplicationRegisterInputWithTemplate 48 setupTenantSvc func() *automock.TenantService 49 setupTbtSvc func() *automock.TenantBusinessTypeService 50 setupTemplateRendererSvc func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInput) *automock.TemplateRenderer 51 setupSystemSvc func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.SystemsService 52 setupSystemsSyncSvc func() *automock.SystemsSyncService 53 setupSysAPIClient func(testSystems []systemfetcher.System) *automock.SystemsAPIClient 54 setupDirectorClient func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.DirectorClient 55 verificationTenant string 56 expectedErr error 57 } 58 tests := []testCase{ 59 { 60 name: "Success with one tenant and one system", 61 mockTransactioner: func() (*pAutomock.PersistenceTx, *pAutomock.Transactioner) { 62 mockedTx, transactioner := txtest.NewTransactionContextGenerator(nil).ThatSucceedsMultipleTimes(3) 63 return mockedTx, transactioner 64 }, 65 fixTestSystems: func() []systemfetcher.System { 66 systems := fixSystems() 67 systems[0].TemplateID = appTemplateID 68 systems[0].SystemPayload["productId"] = "TEST" 69 return systems 70 }, 71 fixAppInputs: func(systems []systemfetcher.System) []model.ApplicationRegisterInputWithTemplate { 72 return fixAppsInputsWithTemplatesBySystems(t, systems) 73 }, 74 setupTenantSvc: func() *automock.TenantService { 75 tenants := []*model.BusinessTenantMapping{ 76 newModelBusinessTenantMapping("t1", "tenant1"), 77 } 78 tenantSvc := &automock.TenantService{} 79 tenantSvc.On("ListByType", txtest.CtxWithDBMatcher(), tenantEntity.Account).Return(tenants, nil).Once() 80 return tenantSvc 81 }, 82 setupTbtSvc: func() *automock.TenantBusinessTypeService { 83 tbtSvc := &automock.TenantBusinessTypeService{} 84 tbtSvc.On("ListAll", txtest.CtxWithDBMatcher()).Return([]*model.TenantBusinessType{}, nil) 85 return tbtSvc 86 }, 87 setupTemplateRendererSvc: setupSuccessfulTemplateRenderer, 88 setupSystemSvc: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.SystemsService { 89 systemSvc := &automock.SystemsService{} 90 systemSvc.On("TrustedUpsertFromTemplate", txtest.CtxWithDBMatcher(), appsInputs[0].ApplicationRegisterInput, mock.Anything).Return(nil).Once() 91 systemSvc.On("GetBySystemNumber", txtest.CtxWithDBMatcher(), *appsInputs[0].SystemNumber).Return(&model.Application{ 92 BaseEntity: &model.BaseEntity{ 93 ID: "id", 94 }, 95 }, nil) 96 return systemSvc 97 }, 98 setupSystemsSyncSvc: emptySystemsSyncSvc, 99 setupSysAPIClient: func(testSystems []systemfetcher.System) *automock.SystemsAPIClient { 100 sysAPIClient := &automock.SystemsAPIClient{} 101 sysAPIClient.On("FetchSystemsForTenant", mock.Anything, "external", &mutex).Return(testSystems, nil).Once() 102 return sysAPIClient 103 }, 104 setupDirectorClient: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.DirectorClient { 105 return &automock.DirectorClient{} 106 }, 107 }, 108 { 109 name: "Success with one tenant and one system which has tbt and tbt does not exist in the db", 110 mockTransactioner: func() (*pAutomock.PersistenceTx, *pAutomock.Transactioner) { 111 mockedTx, transactioner := txtest.NewTransactionContextGenerator(nil).ThatSucceedsMultipleTimes(3) 112 return mockedTx, transactioner 113 }, 114 fixTestSystems: func() []systemfetcher.System { 115 systems := fixSystemsWithTbt() 116 systems[0].TemplateID = appTemplateID 117 systems[0].SystemPayload["productId"] = "TEST" 118 return systems 119 }, 120 fixAppInputs: func(systems []systemfetcher.System) []model.ApplicationRegisterInputWithTemplate { 121 return fixAppsInputsWithTemplatesBySystems(t, systems) 122 }, 123 setupTenantSvc: func() *automock.TenantService { 124 tenants := []*model.BusinessTenantMapping{ 125 newModelBusinessTenantMapping("t1", "tenant1"), 126 } 127 tenantSvc := &automock.TenantService{} 128 tenantSvc.On("ListByType", txtest.CtxWithDBMatcher(), tenantEntity.Account).Return(tenants, nil).Once() 129 return tenantSvc 130 }, 131 setupTbtSvc: func() *automock.TenantBusinessTypeService { 132 tbtSvc := &automock.TenantBusinessTypeService{} 133 tbtSvc.On("ListAll", txtest.CtxWithDBMatcher()).Return([]*model.TenantBusinessType{}, nil).Once() 134 tbtSvc.On("Create", txtest.CtxWithDBMatcher(), &model.TenantBusinessTypeInput{Code: fixSystemsWithTbt()[0].SystemPayload["businessTypeId"].(string), Name: fixSystemsWithTbt()[0].SystemPayload["businessTypeDescription"].(string)}).Return(testID, nil).Once() 135 tbtSvc.On("GetByID", txtest.CtxWithDBMatcher(), testID).Return(&model.TenantBusinessType{ID: testID, Code: fixSystemsWithTbt()[0].SystemPayload["businessTypeId"].(string), Name: fixSystemsWithTbt()[0].SystemPayload["businessTypeDescription"].(string)}, nil).Once() 136 return tbtSvc 137 }, 138 setupTemplateRendererSvc: setupSuccessfulTemplateRenderer, 139 setupSystemSvc: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.SystemsService { 140 systemSvc := &automock.SystemsService{} 141 appsInputs[0].ApplicationRegisterInput.TenantBusinessTypeID = str.Ptr(testID) 142 systemSvc.On("TrustedUpsertFromTemplate", txtest.CtxWithDBMatcher(), appsInputs[0].ApplicationRegisterInput, mock.Anything).Return(nil).Once() 143 systemSvc.On("GetBySystemNumber", txtest.CtxWithDBMatcher(), *appsInputs[0].SystemNumber).Return(&model.Application{ 144 BaseEntity: &model.BaseEntity{ 145 ID: "id", 146 }, 147 }, nil) 148 return systemSvc 149 }, 150 setupSystemsSyncSvc: emptySystemsSyncSvc, 151 setupSysAPIClient: func(testSystems []systemfetcher.System) *automock.SystemsAPIClient { 152 sysAPIClient := &automock.SystemsAPIClient{} 153 sysAPIClient.On("FetchSystemsForTenant", mock.Anything, "external", &mutex).Return(testSystems, nil).Once() 154 return sysAPIClient 155 }, 156 setupDirectorClient: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.DirectorClient { 157 return &automock.DirectorClient{} 158 }, 159 }, 160 { 161 name: "Success with one tenant and one system which has tbt and tbt exists in the db", 162 mockTransactioner: func() (*pAutomock.PersistenceTx, *pAutomock.Transactioner) { 163 mockedTx, transactioner := txtest.NewTransactionContextGenerator(nil).ThatSucceedsMultipleTimes(3) 164 return mockedTx, transactioner 165 }, 166 fixTestSystems: func() []systemfetcher.System { 167 systems := fixSystemsWithTbt() 168 systems[0].TemplateID = appTemplateID 169 systems[0].SystemPayload["productId"] = "TEST" 170 return systems 171 }, 172 fixAppInputs: func(systems []systemfetcher.System) []model.ApplicationRegisterInputWithTemplate { 173 return fixAppsInputsWithTemplatesBySystems(t, systems) 174 }, 175 setupTenantSvc: func() *automock.TenantService { 176 tenants := []*model.BusinessTenantMapping{ 177 newModelBusinessTenantMapping("t1", "tenant1"), 178 } 179 tenantSvc := &automock.TenantService{} 180 tenantSvc.On("ListByType", txtest.CtxWithDBMatcher(), tenantEntity.Account).Return(tenants, nil).Once() 181 return tenantSvc 182 }, 183 setupTbtSvc: func() *automock.TenantBusinessTypeService { 184 tbtSvc := &automock.TenantBusinessTypeService{} 185 systemPayload, err := json.Marshal(fixSystemsWithTbt()[0].SystemPayload) 186 require.NoError(t, err) 187 188 tbtSvc.On("ListAll", txtest.CtxWithDBMatcher()).Return([]*model.TenantBusinessType{{ID: testID, Code: gjson.GetBytes(systemPayload, "businessTypeId").String(), Name: gjson.GetBytes(systemPayload, "BusinessTypeDescription").String()}}, nil).Once() 189 return tbtSvc 190 }, 191 setupTemplateRendererSvc: setupSuccessfulTemplateRenderer, 192 setupSystemSvc: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.SystemsService { 193 systemSvc := &automock.SystemsService{} 194 appsInputs[0].ApplicationRegisterInput.TenantBusinessTypeID = str.Ptr(testID) 195 systemSvc.On("TrustedUpsertFromTemplate", txtest.CtxWithDBMatcher(), appsInputs[0].ApplicationRegisterInput, mock.Anything).Return(nil).Once() 196 systemSvc.On("GetBySystemNumber", txtest.CtxWithDBMatcher(), *appsInputs[0].SystemNumber).Return(&model.Application{ 197 BaseEntity: &model.BaseEntity{ 198 ID: "id", 199 }, 200 }, nil) 201 return systemSvc 202 }, 203 setupSystemsSyncSvc: emptySystemsSyncSvc, 204 setupSysAPIClient: func(testSystems []systemfetcher.System) *automock.SystemsAPIClient { 205 sysAPIClient := &automock.SystemsAPIClient{} 206 sysAPIClient.On("FetchSystemsForTenant", mock.Anything, "external", &mutex).Return(testSystems, nil).Once() 207 return sysAPIClient 208 }, 209 setupDirectorClient: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.DirectorClient { 210 return &automock.DirectorClient{} 211 }, 212 }, 213 { 214 name: "Success when in verification mode", 215 mockTransactioner: func() (*pAutomock.PersistenceTx, *pAutomock.Transactioner) { 216 mockedTx, transactioner := txtest.NewTransactionContextGenerator(nil).ThatSucceedsMultipleTimes(3) 217 return mockedTx, transactioner 218 }, 219 fixTestSystems: func() []systemfetcher.System { 220 systems := fixSystems() 221 systems[0].TemplateID = appTemplateID 222 systems[0].SystemPayload["productId"] = "TEST" 223 return systems 224 }, 225 fixAppInputs: func(systems []systemfetcher.System) []model.ApplicationRegisterInputWithTemplate { 226 return fixAppsInputsWithTemplatesBySystems(t, systems) 227 }, 228 setupTenantSvc: func() *automock.TenantService { 229 tenants := []*model.BusinessTenantMapping{ 230 newModelBusinessTenantMapping("t1", "tenant1"), 231 } 232 tenantSvc := &automock.TenantService{} 233 tenantSvc.On("GetTenantByExternalID", txtest.CtxWithDBMatcher(), "t1").Return(tenants[0], nil).Once() 234 return tenantSvc 235 }, 236 setupTbtSvc: func() *automock.TenantBusinessTypeService { 237 tbtSvc := &automock.TenantBusinessTypeService{} 238 tbtSvc.On("ListAll", txtest.CtxWithDBMatcher()).Return([]*model.TenantBusinessType{}, nil) 239 return tbtSvc 240 }, 241 setupTemplateRendererSvc: setupSuccessfulTemplateRenderer, 242 setupSystemSvc: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.SystemsService { 243 systemSvc := &automock.SystemsService{} 244 systemSvc.On("TrustedUpsertFromTemplate", txtest.CtxWithDBMatcher(), appsInputs[0].ApplicationRegisterInput, mock.Anything).Return(nil).Once() 245 systemSvc.On("GetBySystemNumber", txtest.CtxWithDBMatcher(), *appsInputs[0].SystemNumber).Return(&model.Application{ 246 BaseEntity: &model.BaseEntity{ 247 ID: "id", 248 }, 249 }, nil) 250 return systemSvc 251 }, 252 setupSystemsSyncSvc: emptySystemsSyncSvc, 253 setupSysAPIClient: func(testSystems []systemfetcher.System) *automock.SystemsAPIClient { 254 sysAPIClient := &automock.SystemsAPIClient{} 255 sysAPIClient.On("FetchSystemsForTenant", mock.Anything, "external", &mutex).Return(testSystems, nil).Once() 256 return sysAPIClient 257 }, 258 setupDirectorClient: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.DirectorClient { 259 return &automock.DirectorClient{} 260 }, 261 verificationTenant: "t1", 262 }, 263 { 264 name: "Success with one tenant and one system that has already been in the database and will not have it's status condition changed", 265 mockTransactioner: func() (*pAutomock.PersistenceTx, *pAutomock.Transactioner) { 266 mockedTx, transactioner := txtest.NewTransactionContextGenerator(nil).ThatSucceedsMultipleTimes(3) 267 return mockedTx, transactioner 268 }, 269 fixTestSystems: func() []systemfetcher.System { 270 systems := fixSystems() 271 systems[0].TemplateID = appTemplateID 272 systems[0].SystemPayload["productId"] = "TEST" 273 return systems 274 }, 275 fixAppInputs: func(systems []systemfetcher.System) []model.ApplicationRegisterInputWithTemplate { 276 return fixAppsInputsWithTemplatesBySystems(t, systems) 277 }, 278 setupTenantSvc: func() *automock.TenantService { 279 tenants := []*model.BusinessTenantMapping{ 280 newModelBusinessTenantMapping("t1", "tenant1"), 281 } 282 tenantSvc := &automock.TenantService{} 283 tenantSvc.On("ListByType", txtest.CtxWithDBMatcher(), tenantEntity.Account).Return(tenants, nil).Once() 284 return tenantSvc 285 }, 286 setupTbtSvc: func() *automock.TenantBusinessTypeService { 287 tbtSvc := &automock.TenantBusinessTypeService{} 288 tbtSvc.On("ListAll", txtest.CtxWithDBMatcher()).Return([]*model.TenantBusinessType{}, nil) 289 return tbtSvc 290 }, 291 setupTemplateRendererSvc: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInput) *automock.TemplateRenderer { 292 svc := &automock.TemplateRenderer{} 293 connectedStatus := model.ApplicationStatusConditionConnected 294 295 for i := range appsInputs { 296 input := systems[i] 297 input.StatusCondition = connectedStatus 298 299 result := appsInputs[i] 300 result.StatusCondition = &connectedStatus 301 302 svc.On("ApplicationRegisterInputFromTemplate", txtest.CtxWithDBMatcher(), input).Return(&result, nil).Once() 303 } 304 return svc 305 }, 306 setupSystemSvc: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.SystemsService { 307 systemSvc := &automock.SystemsService{} 308 309 connectedStatus := model.ApplicationStatusConditionConnected 310 appInput := appsInputs[0].ApplicationRegisterInput 311 appInput.StatusCondition = &connectedStatus 312 313 systemSvc.On("TrustedUpsertFromTemplate", txtest.CtxWithDBMatcher(), appInput, mock.Anything).Return(nil).Once() 314 systemSvc.On("GetBySystemNumber", txtest.CtxWithDBMatcher(), *appsInputs[0].SystemNumber).Return(&model.Application{ 315 BaseEntity: &model.BaseEntity{ 316 ID: "id", 317 }, 318 Status: &model.ApplicationStatus{ 319 Condition: model.ApplicationStatusConditionConnected, 320 }, 321 }, nil) 322 return systemSvc 323 }, 324 setupSystemsSyncSvc: emptySystemsSyncSvc, 325 setupSysAPIClient: func(testSystems []systemfetcher.System) *automock.SystemsAPIClient { 326 sysAPIClient := &automock.SystemsAPIClient{} 327 sysAPIClient.On("FetchSystemsForTenant", mock.Anything, "external", &mutex).Return(testSystems, nil).Once() 328 return sysAPIClient 329 }, 330 setupDirectorClient: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.DirectorClient { 331 return &automock.DirectorClient{} 332 }, 333 }, 334 { 335 name: "Success with one tenant and one system with null base url", 336 mockTransactioner: func() (*pAutomock.PersistenceTx, *pAutomock.Transactioner) { 337 mockedTx, transactioner := txtest.NewTransactionContextGenerator(nil).ThatSucceedsMultipleTimes(3) 338 return mockedTx, transactioner 339 }, 340 fixTestSystems: func() []systemfetcher.System { 341 systems := []systemfetcher.System{ 342 { 343 SystemPayload: map[string]interface{}{ 344 "displayName": "System1", 345 "productDescription": "System1 description", 346 "infrastructureProvider": "test", 347 }, 348 StatusCondition: model.ApplicationStatusConditionInitial, 349 }, 350 } 351 systems[0].TemplateID = "type1" 352 systems[0].SystemPayload["productId"] = "TEST" 353 return systems 354 }, 355 fixAppInputs: func(systems []systemfetcher.System) []model.ApplicationRegisterInputWithTemplate { 356 return fixAppsInputsWithTemplatesBySystems(t, systems) 357 }, 358 setupTenantSvc: func() *automock.TenantService { 359 tenants := []*model.BusinessTenantMapping{ 360 newModelBusinessTenantMapping("t1", "tenant1"), 361 } 362 tenantSvc := &automock.TenantService{} 363 tenantSvc.On("ListByType", txtest.CtxWithDBMatcher(), tenantEntity.Account).Return(tenants, nil).Once() 364 return tenantSvc 365 }, 366 setupTbtSvc: func() *automock.TenantBusinessTypeService { 367 tbtSvc := &automock.TenantBusinessTypeService{} 368 tbtSvc.On("ListAll", txtest.CtxWithDBMatcher()).Return([]*model.TenantBusinessType{}, nil) 369 return tbtSvc 370 }, 371 setupTemplateRendererSvc: setupSuccessfulTemplateRenderer, 372 setupSystemSvc: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.SystemsService { 373 systemSvc := &automock.SystemsService{} 374 systemSvc.On("TrustedUpsertFromTemplate", txtest.CtxWithDBMatcher(), mock.AnythingOfType("model.ApplicationRegisterInput"), mock.Anything).Return(nil).Once() 375 systemSvc.On("GetBySystemNumber", txtest.CtxWithDBMatcher(), *appsInputs[0].SystemNumber).Return(&model.Application{ 376 BaseEntity: &model.BaseEntity{ 377 ID: "id", 378 }, 379 }, nil) 380 return systemSvc 381 }, 382 setupSystemsSyncSvc: emptySystemsSyncSvc, 383 setupSysAPIClient: func(testSystems []systemfetcher.System) *automock.SystemsAPIClient { 384 sysAPIClient := &automock.SystemsAPIClient{} 385 sysAPIClient.On("FetchSystemsForTenant", mock.Anything, "external", &mutex).Return(testSystems, nil).Once() 386 return sysAPIClient 387 }, 388 setupDirectorClient: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.DirectorClient { 389 return &automock.DirectorClient{} 390 }, 391 }, 392 { 393 name: "Success with one tenant and one system without template", 394 mockTransactioner: func() (*pAutomock.PersistenceTx, *pAutomock.Transactioner) { 395 mockedTx, transactioner := txtest.NewTransactionContextGenerator(nil).ThatSucceedsMultipleTimes(3) 396 return mockedTx, transactioner 397 }, 398 fixTestSystems: fixSystems, 399 fixAppInputs: func(systems []systemfetcher.System) []model.ApplicationRegisterInputWithTemplate { 400 return fixAppsInputsWithTemplatesBySystems(t, systems) 401 }, 402 setupTenantSvc: func() *automock.TenantService { 403 tenants := []*model.BusinessTenantMapping{ 404 newModelBusinessTenantMapping("t1", "tenant1"), 405 } 406 tenantSvc := &automock.TenantService{} 407 tenantSvc.On("ListByType", txtest.CtxWithDBMatcher(), tenantEntity.Account).Return(tenants, nil).Once() 408 return tenantSvc 409 }, 410 setupTbtSvc: func() *automock.TenantBusinessTypeService { 411 tbtSvc := &automock.TenantBusinessTypeService{} 412 tbtSvc.On("ListAll", txtest.CtxWithDBMatcher()).Return([]*model.TenantBusinessType{}, nil) 413 return tbtSvc 414 }, 415 setupTemplateRendererSvc: func(_ []systemfetcher.System, _ []model.ApplicationRegisterInput) *automock.TemplateRenderer { 416 return &automock.TemplateRenderer{} 417 }, 418 setupSystemSvc: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.SystemsService { 419 systemSvc := &automock.SystemsService{} 420 systemSvc.On("TrustedUpsert", txtest.CtxWithDBMatcher(), appsInputs[0].ApplicationRegisterInput, mock.Anything).Return(nil).Once() 421 systemSvc.On("GetBySystemNumber", txtest.CtxWithDBMatcher(), *appsInputs[0].SystemNumber).Return(&model.Application{ 422 BaseEntity: &model.BaseEntity{ 423 ID: "id", 424 }, 425 }, nil) 426 return systemSvc 427 }, 428 setupSystemsSyncSvc: emptySystemsSyncSvc, 429 setupSysAPIClient: func(testSystems []systemfetcher.System) *automock.SystemsAPIClient { 430 sysAPIClient := &automock.SystemsAPIClient{} 431 sysAPIClient.On("FetchSystemsForTenant", mock.Anything, "external", &mutex).Return(testSystems, nil).Once() 432 return sysAPIClient 433 }, 434 setupDirectorClient: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.DirectorClient { 435 return &automock.DirectorClient{} 436 }, 437 }, 438 { 439 name: "Success with one tenant and multiple systems", 440 mockTransactioner: func() (*pAutomock.PersistenceTx, *pAutomock.Transactioner) { 441 mockedTx, transactioner := txtest.NewTransactionContextGenerator(nil).ThatSucceedsMultipleTimes(4) 442 return mockedTx, transactioner 443 }, 444 fixTestSystems: func() []systemfetcher.System { 445 systems := fixSystems() 446 systems[0].TemplateID = appTemplateID 447 systems = append(systems, systemfetcher.System{ 448 SystemPayload: map[string]interface{}{ 449 "displayName": "System2", 450 "productDescription": "System2 description", 451 "baseUrl": "http://example2.com", 452 "infrastructureProvider": "test", 453 }, 454 TemplateID: "appTmp2", 455 StatusCondition: model.ApplicationStatusConditionInitial, 456 }) 457 return systems 458 }, 459 fixAppInputs: func(systems []systemfetcher.System) []model.ApplicationRegisterInputWithTemplate { 460 return fixAppsInputsWithTemplatesBySystems(t, systems) 461 }, 462 setupTenantSvc: func() *automock.TenantService { 463 tenants := []*model.BusinessTenantMapping{ 464 newModelBusinessTenantMapping("t1", "tenant1"), 465 } 466 tenantSvc := &automock.TenantService{} 467 tenantSvc.On("ListByType", txtest.CtxWithDBMatcher(), tenantEntity.Account).Return(tenants, nil).Once() 468 return tenantSvc 469 }, 470 setupTbtSvc: func() *automock.TenantBusinessTypeService { 471 tbtSvc := &automock.TenantBusinessTypeService{} 472 tbtSvc.On("ListAll", txtest.CtxWithDBMatcher()).Return([]*model.TenantBusinessType{}, nil) 473 return tbtSvc 474 }, 475 setupTemplateRendererSvc: setupSuccessfulTemplateRenderer, 476 setupSystemSvc: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.SystemsService { 477 systemSvc := &automock.SystemsService{} 478 systemSvc.On("TrustedUpsertFromTemplate", txtest.CtxWithDBMatcher(), appsInputs[0].ApplicationRegisterInput, mock.Anything).Return(nil).Once() 479 systemSvc.On("TrustedUpsertFromTemplate", txtest.CtxWithDBMatcher(), appsInputs[1].ApplicationRegisterInput, mock.Anything).Return(nil).Once() 480 systemSvc.On("GetBySystemNumber", txtest.CtxWithDBMatcher(), *appsInputs[0].SystemNumber).Return(&model.Application{ 481 BaseEntity: &model.BaseEntity{ 482 ID: "id", 483 }, 484 }, nil) 485 systemSvc.On("GetBySystemNumber", txtest.CtxWithDBMatcher(), *appsInputs[1].SystemNumber).Return(&model.Application{ 486 BaseEntity: &model.BaseEntity{ 487 ID: "id", 488 }, 489 }, nil) 490 return systemSvc 491 }, 492 setupSystemsSyncSvc: emptySystemsSyncSvc, 493 setupSysAPIClient: func(testSystems []systemfetcher.System) *automock.SystemsAPIClient { 494 sysAPIClient := &automock.SystemsAPIClient{} 495 sysAPIClient.On("FetchSystemsForTenant", mock.Anything, "external", &mutex).Return(testSystems, nil).Once() 496 return sysAPIClient 497 }, 498 setupDirectorClient: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.DirectorClient { 499 return &automock.DirectorClient{} 500 }, 501 }, 502 { 503 name: "Success with multiple tenants with one system", 504 mockTransactioner: func() (*pAutomock.PersistenceTx, *pAutomock.Transactioner) { 505 mockedTx, transactioner := txtest.NewTransactionContextGenerator(nil).ThatSucceedsMultipleTimes(4) 506 return mockedTx, transactioner 507 }, 508 fixTestSystems: func() []systemfetcher.System { 509 systems := fixSystems() 510 systems[0].TemplateID = appTemplateID 511 systems = append(systems, systemfetcher.System{ 512 SystemPayload: map[string]interface{}{ 513 "displayName": "System2", 514 "productDescription": "System2 description", 515 "baseUrl": "http://example2.com", 516 "infrastructureProvider": "test", 517 }, 518 TemplateID: "appTmp2", 519 StatusCondition: model.ApplicationStatusConditionInitial, 520 }) 521 return systems 522 }, 523 fixAppInputs: func(systems []systemfetcher.System) []model.ApplicationRegisterInputWithTemplate { 524 return fixAppsInputsWithTemplatesBySystems(t, systems) 525 }, 526 setupTenantSvc: func() *automock.TenantService { 527 firstTenant := newModelBusinessTenantMapping("t1", "tenant1") 528 firstTenant.ExternalTenant = "t1" 529 secondTenant := newModelBusinessTenantMapping("t2", "tenant2") 530 secondTenant.ExternalTenant = "t2" 531 tenants := []*model.BusinessTenantMapping{firstTenant, secondTenant} 532 tenantSvc := &automock.TenantService{} 533 tenantSvc.On("ListByType", txtest.CtxWithDBMatcher(), tenantEntity.Account).Return(tenants, nil).Once() 534 return tenantSvc 535 }, 536 setupTbtSvc: func() *automock.TenantBusinessTypeService { 537 tbtSvc := &automock.TenantBusinessTypeService{} 538 tbtSvc.On("ListAll", txtest.CtxWithDBMatcher()).Return([]*model.TenantBusinessType{}, nil) 539 return tbtSvc 540 }, 541 setupTemplateRendererSvc: setupSuccessfulTemplateRenderer, 542 setupSystemSvc: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.SystemsService { 543 systemSvc := &automock.SystemsService{} 544 systemSvc.On("TrustedUpsertFromTemplate", txtest.CtxWithDBMatcher(), appsInputs[0].ApplicationRegisterInput, mock.Anything).Return(nil).Once() 545 systemSvc.On("TrustedUpsertFromTemplate", txtest.CtxWithDBMatcher(), appsInputs[1].ApplicationRegisterInput, mock.Anything).Return(nil).Once() 546 systemSvc.On("GetBySystemNumber", txtest.CtxWithDBMatcher(), *appsInputs[0].SystemNumber).Return(&model.Application{ 547 BaseEntity: &model.BaseEntity{ 548 ID: "id", 549 }, 550 }, nil) 551 systemSvc.On("GetBySystemNumber", txtest.CtxWithDBMatcher(), *appsInputs[1].SystemNumber).Return(&model.Application{ 552 BaseEntity: &model.BaseEntity{ 553 ID: "id", 554 }, 555 }, nil) 556 return systemSvc 557 }, 558 setupSystemsSyncSvc: emptySystemsSyncSvc, 559 setupSysAPIClient: func(testSystems []systemfetcher.System) *automock.SystemsAPIClient { 560 sysAPIClient := &automock.SystemsAPIClient{} 561 sysAPIClient.On("FetchSystemsForTenant", mock.Anything, "t1", &mutex).Return([]systemfetcher.System{testSystems[0]}, nil).Once() 562 sysAPIClient.On("FetchSystemsForTenant", mock.Anything, "t2", &mutex).Return([]systemfetcher.System{testSystems[1]}, nil).Once() 563 return sysAPIClient 564 }, 565 setupDirectorClient: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.DirectorClient { 566 return &automock.DirectorClient{} 567 }, 568 }, 569 { 570 name: "Fail when listing all tenant business types", 571 mockTransactioner: func() (*pAutomock.PersistenceTx, *pAutomock.Transactioner) { 572 persistTx := &pAutomock.PersistenceTx{} 573 persistTx.On("Commit").Return(nil).Once() 574 575 transact := &pAutomock.Transactioner{} 576 transact.On("Begin").Return(persistTx, nil).Twice() 577 transact.On("RollbackUnlessCommitted", mock.Anything, persistTx).Return(false).Once() 578 transact.On("RollbackUnlessCommitted", mock.Anything, persistTx).Return(true).Once() 579 580 return persistTx, transact 581 }, 582 fixTestSystems: func() []systemfetcher.System { 583 return fixSystemsWithTbt() 584 }, 585 fixAppInputs: func(systems []systemfetcher.System) []model.ApplicationRegisterInputWithTemplate { 586 return fixAppsInputsWithTemplatesBySystems(t, systems) 587 }, 588 setupTenantSvc: func() *automock.TenantService { 589 tenants := []*model.BusinessTenantMapping{ 590 newModelBusinessTenantMapping("t1", "tenant1"), 591 } 592 tenantSvc := &automock.TenantService{} 593 tenantSvc.On("ListByType", txtest.CtxWithDBMatcher(), tenantEntity.Account).Return(tenants, nil).Once() 594 return tenantSvc 595 }, 596 setupTbtSvc: func() *automock.TenantBusinessTypeService { 597 tbtSvc := &automock.TenantBusinessTypeService{} 598 tbtSvc.On("ListAll", txtest.CtxWithDBMatcher()).Return(nil, testErr).Once() 599 return tbtSvc 600 }, 601 setupTemplateRendererSvc: func(_ []systemfetcher.System, _ []model.ApplicationRegisterInput) *automock.TemplateRenderer { 602 return &automock.TemplateRenderer{} 603 }, 604 setupSystemSvc: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.SystemsService { 605 return &automock.SystemsService{} 606 }, 607 setupSystemsSyncSvc: emptySystemsSyncSvc, 608 setupSysAPIClient: func(testSystems []systemfetcher.System) *automock.SystemsAPIClient { 609 return &automock.SystemsAPIClient{} 610 }, 611 setupDirectorClient: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.DirectorClient { 612 return &automock.DirectorClient{} 613 }, 614 expectedErr: testErr, 615 }, 616 { 617 name: "Begin transaction fails when listing all tenant business types", 618 mockTransactioner: func() (*pAutomock.PersistenceTx, *pAutomock.Transactioner) { 619 persistTx := &pAutomock.PersistenceTx{} 620 persistTx.On("Commit").Return(nil).Once() 621 622 transact := &pAutomock.Transactioner{} 623 transact.On("Begin").Return(persistTx, nil).Once() 624 transact.On("Begin").Return(persistTx, testErr).Once() 625 transact.On("RollbackUnlessCommitted", mock.Anything, persistTx).Return(false).Once() 626 627 return persistTx, transact 628 }, 629 fixTestSystems: func() []systemfetcher.System { 630 return fixSystemsWithTbt() 631 }, 632 fixAppInputs: func(systems []systemfetcher.System) []model.ApplicationRegisterInputWithTemplate { 633 return fixAppsInputsWithTemplatesBySystems(t, systems) 634 }, 635 setupTenantSvc: func() *automock.TenantService { 636 tenants := []*model.BusinessTenantMapping{ 637 newModelBusinessTenantMapping("t1", "tenant1"), 638 } 639 tenantSvc := &automock.TenantService{} 640 tenantSvc.On("ListByType", txtest.CtxWithDBMatcher(), tenantEntity.Account).Return(tenants, nil).Once() 641 return tenantSvc 642 }, 643 setupTbtSvc: func() *automock.TenantBusinessTypeService { 644 return &automock.TenantBusinessTypeService{} 645 }, 646 setupTemplateRendererSvc: func(_ []systemfetcher.System, _ []model.ApplicationRegisterInput) *automock.TemplateRenderer { 647 return &automock.TemplateRenderer{} 648 }, 649 setupSystemSvc: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.SystemsService { 650 return &automock.SystemsService{} 651 }, 652 setupSystemsSyncSvc: emptySystemsSyncSvc, 653 setupSysAPIClient: func(testSystems []systemfetcher.System) *automock.SystemsAPIClient { 654 return &automock.SystemsAPIClient{} 655 }, 656 setupDirectorClient: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.DirectorClient { 657 return &automock.DirectorClient{} 658 }, 659 expectedErr: testErr, 660 }, 661 { 662 name: "Commit transaction fails when listing all tenant business types", 663 mockTransactioner: func() (*pAutomock.PersistenceTx, *pAutomock.Transactioner) { 664 persistTx := &pAutomock.PersistenceTx{} 665 persistTx.On("Commit").Return(nil).Once() 666 persistTx.On("Commit").Return(testErr).Once() 667 668 transact := &pAutomock.Transactioner{} 669 transact.On("Begin").Return(persistTx, nil).Twice() 670 transact.On("RollbackUnlessCommitted", mock.Anything, persistTx).Return(false).Once() 671 transact.On("RollbackUnlessCommitted", mock.Anything, persistTx).Return(true).Once() 672 673 return persistTx, transact 674 }, 675 fixTestSystems: func() []systemfetcher.System { 676 return fixSystemsWithTbt() 677 }, 678 fixAppInputs: func(systems []systemfetcher.System) []model.ApplicationRegisterInputWithTemplate { 679 return fixAppsInputsWithTemplatesBySystems(t, systems) 680 }, 681 setupTenantSvc: func() *automock.TenantService { 682 tenants := []*model.BusinessTenantMapping{ 683 newModelBusinessTenantMapping("t1", "tenant1"), 684 } 685 tenantSvc := &automock.TenantService{} 686 tenantSvc.On("ListByType", txtest.CtxWithDBMatcher(), tenantEntity.Account).Return(tenants, nil).Once() 687 return tenantSvc 688 }, 689 setupTbtSvc: func() *automock.TenantBusinessTypeService { 690 tbtSvc := &automock.TenantBusinessTypeService{} 691 tbtSvc.On("ListAll", txtest.CtxWithDBMatcher()).Return([]*model.TenantBusinessType{{ID: testID, Code: fixSystemsWithTbt()[0].SystemPayload["businessTypeId"].(string), Name: fixSystemsWithTbt()[0].SystemPayload["businessTypeDescription"].(string)}}, nil).Once() 692 return tbtSvc 693 }, 694 setupTemplateRendererSvc: func(_ []systemfetcher.System, _ []model.ApplicationRegisterInput) *automock.TemplateRenderer { 695 return &automock.TemplateRenderer{} 696 }, 697 setupSystemSvc: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.SystemsService { 698 return &automock.SystemsService{} 699 }, 700 setupSystemsSyncSvc: emptySystemsSyncSvc, 701 setupSysAPIClient: func(testSystems []systemfetcher.System) *automock.SystemsAPIClient { 702 return &automock.SystemsAPIClient{} 703 }, 704 setupDirectorClient: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.DirectorClient { 705 return &automock.DirectorClient{} 706 }, 707 expectedErr: testErr, 708 }, 709 { 710 name: "Fails when creating new tenant business type", 711 mockTransactioner: func() (*pAutomock.PersistenceTx, *pAutomock.Transactioner) { 712 persistTx := &pAutomock.PersistenceTx{} 713 persistTx.On("Commit").Return(nil).Twice() 714 715 transact := &pAutomock.Transactioner{} 716 transact.On("Begin").Return(persistTx, nil).Times(3) 717 transact.On("RollbackUnlessCommitted", mock.Anything, persistTx).Return(false).Twice() 718 transact.On("RollbackUnlessCommitted", mock.Anything, persistTx).Return(true).Once() 719 720 return persistTx, transact 721 }, 722 fixTestSystems: func() []systemfetcher.System { 723 return fixSystemsWithTbt() 724 }, 725 fixAppInputs: func(systems []systemfetcher.System) []model.ApplicationRegisterInputWithTemplate { 726 return fixAppsInputsWithTemplatesBySystems(t, systems) 727 }, 728 setupTenantSvc: func() *automock.TenantService { 729 tenants := []*model.BusinessTenantMapping{ 730 newModelBusinessTenantMapping("t1", "tenant1"), 731 } 732 tenantSvc := &automock.TenantService{} 733 tenantSvc.On("ListByType", txtest.CtxWithDBMatcher(), tenantEntity.Account).Return(tenants, nil).Once() 734 return tenantSvc 735 }, 736 setupTbtSvc: func() *automock.TenantBusinessTypeService { 737 tbtSvc := &automock.TenantBusinessTypeService{} 738 tbtSvc.On("ListAll", txtest.CtxWithDBMatcher()).Return([]*model.TenantBusinessType{}, nil).Once() 739 tbtSvc.On("Create", txtest.CtxWithDBMatcher(), &model.TenantBusinessTypeInput{Code: fixSystemsWithTbt()[0].SystemPayload["businessTypeId"].(string), Name: fixSystemsWithTbt()[0].SystemPayload["businessTypeDescription"].(string)}).Return("", testErr).Once() 740 return tbtSvc 741 }, 742 setupTemplateRendererSvc: func(_ []systemfetcher.System, _ []model.ApplicationRegisterInput) *automock.TemplateRenderer { 743 return &automock.TemplateRenderer{} 744 }, 745 setupSystemSvc: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.SystemsService { 746 systemSvc := &automock.SystemsService{} 747 systemSvc.On("GetBySystemNumber", txtest.CtxWithDBMatcher(), *appsInputs[0].SystemNumber).Return(&model.Application{ 748 BaseEntity: &model.BaseEntity{ 749 ID: "id", 750 }, 751 }, nil) 752 return systemSvc 753 }, 754 setupSystemsSyncSvc: emptySystemsSyncSvc, 755 setupSysAPIClient: func(testSystems []systemfetcher.System) *automock.SystemsAPIClient { 756 sysAPIClient := &automock.SystemsAPIClient{} 757 sysAPIClient.On("FetchSystemsForTenant", mock.Anything, "external", &mutex).Return(testSystems, nil).Once() 758 return sysAPIClient 759 }, 760 setupDirectorClient: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.DirectorClient { 761 return &automock.DirectorClient{} 762 }, 763 }, 764 { 765 name: "Fails when getting by id newly created tenant business type", 766 mockTransactioner: func() (*pAutomock.PersistenceTx, *pAutomock.Transactioner) { 767 persistTx := &pAutomock.PersistenceTx{} 768 persistTx.On("Commit").Return(nil).Twice() 769 770 transact := &pAutomock.Transactioner{} 771 transact.On("Begin").Return(persistTx, nil).Times(3) 772 transact.On("RollbackUnlessCommitted", mock.Anything, persistTx).Return(false).Twice() 773 transact.On("RollbackUnlessCommitted", mock.Anything, persistTx).Return(true).Once() 774 775 return persistTx, transact 776 }, 777 fixTestSystems: func() []systemfetcher.System { 778 return fixSystemsWithTbt() 779 }, 780 fixAppInputs: func(systems []systemfetcher.System) []model.ApplicationRegisterInputWithTemplate { 781 return fixAppsInputsWithTemplatesBySystems(t, systems) 782 }, 783 setupTenantSvc: func() *automock.TenantService { 784 tenants := []*model.BusinessTenantMapping{ 785 newModelBusinessTenantMapping("t1", "tenant1"), 786 } 787 tenantSvc := &automock.TenantService{} 788 tenantSvc.On("ListByType", txtest.CtxWithDBMatcher(), tenantEntity.Account).Return(tenants, nil).Once() 789 return tenantSvc 790 }, 791 setupTbtSvc: func() *automock.TenantBusinessTypeService { 792 tbtSvc := &automock.TenantBusinessTypeService{} 793 tbtSvc.On("ListAll", txtest.CtxWithDBMatcher()).Return([]*model.TenantBusinessType{}, nil).Once() 794 tbtSvc.On("Create", txtest.CtxWithDBMatcher(), &model.TenantBusinessTypeInput{Code: fixSystemsWithTbt()[0].SystemPayload["businessTypeId"].(string), Name: fixSystemsWithTbt()[0].SystemPayload["businessTypeDescription"].(string)}).Return(testID, nil).Once() 795 tbtSvc.On("GetByID", txtest.CtxWithDBMatcher(), testID).Return(nil, testErr).Once() 796 return tbtSvc 797 }, 798 setupTemplateRendererSvc: func(_ []systemfetcher.System, _ []model.ApplicationRegisterInput) *automock.TemplateRenderer { 799 return &automock.TemplateRenderer{} 800 }, 801 setupSystemSvc: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.SystemsService { 802 systemSvc := &automock.SystemsService{} 803 systemSvc.On("GetBySystemNumber", txtest.CtxWithDBMatcher(), *appsInputs[0].SystemNumber).Return(&model.Application{ 804 BaseEntity: &model.BaseEntity{ 805 ID: "id", 806 }, 807 }, nil) 808 return systemSvc 809 }, 810 setupSystemsSyncSvc: emptySystemsSyncSvc, 811 setupSysAPIClient: func(testSystems []systemfetcher.System) *automock.SystemsAPIClient { 812 sysAPIClient := &automock.SystemsAPIClient{} 813 sysAPIClient.On("FetchSystemsForTenant", mock.Anything, "external", &mutex).Return(testSystems, nil).Once() 814 return sysAPIClient 815 }, 816 setupDirectorClient: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.DirectorClient { 817 return &automock.DirectorClient{} 818 }, 819 }, 820 { 821 name: "Fail when tenant fetching fails", 822 mockTransactioner: func() (*pAutomock.PersistenceTx, *pAutomock.Transactioner) { 823 mockedTx, transactioner := txtest.NewTransactionContextGenerator(nil).ThatDoesntExpectCommit() 824 825 return mockedTx, transactioner 826 }, 827 fixTestSystems: fixSystems, 828 fixAppInputs: func(systems []systemfetcher.System) []model.ApplicationRegisterInputWithTemplate { 829 return fixAppsInputsWithTemplatesBySystems(t, systems) 830 }, 831 setupTenantSvc: func() *automock.TenantService { 832 tenantSvc := &automock.TenantService{} 833 tenantSvc.On("ListByType", txtest.CtxWithDBMatcher(), tenantEntity.Account).Return(nil, testErr).Once() 834 return tenantSvc 835 }, 836 setupTbtSvc: func() *automock.TenantBusinessTypeService { 837 return &automock.TenantBusinessTypeService{} 838 }, 839 setupTemplateRendererSvc: func(_ []systemfetcher.System, _ []model.ApplicationRegisterInput) *automock.TemplateRenderer { 840 return &automock.TemplateRenderer{} 841 }, 842 setupSystemSvc: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.SystemsService { 843 return &automock.SystemsService{} 844 }, 845 setupSystemsSyncSvc: emptySystemsSyncSvc, 846 setupSysAPIClient: func(testSystems []systemfetcher.System) *automock.SystemsAPIClient { 847 return &automock.SystemsAPIClient{} 848 }, 849 setupDirectorClient: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.DirectorClient { 850 return &automock.DirectorClient{} 851 }, 852 expectedErr: testErr, 853 }, 854 { 855 name: "Fail when transaction cannot be started", 856 mockTransactioner: func() (*pAutomock.PersistenceTx, *pAutomock.Transactioner) { 857 mockedTx, transactioner := txtest.NewTransactionContextGenerator(testErr).ThatFailsOnBegin() 858 859 return mockedTx, transactioner 860 }, 861 fixTestSystems: fixSystems, 862 fixAppInputs: func(systems []systemfetcher.System) []model.ApplicationRegisterInputWithTemplate { 863 return fixAppsInputsWithTemplatesBySystems(t, systems) 864 }, 865 setupTenantSvc: func() *automock.TenantService { 866 return &automock.TenantService{} 867 }, 868 setupTbtSvc: func() *automock.TenantBusinessTypeService { 869 return &automock.TenantBusinessTypeService{} 870 }, 871 setupTemplateRendererSvc: func(_ []systemfetcher.System, _ []model.ApplicationRegisterInput) *automock.TemplateRenderer { 872 return &automock.TemplateRenderer{} 873 }, 874 setupSystemSvc: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.SystemsService { 875 return &automock.SystemsService{} 876 }, 877 setupSystemsSyncSvc: emptySystemsSyncSvc, 878 setupSysAPIClient: func(testSystems []systemfetcher.System) *automock.SystemsAPIClient { 879 return &automock.SystemsAPIClient{} 880 }, 881 setupDirectorClient: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.DirectorClient { 882 return &automock.DirectorClient{} 883 }, 884 expectedErr: testErr, 885 }, 886 { 887 name: "Fail when commit fails", 888 mockTransactioner: func() (*pAutomock.PersistenceTx, *pAutomock.Transactioner) { 889 mockedTx, transactioner := txtest.NewTransactionContextGenerator(testErr).ThatFailsOnCommit() 890 return mockedTx, transactioner 891 }, 892 fixTestSystems: func() []systemfetcher.System { 893 systems := fixSystems() 894 systems[0].TemplateID = appTemplateID 895 return systems 896 }, 897 fixAppInputs: func(systems []systemfetcher.System) []model.ApplicationRegisterInputWithTemplate { 898 return fixAppsInputsWithTemplatesBySystems(t, systems) 899 }, 900 setupTenantSvc: func() *automock.TenantService { 901 tenants := []*model.BusinessTenantMapping{ 902 newModelBusinessTenantMapping("t1", "tenant1"), 903 } 904 tenantSvc := &automock.TenantService{} 905 tenantSvc.On("ListByType", txtest.CtxWithDBMatcher(), tenantEntity.Account).Return(tenants, nil).Once() 906 return tenantSvc 907 }, 908 setupTbtSvc: func() *automock.TenantBusinessTypeService { 909 return &automock.TenantBusinessTypeService{} 910 }, 911 setupTemplateRendererSvc: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInput) *automock.TemplateRenderer { 912 return &automock.TemplateRenderer{} 913 }, 914 setupSystemSvc: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.SystemsService { 915 return &automock.SystemsService{} 916 }, 917 setupSystemsSyncSvc: emptySystemsSyncSvc, 918 setupSysAPIClient: func(testSystems []systemfetcher.System) *automock.SystemsAPIClient { 919 return &automock.SystemsAPIClient{} 920 }, 921 setupDirectorClient: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.DirectorClient { 922 return &automock.DirectorClient{} 923 }, 924 expectedErr: testErr, 925 }, 926 { 927 name: "Fail when client fails to fetch systems", 928 mockTransactioner: func() (*pAutomock.PersistenceTx, *pAutomock.Transactioner) { 929 mockedTx, transactioner := txtest.NewTransactionContextGenerator(nil).ThatSucceedsMultipleTimes(2) 930 931 return mockedTx, transactioner 932 }, 933 fixTestSystems: func() []systemfetcher.System { 934 return fixSystems() 935 }, 936 fixAppInputs: func(systems []systemfetcher.System) []model.ApplicationRegisterInputWithTemplate { 937 return fixAppsInputsWithTemplatesBySystems(t, systems) 938 }, 939 setupTenantSvc: func() *automock.TenantService { 940 tenants := []*model.BusinessTenantMapping{ 941 newModelBusinessTenantMapping("t1", "tenant1"), 942 } 943 tenantSvc := &automock.TenantService{} 944 tenantSvc.On("ListByType", txtest.CtxWithDBMatcher(), tenantEntity.Account).Return(tenants, nil).Once() 945 return tenantSvc 946 }, 947 setupTbtSvc: func() *automock.TenantBusinessTypeService { 948 tbtSvc := &automock.TenantBusinessTypeService{} 949 tbtSvc.On("ListAll", txtest.CtxWithDBMatcher()).Return([]*model.TenantBusinessType{}, nil) 950 return tbtSvc 951 }, 952 setupTemplateRendererSvc: func(_ []systemfetcher.System, _ []model.ApplicationRegisterInput) *automock.TemplateRenderer { 953 return &automock.TemplateRenderer{} 954 }, 955 setupSystemSvc: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.SystemsService { 956 return &automock.SystemsService{} 957 }, 958 setupSystemsSyncSvc: emptySystemsSyncSvc, 959 setupSysAPIClient: func(testSystems []systemfetcher.System) *automock.SystemsAPIClient { 960 sysAPIClient := &automock.SystemsAPIClient{} 961 sysAPIClient.On("FetchSystemsForTenant", mock.Anything, "external", &mutex).Return(nil, errors.New("expected")).Once() 962 return sysAPIClient 963 }, 964 setupDirectorClient: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.DirectorClient { 965 return &automock.DirectorClient{} 966 }, 967 }, 968 { 969 name: "Fail when service fails to save systems", 970 mockTransactioner: func() (*pAutomock.PersistenceTx, *pAutomock.Transactioner) { 971 mockedTx, transactioner := txtest.NewTransactionContextGenerator(nil).ThatSucceedsMultipleTimes(2) 972 persistTx := &pAutomock.PersistenceTx{} 973 974 transactioner.On("Begin").Return(persistTx, nil).Once() 975 persistTx.On("Commit").Return(nil).Once() 976 transactioner.On("RollbackUnlessCommitted", mock.Anything, persistTx).Return(true).Once() 977 978 return mockedTx, transactioner 979 }, 980 fixTestSystems: func() []systemfetcher.System { 981 systems := fixSystems() 982 systems[0].TemplateID = appTemplateID 983 return systems 984 }, 985 fixAppInputs: func(systems []systemfetcher.System) []model.ApplicationRegisterInputWithTemplate { 986 return fixAppsInputsWithTemplatesBySystems(t, systems) 987 }, 988 setupTenantSvc: func() *automock.TenantService { 989 tenants := []*model.BusinessTenantMapping{ 990 newModelBusinessTenantMapping("t1", "tenant1"), 991 } 992 tenantSvc := &automock.TenantService{} 993 tenantSvc.On("ListByType", txtest.CtxWithDBMatcher(), tenantEntity.Account).Return(tenants, nil).Once() 994 return tenantSvc 995 }, 996 setupTbtSvc: func() *automock.TenantBusinessTypeService { 997 tbtSvc := &automock.TenantBusinessTypeService{} 998 tbtSvc.On("ListAll", txtest.CtxWithDBMatcher()).Return([]*model.TenantBusinessType{}, nil) 999 return tbtSvc 1000 }, 1001 setupTemplateRendererSvc: setupSuccessfulTemplateRenderer, 1002 setupSystemSvc: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.SystemsService { 1003 systemSvc := &automock.SystemsService{} 1004 systemSvc.On("TrustedUpsertFromTemplate", txtest.CtxWithDBMatcher(), appsInputs[0].ApplicationRegisterInput, mock.Anything).Return(errors.New("expected")).Once() 1005 systemSvc.On("GetBySystemNumber", txtest.CtxWithDBMatcher(), *appsInputs[0].SystemNumber).Return(&model.Application{ 1006 BaseEntity: &model.BaseEntity{ 1007 ID: "id", 1008 }, 1009 }, nil) 1010 return systemSvc 1011 }, 1012 setupSystemsSyncSvc: emptySystemsSyncSvc, 1013 setupSysAPIClient: func(testSystems []systemfetcher.System) *automock.SystemsAPIClient { 1014 sysAPIClient := &automock.SystemsAPIClient{} 1015 sysAPIClient.On("FetchSystemsForTenant", mock.Anything, "external", &mutex).Return([]systemfetcher.System{testSystems[0]}, nil).Once() 1016 return sysAPIClient 1017 }, 1018 setupDirectorClient: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.DirectorClient { 1019 return &automock.DirectorClient{} 1020 }, 1021 }, 1022 { 1023 name: "Fail when application from template cannot be rendered", 1024 mockTransactioner: func() (*pAutomock.PersistenceTx, *pAutomock.Transactioner) { 1025 mockedTx, transactioner := txtest.NewTransactionContextGenerator(nil).ThatSucceedsMultipleTimes(2) 1026 persistTx := &pAutomock.PersistenceTx{} 1027 1028 transactioner.On("Begin").Return(persistTx, nil).Once() 1029 transactioner.On("RollbackUnlessCommitted", mock.Anything, persistTx).Return(true).Once() 1030 1031 return mockedTx, transactioner 1032 }, 1033 fixTestSystems: func() []systemfetcher.System { 1034 systems := fixSystems() 1035 systems[0].TemplateID = appTemplateID 1036 return systems 1037 }, 1038 fixAppInputs: func(systems []systemfetcher.System) []model.ApplicationRegisterInputWithTemplate { 1039 return fixAppsInputsWithTemplatesBySystems(t, systems) 1040 }, 1041 setupTenantSvc: func() *automock.TenantService { 1042 tenants := []*model.BusinessTenantMapping{ 1043 newModelBusinessTenantMapping("t1", "tenant1"), 1044 } 1045 tenantSvc := &automock.TenantService{} 1046 tenantSvc.On("ListByType", txtest.CtxWithDBMatcher(), tenantEntity.Account).Return(tenants, nil).Once() 1047 return tenantSvc 1048 }, 1049 setupTbtSvc: func() *automock.TenantBusinessTypeService { 1050 tbtSvc := &automock.TenantBusinessTypeService{} 1051 tbtSvc.On("ListAll", txtest.CtxWithDBMatcher()).Return([]*model.TenantBusinessType{}, nil) 1052 return tbtSvc 1053 }, 1054 setupTemplateRendererSvc: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInput) *automock.TemplateRenderer { 1055 svc := &automock.TemplateRenderer{} 1056 for i := range appsInputs { 1057 svc.On("ApplicationRegisterInputFromTemplate", txtest.CtxWithDBMatcher(), systems[i]).Return(nil, testErr).Once() 1058 } 1059 return svc 1060 }, 1061 setupSystemSvc: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.SystemsService { 1062 systemSvc := &automock.SystemsService{} 1063 systemSvc.On("GetBySystemNumber", txtest.CtxWithDBMatcher(), *appsInputs[0].SystemNumber).Return(&model.Application{ 1064 BaseEntity: &model.BaseEntity{ 1065 ID: "id", 1066 }, 1067 }, nil) 1068 1069 return systemSvc 1070 }, 1071 setupSystemsSyncSvc: emptySystemsSyncSvc, 1072 setupSysAPIClient: func(testSystems []systemfetcher.System) *automock.SystemsAPIClient { 1073 sysAPIClient := &automock.SystemsAPIClient{} 1074 sysAPIClient.On("FetchSystemsForTenant", mock.Anything, "external", &mutex).Return([]systemfetcher.System{testSystems[0]}, nil).Once() 1075 return sysAPIClient 1076 }, 1077 setupDirectorClient: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.DirectorClient { 1078 return &automock.DirectorClient{} 1079 }, 1080 }, 1081 { 1082 name: "Succeed when client fails to fetch systems only for some tenants", 1083 mockTransactioner: func() (*pAutomock.PersistenceTx, *pAutomock.Transactioner) { 1084 mockedTx, transactioner := txtest.NewTransactionContextGenerator(nil).ThatSucceedsMultipleTimes(4) 1085 1086 return mockedTx, transactioner 1087 }, 1088 fixTestSystems: func() []systemfetcher.System { 1089 systems := fixSystems() 1090 systems[0].TemplateID = "type1" 1091 systems = append(systems, systemfetcher.System{ 1092 SystemPayload: map[string]interface{}{ 1093 "displayName": "System2", 1094 "productDescription": "System2 description", 1095 "baseUrl": "http://example2.com", 1096 "infrastructureProvider": "test", 1097 }, 1098 TemplateID: "type2", 1099 StatusCondition: model.ApplicationStatusConditionInitial, 1100 }) 1101 return systems 1102 }, 1103 fixAppInputs: func(systems []systemfetcher.System) []model.ApplicationRegisterInputWithTemplate { 1104 return fixAppsInputsWithTemplatesBySystems(t, systems) 1105 }, 1106 setupTenantSvc: func() *automock.TenantService { 1107 tenants := []*model.BusinessTenantMapping{ 1108 newModelBusinessTenantMapping("t1", "tenant1"), 1109 newModelBusinessTenantMapping("t2", "tenant2"), 1110 newModelBusinessTenantMapping("t3", "tenant3"), 1111 } 1112 tenantSvc := &automock.TenantService{} 1113 tenantSvc.On("ListByType", txtest.CtxWithDBMatcher(), tenantEntity.Account).Return(tenants, nil).Once() 1114 return tenantSvc 1115 }, 1116 setupTbtSvc: func() *automock.TenantBusinessTypeService { 1117 tbtSvc := &automock.TenantBusinessTypeService{} 1118 tbtSvc.On("ListAll", txtest.CtxWithDBMatcher()).Return([]*model.TenantBusinessType{}, nil) 1119 return tbtSvc 1120 }, 1121 setupTemplateRendererSvc: setupSuccessfulTemplateRenderer, 1122 setupSystemSvc: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.SystemsService { 1123 systemSvc := &automock.SystemsService{} 1124 systemSvc.On("TrustedUpsertFromTemplate", txtest.CtxWithDBMatcher(), mock.AnythingOfType("model.ApplicationRegisterInput"), mock.Anything).Return(nil).Once() 1125 systemSvc.On("TrustedUpsertFromTemplate", txtest.CtxWithDBMatcher(), mock.AnythingOfType("model.ApplicationRegisterInput"), mock.Anything).Return(nil).Once() 1126 systemSvc.On("GetBySystemNumber", txtest.CtxWithDBMatcher(), *appsInputs[0].SystemNumber).Return(&model.Application{ 1127 BaseEntity: &model.BaseEntity{ 1128 ID: "id", 1129 }, 1130 }, nil) 1131 systemSvc.On("GetBySystemNumber", txtest.CtxWithDBMatcher(), *appsInputs[1].SystemNumber).Return(&model.Application{ 1132 BaseEntity: &model.BaseEntity{ 1133 ID: "id", 1134 }, 1135 }, nil) 1136 return systemSvc 1137 }, 1138 setupSystemsSyncSvc: emptySystemsSyncSvc, 1139 setupSysAPIClient: func(testSystems []systemfetcher.System) *automock.SystemsAPIClient { 1140 sysAPIClient := &automock.SystemsAPIClient{} 1141 sysAPIClient.On("FetchSystemsForTenant", mock.Anything, "external", &mutex).Return([]systemfetcher.System{testSystems[0]}, nil).Once() 1142 sysAPIClient.On("FetchSystemsForTenant", mock.Anything, "external", &mutex).Return(nil, errors.New("expected")).Once() 1143 sysAPIClient.On("FetchSystemsForTenant", mock.Anything, "external", &mutex).Return([]systemfetcher.System{testSystems[1]}, nil).Once() 1144 return sysAPIClient 1145 }, 1146 setupDirectorClient: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.DirectorClient { 1147 return &automock.DirectorClient{} 1148 }, 1149 }, 1150 { 1151 name: "Do nothing if system is already being deleted", 1152 mockTransactioner: func() (*pAutomock.PersistenceTx, *pAutomock.Transactioner) { 1153 mockedTx, transactioner := txtest.NewTransactionContextGenerator(nil).ThatSucceedsMultipleTimes(2) 1154 persistTx := &pAutomock.PersistenceTx{} 1155 1156 transactioner.On("Begin").Return(persistTx, nil).Twice() 1157 persistTx.On("Commit").Return(nil).Once() 1158 transactioner.On("RollbackUnlessCommitted", mock.Anything, persistTx).Return(true).Twice() 1159 1160 return mockedTx, transactioner 1161 }, 1162 fixTestSystems: func() []systemfetcher.System { 1163 systems := fixSystems() 1164 systems[0].TemplateID = "type1" 1165 systems = append(systems, systemfetcher.System{ 1166 SystemPayload: map[string]interface{}{ 1167 "displayName": "System2", 1168 "productDescription": "System2 description", 1169 "baseUrl": "http://example2.com", 1170 "infrastructureProvider": "test", 1171 "additionalAttributes": map[string]string{ 1172 systemfetcher.LifecycleAttributeName: systemfetcher.LifecycleDeleted, 1173 }, 1174 "systemNumber": "sysNumber1", 1175 }, 1176 TemplateID: "type2", 1177 StatusCondition: model.ApplicationStatusConditionInitial, 1178 }) 1179 return systems 1180 }, 1181 fixAppInputs: func(systems []systemfetcher.System) []model.ApplicationRegisterInputWithTemplate { 1182 return fixAppsInputsWithTemplatesBySystems(t, systems) 1183 }, 1184 setupTenantSvc: func() *automock.TenantService { 1185 firstTenant := newModelBusinessTenantMapping("t1", "tenant1") 1186 firstTenant.ExternalTenant = "t1" 1187 secondTenant := newModelBusinessTenantMapping("t2", "tenant2") 1188 secondTenant.ExternalTenant = "t2" 1189 tenants := []*model.BusinessTenantMapping{firstTenant, secondTenant} 1190 tenantSvc := &automock.TenantService{} 1191 tenantSvc.On("ListByType", txtest.CtxWithDBMatcher(), tenantEntity.Account).Return(tenants, nil).Once() 1192 return tenantSvc 1193 }, 1194 setupTbtSvc: func() *automock.TenantBusinessTypeService { 1195 tbtSvc := &automock.TenantBusinessTypeService{} 1196 tbtSvc.On("ListAll", txtest.CtxWithDBMatcher()).Return([]*model.TenantBusinessType{}, nil) 1197 return tbtSvc 1198 }, 1199 setupTemplateRendererSvc: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInput) *automock.TemplateRenderer { 1200 svc := &automock.TemplateRenderer{} 1201 appInput := appsInputs[0] // appsInputs[1] belongs to a system with status "DELETED" 1202 svc.On("ApplicationRegisterInputFromTemplate", txtest.CtxWithDBMatcher(), systems[0]).Return(&appInput, nil) 1203 return svc 1204 }, 1205 setupSystemSvc: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.SystemsService { 1206 systemSvc := &automock.SystemsService{} 1207 1208 systemSvc.On("TrustedUpsertFromTemplate", txtest.CtxWithDBMatcher(), mock.AnythingOfType("model.ApplicationRegisterInput"), mock.Anything).Return(nil).Once() 1209 systemSvc.On("GetBySystemNumber", txtest.CtxWithDBMatcher(), *appsInputs[0].SystemNumber).Return(&model.Application{ 1210 BaseEntity: &model.BaseEntity{ 1211 ID: "id", 1212 }, 1213 }, nil) 1214 systemSvc.On("GetBySystemNumber", txtest.CtxWithDBMatcher(), *appsInputs[1].SystemNumber).Return(&model.Application{ 1215 BaseEntity: &model.BaseEntity{ 1216 ID: "id", 1217 }, 1218 }, nil) 1219 return systemSvc 1220 }, 1221 setupSystemsSyncSvc: emptySystemsSyncSvc, 1222 setupSysAPIClient: func(testSystems []systemfetcher.System) *automock.SystemsAPIClient { 1223 sysAPIClient := &automock.SystemsAPIClient{} 1224 sysAPIClient.On("FetchSystemsForTenant", mock.Anything, "t1", &mutex).Return([]systemfetcher.System{testSystems[0]}, nil).Once() 1225 sysAPIClient.On("FetchSystemsForTenant", mock.Anything, "t2", &mutex).Return([]systemfetcher.System{testSystems[1]}, nil).Once() 1226 return sysAPIClient 1227 }, 1228 setupDirectorClient: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.DirectorClient { 1229 directorClient := &automock.DirectorClient{} 1230 directorClient.On("DeleteSystemAsync", mock.Anything, "id", "t2").Return(nil).Once() 1231 return directorClient 1232 }, 1233 }, 1234 { 1235 name: "Do nothing if system has already been deleted", 1236 mockTransactioner: func() (*pAutomock.PersistenceTx, *pAutomock.Transactioner) { 1237 mockedTx, transactioner := txtest.NewTransactionContextGenerator(nil).ThatSucceedsMultipleTimes(2) 1238 persistTx := &pAutomock.PersistenceTx{} 1239 1240 transactioner.On("Begin").Return(persistTx, nil).Twice() 1241 persistTx.On("Commit").Return(nil).Once() 1242 transactioner.On("RollbackUnlessCommitted", mock.Anything, persistTx).Return(true).Twice() 1243 1244 return mockedTx, transactioner 1245 }, 1246 fixTestSystems: func() []systemfetcher.System { 1247 systems := fixSystems() 1248 systems[0].TemplateID = "type1" 1249 systems = append(systems, systemfetcher.System{ 1250 SystemPayload: map[string]interface{}{ 1251 "displayName": "System2", 1252 "productDescription": "System2 description", 1253 "baseUrl": "http://example2.com", 1254 "infrastructureProvider": "test", 1255 "additionalAttributes": map[string]string{ 1256 systemfetcher.LifecycleAttributeName: systemfetcher.LifecycleDeleted, 1257 }, 1258 "systemNumber": "sysNumber1", 1259 }, 1260 TemplateID: "type2", 1261 StatusCondition: model.ApplicationStatusConditionInitial, 1262 }) 1263 return systems 1264 }, 1265 fixAppInputs: func(systems []systemfetcher.System) []model.ApplicationRegisterInputWithTemplate { 1266 return fixAppsInputsWithTemplatesBySystems(t, systems) 1267 }, 1268 setupTenantSvc: func() *automock.TenantService { 1269 firstTenant := newModelBusinessTenantMapping("t1", "tenant1") 1270 firstTenant.ExternalTenant = "t1" 1271 secondTenant := newModelBusinessTenantMapping("t2", "tenant2") 1272 secondTenant.ExternalTenant = "t2" 1273 tenants := []*model.BusinessTenantMapping{firstTenant, secondTenant} 1274 tenantSvc := &automock.TenantService{} 1275 tenantSvc.On("ListByType", txtest.CtxWithDBMatcher(), tenantEntity.Account).Return(tenants, nil).Once() 1276 return tenantSvc 1277 }, 1278 setupTbtSvc: func() *automock.TenantBusinessTypeService { 1279 tbtSvc := &automock.TenantBusinessTypeService{} 1280 tbtSvc.On("ListAll", txtest.CtxWithDBMatcher()).Return([]*model.TenantBusinessType{}, nil) 1281 return tbtSvc 1282 }, 1283 setupTemplateRendererSvc: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInput) *automock.TemplateRenderer { 1284 svc := &automock.TemplateRenderer{} 1285 appInput := appsInputs[0] // appsInputs[1] belongs to a system with status "DELETED" 1286 svc.On("ApplicationRegisterInputFromTemplate", txtest.CtxWithDBMatcher(), systems[0]).Return(&appInput, nil) 1287 return svc 1288 }, 1289 setupSystemSvc: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.SystemsService { 1290 systemSvc := &automock.SystemsService{} 1291 1292 systemSvc.On("TrustedUpsertFromTemplate", txtest.CtxWithDBMatcher(), mock.AnythingOfType("model.ApplicationRegisterInput"), mock.Anything).Return(nil).Once() 1293 systemSvc.On("GetBySystemNumber", txtest.CtxWithDBMatcher(), *appsInputs[0].SystemNumber).Return(&model.Application{ 1294 BaseEntity: &model.BaseEntity{ 1295 ID: "id", 1296 }, 1297 }, nil) 1298 systemSvc.On("GetBySystemNumber", txtest.CtxWithDBMatcher(), *appsInputs[1].SystemNumber).Return(nil, nil) 1299 return systemSvc 1300 }, 1301 setupSystemsSyncSvc: emptySystemsSyncSvc, 1302 setupSysAPIClient: func(testSystems []systemfetcher.System) *automock.SystemsAPIClient { 1303 sysAPIClient := &automock.SystemsAPIClient{} 1304 sysAPIClient.On("FetchSystemsForTenant", mock.Anything, "t1", &mutex).Return([]systemfetcher.System{testSystems[0]}, nil).Once() 1305 sysAPIClient.On("FetchSystemsForTenant", mock.Anything, "t2", &mutex).Return([]systemfetcher.System{testSystems[1]}, nil).Once() 1306 return sysAPIClient 1307 }, 1308 setupDirectorClient: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.DirectorClient { 1309 directorClient := &automock.DirectorClient{} 1310 directorClient.On("DeleteSystemAsync", mock.Anything, "id", "t2").Return(nil).Once() 1311 return directorClient 1312 }, 1313 }, 1314 } 1315 1316 for _, testCase := range tests { 1317 t.Run(testCase.name, func(t *testing.T) { 1318 mockedTx, transactioner := testCase.mockTransactioner() 1319 tenantSvc := testCase.setupTenantSvc() 1320 tbtSvc := testCase.setupTbtSvc() 1321 testSystems := testCase.fixTestSystems() 1322 appsInputs := testCase.fixAppInputs(testSystems) 1323 systemSvc := testCase.setupSystemSvc(testSystems, appsInputs) 1324 systemsSyncSvc := testCase.setupSystemsSyncSvc() 1325 appInputsWithoutTemplates := make([]model.ApplicationRegisterInput, 0) 1326 for _, in := range appsInputs { 1327 appInputsWithoutTemplates = append(appInputsWithoutTemplates, in.ApplicationRegisterInput) 1328 } 1329 templateAppResolver := testCase.setupTemplateRendererSvc(testSystems, appInputsWithoutTemplates) 1330 sysAPIClient := testCase.setupSysAPIClient(testSystems) 1331 directorClient := testCase.setupDirectorClient(testSystems, appsInputs) 1332 defer mock.AssertExpectationsForObjects(t, tenantSvc, tbtSvc, sysAPIClient, systemSvc, templateAppResolver, mockedTx, transactioner) 1333 1334 svc := systemfetcher.NewSystemFetcher(transactioner, tenantSvc, systemSvc, systemsSyncSvc, tbtSvc, templateAppResolver, sysAPIClient, directorClient, systemfetcher.Config{ 1335 SystemsQueueSize: 100, 1336 FetcherParallellism: 30, 1337 EnableSystemDeletion: true, 1338 VerifyTenant: testCase.verificationTenant, 1339 }) 1340 1341 err := svc.SyncSystems(context.TODO()) 1342 if testCase.expectedErr != nil { 1343 require.ErrorIs(t, err, testCase.expectedErr) 1344 } else { 1345 require.NoError(t, err) 1346 } 1347 }) 1348 } 1349 } 1350 1351 func TestUpsertSystemsSyncTimestamps(t *testing.T) { 1352 testError := errors.New("testError") 1353 1354 systemfetcher.SystemSynchronizationTimestamps = map[string]map[string]systemfetcher.SystemSynchronizationTimestamp{ 1355 "t": { 1356 "type1": { 1357 ID: "time", 1358 LastSyncTimestamp: time.Date(2023, 5, 2, 20, 30, 0, 0, time.UTC).UTC(), 1359 }, 1360 }, 1361 } 1362 1363 type testCase struct { 1364 name string 1365 mockTransactioner func() (*pAutomock.PersistenceTx, *pAutomock.Transactioner) 1366 fixTestSystems func() []systemfetcher.System 1367 fixAppInputs func(systems []systemfetcher.System) []model.ApplicationRegisterInputWithTemplate 1368 setupTenantSvc func() *automock.TenantService 1369 setupTbtSvc func() *automock.TenantBusinessTypeService 1370 setupTemplateRendererSvc func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInput) *automock.TemplateRenderer 1371 setupSystemSvc func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.SystemsService 1372 setupSystemsSyncSvc func() *automock.SystemsSyncService 1373 setupSysAPIClient func(testSystems []systemfetcher.System) *automock.SystemsAPIClient 1374 setupDirectorClient func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.DirectorClient 1375 verificationTenant string 1376 expectedErr error 1377 } 1378 1379 tests := []testCase{ 1380 { 1381 name: "Success", 1382 mockTransactioner: func() (*pAutomock.PersistenceTx, *pAutomock.Transactioner) { 1383 mockedTx, transactioner := txtest.NewTransactionContextGenerator(nil).ThatSucceedsMultipleTimes(1) 1384 return mockedTx, transactioner 1385 }, 1386 fixTestSystems: func() []systemfetcher.System { 1387 return []systemfetcher.System{} 1388 }, 1389 fixAppInputs: func(systems []systemfetcher.System) []model.ApplicationRegisterInputWithTemplate { 1390 return []model.ApplicationRegisterInputWithTemplate{} 1391 }, 1392 setupTenantSvc: func() *automock.TenantService { 1393 return &automock.TenantService{} 1394 }, 1395 setupTbtSvc: func() *automock.TenantBusinessTypeService { 1396 return &automock.TenantBusinessTypeService{} 1397 }, 1398 setupTemplateRendererSvc: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInput) *automock.TemplateRenderer { 1399 return &automock.TemplateRenderer{} 1400 }, 1401 setupSystemSvc: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.SystemsService { 1402 return &automock.SystemsService{} 1403 }, 1404 setupSystemsSyncSvc: func() *automock.SystemsSyncService { 1405 syncMock := &automock.SystemsSyncService{} 1406 syncMock.On("Upsert", mock.Anything, mock.Anything).Return(nil) 1407 return syncMock 1408 }, 1409 setupSysAPIClient: func(testSystems []systemfetcher.System) *automock.SystemsAPIClient { 1410 return &automock.SystemsAPIClient{} 1411 }, 1412 setupDirectorClient: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.DirectorClient { 1413 return &automock.DirectorClient{} 1414 }, 1415 }, 1416 { 1417 name: "Error while upserting", 1418 mockTransactioner: func() (*pAutomock.PersistenceTx, *pAutomock.Transactioner) { 1419 mockedTx, transactioner := txtest.NewTransactionContextGenerator(nil).ThatDoesntExpectCommit() 1420 return mockedTx, transactioner 1421 }, 1422 fixTestSystems: func() []systemfetcher.System { 1423 return []systemfetcher.System{} 1424 }, 1425 fixAppInputs: func(systems []systemfetcher.System) []model.ApplicationRegisterInputWithTemplate { 1426 return []model.ApplicationRegisterInputWithTemplate{} 1427 }, 1428 setupTenantSvc: func() *automock.TenantService { 1429 return &automock.TenantService{} 1430 }, 1431 setupTbtSvc: func() *automock.TenantBusinessTypeService { 1432 return &automock.TenantBusinessTypeService{} 1433 }, 1434 setupTemplateRendererSvc: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInput) *automock.TemplateRenderer { 1435 return &automock.TemplateRenderer{} 1436 }, 1437 setupSystemSvc: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.SystemsService { 1438 return &automock.SystemsService{} 1439 }, 1440 setupSystemsSyncSvc: func() *automock.SystemsSyncService { 1441 syncMock := &automock.SystemsSyncService{} 1442 syncMock.On("Upsert", mock.Anything, mock.Anything).Return(testError) 1443 return syncMock 1444 }, 1445 setupSysAPIClient: func(testSystems []systemfetcher.System) *automock.SystemsAPIClient { 1446 return &automock.SystemsAPIClient{} 1447 }, 1448 setupDirectorClient: func(systems []systemfetcher.System, appsInputs []model.ApplicationRegisterInputWithTemplate) *automock.DirectorClient { 1449 return &automock.DirectorClient{} 1450 }, 1451 expectedErr: testError, 1452 }, 1453 } 1454 1455 for _, testCase := range tests { 1456 t.Run(testCase.name, func(t *testing.T) { 1457 mockedTx, transactioner := testCase.mockTransactioner() 1458 tenantSvc := testCase.setupTenantSvc() 1459 tbtSvc := testCase.setupTbtSvc() 1460 testSystems := testCase.fixTestSystems() 1461 appsInputs := testCase.fixAppInputs(testSystems) 1462 systemSvc := testCase.setupSystemSvc(testSystems, appsInputs) 1463 systemsSyncSvc := testCase.setupSystemsSyncSvc() 1464 appInputsWithoutTemplates := make([]model.ApplicationRegisterInput, 0) 1465 for _, in := range appsInputs { 1466 appInputsWithoutTemplates = append(appInputsWithoutTemplates, in.ApplicationRegisterInput) 1467 } 1468 templateAppResolver := testCase.setupTemplateRendererSvc(testSystems, appInputsWithoutTemplates) 1469 sysAPIClient := testCase.setupSysAPIClient(testSystems) 1470 directorClient := testCase.setupDirectorClient(testSystems, appsInputs) 1471 defer mock.AssertExpectationsForObjects(t, tenantSvc, sysAPIClient, systemSvc, templateAppResolver, mockedTx, transactioner) 1472 1473 svc := systemfetcher.NewSystemFetcher(transactioner, tenantSvc, systemSvc, systemsSyncSvc, tbtSvc, templateAppResolver, sysAPIClient, directorClient, systemfetcher.Config{ 1474 SystemsQueueSize: 100, 1475 FetcherParallellism: 30, 1476 EnableSystemDeletion: true, 1477 VerifyTenant: testCase.verificationTenant, 1478 }) 1479 1480 err := svc.UpsertSystemsSyncTimestamps(context.TODO(), transactioner) 1481 if testCase.expectedErr != nil { 1482 require.ErrorIs(t, err, testCase.expectedErr) 1483 } else { 1484 require.NoError(t, err) 1485 } 1486 }) 1487 } 1488 1489 systemfetcher.SystemSynchronizationTimestamps = nil 1490 } 1491 1492 func fixAppsInputsWithTemplatesBySystems(t *testing.T, systems []systemfetcher.System) []model.ApplicationRegisterInputWithTemplate { 1493 initStatusCond := model.ApplicationStatusConditionInitial 1494 result := make([]model.ApplicationRegisterInputWithTemplate, 0, len(systems)) 1495 for _, s := range systems { 1496 systemPayload, err := json.Marshal(s.SystemPayload) 1497 require.NoError(t, err) 1498 input := model.ApplicationRegisterInputWithTemplate{ 1499 ApplicationRegisterInput: model.ApplicationRegisterInput{ 1500 Name: gjson.GetBytes(systemPayload, "displayName").String(), 1501 Description: str.Ptr(gjson.GetBytes(systemPayload, "productDescription").String()), 1502 BaseURL: str.Ptr(gjson.GetBytes(systemPayload, "additionalUrls"+"."+mainURLKey).String()), 1503 ProviderName: str.Ptr(gjson.GetBytes(systemPayload, "infrastructureProvider").String()), 1504 SystemNumber: str.Ptr(gjson.GetBytes(systemPayload, "systemNumber").String()), 1505 StatusCondition: &initStatusCond, 1506 Labels: map[string]interface{}{ 1507 "managed": "true", 1508 "productId": str.Ptr(gjson.GetBytes(systemPayload, "productId").String()), 1509 "ppmsProductVersionId": str.Ptr(gjson.GetBytes(systemPayload, "ppmsProductVersionId").String()), 1510 }, 1511 }, 1512 TemplateID: s.TemplateID, 1513 } 1514 if len(input.TemplateID) > 0 { 1515 input.Labels["applicationType"] = appType 1516 } 1517 result = append(result, input) 1518 } 1519 return result 1520 } 1521 1522 func emptySystemsSyncSvc() *automock.SystemsSyncService { 1523 return &automock.SystemsSyncService{} 1524 }