github.com/kyma-project/kyma-environment-broker@v0.0.1/internal/orchestration/manager/upgrade_cluster.go (about) 1 package manager 2 3 import ( 4 "fmt" 5 "time" 6 7 internalOrchestration "github.com/kyma-project/kyma-environment-broker/internal/orchestration" 8 9 "sigs.k8s.io/controller-runtime/pkg/client" 10 11 "github.com/google/uuid" 12 "github.com/kyma-project/kyma-environment-broker/common/orchestration" 13 14 "github.com/kyma-project/kyma-environment-broker/internal" 15 "github.com/kyma-project/kyma-environment-broker/internal/notification" 16 "github.com/kyma-project/kyma-environment-broker/internal/process" 17 "github.com/kyma-project/kyma-environment-broker/internal/storage" 18 "github.com/kyma-project/kyma-environment-broker/internal/storage/dbmodel" 19 "github.com/pivotal-cf/brokerapi/v8/domain" 20 "github.com/sirupsen/logrus" 21 ) 22 23 type upgradeClusterFactory struct { 24 operationStorage storage.Operations 25 } 26 27 func NewUpgradeClusterManager(orchestrationStorage storage.Orchestrations, operationStorage storage.Operations, instanceStorage storage.Instances, 28 kymaClusterExecutor orchestration.OperationExecutor, resolver orchestration.RuntimeResolver, pollingInterval time.Duration, 29 log logrus.FieldLogger, cli client.Client, cfg internalOrchestration.Config, bundleBuilder notification.BundleBuilder, speedFactor int) process.Executor { 30 return &orchestrationManager{ 31 orchestrationStorage: orchestrationStorage, 32 operationStorage: operationStorage, 33 instanceStorage: instanceStorage, 34 resolver: resolver, 35 factory: &upgradeClusterFactory{ 36 operationStorage: operationStorage, 37 }, 38 executor: kymaClusterExecutor, 39 pollingInterval: pollingInterval, 40 log: log, 41 k8sClient: cli, 42 configNamespace: cfg.Namespace, 43 configName: cfg.Name, 44 kymaVersion: cfg.KymaVersion, 45 kubernetesVersion: cfg.KubernetesVersion, 46 bundleBuilder: bundleBuilder, 47 speedFactor: speedFactor, 48 } 49 } 50 51 func (u *upgradeClusterFactory) NewOperation(o internal.Orchestration, r orchestration.Runtime, i internal.Instance, state domain.LastOperationState) (orchestration.RuntimeOperation, error) { 52 id := uuid.New().String() 53 r.Region = i.ProviderRegion 54 op := internal.UpgradeClusterOperation{ 55 Operation: internal.Operation{ 56 ID: id, 57 Version: 0, 58 CreatedAt: time.Now(), 59 UpdatedAt: time.Now(), 60 Type: internal.OperationTypeUpgradeCluster, 61 InstanceID: r.InstanceID, 62 State: state, 63 Description: "Operation created", 64 OrchestrationID: o.OrchestrationID, 65 ProvisioningParameters: i.Parameters, 66 InstanceDetails: i.InstanceDetails, 67 RuntimeOperation: orchestration.RuntimeOperation{ 68 ID: id, 69 Runtime: r, 70 DryRun: o.Parameters.DryRun, 71 Notification: o.Parameters.Notification, 72 }, 73 }, 74 } 75 76 err := u.operationStorage.InsertUpgradeClusterOperation(op) 77 return op.RuntimeOperation, err 78 } 79 80 func (u *upgradeClusterFactory) ResumeOperations(orchestrationID string) ([]orchestration.RuntimeOperation, error) { 81 ops, _, _, err := u.operationStorage.ListUpgradeClusterOperationsByOrchestrationID(orchestrationID, dbmodel.OperationFilter{States: []string{orchestration.InProgress, orchestration.Retrying, orchestration.Pending}}) 82 if err != nil { 83 return nil, err 84 } 85 86 pending := make([]orchestration.RuntimeOperation, 0) 87 retrying := make([]orchestration.RuntimeOperation, 0) 88 inProgress := make([]orchestration.RuntimeOperation, 0) 89 for _, op := range ops { 90 if op.State == orchestration.Pending { 91 pending = append(pending, op.RuntimeOperation) 92 } 93 if op.State == orchestration.Retrying { 94 runtimeop, err := u.updateRetryingOperation(op) 95 if err != nil { 96 return nil, err 97 } 98 retrying = append(retrying, runtimeop) 99 } 100 if op.State == orchestration.InProgress { 101 inProgress = append(inProgress, op.RuntimeOperation) 102 } 103 } 104 105 return append(inProgress, append(retrying, pending...)...), nil 106 } 107 108 func (u *upgradeClusterFactory) CancelOperation(orchestrationID string, runtimeID string) error { 109 ops, _, _, err := u.operationStorage.ListUpgradeClusterOperationsByOrchestrationID(orchestrationID, dbmodel.OperationFilter{States: []string{orchestration.Pending}}) 110 if err != nil { 111 return fmt.Errorf("while listing upgrade cluster operations: %w", err) 112 } 113 for _, op := range ops { 114 if op.InstanceDetails.RuntimeID == runtimeID { 115 op.State = orchestration.Canceled 116 op.Description = "Operation was canceled" 117 _, err := u.operationStorage.UpdateUpgradeClusterOperation(op) 118 if err != nil { 119 return fmt.Errorf("while updating upgrade cluster operation: %w", err) 120 } 121 } 122 } 123 124 return nil 125 } 126 127 func (u *upgradeClusterFactory) CancelOperations(orchestrationID string) error { 128 ops, _, _, err := u.operationStorage.ListUpgradeClusterOperationsByOrchestrationID(orchestrationID, dbmodel.OperationFilter{States: []string{orchestration.Pending}}) 129 if err != nil { 130 return fmt.Errorf("while listing upgrade cluster operations: %w", err) 131 } 132 for _, op := range ops { 133 op.State = orchestration.Canceled 134 op.Description = "Operation was canceled" 135 _, err := u.operationStorage.UpdateUpgradeClusterOperation(op) 136 if err != nil { 137 return fmt.Errorf("while updating upgrade cluster operation: %w", err) 138 } 139 } 140 141 return nil 142 } 143 144 // get current retrying operations 145 func (u *upgradeClusterFactory) RetryOperations(retryOps []string) ([]orchestration.RuntimeOperation, error) { 146 147 result := []orchestration.RuntimeOperation{} 148 for _, opId := range retryOps { 149 runtimeop, err := u.operationStorage.GetUpgradeClusterOperationByID(opId) 150 if err != nil { 151 return nil, fmt.Errorf("while geting (retrying) upgrade cluster operation %s in storage: %w", opId, err) 152 153 } 154 result = append(result, runtimeop.RuntimeOperation) 155 } 156 157 return result, nil 158 } 159 160 // update storage in corresponding upgrade factory to avoid too many storage read and write 161 func (u *upgradeClusterFactory) updateRetryingOperation(op internal.UpgradeClusterOperation) (orchestration.RuntimeOperation, error) { 162 op.UpdatedAt = time.Now() 163 op.State = orchestration.Pending 164 op.Description = "Operation retry triggered" 165 op.ProvisionerOperationID = "" 166 167 opUpdated, err := u.operationStorage.UpdateUpgradeClusterOperation(op) 168 if err != nil { 169 return orchestration.RuntimeOperation{}, fmt.Errorf("while updating (retrying) upgrade cluster operation %s in storage: %w", op.Operation.ID, err) 170 } 171 172 return opUpdated.RuntimeOperation, nil 173 } 174 175 func (u *upgradeClusterFactory) QueryOperation(orchestrationID string, r orchestration.Runtime) (bool, orchestration.RuntimeOperation, error) { 176 ops, _, _, err := u.operationStorage.ListUpgradeClusterOperationsByOrchestrationID(orchestrationID, dbmodel.OperationFilter{States: []string{orchestration.Pending}}) 177 if err != nil { 178 return false, orchestration.RuntimeOperation{}, fmt.Errorf("while listing upgrade cluster operations: %w", err) 179 } 180 for _, op := range ops { 181 if op.InstanceDetails.RuntimeID == r.RuntimeID { 182 return true, op.RuntimeOperation, nil 183 } 184 } 185 186 return false, orchestration.RuntimeOperation{}, nil 187 } 188 189 func (u *upgradeClusterFactory) QueryOperations(orchestrationID string) ([]orchestration.RuntimeOperation, error) { 190 ops, _, _, err := u.operationStorage.ListUpgradeClusterOperationsByOrchestrationID(orchestrationID, dbmodel.OperationFilter{States: []string{orchestration.Pending}}) 191 if err != nil { 192 return []orchestration.RuntimeOperation{}, fmt.Errorf("while listing upgrade cluster operations: %w", err) 193 } 194 result := []orchestration.RuntimeOperation{} 195 for _, op := range ops { 196 result = append(result, op.RuntimeOperation) 197 } 198 199 return result, nil 200 } 201 202 func (u *upgradeClusterFactory) NotifyOperation(orchestrationID string, runtimeID string, oState string, notifyState orchestration.NotificationStateType) error { 203 ops, _, _, err := u.operationStorage.ListUpgradeClusterOperationsByOrchestrationID(orchestrationID, dbmodel.OperationFilter{States: []string{oState}}) 204 if err != nil { 205 return fmt.Errorf("while listing upgrade cluster operations: %w", err) 206 } 207 for _, op := range ops { 208 if op.InstanceDetails.RuntimeID == runtimeID { 209 op.RuntimeOperation.NotificationState = notifyState 210 _, err := u.operationStorage.UpdateUpgradeClusterOperation(op) 211 if err != nil { 212 return fmt.Errorf("while updating pending upgrade cluster operation %s in storage: %w", op.Operation.ID, err) 213 } 214 } 215 } 216 return nil 217 }