github.com/kyma-project/kyma-environment-broker@v0.0.1/internal/broker/instance_deprovision.go (about) 1 package broker 2 3 import ( 4 "context" 5 "fmt" 6 "net/http" 7 8 "github.com/kyma-project/kyma-environment-broker/internal" 9 10 "github.com/google/uuid" 11 "github.com/kyma-project/kyma-environment-broker/internal/storage" 12 13 "github.com/kyma-project/kyma-environment-broker/internal/storage/dberr" 14 "github.com/pivotal-cf/brokerapi/v8/domain" 15 "github.com/pivotal-cf/brokerapi/v8/domain/apiresponses" 16 "github.com/sirupsen/logrus" 17 ) 18 19 type DeprovisionEndpoint struct { 20 log logrus.FieldLogger 21 22 instancesStorage storage.Instances 23 operationsStorage storage.Deprovisioning 24 25 queue Queue 26 } 27 28 func NewDeprovision(instancesStorage storage.Instances, operationsStorage storage.Operations, q Queue, log logrus.FieldLogger) *DeprovisionEndpoint { 29 return &DeprovisionEndpoint{ 30 log: log.WithField("service", "DeprovisionEndpoint"), 31 instancesStorage: instancesStorage, 32 operationsStorage: operationsStorage, 33 34 queue: q, 35 } 36 } 37 38 // Deprovision deletes an existing service instance 39 // 40 // DELETE /v2/service_instances/{instance_id} 41 func (b *DeprovisionEndpoint) Deprovision(ctx context.Context, instanceID string, details domain.DeprovisionDetails, asyncAllowed bool) (domain.DeprovisionServiceSpec, error) { 42 logger := b.log.WithFields(logrus.Fields{"instanceID": instanceID}) 43 logger.Infof("Deprovisioning triggered, details: %+v", details) 44 45 instance, err := b.instancesStorage.GetByID(instanceID) 46 switch { 47 case err == nil: 48 case dberr.IsNotFound(err): 49 logger.Warn("instance does not exist") 50 return domain.DeprovisionServiceSpec{ 51 IsAsync: false, 52 }, nil 53 default: 54 logger.Errorf("unable to get instance from a storage: %s", err) 55 return domain.DeprovisionServiceSpec{}, apiresponses.NewFailureResponse(fmt.Errorf("unable to get instance from the storage"), http.StatusInternalServerError, fmt.Sprintf("could not deprovision runtime, instanceID %s", instanceID)) 56 } 57 58 logger = logger.WithFields(logrus.Fields{"runtimeID": instance.RuntimeID, "globalAccountID": instance.GlobalAccountID, "planID": instance.ServicePlanID}) 59 60 // check if operation with the same instance ID is already created 61 existingOperation, errStorage := b.operationsStorage.GetDeprovisioningOperationByInstanceID(instanceID) 62 if errStorage != nil && !dberr.IsNotFound(errStorage) { 63 logger.Errorf("cannot get existing operation from storage %s", errStorage) 64 return domain.DeprovisionServiceSpec{}, fmt.Errorf("cannot get existing operation from storage") 65 } 66 67 // temporary deprovisioning means suspension 68 previousOperationIsNotTemporary := existingOperation != nil && !existingOperation.Temporary 69 if previousOperationIsNotTemporary { 70 switch { 71 // there is an ongoing operation 72 case existingOperation.State != domain.Failed && existingOperation.State != domain.Succeeded: 73 logger.Info("deprovision operation already ongoing - not creating a new operation") 74 return domain.DeprovisionServiceSpec{ 75 IsAsync: true, 76 OperationData: existingOperation.ID, 77 }, nil 78 case existingOperation.State == domain.Succeeded && len(existingOperation.ExcutedButNotCompleted) == 0: 79 logger.Info("no steps to retry - not creating a new operation") 80 return domain.DeprovisionServiceSpec{ 81 IsAsync: true, 82 OperationData: existingOperation.ID, 83 }, nil 84 } 85 } 86 87 // create and save new operation 88 operationID := uuid.New().String() 89 logger = logger.WithField("operationID", operationID) 90 operation, err := internal.NewDeprovisioningOperationWithID(operationID, instance) 91 if err != nil { 92 logger.Errorf("cannot create new operation: %s", err) 93 return domain.DeprovisionServiceSpec{}, fmt.Errorf("cannot create new operation") 94 } 95 if v := ctx.Value("User-Agent"); v != nil { 96 operation.UserAgent = v.(string) 97 } 98 err = b.operationsStorage.InsertDeprovisioningOperation(operation) 99 if err != nil { 100 logger.Errorf("cannot save operation: %s", err) 101 return domain.DeprovisionServiceSpec{}, fmt.Errorf("cannot save operation") 102 } 103 104 logger.Info("Adding operation to deprovisioning queue") 105 b.queue.Add(operationID) 106 107 return domain.DeprovisionServiceSpec{ 108 IsAsync: true, 109 OperationData: operationID, 110 }, nil 111 }