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

     1  package provisioning
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  
     7  	"github.com/kyma-project/control-plane/components/provisioner/pkg/gqlschema"
     8  	"github.com/kyma-project/kyma-environment-broker/internal"
     9  	kebError "github.com/kyma-project/kyma-environment-broker/internal/error"
    10  	"github.com/kyma-project/kyma-environment-broker/internal/process"
    11  	"github.com/kyma-project/kyma-environment-broker/internal/provisioner"
    12  	"github.com/kyma-project/kyma-environment-broker/internal/storage"
    13  	"github.com/kyma-project/kyma-environment-broker/internal/storage/dberr"
    14  	"github.com/sirupsen/logrus"
    15  )
    16  
    17  const (
    18  	// the time after which the operation is marked as expired
    19  	CreateRuntimeTimeout = 1 * time.Hour
    20  
    21  	brokerKeyPrefix = "broker_"
    22  	globalKeyPrefix = "global_"
    23  )
    24  
    25  type CreateRuntimeWithoutKymaStep struct {
    26  	operationManager    *process.OperationManager
    27  	instanceStorage     storage.Instances
    28  	runtimeStateStorage storage.RuntimeStates
    29  	provisionerClient   provisioner.Client
    30  }
    31  
    32  func NewCreateRuntimeWithoutKymaStep(os storage.Operations, runtimeStorage storage.RuntimeStates, is storage.Instances, cli provisioner.Client) *CreateRuntimeWithoutKymaStep {
    33  	return &CreateRuntimeWithoutKymaStep{
    34  		operationManager:    process.NewOperationManager(os),
    35  		instanceStorage:     is,
    36  		provisionerClient:   cli,
    37  		runtimeStateStorage: runtimeStorage,
    38  	}
    39  }
    40  
    41  func (s *CreateRuntimeWithoutKymaStep) Name() string {
    42  	return "Create_Runtime_Without_Kyma"
    43  }
    44  
    45  func (s *CreateRuntimeWithoutKymaStep) Run(operation internal.Operation, log logrus.FieldLogger) (internal.Operation, time.Duration, error) {
    46  	if operation.RuntimeID != "" {
    47  		log.Infof("RuntimeID already set %s, skipping", operation.RuntimeID)
    48  		return operation, 0, nil
    49  	}
    50  	if time.Since(operation.UpdatedAt) > CreateRuntimeTimeout {
    51  		log.Infof("operation has reached the time limit: updated operation time: %s", operation.UpdatedAt)
    52  		return s.operationManager.OperationFailed(operation, fmt.Sprintf("operation has reached the time limit: %s", CreateRuntimeTimeout), nil, log)
    53  	}
    54  
    55  	requestInput, err := s.createProvisionInput(operation)
    56  	if err != nil {
    57  		log.Errorf("Unable to create provisioning input: %s", err.Error())
    58  		return s.operationManager.OperationFailed(operation, "invalid operation data - cannot create provisioning input", err, log)
    59  	}
    60  
    61  	log.Infof("call ProvisionRuntime: kubernetesVersion=%s, region=%s, provider=%s, name=%s, workers=%s, pods=%s, services=%s",
    62  		requestInput.ClusterConfig.GardenerConfig.KubernetesVersion,
    63  		requestInput.ClusterConfig.GardenerConfig.Region,
    64  		requestInput.ClusterConfig.GardenerConfig.Provider,
    65  		requestInput.ClusterConfig.GardenerConfig.Name,
    66  		requestInput.ClusterConfig.GardenerConfig.WorkerCidr,
    67  		valueOfString(requestInput.ClusterConfig.GardenerConfig.PodsCidr),
    68  		valueOfString(requestInput.ClusterConfig.GardenerConfig.ServicesCidr))
    69  
    70  	provisionerResponse, err := s.provisionerClient.ProvisionRuntime(operation.ProvisioningParameters.ErsContext.GlobalAccountID, operation.ProvisioningParameters.ErsContext.SubAccountID, requestInput)
    71  	switch {
    72  	case kebError.IsTemporaryError(err):
    73  		log.Errorf("call to provisioner failed (temporary error): %s", err)
    74  		return operation, 5 * time.Second, nil
    75  	case err != nil:
    76  		log.Errorf("call to Provisioner failed: %s", err)
    77  		return s.operationManager.OperationFailed(operation, "call to the provisioner service failed", err, log)
    78  	}
    79  	log.Infof("Provisioning runtime in the Provisioner started, RuntimeID=%s, provisioner operation=%s", *provisionerResponse.RuntimeID, *provisionerResponse.ID)
    80  
    81  	repeat := time.Duration(0)
    82  	operation, repeat, _ = s.operationManager.UpdateOperation(operation, func(operation *internal.Operation) {
    83  		operation.ProvisionerOperationID = *provisionerResponse.ID
    84  		if provisionerResponse.RuntimeID != nil {
    85  			operation.RuntimeID = *provisionerResponse.RuntimeID
    86  			operation.Region = requestInput.ClusterConfig.GardenerConfig.Region
    87  		}
    88  	}, log)
    89  	if repeat != 0 {
    90  		log.Errorf("cannot save neither runtime ID nor region from provisioner")
    91  		return operation, 5 * time.Second, nil
    92  	}
    93  
    94  	rs := internal.NewRuntimeState(*provisionerResponse.RuntimeID, operation.ID, requestInput.KymaConfig, requestInput.ClusterConfig.GardenerConfig)
    95  	rs.KymaVersion = operation.RuntimeVersion.Version
    96  	err = s.runtimeStateStorage.Insert(rs)
    97  
    98  	if err != nil {
    99  		log.Errorf("cannot insert runtimeState: %s", err)
   100  		return operation, 10 * time.Second, nil
   101  	}
   102  
   103  	err = s.updateInstance(operation.InstanceID,
   104  		*provisionerResponse.RuntimeID,
   105  		requestInput.ClusterConfig.GardenerConfig.Region)
   106  
   107  	switch {
   108  	case err == nil:
   109  	case dberr.IsConflict(err):
   110  		err := s.updateInstance(operation.InstanceID, *provisionerResponse.RuntimeID, requestInput.ClusterConfig.GardenerConfig.Region)
   111  		if err != nil {
   112  			log.Errorf("cannot update instance: %s", err)
   113  			return operation, 1 * time.Minute, nil
   114  		}
   115  	}
   116  
   117  	log.Info("runtime creation process initiated successfully")
   118  	return operation, 0, nil
   119  }
   120  
   121  func valueOfString(val *string) string {
   122  	if val == nil {
   123  		return "<nil>"
   124  	}
   125  	return *val
   126  }
   127  
   128  func (s *CreateRuntimeWithoutKymaStep) updateInstance(id, runtimeID, region string) error {
   129  	instance, err := s.instanceStorage.GetByID(id)
   130  	if err != nil {
   131  		return fmt.Errorf("while getting instance: %w", err)
   132  	}
   133  	instance.RuntimeID = runtimeID
   134  	instance.ProviderRegion = region
   135  	_, err = s.instanceStorage.Update(*instance)
   136  	if err != nil {
   137  		return fmt.Errorf("while updating instance: %w", err)
   138  	}
   139  
   140  	return nil
   141  }
   142  
   143  func (s *CreateRuntimeWithoutKymaStep) createProvisionInput(operation internal.Operation) (gqlschema.ProvisionRuntimeInput, error) {
   144  	operation.InputCreator.SetProvisioningParameters(operation.ProvisioningParameters)
   145  	operation.InputCreator.SetShootName(operation.ShootName)
   146  	operation.InputCreator.SetShootDomain(operation.ShootDomain)
   147  	operation.InputCreator.SetShootDNSProviders(operation.ShootDNSProviders)
   148  	operation.InputCreator.SetLabel(brokerKeyPrefix+"instance_id", operation.InstanceID)
   149  	operation.InputCreator.SetLabel(globalKeyPrefix+"subaccount_id", operation.ProvisioningParameters.ErsContext.SubAccountID)
   150  	operation.InputCreator.SetLabel(grafanaURLLabel, fmt.Sprintf("https://grafana.%s", operation.ShootDomain))
   151  	request, err := operation.InputCreator.CreateProvisionClusterInput()
   152  	if err != nil {
   153  		return request, fmt.Errorf("while building input for provisioner: %w", err)
   154  	}
   155  	request.ClusterConfig.GardenerConfig.ShootNetworkingFilterDisabled = operation.ProvisioningParameters.ErsContext.DisableEnterprisePolicyFilter()
   156  	request.ClusterConfig.GardenerConfig.EuAccess = &operation.InstanceDetails.EuAccess
   157  
   158  	return request, nil
   159  }