Skip to content
This repository has been archived by the owner on Jul 4, 2024. It is now read-only.

Commit

Permalink
Fix assign formation not found errors (#3804)
Browse files Browse the repository at this point in the history
* Initial implementation and unit tests.

* Update values.yaml

* Add missing unti test.
  • Loading branch information
la4ezar authored Apr 11, 2024
1 parent dbb628e commit 81606c1
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 12 deletions.
2 changes: 1 addition & 1 deletion chart/compass/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ global:
name: compass-pairing-adapter
director:
dir: dev/incubator/
version: "PR-3802"
version: "PR-3804"
name: compass-director
hydrator:
dir: dev/incubator/
Expand Down
112 changes: 110 additions & 2 deletions components/director/internal/domain/formation/assign_formation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,8 @@ func TestServiceAssignFormation(t *testing.T) {
TargetTenantID: TargetTenant,
}

runtime := &model.Runtime{ID: RuntimeID}

testCases := []struct {
Name string
TxFn func() (*persistenceautomock.PersistenceTx, *persistenceautomock.Transactioner)
Expand All @@ -251,6 +253,7 @@ func TestServiceAssignFormation(t *testing.T) {
AsaRepoFn func() *automock.AutomaticFormationAssignmentRepository
AsaServiceFN func() *automock.AutomaticFormationAssignmentService
RuntimeContextRepoFn func() *automock.RuntimeContextRepository
RuntimeRepoFn func() *automock.RuntimeRepository
FormationRepositoryFn func() *automock.FormationRepository
NotificationServiceFN func() *automock.NotificationsService
FormationTemplateRepositoryFn func() *automock.FormationTemplateRepository
Expand Down Expand Up @@ -503,6 +506,11 @@ func TestServiceAssignFormation(t *testing.T) {
repo.On("Get", ctx, FormationTemplateID).Return(expectedFormationTemplate, nil).Once()
return repo
},
RuntimeRepoFn: func() *automock.RuntimeRepository {
runtimeRepo := &automock.RuntimeRepository{}
runtimeRepo.On("GetByID", ctx, TntInternalID, RuntimeID).Return(runtime, nil).Once()
return runtimeRepo
},
NotificationServiceFN: func() *automock.NotificationsService {
notificationSvc := &automock.NotificationsService{}
notificationSvc.On("GenerateFormationAssignmentNotifications", ctx, TntInternalID, RuntimeID, expectedFormation, model.AssignFormation, graphql.FormationObjectTypeRuntime).Return(notifications, nil).Once()
Expand Down Expand Up @@ -546,6 +554,11 @@ func TestServiceAssignFormation(t *testing.T) {
repo.On("Get", ctx, FormationTemplateID).Return(expectedFormationTemplate, nil).Once()
return repo
},
RuntimeRepoFn: func() *automock.RuntimeRepository {
runtimeRepo := &automock.RuntimeRepository{}
runtimeRepo.On("GetByID", ctx, TntInternalID, RuntimeID).Return(runtime, nil).Once()
return runtimeRepo
},
NotificationServiceFN: func() *automock.NotificationsService {
notificationSvc := &automock.NotificationsService{}
notificationSvc.On("GenerateFormationAssignmentNotifications", ctx, TntInternalID, RuntimeID, expectedFormation, model.AssignFormation, graphql.FormationObjectTypeRuntime).Return(notifications, nil).Once()
Expand Down Expand Up @@ -596,6 +609,11 @@ func TestServiceAssignFormation(t *testing.T) {
notificationSvc.On("GenerateFormationAssignmentNotifications", ctx, TntInternalID, RuntimeID, expectedSecondFormation, model.AssignFormation, graphql.FormationObjectTypeRuntime).Return(notifications, nil).Once()
return notificationSvc
},
RuntimeRepoFn: func() *automock.RuntimeRepository {
runtimeRepo := &automock.RuntimeRepository{}
runtimeRepo.On("GetByID", ctx, TntInternalID, RuntimeID).Return(runtime, nil).Once()
return runtimeRepo
},
FormationAssignmentServiceFn: func() *automock.FormationAssignmentService {
formationAssignmentSvc := &automock.FormationAssignmentService{}
formationAssignmentSvc.On("GenerateAssignments", ctx, TntInternalID, RuntimeID, graphql.FormationObjectTypeRuntime, expectedSecondFormation).Return(formationAssignmentInputs, nil).Once()
Expand Down Expand Up @@ -969,6 +987,7 @@ func TestServiceAssignFormation(t *testing.T) {
repo := &automock.ApplicationRepository{}
repo.On("GetByID", mock.Anything, TntInternalID, ApplicationID).Return(&model.Application{
BaseEntity: &model.BaseEntity{
ID: ApplicationID,
Ready: false,
},
}, nil).Once()
Expand Down Expand Up @@ -1006,6 +1025,7 @@ func TestServiceAssignFormation(t *testing.T) {
repo := &automock.ApplicationRepository{}
repo.On("GetByID", mock.Anything, TntInternalID, ApplicationID).Return(&model.Application{
BaseEntity: &model.BaseEntity{
ID: ApplicationID,
DeletedAt: &time.Time{},
Ready: true,
},
Expand Down Expand Up @@ -1126,6 +1146,7 @@ func TestServiceAssignFormation(t *testing.T) {
labelService.On("GetLabel", ctx, TntInternalID, &applicationTypeLblInput).Return(emptyApplicationType, nil).Once()
return labelService
},
ApplicationRepoFn: expectEmptySliceApplicationAndReadyApplicationRepo,
FormationRepositoryFn: func() *automock.FormationRepository {
formationRepo := &automock.FormationRepository{}
formationRepo.On("GetByName", ctx, testFormationName, TntInternalID).Return(expectedSecondFormation, nil).Once()
Expand Down Expand Up @@ -1164,6 +1185,11 @@ func TestServiceAssignFormation(t *testing.T) {
labelService.On("GetLabel", ctx, TntInternalID, &applicationTypeLblInput).Return(emptyApplicationType, nil).Once()
return labelService
},
ApplicationRepoFn: func() *automock.ApplicationRepository {
repo := &automock.ApplicationRepository{}
repo.On("GetByID", mock.Anything, TntInternalID, ApplicationID).Return(existingApp, nil).Once()
return repo
},
FormationRepositoryFn: func() *automock.FormationRepository {
formationRepo := &automock.FormationRepository{}
formationRepo.On("GetByName", ctx, testFormationName, TntInternalID).Return(expectedSecondFormation, nil).Once()
Expand Down Expand Up @@ -1193,6 +1219,11 @@ func TestServiceAssignFormation(t *testing.T) {
labelService.On("GetLabel", ctx, TntInternalID, &applicationTypeLblInput).Return(nil, testErr).Once()
return labelService
},
ApplicationRepoFn: func() *automock.ApplicationRepository {
repo := &automock.ApplicationRepository{}
repo.On("GetByID", mock.Anything, TntInternalID, ApplicationID).Return(existingApp, nil).Once()
return repo
},
FormationRepositoryFn: func() *automock.FormationRepository {
formationRepo := &automock.FormationRepository{}
formationRepo.On("GetByName", ctx, testFormationName, TntInternalID).Return(expectedSecondFormation, nil).Once()
Expand Down Expand Up @@ -1244,6 +1275,39 @@ func TestServiceAssignFormation(t *testing.T) {
InputFormation: inputFormation,
ExpectedErrMessage: testErr.Error(),
},
{
Name: "error for runtime when runtime does not exist",
TxFn: txGen.ThatDoesntExpectCommit,
RuntimeRepoFn: func() *automock.RuntimeRepository {
repo := &automock.RuntimeRepository{}
repo.On("GetByID", ctx, TntInternalID, RuntimeID).Return(nil, testErr).Once()
return repo
},
FormationRepositoryFn: func() *automock.FormationRepository {
formationRepo := &automock.FormationRepository{}
formationRepo.On("GetByName", ctx, testFormationName, TntInternalID).Return(expectedFormation, nil).Once()
return formationRepo
},
FormationTemplateRepositoryFn: func() *automock.FormationTemplateRepository {
repo := &automock.FormationTemplateRepository{}
repo.On("Get", ctx, FormationTemplateID).Return(expectedFormationTemplate, nil).Once()
return repo
},
LabelServiceFn: func() *automock.LabelService {
labelService := &automock.LabelService{}
labelService.On("GetLabel", ctx, TntInternalID, &runtimeTypeLblInput).Return(runtimeTypeLbl, nil).Once()
return labelService
},
ConstraintEngineFn: func() *automock.ConstraintEngine {
engine := &automock.ConstraintEngine{}
engine.On("EnforceConstraints", ctx, preAssignLocation, fixAssignRuntimeDetails(testFormationName), FormationTemplateID).Return(nil).Once()
return engine
},
ObjectType: graphql.FormationObjectTypeRuntime,
ObjectID: RuntimeID,
InputFormation: inputFormation,
ExpectedErrMessage: testErr.Error(),
},
{
Name: "error for runtime when label does not exist and can't create it",
TxFn: txGen.ThatDoesntExpectCommit,
Expand All @@ -1252,6 +1316,11 @@ func TestServiceAssignFormation(t *testing.T) {
uidService.On("Generate").Return(fixUUID()).Once()
return uidService
},
RuntimeRepoFn: func() *automock.RuntimeRepository {
repo := &automock.RuntimeRepository{}
repo.On("GetByID", ctx, TntInternalID, RuntimeID).Return(runtime, nil).Once()
return repo
},
FormationRepositoryFn: func() *automock.FormationRepository {
formationRepo := &automock.FormationRepository{}
formationRepo.On("GetByName", ctx, testFormationName, TntInternalID).Return(expectedFormation, nil).Once()
Expand Down Expand Up @@ -1288,6 +1357,11 @@ func TestServiceAssignFormation(t *testing.T) {
labelService.On("GetLabel", ctx, TntInternalID, &runtimeLblInput).Return(nil, testErr).Once()
return labelService
},
RuntimeRepoFn: func() *automock.RuntimeRepository {
repo := &automock.RuntimeRepository{}
repo.On("GetByID", ctx, TntInternalID, RuntimeID).Return(runtime, nil).Once()
return repo
},
FormationTemplateRepositoryFn: func() *automock.FormationTemplateRepository {
repo := &automock.FormationTemplateRepository{}
repo.On("Get", ctx, FormationTemplateID).Return(expectedFormationTemplate, nil).Once()
Expand Down Expand Up @@ -1331,6 +1405,11 @@ func TestServiceAssignFormation(t *testing.T) {
}, nil).Once()
return labelService
},
RuntimeRepoFn: func() *automock.RuntimeRepository {
repo := &automock.RuntimeRepository{}
repo.On("GetByID", ctx, TntInternalID, RuntimeID).Return(runtime, nil).Once()
return repo
},
FormationTemplateRepositoryFn: func() *automock.FormationTemplateRepository {
repo := &automock.FormationTemplateRepository{}
repo.On("Get", ctx, FormationTemplateID).Return(expectedFormationTemplate, nil).Once()
Expand Down Expand Up @@ -1368,6 +1447,11 @@ func TestServiceAssignFormation(t *testing.T) {
}, nil).Once()
return labelService
},
RuntimeRepoFn: func() *automock.RuntimeRepository {
repo := &automock.RuntimeRepository{}
repo.On("GetByID", ctx, TntInternalID, RuntimeID).Return(runtime, nil).Once()
return repo
},
FormationTemplateRepositoryFn: func() *automock.FormationTemplateRepository {
repo := &automock.FormationTemplateRepository{}
repo.On("Get", ctx, FormationTemplateID).Return(expectedFormationTemplate, nil).Once()
Expand Down Expand Up @@ -1398,6 +1482,11 @@ func TestServiceAssignFormation(t *testing.T) {
labelService.On("UpdateLabel", ctx, TntInternalID, runtimeLbl.ID, &runtimeLblInput).Return(testErr).Once()
return labelService
},
RuntimeRepoFn: func() *automock.RuntimeRepository {
repo := &automock.RuntimeRepository{}
repo.On("GetByID", ctx, TntInternalID, RuntimeID).Return(runtime, nil).Once()
return repo
},
FormationTemplateRepositoryFn: func() *automock.FormationTemplateRepository {
repo := &automock.FormationTemplateRepository{}
repo.On("Get", ctx, FormationTemplateID).Return(expectedFormationTemplate, nil).Once()
Expand Down Expand Up @@ -1547,6 +1636,11 @@ func TestServiceAssignFormation(t *testing.T) {
labelService.On("GetLabel", ctx, TntInternalID, &runtimeTypeLblInput).Return(runtimeTypeLbl, nil).Once()
return labelService
},
RuntimeRepoFn: func() *automock.RuntimeRepository {
repo := &automock.RuntimeRepository{}
repo.On("GetByID", ctx, TntInternalID, RuntimeID).Return(runtime, nil).Once()
return repo
},
FormationRepositoryFn: func() *automock.FormationRepository {
formationRepo := &automock.FormationRepository{}
formationRepo.On("GetByName", ctx, testFormationName, TntInternalID).Return(expectedFormation, nil).Once()
Expand Down Expand Up @@ -1590,6 +1684,11 @@ func TestServiceAssignFormation(t *testing.T) {
labelService.On("GetLabel", ctx, TntInternalID, &runtimeTypeLblInput).Return(emptyRuntimeType, nil).Once()
return labelService
},
RuntimeRepoFn: func() *automock.RuntimeRepository {
repo := &automock.RuntimeRepository{}
repo.On("GetByID", ctx, TntInternalID, RuntimeID).Return(runtime, nil).Once()
return repo
},
FormationRepositoryFn: func() *automock.FormationRepository {
formationRepo := &automock.FormationRepository{}
formationRepo.On("GetByName", ctx, testFormationName, TntInternalID).Return(expectedFormation, nil).Once()
Expand Down Expand Up @@ -1619,6 +1718,11 @@ func TestServiceAssignFormation(t *testing.T) {
labelService.On("GetLabel", ctx, TntInternalID, &runtimeTypeLblInput).Return(nil, testErr).Once()
return labelService
},
RuntimeRepoFn: func() *automock.RuntimeRepository {
repo := &automock.RuntimeRepository{}
repo.On("GetByID", ctx, TntInternalID, RuntimeID).Return(runtime, nil).Once()
return repo
},
FormationRepositoryFn: func() *automock.FormationRepository {
formationRepo := &automock.FormationRepository{}
formationRepo.On("GetByName", ctx, testFormationName, TntInternalID).Return(expectedFormation, nil).Once()
Expand Down Expand Up @@ -2729,6 +2833,10 @@ func TestServiceAssignFormation(t *testing.T) {
if testCase.RuntimeContextRepoFn != nil {
runtimeContextRepo = testCase.RuntimeContextRepoFn()
}
runtimeRepo := unusedRuntimeRepo()
if testCase.RuntimeRepoFn != nil {
runtimeRepo = testCase.RuntimeRepoFn()
}
formationRepo := unusedFormationRepo()
if testCase.FormationRepositoryFn != nil {
formationRepo = testCase.FormationRepositoryFn()
Expand Down Expand Up @@ -2756,7 +2864,7 @@ func TestServiceAssignFormation(t *testing.T) {
asaEngine = testCase.ASAEngineFn()
}

svc := formation.NewServiceWithAsaEngine(transact, applicationRepository, nil, nil, formationRepo, formationTemplateRepo, labelService, uidService, labelDefService, asaRepo, asaService, tenantSvc, nil, runtimeContextRepo, formationAssignmentSvc, nil, nil, notificationSvc, constraintEngine, runtimeType, applicationType, asaEngine, nil)
svc := formation.NewServiceWithAsaEngine(transact, applicationRepository, nil, nil, formationRepo, formationTemplateRepo, labelService, uidService, labelDefService, asaRepo, asaService, tenantSvc, runtimeRepo, runtimeContextRepo, formationAssignmentSvc, nil, nil, notificationSvc, constraintEngine, runtimeType, applicationType, asaEngine, nil)

// WHEN
actual, err := svc.AssignFormation(ctx, TntInternalID, testCase.ObjectID, testCase.ObjectType, testCase.InputFormation)
Expand All @@ -2771,7 +2879,7 @@ func TestServiceAssignFormation(t *testing.T) {
require.Nil(t, actual)
}

mock.AssertExpectationsForObjects(t, persist, uidService, applicationRepository, labelService, asaRepo, asaService, tenantSvc, labelDefService, runtimeContextRepo, formationRepo, formationTemplateRepo, webhookClient, notificationSvc, formationAssignmentSvc, constraintEngine, asaEngine)
mock.AssertExpectationsForObjects(t, persist, uidService, applicationRepository, labelService, asaRepo, asaService, tenantSvc, labelDefService, runtimeContextRepo, runtimeRepo, formationRepo, formationTemplateRepo, webhookClient, notificationSvc, formationAssignmentSvc, constraintEngine, asaEngine)
})
}
}
20 changes: 11 additions & 9 deletions components/director/internal/domain/formation/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -808,13 +808,20 @@ func (s *service) UnassignFromScenarioLabel(ctx context.Context, tnt, objectID s
func (s *service) checkFormationTemplateTypes(ctx context.Context, tnt, objectID string, objectType graphql.FormationObjectType, formationTemplate *model.FormationTemplate) error {
switch objectType {
case graphql.FormationObjectTypeApplication:
app, err := s.applicationRepository.GetByID(ctx, tnt, objectID)
if err != nil {
return errors.Wrapf(err, "while getting application with ID: %q", objectID)
}
if err := s.isValidApplicationType(ctx, tnt, objectID, formationTemplate); err != nil {
return errors.Wrapf(err, "while validating application type for application %q", objectID)
}
if err := s.isValidApplication(ctx, tnt, objectID); err != nil {
if err := s.isValidApplication(app); err != nil {
return errors.Wrapf(err, "while validating application with ID: %q", objectID)
}
case graphql.FormationObjectTypeRuntime:
if _, err := s.runtimeRepo.GetByID(ctx, tnt, objectID); err != nil {
return errors.Wrapf(err, "while getting runtime with ID: %q", objectID)
}
if err := s.isValidRuntimeType(ctx, tnt, objectID, formationTemplate); err != nil {
return errors.Wrapf(err, "while validating runtime type")
}
Expand Down Expand Up @@ -1820,17 +1827,12 @@ func (s *service) isValidRuntimeType(ctx context.Context, tnt string, runtimeID
return nil
}

func (s *service) isValidApplication(ctx context.Context, tnt string, applicationID string) error {
application, err := s.applicationRepository.GetByID(ctx, tnt, applicationID)
if err != nil {
return errors.Wrapf(err, "while getting application with ID %q", applicationID)
}

func (s *service) isValidApplication(application *model.Application) error {
if application.DeletedAt != nil {
return apperrors.NewInvalidOperationError(fmt.Sprintf("application with ID %q is currently being deleted", applicationID))
return apperrors.NewInvalidOperationError(fmt.Sprintf("application with ID %q is currently being deleted", application.ID))
}
if !application.Ready {
return apperrors.NewInvalidOperationError(fmt.Sprintf("application with ID %q is not ready", applicationID))
return apperrors.NewInvalidOperationError(fmt.Sprintf("application with ID %q is not ready", application.ID))
}
return nil
}
Expand Down

0 comments on commit 81606c1

Please sign in to comment.