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 }