github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/internal/domain/destination/repository.go (about) 1 package destination 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/log" 10 "github.com/kyma-incubator/compass/components/director/pkg/resource" 11 ) 12 13 const ( 14 destinationTable = "public.destinations" 15 revisionColumn = "revision" 16 tenantIDColumn = "tenant_id" 17 formationAssignmentIDColumn = "formation_assignment_id" 18 destinationNameColumn = "name" 19 ) 20 21 var ( 22 destinationColumns = []string{"id", "name", "type", "url", "authentication", "tenant_id", "bundle_id", "revision", "formation_assignment_id"} 23 conflictingColumns = []string{"name", "tenant_id"} 24 updateColumns = []string{"name", "type", "url", "authentication", "revision"} 25 ) 26 27 // EntityConverter missing godoc 28 // 29 //go:generate mockery --name=EntityConverter --output=automock --outpkg=automock --case=underscore --disable-version-string 30 type EntityConverter interface { 31 ToEntity(in *model.Destination) *Entity 32 FromEntity(entity *Entity) *model.Destination 33 } 34 35 type repository struct { 36 conv EntityConverter 37 globalCreator repo.CreatorGlobal 38 deleter repo.Deleter 39 globalDeleter repo.DeleterGlobal 40 upserterWithEmbeddedTenant repo.UpserterGlobal 41 upserterGlobal repo.UpserterGlobal 42 lister repo.Lister 43 } 44 45 // NewRepository returns new destination repository 46 func NewRepository(converter EntityConverter) *repository { 47 return &repository{ 48 conv: converter, 49 globalCreator: repo.NewCreatorGlobal(resource.Destination, destinationTable, destinationColumns), 50 deleter: repo.NewDeleterWithEmbeddedTenant(destinationTable, tenantIDColumn), 51 globalDeleter: repo.NewDeleterGlobal(resource.Destination, destinationTable), 52 upserterWithEmbeddedTenant: repo.NewUpserterWithEmbeddedTenant(resource.Destination, destinationTable, destinationColumns, conflictingColumns, updateColumns, tenantIDColumn), 53 upserterGlobal: repo.NewUpserterGlobal(resource.Destination, destinationTable, destinationColumns, conflictingColumns, updateColumns), 54 lister: repo.NewListerWithEmbeddedTenant(destinationTable, tenantIDColumn, destinationColumns), 55 } 56 } 57 58 // Upsert upserts a destination entity in db 59 func (r *repository) Upsert(ctx context.Context, in model.DestinationInput, id, tenantID, bundleID, revisionID string) error { 60 destination := Entity{ 61 ID: id, 62 Name: in.Name, 63 Type: in.Type, 64 URL: in.URL, 65 Authentication: in.Authentication, 66 BundleID: repo.NewNullableString(&bundleID), 67 TenantID: tenantID, 68 Revision: repo.NewNullableString(&revisionID), 69 } 70 return r.upserterGlobal.UpsertGlobal(ctx, destination) 71 } 72 73 // UpsertWithEmbeddedTenant upserts a destination entity in th DB with embedded tenant 74 func (r *repository) UpsertWithEmbeddedTenant(ctx context.Context, destination *model.Destination) error { 75 if destination == nil { 76 return apperrors.NewInternalError("destination model can not be empty") 77 } 78 79 return r.upserterWithEmbeddedTenant.UpsertGlobal(ctx, r.conv.ToEntity(destination)) 80 } 81 82 // DeleteOld deletes all destinations in a given tenant that do not have latestRevision 83 func (r *repository) DeleteOld(ctx context.Context, latestRevision, tenantID string) error { 84 conditions := repo.Conditions{repo.NewNotEqualCondition(revisionColumn, latestRevision), repo.NewEqualCondition(tenantIDColumn, tenantID), repo.NewNotNullCondition(revisionColumn)} 85 return r.globalDeleter.DeleteManyGlobal(ctx, conditions) 86 } 87 88 // CreateDestination creates destination in the DB with the provided `destination` data 89 func (r *repository) CreateDestination(ctx context.Context, destination *model.Destination) error { 90 if destination == nil { 91 return apperrors.NewInternalError("destination model can not be empty") 92 } 93 94 return r.globalCreator.Create(ctx, r.conv.ToEntity(destination)) 95 } 96 97 // ListByTenantIDAndAssignmentID returns all destinations for a given `tenantID` and `formationAssignmentID` 98 func (r *repository) ListByTenantIDAndAssignmentID(ctx context.Context, tenantID, formationAssignmentID string) ([]*model.Destination, error) { 99 log.C(ctx).Infof("Listing destinations by tenant ID: %q and assignment ID: %q from the DB", tenantID, formationAssignmentID) 100 var destCollection EntityCollection 101 conditions := repo.Conditions{repo.NewEqualCondition(formationAssignmentIDColumn, formationAssignmentID)} 102 if err := r.lister.List(ctx, resource.Destination, tenantID, &destCollection, conditions...); err != nil { 103 return nil, err 104 } 105 106 items := make([]*model.Destination, 0, destCollection.Len()) 107 for _, destEntity := range destCollection { 108 items = append(items, r.conv.FromEntity(&destEntity)) 109 } 110 111 return items, nil 112 } 113 114 // DeleteByDestinationNameAndAssignmentID deletes all destinations for a given `destinationName`, `formationAssignmentID` and `tenantID` from the DB 115 func (r *repository) DeleteByDestinationNameAndAssignmentID(ctx context.Context, destinationName, formationAssignmentID, tenantID string) error { 116 log.C(ctx).Infof("Deleting destination(s) by name: %q, assignment ID: %q and tenant ID: %q from the DB", destinationName, tenantID, formationAssignmentID) 117 conditions := repo.Conditions{repo.NewEqualCondition(destinationNameColumn, destinationName), repo.NewEqualCondition(formationAssignmentIDColumn, formationAssignmentID)} 118 return r.deleter.DeleteMany(ctx, resource.Destination, tenantID, conditions) 119 }