From a98d18233ec1aad5d7bc8e9deff6b8e30abc5fd7 Mon Sep 17 00:00:00 2001 From: Andrew O Date: Tue, 25 Apr 2023 01:43:55 -0400 Subject: [PATCH] feat: configure workspace deployment strategy with CheCluster CR (#1666) * feat: configure workspace deployment strategy with CheCluster CR Signed-off-by: Andrew Obuchowicz * chore: add tests for configuring workspace deployment strategy Signed-off-by: Andrew Obuchowicz * chore: update dev resources for devEnvironments.DeploymentStrategy Signed-off-by: Andrew Obuchowicz --------- Signed-off-by: Andrew Obuchowicz --- api/v2/checluster_types.go | 10 ++ .../che-operator.clusterserviceversion.yaml | 4 +- .../org.eclipse.che_checlusters.yaml | 14 ++ .../bases/org.eclipse.che_checlusters.yaml | 14 ++ deploy/deployment/kubernetes/combined.yaml | 14 ++ ....eclipse.che.CustomResourceDefinition.yaml | 14 ++ deploy/deployment/openshift/combined.yaml | 14 ++ ....eclipse.che.CustomResourceDefinition.yaml | 14 ++ ....eclipse.che.CustomResourceDefinition.yaml | 14 ++ pkg/common/constants/constants.go | 1 + .../dev_workspace_config.go | 3 + .../dev_workspace_config_test.go | 167 ++++++++++++++++-- 12 files changed, 269 insertions(+), 14 deletions(-) diff --git a/api/v2/checluster_types.go b/api/v2/checluster_types.go index a231d4cf2..9bb29c683 100644 --- a/api/v2/checluster_types.go +++ b/api/v2/checluster_types.go @@ -31,6 +31,7 @@ import ( imagepullerv1alpha1 "github.com/che-incubator/kubernetes-image-puller-operator/api/v1alpha1" devfile "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2" + appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -137,6 +138,15 @@ type CheClusterDevEnvironments struct { // +kubebuilder:validation:Minimum:=1 // +kubebuilder:default:=300 StartTimeoutSeconds *int32 `json:"startTimeoutSeconds,omitempty"` + // DeploymentStrategy defines the deployment strategy to use to replace existing workspace pods + // with new ones. The available deployment stragies are `Recreate` and `RollingUpdate`. + // With the `Recreate` deployment strategy, the existing workspace pod is killed before the new one is created. + // With the `RollingUpdate` deployment strategy, a new workspace pod is created and the existing workspace pod is deleted + // only when the new workspace pod is in a ready state. + // If not specified, the default `Recreate` deployment strategy is used. + // +optional + // +kubebuilder:validation:Enum=Recreate;RollingUpdate + DeploymentStrategy appsv1.DeploymentStrategyType `json:"deploymentStrategy,omitempty"` // Total number of workspaces, both stopped and running, that a user can keep. // The value, -1, allows users to keep an unlimited number of workspaces. // +kubebuilder:validation:Minimum:=-1 diff --git a/bundle/next/eclipse-che/manifests/che-operator.clusterserviceversion.yaml b/bundle/next/eclipse-che/manifests/che-operator.clusterserviceversion.yaml index c34e64b88..165e47bd1 100644 --- a/bundle/next/eclipse-che/manifests/che-operator.clusterserviceversion.yaml +++ b/bundle/next/eclipse-che/manifests/che-operator.clusterserviceversion.yaml @@ -77,7 +77,7 @@ metadata: operators.operatorframework.io/project_layout: go.kubebuilder.io/v3 repository: https://github.com/eclipse-che/che-operator support: Eclipse Foundation - name: eclipse-che.v7.65.0-789.next + name: eclipse-che.v7.66.0-790.next namespace: placeholder spec: apiservicedefinitions: {} @@ -1243,7 +1243,7 @@ spec: minKubeVersion: 1.19.0 provider: name: Eclipse Foundation - version: 7.65.0-789.next + version: 7.66.0-790.next webhookdefinitions: - admissionReviewVersions: - v1 diff --git a/bundle/next/eclipse-che/manifests/org.eclipse.che_checlusters.yaml b/bundle/next/eclipse-che/manifests/org.eclipse.che_checlusters.yaml index 65bb0a195..2bb9f16dc 100644 --- a/bundle/next/eclipse-che/manifests/org.eclipse.che_checlusters.yaml +++ b/bundle/next/eclipse-che/manifests/org.eclipse.che_checlusters.yaml @@ -7044,6 +7044,20 @@ spec: type: array type: object type: array + deploymentStrategy: + description: DeploymentStrategy defines the deployment strategy + to use to replace existing workspace pods with new ones. The + available deployment stragies are `Recreate` and `RollingUpdate`. + With the `Recreate` deployment strategy, the existing workspace + pod is killed before the new one is created. With the `RollingUpdate` + deployment strategy, a new workspace pod is created and the + existing workspace pod is deleted only when the new workspace + pod is in a ready state. If not specified, the default `Recreate` + deployment strategy is used. + enum: + - Recreate + - RollingUpdate + type: string disableContainerBuildCapabilities: description: Disables the container build capabilities. type: boolean diff --git a/config/crd/bases/org.eclipse.che_checlusters.yaml b/config/crd/bases/org.eclipse.che_checlusters.yaml index 7726af594..757cf6fe3 100644 --- a/config/crd/bases/org.eclipse.che_checlusters.yaml +++ b/config/crd/bases/org.eclipse.che_checlusters.yaml @@ -6849,6 +6849,20 @@ spec: type: array type: object type: array + deploymentStrategy: + description: DeploymentStrategy defines the deployment strategy + to use to replace existing workspace pods with new ones. The + available deployment stragies are `Recreate` and `RollingUpdate`. + With the `Recreate` deployment strategy, the existing workspace + pod is killed before the new one is created. With the `RollingUpdate` + deployment strategy, a new workspace pod is created and the + existing workspace pod is deleted only when the new workspace + pod is in a ready state. If not specified, the default `Recreate` + deployment strategy is used. + enum: + - Recreate + - RollingUpdate + type: string disableContainerBuildCapabilities: description: Disables the container build capabilities. type: boolean diff --git a/deploy/deployment/kubernetes/combined.yaml b/deploy/deployment/kubernetes/combined.yaml index 14af3bbaf..ca5b83ba1 100644 --- a/deploy/deployment/kubernetes/combined.yaml +++ b/deploy/deployment/kubernetes/combined.yaml @@ -6868,6 +6868,20 @@ spec: type: array type: object type: array + deploymentStrategy: + description: DeploymentStrategy defines the deployment strategy + to use to replace existing workspace pods with new ones. The + available deployment stragies are `Recreate` and `RollingUpdate`. + With the `Recreate` deployment strategy, the existing workspace + pod is killed before the new one is created. With the `RollingUpdate` + deployment strategy, a new workspace pod is created and the + existing workspace pod is deleted only when the new workspace + pod is in a ready state. If not specified, the default `Recreate` + deployment strategy is used. + enum: + - Recreate + - RollingUpdate + type: string disableContainerBuildCapabilities: description: Disables the container build capabilities. type: boolean diff --git a/deploy/deployment/kubernetes/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml b/deploy/deployment/kubernetes/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml index b5715b17a..24b982df5 100644 --- a/deploy/deployment/kubernetes/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml +++ b/deploy/deployment/kubernetes/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml @@ -6863,6 +6863,20 @@ spec: type: array type: object type: array + deploymentStrategy: + description: DeploymentStrategy defines the deployment strategy + to use to replace existing workspace pods with new ones. The + available deployment stragies are `Recreate` and `RollingUpdate`. + With the `Recreate` deployment strategy, the existing workspace + pod is killed before the new one is created. With the `RollingUpdate` + deployment strategy, a new workspace pod is created and the + existing workspace pod is deleted only when the new workspace + pod is in a ready state. If not specified, the default `Recreate` + deployment strategy is used. + enum: + - Recreate + - RollingUpdate + type: string disableContainerBuildCapabilities: description: Disables the container build capabilities. type: boolean diff --git a/deploy/deployment/openshift/combined.yaml b/deploy/deployment/openshift/combined.yaml index 0e2366d30..328b8474d 100644 --- a/deploy/deployment/openshift/combined.yaml +++ b/deploy/deployment/openshift/combined.yaml @@ -6868,6 +6868,20 @@ spec: type: array type: object type: array + deploymentStrategy: + description: DeploymentStrategy defines the deployment strategy + to use to replace existing workspace pods with new ones. The + available deployment stragies are `Recreate` and `RollingUpdate`. + With the `Recreate` deployment strategy, the existing workspace + pod is killed before the new one is created. With the `RollingUpdate` + deployment strategy, a new workspace pod is created and the + existing workspace pod is deleted only when the new workspace + pod is in a ready state. If not specified, the default `Recreate` + deployment strategy is used. + enum: + - Recreate + - RollingUpdate + type: string disableContainerBuildCapabilities: description: Disables the container build capabilities. type: boolean diff --git a/deploy/deployment/openshift/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml b/deploy/deployment/openshift/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml index 4c1257e3b..c660b99a3 100644 --- a/deploy/deployment/openshift/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml +++ b/deploy/deployment/openshift/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml @@ -6863,6 +6863,20 @@ spec: type: array type: object type: array + deploymentStrategy: + description: DeploymentStrategy defines the deployment strategy + to use to replace existing workspace pods with new ones. The + available deployment stragies are `Recreate` and `RollingUpdate`. + With the `Recreate` deployment strategy, the existing workspace + pod is killed before the new one is created. With the `RollingUpdate` + deployment strategy, a new workspace pod is created and the + existing workspace pod is deleted only when the new workspace + pod is in a ready state. If not specified, the default `Recreate` + deployment strategy is used. + enum: + - Recreate + - RollingUpdate + type: string disableContainerBuildCapabilities: description: Disables the container build capabilities. type: boolean diff --git a/helmcharts/next/crds/checlusters.org.eclipse.che.CustomResourceDefinition.yaml b/helmcharts/next/crds/checlusters.org.eclipse.che.CustomResourceDefinition.yaml index b5715b17a..24b982df5 100644 --- a/helmcharts/next/crds/checlusters.org.eclipse.che.CustomResourceDefinition.yaml +++ b/helmcharts/next/crds/checlusters.org.eclipse.che.CustomResourceDefinition.yaml @@ -6863,6 +6863,20 @@ spec: type: array type: object type: array + deploymentStrategy: + description: DeploymentStrategy defines the deployment strategy + to use to replace existing workspace pods with new ones. The + available deployment stragies are `Recreate` and `RollingUpdate`. + With the `Recreate` deployment strategy, the existing workspace + pod is killed before the new one is created. With the `RollingUpdate` + deployment strategy, a new workspace pod is created and the + existing workspace pod is deleted only when the new workspace + pod is in a ready state. If not specified, the default `Recreate` + deployment strategy is used. + enum: + - Recreate + - RollingUpdate + type: string disableContainerBuildCapabilities: description: Disables the container build capabilities. type: boolean diff --git a/pkg/common/constants/constants.go b/pkg/common/constants/constants.go index 32d90ee2c..85825dec0 100644 --- a/pkg/common/constants/constants.go +++ b/pkg/common/constants/constants.go @@ -99,6 +99,7 @@ const ( PerWorkspacePVCStorageStrategy = "per-workspace" EphemeralPVCStorageStrategy = "ephemeral" CommonPVCStorageStrategy = "common" + DefaultDeploymentStrategy = "Recreate" DefaultAutoProvision = true DefaultWorkspaceJavaOpts = "-XX:MaxRAM=150m -XX:MaxRAMFraction=2 -XX:+UseParallelGC " + "-XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=20 -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 " + diff --git a/pkg/deploy/dev-workspace-config/dev_workspace_config.go b/pkg/deploy/dev-workspace-config/dev_workspace_config.go index 3f80c6c35..5c81fa112 100644 --- a/pkg/deploy/dev-workspace-config/dev_workspace_config.go +++ b/pkg/deploy/dev-workspace-config/dev_workspace_config.go @@ -20,6 +20,7 @@ import ( "github.com/eclipse-che/che-operator/pkg/common/constants" "github.com/eclipse-che/che-operator/pkg/common/utils" "github.com/eclipse-che/che-operator/pkg/deploy" + v1 "k8s.io/api/apps/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/pointer" @@ -97,6 +98,8 @@ func updateWorkspaceConfig(cheCluster *chev2.CheCluster, operatorConfig *control } updateStartTimeout(operatorConfig, devEnvironments.StartTimeoutSeconds) + + operatorConfig.Workspace.DeploymentStrategy = v1.DeploymentStrategyType(utils.GetValue(string(devEnvironments.DeploymentStrategy), constants.DefaultDeploymentStrategy)) return nil } diff --git a/pkg/deploy/dev-workspace-config/dev_workspace_config_test.go b/pkg/deploy/dev-workspace-config/dev_workspace_config_test.go index 15c15b135..d897952ac 100644 --- a/pkg/deploy/dev-workspace-config/dev_workspace_config_test.go +++ b/pkg/deploy/dev-workspace-config/dev_workspace_config_test.go @@ -91,7 +91,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) { }, }, }, - expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{Workspace: &controllerv1alpha1.WorkspaceConfig{}}, + expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{Workspace: &controllerv1alpha1.WorkspaceConfig{DeploymentStrategy: "Recreate"}}, }, { name: "Create DevWorkspaceOperatorConfig with ephemeral strategy", @@ -117,7 +117,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) { }, }, }, - expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{Workspace: &controllerv1alpha1.WorkspaceConfig{}}, + expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{Workspace: &controllerv1alpha1.WorkspaceConfig{DeploymentStrategy: "Recreate"}}, }, { name: "Create DevWorkspaceOperatorConfig with StorageClassName only", @@ -140,7 +140,8 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) { }, expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{ Workspace: &controllerv1alpha1.WorkspaceConfig{ - StorageClassName: pointer.StringPtr("test-storage"), + StorageClassName: pointer.StringPtr("test-storage"), + DeploymentStrategy: "Recreate", }, }, }, @@ -170,6 +171,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) { DefaultStorageSize: &controllerv1alpha1.StorageSizes{ Common: &quantity15Gi, }, + DeploymentStrategy: "Recreate", }, }, }, @@ -199,6 +201,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) { DefaultStorageSize: &controllerv1alpha1.StorageSizes{ PerWorkspace: &quantity15Gi, }, + DeploymentStrategy: "Recreate", }, }, }, @@ -248,6 +251,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) { DefaultStorageSize: &controllerv1alpha1.StorageSizes{ PerWorkspace: &quantity15Gi, }, + DeploymentStrategy: "Recreate", }, }, }, @@ -297,6 +301,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) { DefaultStorageSize: &controllerv1alpha1.StorageSizes{ Common: &quantity15Gi, }, + DeploymentStrategy: "Recreate", }, }, }, @@ -350,6 +355,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) { DefaultStorageSize: &controllerv1alpha1.StorageSizes{ Common: &quantity15Gi, }, + DeploymentStrategy: "Recreate", }, }, }, @@ -367,7 +373,9 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) { }, }, expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{ - Workspace: &controllerv1alpha1.WorkspaceConfig{}, + Workspace: &controllerv1alpha1.WorkspaceConfig{ + DeploymentStrategy: "Recreate", + }, }, }, { @@ -394,6 +402,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) { }, AllowPrivilegeEscalation: pointer.BoolPtr(true), }, + DeploymentStrategy: "Recreate", }, }, }, @@ -445,6 +454,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) { }, AllowPrivilegeEscalation: pointer.BoolPtr(true), }, + DeploymentStrategy: "Recreate", }, }, }, @@ -478,6 +488,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) { Common: &quantity10Gi, }, ContainerSecurityContext: &corev1.SecurityContext{}, + DeploymentStrategy: "Recreate", }, }, }, @@ -488,6 +499,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) { DefaultStorageSize: &controllerv1alpha1.StorageSizes{ Common: &quantity10Gi, }, + DeploymentStrategy: "Recreate", }, }, }, @@ -507,7 +519,8 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) { }, expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{ Workspace: &controllerv1alpha1.WorkspaceConfig{ - ProgressTimeout: "600s", + ProgressTimeout: "600s", + DeploymentStrategy: "Recreate", }, }, }, @@ -551,7 +564,8 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) { DefaultStorageSize: &controllerv1alpha1.StorageSizes{ Common: &quantity10Gi, }, - ProgressTimeout: "600s", + ProgressTimeout: "600s", + DeploymentStrategy: "Recreate", }, }, }, @@ -596,7 +610,8 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) { DefaultStorageSize: &controllerv1alpha1.StorageSizes{ Common: &quantity10Gi, }, - ProgressTimeout: "420s", + ProgressTimeout: "420s", + DeploymentStrategy: "Recreate", }, }, }, @@ -640,6 +655,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) { DefaultStorageSize: &controllerv1alpha1.StorageSizes{ Common: &quantity10Gi, }, + DeploymentStrategy: "Recreate", }, }, }, @@ -703,6 +719,7 @@ func TestReconcileServiceAccountConfig(t *testing.T) { ServiceAccountName: "service-account", DisableCreation: pointer.BoolPtr(false), }, + DeploymentStrategy: "Recreate", }, }, }, @@ -728,6 +745,7 @@ func TestReconcileServiceAccountConfig(t *testing.T) { ServiceAccountName: "service-account", DisableCreation: pointer.BoolPtr(true), }, + DeploymentStrategy: "Recreate", }, }, }, @@ -747,6 +765,7 @@ func TestReconcileServiceAccountConfig(t *testing.T) { ServiceAccount: &controllerv1alpha1.ServiceAccountConfig{ DisableCreation: pointer.BoolPtr(false), }, + DeploymentStrategy: "Recreate", }, }, }, @@ -770,6 +789,7 @@ func TestReconcileServiceAccountConfig(t *testing.T) { ServiceAccount: &controllerv1alpha1.ServiceAccountConfig{ DisableCreation: pointer.BoolPtr(false), }, + DeploymentStrategy: "Recreate", }, }, }, @@ -817,7 +837,8 @@ func TestReconcileDevWorkspaceConfigPodSchedulerName(t *testing.T) { }, expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{ Workspace: &controllerv1alpha1.WorkspaceConfig{ - SchedulerName: "test-scheduler", + SchedulerName: "test-scheduler", + DeploymentStrategy: "Recreate", }, }, }, @@ -848,7 +869,8 @@ func TestReconcileDevWorkspaceConfigPodSchedulerName(t *testing.T) { }, expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{ Workspace: &controllerv1alpha1.WorkspaceConfig{ - SchedulerName: "test-scheduler", + SchedulerName: "test-scheduler", + DeploymentStrategy: "Recreate", }, }, }, @@ -884,7 +906,8 @@ func TestReconcileDevWorkspaceConfigPodSchedulerName(t *testing.T) { }, expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{ Workspace: &controllerv1alpha1.WorkspaceConfig{ - SchedulerName: "test-scheduler", + SchedulerName: "test-scheduler", + DeploymentStrategy: "Recreate", }, }, }, @@ -919,7 +942,9 @@ func TestReconcileDevWorkspaceConfigPodSchedulerName(t *testing.T) { }, }, expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{ - Workspace: &controllerv1alpha1.WorkspaceConfig{}, + Workspace: &controllerv1alpha1.WorkspaceConfig{ + DeploymentStrategy: "Recreate", + }, }, }, } @@ -993,6 +1018,7 @@ func TestReconcileDevWorkspaceConfigServiceAccountTokens(t *testing.T) { ExpirationSeconds: 180, }, }}, + DeploymentStrategy: "Recreate", }, }, }, @@ -1052,6 +1078,7 @@ func TestReconcileDevWorkspaceConfigServiceAccountTokens(t *testing.T) { }, }, }, + DeploymentStrategy: "Recreate", }, }, }, @@ -1113,6 +1140,7 @@ func TestReconcileDevWorkspaceConfigServiceAccountTokens(t *testing.T) { }, }, }, + DeploymentStrategy: "Recreate", }, }, }, @@ -1163,7 +1191,8 @@ func TestReconcileDevWorkspaceConfigServiceAccountTokens(t *testing.T) { }, expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{ Workspace: &controllerv1alpha1.WorkspaceConfig{ - ServiceAccount: &controllerv1alpha1.ServiceAccountConfig{}, + ServiceAccount: &controllerv1alpha1.ServiceAccountConfig{}, + DeploymentStrategy: "Recreate", }, }, }, @@ -1185,3 +1214,117 @@ func TestReconcileDevWorkspaceConfigServiceAccountTokens(t *testing.T) { }) } } + +func TestReconcileDevWorkspaceConfigDeploymentStrategy(t *testing.T) { + type testCase struct { + name string + cheCluster *chev2.CheCluster + existedObjects []runtime.Object + expectedOperatorConfig *controllerv1alpha1.OperatorConfiguration + } + + var testCases = []testCase{ + { + name: "Create DevWorkspaceOperatorConfig with DeploymentStrategy", + cheCluster: &chev2.CheCluster{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "eclipse-che", + Name: "eclipse-che", + }, + Spec: chev2.CheClusterSpec{ + DevEnvironments: chev2.CheClusterDevEnvironments{ + DeploymentStrategy: "Recreate", + }, + }, + }, + expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{ + Workspace: &controllerv1alpha1.WorkspaceConfig{ + DeploymentStrategy: "Recreate", + }, + }, + }, + { + name: "Update existing DevWorkspaceOperatorConfig when DeploymentStrategy is added", + cheCluster: &chev2.CheCluster{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "eclipse-che", + Name: "eclipse-che", + }, + Spec: chev2.CheClusterSpec{ + DevEnvironments: chev2.CheClusterDevEnvironments{ + DeploymentStrategy: "Recreate", + }, + }, + }, + existedObjects: []runtime.Object{ + &controllerv1alpha1.DevWorkspaceOperatorConfig{ + ObjectMeta: metav1.ObjectMeta{ + Name: devWorkspaceConfigName, + Namespace: "eclipse-che", + }, + TypeMeta: metav1.TypeMeta{ + Kind: "DevWorkspaceOperatorConfig", + APIVersion: controllerv1alpha1.GroupVersion.String(), + }, + }, + }, + expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{ + Workspace: &controllerv1alpha1.WorkspaceConfig{ + DeploymentStrategy: "Recreate", + }, + }, + }, + { + name: "Update existing DevWorkspaceOperatorConfig when DeploymentStrategy is changed", + cheCluster: &chev2.CheCluster{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "eclipse-che", + Name: "eclipse-che", + }, + Spec: chev2.CheClusterSpec{ + DevEnvironments: chev2.CheClusterDevEnvironments{ + DeploymentStrategy: "RollingUpdate", + }, + }, + }, + existedObjects: []runtime.Object{ + &controllerv1alpha1.DevWorkspaceOperatorConfig{ + ObjectMeta: metav1.ObjectMeta{ + Name: devWorkspaceConfigName, + Namespace: "eclipse-che", + }, + TypeMeta: metav1.TypeMeta{ + Kind: "DevWorkspaceOperatorConfig", + APIVersion: controllerv1alpha1.GroupVersion.String(), + }, + Config: &controllerv1alpha1.OperatorConfiguration{ + Workspace: &controllerv1alpha1.WorkspaceConfig{ + DeploymentStrategy: "Recreate", + }, + }, + }, + }, + expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{ + Workspace: &controllerv1alpha1.WorkspaceConfig{ + DeploymentStrategy: "RollingUpdate", + }, + }, + }, + } + + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + deployContext := test.GetDeployContext(testCase.cheCluster, []runtime.Object{}) + infrastructure.InitializeForTesting(infrastructure.OpenShiftv4) + + devWorkspaceConfigReconciler := NewDevWorkspaceConfigReconciler() + _, _, err := devWorkspaceConfigReconciler.Reconcile(deployContext) + assert.NoError(t, err) + + dwoc := &controllerv1alpha1.DevWorkspaceOperatorConfig{} + err = deployContext.ClusterAPI.Client.Get(context.TODO(), types.NamespacedName{Name: devWorkspaceConfigName, Namespace: testCase.cheCluster.Namespace}, dwoc) + assert.NoError(t, err) + assert.Equal(t, testCase.expectedOperatorConfig.Workspace.DeploymentStrategy, dwoc.Config.Workspace.DeploymentStrategy) + }) + } +}