github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/internal/operations_manager/opcreator.go (about) 1 package operationsmanager 2 3 import ( 4 "context" 5 "encoding/json" 6 "time" 7 8 "github.com/kyma-incubator/compass/components/director/internal/model" 9 "github.com/kyma-incubator/compass/components/director/pkg/log" 10 "github.com/kyma-incubator/compass/components/director/pkg/persistence" 11 "github.com/pkg/errors" 12 ) 13 14 const ( 15 // OrdCreatorType specifies open resource discovery creator type 16 OrdCreatorType = "ORD" 17 // OrdAggregationOpType specifies open resource discovery operation type 18 OrdAggregationOpType = "ORD_AGGREGATION" 19 ) 20 21 // OperationCreator is responsible for creation of different types of operations. 22 //go:generate mockery --name=OperationCreator --output=automock --outpkg=automock --case=underscore --disable-version-string 23 type OperationCreator interface { 24 Create(ctx context.Context) error 25 } 26 27 // ORDOperationCreator consists of various resource services responsible for operations creation. 28 type ORDOperationCreator struct { 29 transact persistence.Transactioner 30 opSvc OperationService 31 webhookSvc WebhookService 32 appSvc ApplicationService 33 } 34 35 // Create lists all webhooks of type "OPEN_RESOURCE_DISCOVERY" and for every application creates corresponding operation 36 func (oc *ORDOperationCreator) Create(ctx context.Context) error { 37 operations, err := oc.buildOperationInputs(ctx) 38 if err != nil { 39 return errors.Wrap(err, "while building operation inputs") 40 } 41 42 tx, err := oc.transact.Begin() 43 if err != nil { 44 return err 45 } 46 defer oc.transact.RollbackUnlessCommitted(ctx, tx) 47 ctx = persistence.SaveToContext(ctx, tx) 48 49 if err := oc.opSvc.CreateMultiple(ctx, operations); err != nil { 50 return errors.Wrap(err, "while creating multiple operations") 51 } 52 53 return tx.Commit() 54 } 55 56 func (oc *ORDOperationCreator) buildOperationInputs(ctx context.Context) ([]*model.OperationInput, error) { 57 ordWebhooks, err := oc.getWebhooksWithOrdType(ctx) 58 if err != nil { 59 return nil, errors.Wrapf(err, "while getting webhooks of type %s", model.WebhookTypeOpenResourceDiscovery) 60 } 61 62 operations := make([]*model.OperationInput, 0) 63 for _, webhook := range ordWebhooks { 64 if webhook.ObjectType == model.ApplicationTemplateWebhookReference { 65 ops, err := oc.appTemplateWebhookToOperations(ctx, webhook) 66 if err != nil { 67 return nil, errors.Wrapf(err, "while creating operations from application template webhook") 68 } 69 operations = append(operations, ops...) 70 } else if webhook.ObjectType == model.ApplicationWebhookReference { 71 opData := NewOrdOperationData(webhook.ObjectID, "") 72 data, err := opData.GetData() 73 if err != nil { 74 return nil, err 75 } 76 operations = append(operations, buildORDOperationInput(data)) 77 } 78 } 79 80 return operations, nil 81 } 82 83 func (oc *ORDOperationCreator) appTemplateWebhookToOperations(ctx context.Context, webhook *model.Webhook) ([]*model.OperationInput, error) { 84 operations := make([]*model.OperationInput, 0) 85 if webhook.ObjectType != model.ApplicationTemplateWebhookReference { 86 return operations, nil 87 } 88 89 apps, err := oc.getApplicationsForAppTemplate(ctx, webhook.ObjectID) 90 if err != nil { 91 return nil, err 92 } 93 94 for _, app := range apps { 95 opData := NewOrdOperationData(app.ID, webhook.ObjectID) 96 data, err := opData.GetData() 97 if err != nil { 98 return nil, err 99 } 100 operations = append(operations, buildORDOperationInput(data)) 101 } 102 103 return operations, nil 104 } 105 106 func (oc *ORDOperationCreator) getWebhooksWithOrdType(ctx context.Context) ([]*model.Webhook, error) { 107 tx, err := oc.transact.Begin() 108 if err != nil { 109 return nil, err 110 } 111 defer oc.transact.RollbackUnlessCommitted(ctx, tx) 112 113 ctx = persistence.SaveToContext(ctx, tx) 114 ordWebhooks, err := oc.webhookSvc.ListByWebhookType(ctx, model.WebhookTypeOpenResourceDiscovery) 115 if err != nil { 116 log.C(ctx).WithError(err).Errorf("error while fetching webhooks with type %s", model.WebhookTypeOpenResourceDiscovery) 117 return nil, err 118 } 119 120 if err := tx.Commit(); err != nil { 121 return nil, err 122 } 123 124 return ordWebhooks, nil 125 } 126 127 func (oc *ORDOperationCreator) getApplicationsForAppTemplate(ctx context.Context, appTemplateID string) ([]*model.Application, error) { 128 tx, err := oc.transact.Begin() 129 if err != nil { 130 return nil, err 131 } 132 defer oc.transact.RollbackUnlessCommitted(ctx, tx) 133 134 ctx = persistence.SaveToContext(ctx, tx) 135 apps, err := oc.appSvc.ListAllByApplicationTemplateID(ctx, appTemplateID) 136 if err != nil { 137 return nil, err 138 } 139 140 if err := tx.Commit(); err != nil { 141 return nil, err 142 } 143 144 return apps, err 145 } 146 147 func buildORDOperationInput(data string) *model.OperationInput { 148 now := time.Now() 149 return &model.OperationInput{ 150 OpType: OrdAggregationOpType, 151 Status: scheduledOpStatus, 152 Data: json.RawMessage(data), 153 Error: nil, 154 Priority: 1, 155 CreatedAt: &now, 156 FinishedAt: nil, 157 } 158 } 159 160 // NewOperationCreator creates OperationCreator based on kind 161 func NewOperationCreator(kind string, transact persistence.Transactioner, opSvc OperationService, webhookSvc WebhookService, appSvc ApplicationService) OperationCreator { 162 if kind == OrdCreatorType { 163 return &ORDOperationCreator{ 164 transact: transact, 165 opSvc: opSvc, 166 webhookSvc: webhookSvc, 167 appSvc: appSvc, 168 } 169 } 170 return nil 171 }