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

     1  package upgrade_cluster
     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  	"github.com/kyma-project/kyma-environment-broker/internal/process"
    10  	"github.com/kyma-project/kyma-environment-broker/internal/provisioner"
    11  	"github.com/kyma-project/kyma-environment-broker/internal/storage"
    12  	"github.com/sirupsen/logrus"
    13  )
    14  
    15  const DryRunPrefix = "dry_run-"
    16  
    17  type UpgradeClusterStep struct {
    18  	operationManager    *process.UpgradeClusterOperationManager
    19  	provisionerClient   provisioner.Client
    20  	runtimeStateStorage storage.RuntimeStates
    21  	timeSchedule        TimeSchedule
    22  }
    23  
    24  func NewUpgradeClusterStep(
    25  	os storage.Operations,
    26  	runtimeStorage storage.RuntimeStates,
    27  	cli provisioner.Client,
    28  	timeSchedule *TimeSchedule) *UpgradeClusterStep {
    29  	ts := timeSchedule
    30  	if ts == nil {
    31  		ts = &TimeSchedule{
    32  			Retry:                 5 * time.Second,
    33  			StatusCheck:           time.Minute,
    34  			UpgradeClusterTimeout: time.Hour,
    35  		}
    36  	}
    37  
    38  	return &UpgradeClusterStep{
    39  		operationManager:    process.NewUpgradeClusterOperationManager(os),
    40  		provisionerClient:   cli,
    41  		runtimeStateStorage: runtimeStorage,
    42  		timeSchedule:        *ts,
    43  	}
    44  }
    45  
    46  func (s *UpgradeClusterStep) Name() string {
    47  	return "Upgrade_Cluster"
    48  }
    49  
    50  func (s *UpgradeClusterStep) Run(operation internal.UpgradeClusterOperation, log logrus.FieldLogger) (internal.UpgradeClusterOperation, time.Duration, error) {
    51  	if time.Since(operation.UpdatedAt) > s.timeSchedule.UpgradeClusterTimeout {
    52  		log.Infof("operation has reached the time limit: updated operation time: %s", operation.UpdatedAt)
    53  		return s.operationManager.OperationFailed(operation, fmt.Sprintf("operation has reached the time limit: %s", s.timeSchedule.UpgradeClusterTimeout), nil, log)
    54  	}
    55  
    56  	latestRuntimeStateWithOIDC, err := s.runtimeStateStorage.GetLatestWithOIDCConfigByRuntimeID(operation.InstanceDetails.RuntimeID)
    57  	if err != nil {
    58  		return s.operationManager.RetryOperation(operation, err.Error(), err, 5*time.Second, 1*time.Minute, log)
    59  	}
    60  
    61  	input, err := s.createUpgradeShootInput(operation, &latestRuntimeStateWithOIDC.ClusterConfig)
    62  	if err != nil {
    63  		return s.operationManager.OperationFailed(operation, "invalid operation data - cannot create upgradeShoot input", err, log)
    64  	}
    65  
    66  	if operation.DryRun {
    67  		// runtimeID is set with prefix to indicate the fake runtime state
    68  		err = s.runtimeStateStorage.Insert(
    69  			internal.NewRuntimeState(fmt.Sprintf("%s%s", DryRunPrefix, operation.RuntimeOperation.RuntimeID), operation.Operation.ID, nil, gardenerUpgradeInputToConfigInput(input)),
    70  		)
    71  		if err != nil {
    72  			return operation, 10 * time.Second, nil
    73  		}
    74  		return s.operationManager.OperationSucceeded(operation, "dry run succeeded", log)
    75  	}
    76  
    77  	var provisionerResponse gqlschema.OperationStatus
    78  	if operation.ProvisionerOperationID == "" {
    79  		// trigger upgradeRuntime mutation
    80  		provisionerResponse, err = s.provisionerClient.UpgradeShoot(operation.ProvisioningParameters.ErsContext.GlobalAccountID, operation.RuntimeOperation.RuntimeID, input)
    81  		if err != nil {
    82  			log.Errorf("call to provisioner failed: %s", err)
    83  			return operation, s.timeSchedule.Retry, nil
    84  		}
    85  
    86  		repeat := time.Duration(0)
    87  		operation, repeat, _ = s.operationManager.UpdateOperation(operation, func(op *internal.UpgradeClusterOperation) {
    88  			op.ProvisionerOperationID = *provisionerResponse.ID
    89  			op.Description = "cluster upgrade in progress"
    90  		}, log)
    91  		if repeat != 0 {
    92  			log.Errorf("cannot save operation ID from provisioner")
    93  			return operation, s.timeSchedule.Retry, nil
    94  		}
    95  	}
    96  
    97  	if provisionerResponse.RuntimeID == nil {
    98  		provisionerResponse, err = s.provisionerClient.RuntimeOperationStatus(operation.ProvisioningParameters.ErsContext.GlobalAccountID, operation.ProvisionerOperationID)
    99  		if err != nil {
   100  			log.Errorf("call to provisioner about operation status failed: %s", err)
   101  			return operation, s.timeSchedule.Retry, nil
   102  		}
   103  	}
   104  	if provisionerResponse.RuntimeID == nil {
   105  		return operation, s.timeSchedule.StatusCheck, nil
   106  	}
   107  	log = log.WithField("runtimeID", *provisionerResponse.RuntimeID)
   108  	log.Infof("call to provisioner for upgrade succeeded, got operation ID %q", *provisionerResponse.ID)
   109  
   110  	rs := internal.NewRuntimeState(*provisionerResponse.RuntimeID, operation.Operation.ID, nil, gardenerUpgradeInputToConfigInput(input))
   111  	err = s.runtimeStateStorage.Insert(rs)
   112  	if err != nil {
   113  		log.Errorf("cannot insert runtimeState: %s", err)
   114  		return operation, 10 * time.Second, nil
   115  	}
   116  
   117  	log.Infof("cluster upgrade process initiated successfully")
   118  
   119  	// return repeat mode to start the initialization step which will now check the runtime status
   120  	return operation, s.timeSchedule.Retry, nil
   121  
   122  }
   123  
   124  func (s *UpgradeClusterStep) createUpgradeShootInput(operation internal.UpgradeClusterOperation, lastClusterConfig *gqlschema.GardenerConfigInput) (gqlschema.UpgradeShootInput, error) {
   125  	operation.InputCreator.SetProvisioningParameters(operation.ProvisioningParameters)
   126  	if lastClusterConfig.OidcConfig != nil {
   127  		operation.InputCreator.SetOIDCLastValues(*lastClusterConfig.OidcConfig)
   128  	}
   129  	input, err := operation.InputCreator.CreateUpgradeShootInput()
   130  	if err != nil {
   131  		return input, fmt.Errorf("while building upgradeShootInput for provisioner: %w", err)
   132  	}
   133  	input.GardenerConfig.ShootNetworkingFilterDisabled = operation.ProvisioningParameters.ErsContext.DisableEnterprisePolicyFilter()
   134  
   135  	return input, nil
   136  }
   137  
   138  func gardenerUpgradeInputToConfigInput(input gqlschema.UpgradeShootInput) *gqlschema.GardenerConfigInput {
   139  	disabled := false
   140  	result := &gqlschema.GardenerConfigInput{
   141  		MachineImage:                        input.GardenerConfig.MachineImage,
   142  		MachineImageVersion:                 input.GardenerConfig.MachineImageVersion,
   143  		DiskType:                            input.GardenerConfig.DiskType,
   144  		VolumeSizeGb:                        input.GardenerConfig.VolumeSizeGb,
   145  		Purpose:                             input.GardenerConfig.Purpose,
   146  		OidcConfig:                          input.GardenerConfig.OidcConfig,
   147  		EnableKubernetesVersionAutoUpdate:   input.GardenerConfig.EnableKubernetesVersionAutoUpdate,
   148  		EnableMachineImageVersionAutoUpdate: input.GardenerConfig.EnableMachineImageVersionAutoUpdate,
   149  		ShootNetworkingFilterDisabled:       &disabled,
   150  	}
   151  	if input.GardenerConfig.KubernetesVersion != nil {
   152  		result.KubernetesVersion = *input.GardenerConfig.KubernetesVersion
   153  	}
   154  	if input.GardenerConfig.MachineType != nil {
   155  		result.MachineType = *input.GardenerConfig.MachineType
   156  	}
   157  	if input.GardenerConfig.AutoScalerMin != nil {
   158  		result.AutoScalerMin = *input.GardenerConfig.AutoScalerMin
   159  	}
   160  	if input.GardenerConfig.AutoScalerMax != nil {
   161  		result.AutoScalerMax = *input.GardenerConfig.AutoScalerMax
   162  	}
   163  	if input.GardenerConfig.MaxSurge != nil {
   164  		result.MaxSurge = *input.GardenerConfig.MaxSurge
   165  	}
   166  	if input.GardenerConfig.MaxUnavailable != nil {
   167  		result.MaxUnavailable = *input.GardenerConfig.MaxUnavailable
   168  	}
   169  	result.ShootNetworkingFilterDisabled = input.GardenerConfig.ShootNetworkingFilterDisabled
   170  
   171  	return result
   172  }