github.com/kyma-project/kyma-environment-broker@v0.0.1/internal/broker/instance_last_operation.go (about)

     1  package broker
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net/http"
     7  
     8  	"github.com/kyma-project/kyma-environment-broker/common/orchestration"
     9  	"github.com/kyma-project/kyma-environment-broker/internal/storage"
    10  	"github.com/kyma-project/kyma-environment-broker/internal/storage/dberr"
    11  	"github.com/pivotal-cf/brokerapi/v8/domain"
    12  	"github.com/pivotal-cf/brokerapi/v8/domain/apiresponses"
    13  	"github.com/sirupsen/logrus"
    14  )
    15  
    16  type LastOperationEndpoint struct {
    17  	operationStorage storage.Operations
    18  
    19  	log logrus.FieldLogger
    20  }
    21  
    22  func NewLastOperation(os storage.Operations, log logrus.FieldLogger) *LastOperationEndpoint {
    23  	return &LastOperationEndpoint{
    24  		operationStorage: os,
    25  		log:              log.WithField("service", "LastOperationEndpoint"),
    26  	}
    27  }
    28  
    29  // LastOperation fetches last operation state for a service instance
    30  //
    31  //	GET /v2/service_instances/{instance_id}/last_operation
    32  func (b *LastOperationEndpoint) LastOperation(ctx context.Context, instanceID string, details domain.PollDetails) (domain.LastOperation, error) {
    33  	logger := b.log.WithField("instanceID", instanceID).WithField("operationID", details.OperationData)
    34  
    35  	if details.OperationData == "" {
    36  		lastOp, err := b.operationStorage.GetLastOperation(instanceID)
    37  		if err != nil {
    38  			logger.Errorf("cannot get operation from storage: %s", err)
    39  			statusCode := http.StatusInternalServerError
    40  			if dberr.IsNotFound(err) {
    41  				statusCode = http.StatusNotFound
    42  			}
    43  			return domain.LastOperation{}, apiresponses.NewFailureResponse(err, statusCode,
    44  				fmt.Sprintf("while getting last operation from storage"))
    45  		}
    46  		return domain.LastOperation{
    47  			State:       mapStateToOSBCompliantState(lastOp.State),
    48  			Description: lastOp.Description,
    49  		}, nil
    50  	}
    51  
    52  	operation, err := b.operationStorage.GetOperationByID(details.OperationData)
    53  	if err != nil {
    54  		logger.Errorf("cannot get operation from storage: %s", err)
    55  		statusCode := http.StatusInternalServerError
    56  		if dberr.IsNotFound(err) {
    57  			statusCode = http.StatusNotFound
    58  		}
    59  		return domain.LastOperation{}, apiresponses.NewFailureResponse(err, statusCode,
    60  			fmt.Sprintf("while getting operation from storage"))
    61  	}
    62  
    63  	if operation.InstanceID != instanceID {
    64  		err := fmt.Errorf("operation exists, but instanceID is invalid")
    65  		logger.Errorf("%s", err.Error())
    66  		return domain.LastOperation{}, apiresponses.NewFailureResponse(err, http.StatusBadRequest, err.Error())
    67  	}
    68  
    69  	return domain.LastOperation{
    70  		State:       mapStateToOSBCompliantState(operation.State),
    71  		Description: operation.Description,
    72  	}, nil
    73  }
    74  
    75  func mapStateToOSBCompliantState(opState domain.LastOperationState) domain.LastOperationState {
    76  	switch {
    77  	case opState == orchestration.Pending || opState == orchestration.Retrying:
    78  		return domain.InProgress
    79  	case opState == orchestration.Canceled || opState == orchestration.Canceling:
    80  		return domain.Succeeded
    81  	default:
    82  		return opState
    83  	}
    84  }