github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/internal/domain/formationconstraint/repository.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/internal/repo"
     8  	"github.com/kyma-incubator/compass/components/director/pkg/apperrors"
     9  	"github.com/kyma-incubator/compass/components/director/pkg/formationconstraint"
    10  	"github.com/kyma-incubator/compass/components/director/pkg/log"
    11  	"github.com/kyma-incubator/compass/components/director/pkg/resource"
    12  	"github.com/pkg/errors"
    13  )
    14  
    15  const (
    16  	tableName          string = `public.formation_constraints`
    17  	idColumn           string = "id"
    18  	resourceSubtypeANY string = "ANY"
    19  )
    20  
    21  var (
    22  	tableColumns     = []string{"id", "name", "constraint_type", "target_operation", "operator", "resource_type", "resource_subtype", "input_template", "constraint_scope"}
    23  	updatableColumns = []string{"input_template"}
    24  	idColumns        = []string{"id"}
    25  )
    26  
    27  // EntityConverter converts between the internal model and entity
    28  //
    29  //go:generate mockery --name=EntityConverter --output=automock --outpkg=automock --case=underscore --disable-version-string
    30  type EntityConverter interface {
    31  	ToEntity(in *model.FormationConstraint) *Entity
    32  	FromEntity(entity *Entity) *model.FormationConstraint
    33  }
    34  
    35  type repository struct {
    36  	conditionTreeLister repo.ConditionTreeListerGlobal
    37  	lister              repo.ListerGlobal
    38  	creator             repo.CreatorGlobal
    39  	singleGetter        repo.SingleGetterGlobal
    40  	deleter             repo.DeleterGlobal
    41  	updater             repo.UpdaterGlobal
    42  	conv                EntityConverter
    43  }
    44  
    45  // NewRepository creates a new FormationConstraint repository
    46  func NewRepository(conv EntityConverter) *repository {
    47  	return &repository{
    48  		conditionTreeLister: repo.NewConditionTreeListerGlobal(tableName, tableColumns),
    49  		lister:              repo.NewListerGlobal(resource.FormationConstraint, tableName, tableColumns),
    50  		creator:             repo.NewCreatorGlobal(resource.FormationConstraint, tableName, tableColumns),
    51  		singleGetter:        repo.NewSingleGetterGlobal(resource.FormationConstraint, tableName, tableColumns),
    52  		deleter:             repo.NewDeleterGlobal(resource.FormationConstraint, tableName),
    53  		updater:             repo.NewUpdaterGlobal(resource.FormationConstraint, tableName, updatableColumns, idColumns),
    54  		conv:                conv,
    55  	}
    56  }
    57  
    58  // Create stores new record in the database
    59  func (r *repository) Create(ctx context.Context, item *model.FormationConstraint) error {
    60  	if item == nil {
    61  		return apperrors.NewInternalError("model can not be empty")
    62  	}
    63  
    64  	log.C(ctx).Debugf("Converting Formation Constraint with id %s to entity", item.ID)
    65  	entity := r.conv.ToEntity(item)
    66  
    67  	log.C(ctx).Debugf("Persisting Formation Constraint entity with id %s to db", item.ID)
    68  	return r.creator.Create(ctx, entity)
    69  }
    70  
    71  // Get fetches the formation constraint from the db by the provided id
    72  func (r *repository) Get(ctx context.Context, id string) (*model.FormationConstraint, error) {
    73  	var entity Entity
    74  	if err := r.singleGetter.GetGlobal(ctx, repo.Conditions{repo.NewEqualCondition("id", id)}, repo.NoOrderBy, &entity); err != nil {
    75  		return nil, err
    76  	}
    77  
    78  	result := r.conv.FromEntity(&entity)
    79  
    80  	return result, nil
    81  }
    82  
    83  // ListAll lists all formation constraints
    84  func (r *repository) ListAll(ctx context.Context) ([]*model.FormationConstraint, error) {
    85  	var entities EntityCollection
    86  
    87  	if err := r.lister.ListGlobal(ctx, &entities); err != nil {
    88  		return nil, err
    89  	}
    90  
    91  	return r.multipleFromEntities(entities)
    92  }
    93  
    94  // ListByIDs lists all formation constraints whose id is in formationConstraintIDs
    95  func (r *repository) ListByIDs(ctx context.Context, formationConstraintIDs []string) ([]*model.FormationConstraint, error) {
    96  	if len(formationConstraintIDs) == 0 {
    97  		return nil, nil
    98  	}
    99  
   100  	var entities EntityCollection
   101  
   102  	if err := r.lister.ListGlobal(ctx, &entities, repo.NewInConditionForStringValues(idColumn, formationConstraintIDs)); err != nil {
   103  		return nil, err
   104  	}
   105  
   106  	return r.multipleFromEntities(entities)
   107  }
   108  
   109  // Delete deletes formation constraint from the database by id
   110  func (r *repository) Delete(ctx context.Context, id string) error {
   111  	return r.deleter.DeleteOneGlobal(ctx, repo.Conditions{repo.NewEqualCondition(idColumn, id)})
   112  }
   113  
   114  // ListMatchingFormationConstraints lists formationConstraints whose ID can be found in formationConstraintIDs or have constraint scope "global" that match on the join point location and matching details
   115  func (r *repository) ListMatchingFormationConstraints(ctx context.Context, formationConstraintIDs []string, location formationconstraint.JoinPointLocation, details formationconstraint.MatchingDetails) ([]*model.FormationConstraint, error) {
   116  	var entityCollection EntityCollection
   117  
   118  	formationTypeRelevanceConditions := []repo.Condition{
   119  		repo.NewEqualCondition("constraint_scope", model.GlobalFormationConstraintScope),
   120  	}
   121  
   122  	if len(formationConstraintIDs) > 0 {
   123  		formationTypeRelevanceConditions = append(formationTypeRelevanceConditions, repo.NewInConditionForStringValues("id", formationConstraintIDs))
   124  	}
   125  
   126  	resourceSubtypeConditions := []repo.Condition{
   127  		repo.NewEqualCondition("resource_subtype", details.ResourceSubtype),
   128  		repo.NewEqualCondition("resource_subtype", resourceSubtypeANY),
   129  	}
   130  
   131  	conditions := repo.And(
   132  		append(
   133  			repo.ConditionTreesFromConditions(
   134  				[]repo.Condition{
   135  					repo.NewEqualCondition("target_operation", location.OperationName),
   136  					repo.NewEqualCondition("constraint_type", location.ConstraintType),
   137  					repo.NewEqualCondition("resource_type", details.ResourceType),
   138  				},
   139  			),
   140  			repo.Or(repo.ConditionTreesFromConditions(
   141  				resourceSubtypeConditions,
   142  			)...),
   143  			repo.Or(repo.ConditionTreesFromConditions(
   144  				formationTypeRelevanceConditions,
   145  			)...),
   146  		)...,
   147  	)
   148  
   149  	if err := r.conditionTreeLister.ListConditionTreeGlobal(ctx, resource.FormationConstraint, &entityCollection, conditions); err != nil {
   150  		return nil, errors.Wrap(err, "while listing constraints")
   151  	}
   152  	return r.multipleFromEntities(entityCollection)
   153  }
   154  
   155  // ListByIDsAndGlobal lists formationConstraints whose ID can be found in formationConstraintIDs or have constraint scope "global"
   156  func (r *repository) ListByIDsAndGlobal(ctx context.Context, formationConstraintIDs []string) ([]*model.FormationConstraint, error) {
   157  	var entityCollection EntityCollection
   158  
   159  	formationTypeRelevanceConditions := []repo.Condition{
   160  		repo.NewEqualCondition("constraint_scope", model.GlobalFormationConstraintScope),
   161  	}
   162  
   163  	if len(formationConstraintIDs) > 0 {
   164  		formationTypeRelevanceConditions = append(formationTypeRelevanceConditions, repo.NewInConditionForStringValues("id", formationConstraintIDs))
   165  	}
   166  
   167  	conditions := repo.Or(repo.ConditionTreesFromConditions(formationTypeRelevanceConditions)...)
   168  
   169  	if err := r.conditionTreeLister.ListConditionTreeGlobal(ctx, resource.FormationConstraint, &entityCollection, conditions); err != nil {
   170  		return nil, errors.Wrap(err, "while listing constraints")
   171  	}
   172  	return r.multipleFromEntities(entityCollection)
   173  }
   174  
   175  // Update updates the FormationConstraint matching the ID of the input model
   176  func (r *repository) Update(ctx context.Context, model *model.FormationConstraint) error {
   177  	if model == nil {
   178  		return apperrors.NewInternalError("model can not be empty")
   179  	}
   180  
   181  	entity := r.conv.ToEntity(model)
   182  
   183  	return r.updater.UpdateSingleGlobal(ctx, entity)
   184  }
   185  
   186  func (r *repository) multipleFromEntities(entities EntityCollection) ([]*model.FormationConstraint, error) {
   187  	items := make([]*model.FormationConstraint, 0, len(entities))
   188  	for _, ent := range entities {
   189  		m := r.conv.FromEntity(&ent)
   190  		items = append(items, m)
   191  	}
   192  	return items, nil
   193  }