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