github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/pkg/operation/k8s/k8s_scheduler.go (about) 1 package k8s 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/kyma-incubator/compass/components/director/pkg/operation" 8 "github.com/kyma-incubator/compass/components/director/pkg/str" 9 "github.com/kyma-incubator/compass/components/operations-controller/api/v1alpha1" 10 v1 "k8s.io/api/core/v1" 11 "k8s.io/apimachinery/pkg/api/errors" 12 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 13 ) 14 15 // K8SClient missing godoc 16 //go:generate mockery --name=K8SClient --output=automock --outpkg=automock --case=underscore --disable-version-string 17 type K8SClient interface { 18 Create(ctx context.Context, operation *v1alpha1.Operation) (*v1alpha1.Operation, error) 19 Get(ctx context.Context, name string, options metav1.GetOptions) (*v1alpha1.Operation, error) 20 Update(ctx context.Context, operation *v1alpha1.Operation) (*v1alpha1.Operation, error) 21 } 22 23 // Scheduler missing godoc 24 type Scheduler struct { 25 kcli K8SClient 26 } 27 28 // NewScheduler missing godoc 29 func NewScheduler(kcli K8SClient) *Scheduler { 30 return &Scheduler{ 31 kcli: kcli, 32 } 33 } 34 35 // Schedule missing godoc 36 func (s *Scheduler) Schedule(ctx context.Context, op *operation.Operation) (string, error) { 37 operationName := fmt.Sprintf("%s-%s", op.ResourceType, op.ResourceID) 38 getOp, err := s.kcli.Get(ctx, operationName, metav1.GetOptions{}) 39 if err != nil { 40 if errors.IsNotFound(err) { 41 k8sOp := toK8SOperation(op) 42 createdOperation, err := s.kcli.Create(ctx, k8sOp) 43 if err != nil { 44 return "", err 45 } 46 return string(createdOperation.UID), nil 47 } 48 return "", err 49 } 50 if isOpInProgress(getOp) { 51 return "", fmt.Errorf("another operation is in progress for resource with ID %q", op.ResourceID) 52 } 53 getOp = updateOperationSpec(op, getOp) 54 updatedOperation, err := s.kcli.Update(ctx, getOp) 55 if err != nil { 56 if errors.IsConflict(err) { 57 return "", fmt.Errorf("another operation is in progress for resource with ID %q", op.ResourceID) 58 } 59 return "", err 60 } 61 return string(updatedOperation.UID), err 62 } 63 64 func isOpInProgress(op *v1alpha1.Operation) bool { 65 for _, cond := range op.Status.Conditions { 66 if cond.Status == v1.ConditionTrue { 67 return false 68 } 69 } 70 return true 71 } 72 73 func toK8SOperation(op *operation.Operation) *v1alpha1.Operation { 74 operationName := fmt.Sprintf("%s-%s", op.ResourceType, op.ResourceID) 75 result := &v1alpha1.Operation{ 76 ObjectMeta: metav1.ObjectMeta{ 77 Name: operationName, 78 }, 79 } 80 return updateOperationSpec(op, result) 81 } 82 83 func updateOperationSpec(op *operation.Operation, k8sOp *v1alpha1.Operation) *v1alpha1.Operation { 84 k8sOp.Spec = v1alpha1.OperationSpec{ 85 OperationCategory: op.OperationCategory, 86 OperationType: v1alpha1.OperationType(str.Title(string(op.OperationType))), 87 ResourceType: string(op.ResourceType), 88 ResourceID: op.ResourceID, 89 CorrelationID: op.CorrelationID, 90 WebhookIDs: op.WebhookIDs, 91 RequestObject: op.RequestObject, 92 } 93 return k8sOp 94 }