github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/internal/domain/formationconstraint/service.go (about) 1 package formationconstraint 2 3 import ( 4 "context" 5 6 "github.com/kyma-incubator/compass/components/director/internal/model" 7 "github.com/kyma-incubator/compass/components/director/pkg/formationconstraint" 8 "github.com/kyma-incubator/compass/components/director/pkg/log" 9 "github.com/pkg/errors" 10 ) 11 12 //go:generate mockery --exported --name=formationConstraintRepository --output=automock --outpkg=automock --case=underscore --disable-version-string 13 type formationConstraintRepository interface { 14 Create(ctx context.Context, item *model.FormationConstraint) error 15 Get(ctx context.Context, id string) (*model.FormationConstraint, error) 16 ListAll(ctx context.Context) ([]*model.FormationConstraint, error) 17 ListByIDs(ctx context.Context, formationConstraintIDs []string) ([]*model.FormationConstraint, error) 18 Delete(ctx context.Context, id string) error 19 Update(ctx context.Context, model *model.FormationConstraint) error 20 ListMatchingFormationConstraints(ctx context.Context, formationConstraintIDs []string, location formationconstraint.JoinPointLocation, details formationconstraint.MatchingDetails) ([]*model.FormationConstraint, error) 21 ListByIDsAndGlobal(ctx context.Context, formationConstraintIDs []string) ([]*model.FormationConstraint, error) 22 } 23 24 //go:generate mockery --exported --name=formationTemplateConstraintReferenceRepository --output=automock --outpkg=automock --case=underscore --disable-version-string 25 type formationTemplateConstraintReferenceRepository interface { 26 ListByFormationTemplateID(ctx context.Context, formationTemplateID string) ([]*model.FormationTemplateConstraintReference, error) 27 ListByFormationTemplateIDs(ctx context.Context, formationTemplateIDs []string) ([]*model.FormationTemplateConstraintReference, error) 28 } 29 30 //go:generate mockery --exported --name=uidService --output=automock --outpkg=automock --case=underscore --disable-version-string 31 type uidService interface { 32 Generate() string 33 } 34 35 type service struct { 36 repo formationConstraintRepository 37 formationTemplateConstraintReferenceRepo formationTemplateConstraintReferenceRepository 38 converter formationConstraintConverter 39 uidSvc uidService 40 } 41 42 // NewService creates a FormationConstraint service 43 func NewService(repo formationConstraintRepository, formationTemplateConstraintReferenceRepo formationTemplateConstraintReferenceRepository, uidSvc uidService, converter formationConstraintConverter) *service { 44 return &service{ 45 repo: repo, 46 formationTemplateConstraintReferenceRepo: formationTemplateConstraintReferenceRepo, 47 uidSvc: uidSvc, 48 converter: converter, 49 } 50 } 51 52 // Create creates formation constraint using the provided input 53 func (s *service) Create(ctx context.Context, in *model.FormationConstraintInput) (string, error) { 54 formationConstraintID := s.uidSvc.Generate() 55 56 log.C(ctx).Debugf("ID %s generated for Formation Constraint with name %s", formationConstraintID, in.Name) 57 58 err := s.repo.Create(ctx, s.converter.FromModelInputToModel(in, formationConstraintID)) 59 if err != nil { 60 return "", errors.Wrapf(err, "while creating Formation Constraint with name %s", in.Name) 61 } 62 63 return formationConstraintID, nil 64 } 65 66 // Get fetches formation constraint by id 67 func (s *service) Get(ctx context.Context, id string) (*model.FormationConstraint, error) { 68 formationConstraint, err := s.repo.Get(ctx, id) 69 if err != nil { 70 return nil, errors.Wrapf(err, "while getting Formation Constraint with id %s", id) 71 } 72 73 return formationConstraint, nil 74 } 75 76 // List lists all formation constraints 77 func (s *service) List(ctx context.Context) ([]*model.FormationConstraint, error) { 78 formationConstraints, err := s.repo.ListAll(ctx) 79 if err != nil { 80 return nil, errors.Wrapf(err, "while listing all Formation Constraints") 81 } 82 return formationConstraints, nil 83 } 84 85 // ListByFormationTemplateID lists all formation constraints associated with the formation template 86 func (s *service) ListByFormationTemplateID(ctx context.Context, formationTemplateID string) ([]*model.FormationConstraint, error) { 87 constraintReferences, err := s.formationTemplateConstraintReferenceRepo.ListByFormationTemplateID(ctx, formationTemplateID) 88 if err != nil { 89 return nil, errors.Wrapf(err, "while listing Formation Constraint References for FormationTemplate with ID: %s", formationTemplateID) 90 } 91 92 formationConstraintIDs := make([]string, 0, len(constraintReferences)) 93 for _, cr := range constraintReferences { 94 formationConstraintIDs = append(formationConstraintIDs, cr.ConstraintID) 95 } 96 97 formationConstraints, err := s.repo.ListByIDs(ctx, formationConstraintIDs) 98 if err != nil { 99 return nil, errors.Wrapf(err, "while listing Formation Constraints for FormationTemplate with ID: %s", formationTemplateID) 100 } 101 return formationConstraints, nil 102 } 103 104 // ListByFormationTemplateIDs lists all formation constraints associated with the formation templates 105 func (s *service) ListByFormationTemplateIDs(ctx context.Context, formationTemplateIDs []string) ([][]*model.FormationConstraint, error) { 106 constraintRefs, err := s.formationTemplateConstraintReferenceRepo.ListByFormationTemplateIDs(ctx, formationTemplateIDs) 107 if err != nil { 108 return nil, errors.Wrapf(err, "while listing Formation Constraint References for FormationTemplates with IDs: %q", formationTemplateIDs) 109 } 110 111 constraintIDs := make([]string, 0, len(constraintRefs)) 112 formationTemplateIDToConstraintIDsMap := make(map[string][]string, len(constraintRefs)) 113 114 for _, cr := range constraintRefs { 115 constraintIDs = append(constraintIDs, cr.ConstraintID) 116 117 formationTemplateIDToConstraintIDsMap[cr.FormationTemplateID] = append(formationTemplateIDToConstraintIDsMap[cr.FormationTemplateID], cr.ConstraintID) 118 } 119 120 formationConstraints, err := s.repo.ListByIDsAndGlobal(ctx, constraintIDs) 121 if err != nil { 122 return nil, errors.Wrapf(err, "while listing Formation Constraints by IDs %q and the global ones", formationTemplateIDs) 123 } 124 125 globalConstraints := make([]*model.FormationConstraint, 0, len(formationConstraints)) 126 attachedConstraintsMap := make(map[string]*model.FormationConstraint, len(formationConstraints)) 127 128 for _, constraint := range formationConstraints { 129 if constraint.ConstraintScope == model.GlobalFormationConstraintScope { 130 globalConstraints = append(globalConstraints, constraint) 131 } else { 132 attachedConstraintsMap[constraint.ID] = constraint 133 } 134 } 135 136 formationConstraintsPerFormationTemplate := make([][]*model.FormationConstraint, len(formationTemplateIDs)) 137 138 for i, ftID := range formationTemplateIDs { 139 // Add attached constraints 140 constraintIDsPerFT := formationTemplateIDToConstraintIDsMap[ftID] 141 for _, constraintID := range constraintIDsPerFT { 142 formationConstraintsPerFormationTemplate[i] = append(formationConstraintsPerFormationTemplate[i], attachedConstraintsMap[constraintID]) 143 } 144 145 // Add global constraints 146 formationConstraintsPerFormationTemplate[i] = append(formationConstraintsPerFormationTemplate[i], globalConstraints...) 147 } 148 149 return formationConstraintsPerFormationTemplate, nil 150 } 151 152 // Delete deletes formation constraint by id 153 func (s *service) Delete(ctx context.Context, id string) error { 154 if err := s.repo.Delete(ctx, id); err != nil { 155 return errors.Wrapf(err, "while deleting Formation Constraint with ID %s", id) 156 } 157 158 return nil 159 } 160 161 // ListMatchingConstraints lists formation constraints that math the provided JoinPointLocation and JoinPointDetails 162 func (s *service) ListMatchingConstraints(ctx context.Context, formationTemplateID string, location formationconstraint.JoinPointLocation, details formationconstraint.MatchingDetails) ([]*model.FormationConstraint, error) { 163 formationTemplateConstraintReferences, err := s.formationTemplateConstraintReferenceRepo.ListByFormationTemplateID(ctx, formationTemplateID) 164 if err != nil { 165 return nil, err 166 } 167 168 constraintIDs := make([]string, 0, len(formationTemplateConstraintReferences)) 169 for _, reference := range formationTemplateConstraintReferences { 170 constraintIDs = append(constraintIDs, reference.ConstraintID) 171 } 172 173 constraints, err := s.repo.ListMatchingFormationConstraints(ctx, constraintIDs, location, details) 174 if err != nil { 175 return nil, errors.Wrapf(err, "while listing matching formation constraints for formation template with ID %q, target operation %q, constraint type %q, resource type %q and resource subtype %q", formationTemplateID, location.OperationName, location.ConstraintType, details.ResourceType, details.ResourceSubtype) 176 } 177 178 return constraints, nil 179 } 180 181 // Update updates a FormationConstraint matching ID `id` using `in` 182 func (s *service) Update(ctx context.Context, id string, in *model.FormationConstraintInput) error { 183 err := s.repo.Update(ctx, s.converter.FromModelInputToModel(in, id)) 184 if err != nil { 185 return errors.Wrapf(err, "while updating Formation Constraint with ID %s", id) 186 } 187 188 return nil 189 }