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

Fix assign formation not found errors #3804

Merged
merged 4 commits into from
Apr 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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)
ivantenevvasilev marked this conversation as resolved.
Show resolved Hide resolved
}
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