fix: Improve a way to check if DevWorkspace resources must be managed… (#1467)

* fix: Improve a way to check if DevWorkspace resources must be managed by Che Operator

Signed-off-by: Anatolii Bazko <abazko@redhat.com>
pull/1470/head
Anatolii Bazko 2022-08-05 17:06:18 +03:00 committed by GitHub
parent 0d79ca94b0
commit 954e5a64f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 116 additions and 345 deletions

View File

@ -583,6 +583,9 @@ bundle: generate manifests download-kustomize download-operator-sdk ## Generate
yq -riY '.metadata.annotations.containerImage = "'$(IMG)'"' $${CSV_PATH}
yq -riY '.spec.install.spec.deployments[0].spec.template.spec.containers[0].image = "'$(IMG)'"' $${CSV_PATH}
# Add No Opt DWO environment variable
yq -riY '.spec.install.spec.deployments[0].spec.template.spec.containers[0].env += [{"name": "NO_OPT_DWO", "value": "true"}]' "$${CSV_PATH}"
# Format file
yq -riY "." "$${BUNDLE_PATH}/manifests/org.eclipse.che_checlusters.yaml"

View File

@ -76,7 +76,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-preview-openshift.v7.52.0-642.next
name: eclipse-che-preview-openshift.v7.52.0-643.next
namespace: placeholder
spec:
apiservicedefinitions: {}
@ -1138,6 +1138,8 @@ spec:
value: "1"
- name: ADD_COMPONENT_READINESS_INIT_CONTAINERS
value: "false"
- name: NO_OPT_DWO
value: 'true'
image: quay.io/eclipse/che-operator:next
imagePullPolicy: Always
livenessProbe:
@ -1390,7 +1392,7 @@ spec:
maturity: stable
provider:
name: Eclipse Foundation
version: 7.52.0-642.next
version: 7.52.0-643.next
webhookdefinitions:
- admissionReviewVersions:
- v1

View File

@ -120,8 +120,9 @@ const (
GatewayAuthenticationContainerName = "oauth-proxy"
GatewayAuthorizationContainerName = "kube-rbac-proxy"
//
// common
CheEclipseOrg = "che.eclipse.org"
DevWorkspaceOperator = "devworkspace-operator"
InstallOrUpdateFailed = "InstallOrUpdateFailed"
)

View File

@ -22,6 +22,9 @@ import (
"strings"
"time"
"github.com/devfile/devworkspace-operator/pkg/infrastructure"
"github.com/eclipse-che/che-operator/pkg/common/test"
"k8s.io/apimachinery/pkg/labels"
corev1 "k8s.io/api/core/v1"
@ -269,3 +272,11 @@ func Whitelist(hostname string) (value string) {
}
return hostname
}
func GetOperatorNamespace() (string, error) {
if test.IsTestMode() {
return "eclipse-che", nil
}
return infrastructure.GetOperatorNamespace()
}

View File

@ -34,14 +34,6 @@ const (
DevWorkspaceNamespace = "devworkspace-controller"
DevWorkspaceDeploymentName = "devworkspace-controller-manager"
DevWorkspaceWebhookName = "controller.devfile.io"
SubscriptionResourceName = "subscriptions"
ClusterServiceVersionResourceName = "clusterserviceversions"
DevWorkspaceCSVNamePrefix = "devworkspace-operator"
WebTerminalOperatorSubscriptionName = "web-terminal"
OperatorNamespace = "openshift-operators"
)
var (
@ -62,19 +54,22 @@ func NewDevWorkspaceReconciler() *DevWorkspaceReconciler {
}
func (d *DevWorkspaceReconciler) Reconcile(ctx *chetypes.DeployContext) (reconcile.Result, bool, error) {
if isDevWorkspaceOperatorCSVExists(ctx) {
// Do nothing if DevWorkspace has been already deployed via OLM
return reconcile.Result{}, true, nil
}
if infrastructure.IsOpenShift() {
wtoInstalled, err := isWebTerminalSubscriptionExist(ctx)
if err != nil {
// Do nothing if explicitly declared not to manage Dev Workspace resources
isNoOptDWO, err := isNoOptDWO()
if isNoOptDWO {
return reconcile.Result{}, true, nil
} else if err != nil {
return reconcile.Result{Requeue: true}, false, err
}
if wtoInstalled {
// Do nothing if WTO exists since it should bring or embeds DWO
// Do nothing if Dev Workspace operator has owner (installed via OLM).
// In this case Dev Workspace operator resources mustn't be managed by Che operator.
isDevWorkspaceOperatorHasOwner, err := isDevWorkspaceOperatorHasOwner(ctx)
if isDevWorkspaceOperatorHasOwner {
return reconcile.Result{}, true, nil
} else if err != nil {
return reconcile.Result{Requeue: true}, false, err
}
}
@ -91,26 +86,9 @@ func (d *DevWorkspaceReconciler) Reconcile(ctx *chetypes.DeployContext) (reconci
namespaceOwnershipAnnotation := namespace.GetAnnotations()[constants.CheEclipseOrgNamespace]
if namespaceOwnershipAnnotation == "" {
// don't manage DWO if namespace is create by someone else not but not Che Operator
// don't manage DWO if namespace is created by someone else not but not Che Operator
return reconcile.Result{}, true, nil
}
// if DWO is managed by another Che, check if we should take control under it after possible removal
if namespaceOwnershipAnnotation != ctx.CheCluster.Namespace {
isOnlyOneOperatorManagesDWResources, err := isOnlyOneOperatorManagesDWResources(ctx)
if err != nil {
return reconcile.Result{Requeue: true}, false, err
}
if !isOnlyOneOperatorManagesDWResources {
// Don't take a control over DWO if CheCluster in another CR is handling it
return reconcile.Result{}, true, nil
}
namespace.GetAnnotations()[constants.CheEclipseOrgNamespace] = ctx.CheCluster.Namespace
_, err = deploy.Sync(ctx, namespace)
if err != nil {
return reconcile.Result{Requeue: true}, false, err
}
}
}
// check if DW exists on the cluster

View File

@ -77,49 +77,6 @@ func TestShouldSyncObjectIfItWasCreatedBySameOriginHashDifferent(t *testing.T) {
assert.Equal(t, "c", actual.Data["a"], "data mismatch")
}
func TestShouldNotSyncObjectIfThereIsAnotherCheCluster(t *testing.T) {
cheCluster := &chev2.CheCluster{
ObjectMeta: metav1.ObjectMeta{
Name: "eclipse-che",
Namespace: "eclipse-che-1",
},
}
anotherCheCluster := &chev2.CheCluster{
ObjectMeta: metav1.ObjectMeta{
Name: "eclipse-che",
Namespace: "eclipse-che-2",
},
}
deployContext := test.GetDeployContext(cheCluster, []runtime.Object{anotherCheCluster})
// creates initial object
initialObject := deploy.GetConfigMapSpec(deployContext, "test", map[string]string{"a": "b"}, "test")
initialObject.SetAnnotations(map[string]string{
constants.CheEclipseOrgHash256: "hash-2",
constants.CheEclipseOrgNamespace: "eclipse-che-2",
})
isCreated, err := deploy.Create(deployContext, initialObject)
assert.NoError(t, err)
assert.True(t, isCreated)
// tries to sync object with a new hash but different origin
newObject := deploy.GetConfigMapSpec(deployContext, "test", map[string]string{"a": "c"}, "test")
newObject.GetAnnotations()[constants.CheEclipseOrgHash256] = "newHash"
isDone, err := syncObject(deployContext, newObject, "eclipse-che")
assert.NoError(t, err, "Failed to sync object")
assert.True(t, isDone, "Failed to sync object")
// reads object and check content, object isn't supposed to be updated
actual := &corev1.ConfigMap{}
exists, err := deploy.GetNamespacedObject(deployContext, "test", actual)
assert.NoError(t, err, "failed to get configmap")
assert.True(t, exists, "configmap is not found")
assert.Equal(t, "eclipse-che-2", actual.GetAnnotations()[constants.CheEclipseOrgNamespace], "hash annotation mismatch")
assert.Equal(t, "hash-2", actual.GetAnnotations()[constants.CheEclipseOrgHash256], "namespace annotation mismatch")
assert.Equal(t, "b", actual.Data["a"], "data mismatch")
}
func TestShouldNotSyncObjectIfHashIsEqual(t *testing.T) {
deployContext := test.GetDeployContext(nil, []runtime.Object{})

View File

@ -15,7 +15,7 @@ import (
"context"
"os"
crdv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
defaults "github.com/eclipse-che/che-operator/pkg/common/operator-defaults"
"k8s.io/apimachinery/pkg/types"
k8sErrors "k8s.io/apimachinery/pkg/api/errors"
@ -27,22 +27,22 @@ import (
"github.com/eclipse-che/che-operator/pkg/common/constants"
"github.com/eclipse-che/che-operator/pkg/common/test"
"github.com/eclipse-che/che-operator/pkg/deploy"
operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1"
"github.com/stretchr/testify/assert"
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
fakeDiscovery "k8s.io/client-go/discovery/fake"
"sigs.k8s.io/controller-runtime/pkg/client"
)
const (
DevWorkspaceCSVName = "devworkspace-operator.v0.11.0"
)
func TestReconcileDevWorkspace(t *testing.T) {
cheOperatorDeployment := &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: defaults.GetCheFlavor() + "-operator",
Namespace: "eclipse-che",
},
}
type testCase struct {
name string
infrastructure infrastructure.Type
@ -82,13 +82,9 @@ func TestReconcileDevWorkspace(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
deployContext := test.GetDeployContext(testCase.cheCluster, []runtime.Object{})
deployContext := test.GetDeployContext(testCase.cheCluster, []runtime.Object{cheOperatorDeployment})
infrastructure.InitializeForTesting(testCase.infrastructure)
err := os.Setenv("ALLOW_DEVWORKSPACE_ENGINE", "true")
assert.NoError(t, err)
devWorkspaceReconciler := NewDevWorkspaceReconciler()
_, done, err := devWorkspaceReconciler.Reconcile(deployContext)
assert.NoError(t, err, "Reconcile failed")
@ -98,13 +94,12 @@ func TestReconcileDevWorkspace(t *testing.T) {
}
func TestShouldReconcileDevWorkspaceIfDevWorkspaceDeploymentExists(t *testing.T) {
cheCluster := &chev2.CheCluster{
cheOperatorDeployment := &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: defaults.GetCheFlavor() + "-operator",
Namespace: "eclipse-che",
Name: "eclipse-che",
},
}
devworkspaceDeployment := &appsv1.Deployment{
TypeMeta: metav1.TypeMeta{
Kind: "Deployment",
@ -113,14 +108,15 @@ func TestShouldReconcileDevWorkspaceIfDevWorkspaceDeploymentExists(t *testing.T)
ObjectMeta: metav1.ObjectMeta{
Name: DevWorkspaceDeploymentName,
Namespace: DevWorkspaceNamespace,
Labels: map[string]string{
constants.KubernetesPartOfLabelKey: constants.DevWorkspaceOperator,
constants.KubernetesNameLabelKey: constants.DevWorkspaceController,
},
},
}
deployContext := test.GetDeployContext(cheCluster, []runtime.Object{devworkspaceDeployment})
deployContext := test.GetDeployContext(nil, []runtime.Object{devworkspaceDeployment, cheOperatorDeployment})
infrastructure.InitializeForTesting(infrastructure.OpenShiftv4)
err := os.Setenv("ALLOW_DEVWORKSPACE_ENGINE", "false")
assert.NoError(t, err)
devWorkspaceReconciler := NewDevWorkspaceReconciler()
_, done, err := devWorkspaceReconciler.Reconcile(deployContext)
@ -129,112 +125,83 @@ func TestShouldReconcileDevWorkspaceIfDevWorkspaceDeploymentExists(t *testing.T)
assert.True(t, done, "DevWorkspace should be reconciled.")
}
func TestReconcileWhenWebTerminalSubscriptionExists(t *testing.T) {
cheCluster := &chev2.CheCluster{
func TestShouldNotReconcileDevWorkspaceIfDevWorkspaceDeploymentManagedByOLM(t *testing.T) {
cheOperatorDeployment := &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: defaults.GetCheFlavor() + "-operator",
Namespace: "eclipse-che",
},
}
subscription := &operatorsv1alpha1.Subscription{
devworkspaceDeployment := &appsv1.Deployment{
TypeMeta: metav1.TypeMeta{
Kind: "Deployment",
APIVersion: "apps/v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: WebTerminalOperatorSubscriptionName,
Namespace: OperatorNamespace,
},
Spec: &operatorsv1alpha1.SubscriptionSpec{},
}
deployContext := test.GetDeployContext(cheCluster, []runtime.Object{subscription})
deployContext.ClusterAPI.Scheme.AddKnownTypes(operatorsv1alpha1.SchemeGroupVersion, &operatorsv1alpha1.Subscription{})
deployContext.ClusterAPI.Scheme.AddKnownTypes(admissionregistrationv1.SchemeGroupVersion, &admissionregistrationv1.MutatingWebhookConfiguration{})
deployContext.ClusterAPI.DiscoveryClient.(*fakeDiscovery.FakeDiscovery).Fake.Resources = []*metav1.APIResourceList{
{
APIResources: []metav1.APIResource{
{Name: SubscriptionResourceName},
Name: DevWorkspaceDeploymentName,
Namespace: DevWorkspaceNamespace,
Labels: map[string]string{
constants.KubernetesPartOfLabelKey: constants.DevWorkspaceOperator,
constants.KubernetesNameLabelKey: constants.DevWorkspaceController,
},
OwnerReferences: []metav1.OwnerReference{{}},
},
}
deployContext := test.GetDeployContext(nil, []runtime.Object{cheOperatorDeployment, devworkspaceDeployment})
infrastructure.InitializeForTesting(infrastructure.OpenShiftv4)
err := os.Setenv("ALLOW_DEVWORKSPACE_ENGINE", "true")
assert.NoError(t, err)
devWorkspaceReconciler := NewDevWorkspaceReconciler()
_, done, err := devWorkspaceReconciler.Reconcile(deployContext)
assert.NoError(t, err)
assert.True(t, done)
// verify that DWO is not provisioned
namespace := &corev1.Namespace{}
err = deployContext.ClusterAPI.NonCachingClient.Get(context.TODO(), types.NamespacedName{Name: DevWorkspaceNamespace}, namespace)
err = deployContext.ClusterAPI.NonCachingClient.Get(context.TODO(), types.NamespacedName{Name: DevWorkspaceNamespace}, &corev1.Namespace{})
assert.True(t, k8sErrors.IsNotFound(err))
}
func TestReconcileDevWorkspaceCheckIfCSVExists(t *testing.T) {
cheCluster := &chev2.CheCluster{
func TestShouldNotReconcileDevWorkspaceIfNoOptExists(t *testing.T) {
os.Setenv("NO_OPT_DWO", "true")
cheOperatorDeployment := &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: defaults.GetCheFlavor() + "-operator",
Namespace: "eclipse-che",
},
}
devWorkspaceCSV := &operatorsv1alpha1.ClusterServiceVersion{
ObjectMeta: metav1.ObjectMeta{
Name: DevWorkspaceCSVName,
Namespace: "openshift-operators",
},
Spec: operatorsv1alpha1.ClusterServiceVersionSpec{},
}
deployContext := test.GetDeployContext(cheCluster, []runtime.Object{})
deployContext.ClusterAPI.Scheme.AddKnownTypes(operatorsv1alpha1.SchemeGroupVersion, &operatorsv1alpha1.ClusterServiceVersion{})
deployContext.ClusterAPI.Scheme.AddKnownTypes(operatorsv1alpha1.SchemeGroupVersion, &operatorsv1alpha1.ClusterServiceVersionList{})
err := deployContext.ClusterAPI.Client.Create(context.TODO(), devWorkspaceCSV)
assert.NoError(t, err)
deployContext.ClusterAPI.DiscoveryClient.(*fakeDiscovery.FakeDiscovery).Fake.Resources = []*metav1.APIResourceList{
{
APIResources: []metav1.APIResource{
{
Name: ClusterServiceVersionResourceName,
},
},
},
}
deployContext := test.GetDeployContext(nil, []runtime.Object{cheOperatorDeployment})
infrastructure.InitializeForTesting(infrastructure.OpenShiftv4)
err = os.Setenv("ALLOW_DEVWORKSPACE_ENGINE", "true")
assert.NoError(t, err)
devWorkspaceReconciler := NewDevWorkspaceReconciler()
_, done, err := devWorkspaceReconciler.Reconcile(deployContext)
assert.True(t, done, "Reconcile is not triggered")
assert.True(t, done)
// Get Devworkspace namespace. If error is thrown means devworkspace is not anymore installed if CSV is detected
err = deployContext.ClusterAPI.Client.Get(context.TODO(), client.ObjectKey{Name: DevWorkspaceNamespace}, &corev1.Namespace{})
assert.True(t, k8sErrors.IsNotFound(err), "DevWorkspace namespace is created when instead DWO CSV is expected to be created")
// verify that DWO is not provisioned
err = deployContext.ClusterAPI.NonCachingClient.Get(context.TODO(), types.NamespacedName{Name: DevWorkspaceNamespace}, &corev1.Namespace{})
assert.True(t, k8sErrors.IsNotFound(err))
os.Unsetenv("NO_OPT_DWO")
}
func TestReconcileDevWorkspaceIfUnmanagedDWONamespaceExists(t *testing.T) {
cheCluster := &chev2.CheCluster{
func TestShouldNotReconcileDevWorkspaceIfUnmanagedDWONamespaceExists(t *testing.T) {
cheOperatorDeployment := &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: defaults.GetCheFlavor() + "-operator",
Namespace: "eclipse-che",
},
}
dwoNamespace := &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: DevWorkspaceNamespace,
// no che annotations are there
},
}
deployContext := test.GetDeployContext(cheCluster, []runtime.Object{})
err := deployContext.ClusterAPI.Client.Create(context.TODO(), dwoNamespace)
assert.NoError(t, err)
deployContext := test.GetDeployContext(nil, []runtime.Object{cheOperatorDeployment, dwoNamespace})
infrastructure.InitializeForTesting(infrastructure.OpenShiftv4)
err = os.Setenv("ALLOW_DEVWORKSPACE_ENGINE", "true")
assert.NoError(t, err)
devWorkspaceReconciler := NewDevWorkspaceReconciler()
_, done, err := devWorkspaceReconciler.Reconcile(deployContext)
@ -246,12 +213,12 @@ func TestReconcileDevWorkspaceIfUnmanagedDWONamespaceExists(t *testing.T) {
}
func TestReconcileDevWorkspaceIfManagedDWONamespaceExists(t *testing.T) {
cheCluster := &chev2.CheCluster{
cheOperatorDeployment := &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: defaults.GetCheFlavor() + "-operator",
Namespace: "eclipse-che",
},
}
dwoNamespace := &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: DevWorkspaceNamespace,
@ -261,19 +228,9 @@ func TestReconcileDevWorkspaceIfManagedDWONamespaceExists(t *testing.T) {
// no che annotations are there
},
}
deployContext := test.GetDeployContext(cheCluster, []runtime.Object{})
err := deployContext.ClusterAPI.NonCachingClient.Create(context.TODO(), dwoNamespace)
assert.NoError(t, err)
exists, err := deploy.Get(deployContext,
types.NamespacedName{Name: DevWorkspaceNamespace, Namespace: DevWorkspaceNamespace},
&corev1.Namespace{})
deployContext := test.GetDeployContext(nil, []runtime.Object{cheOperatorDeployment, dwoNamespace})
infrastructure.InitializeForTesting(infrastructure.OpenShiftv4)
err = os.Setenv("ALLOW_DEVWORKSPACE_ENGINE", "true")
assert.NoError(t, err)
devWorkspaceReconciler := NewDevWorkspaceReconciler()
_, done, err := devWorkspaceReconciler.Reconcile(deployContext)
@ -281,120 +238,9 @@ func TestReconcileDevWorkspaceIfManagedDWONamespaceExists(t *testing.T) {
assert.NoError(t, err, "Reconcile failed")
// check is reconcile created deployment if existing namespace is not annotated in che specific way
exists, err = deploy.Get(deployContext,
exists, err := deploy.Get(deployContext,
types.NamespacedName{Name: DevWorkspaceDeploymentName, Namespace: DevWorkspaceNamespace},
&appsv1.Deployment{})
assert.True(t, exists, "DevWorkspace deployment is not created in Che managed DWO namespace")
assert.NoError(t, err, "Failed to get devworkspace deployment")
}
func TestReconcileDevWorkspaceIfManagedDWOShouldBeTakenUnderControl(t *testing.T) {
cheCluster := &chev2.CheCluster{
ObjectMeta: metav1.ObjectMeta{
Namespace: "eclipse-che",
},
}
dwoNamespace := &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: DevWorkspaceNamespace,
Annotations: map[string]string{
constants.CheEclipseOrgNamespace: "eclipse-che-removed",
},
// no che annotations are there
},
}
deployContext := test.GetDeployContext(cheCluster, []runtime.Object{})
deployContext.ClusterAPI.Scheme.AddKnownTypes(crdv1.SchemeGroupVersion, &crdv1.CustomResourceDefinition{})
err := deployContext.ClusterAPI.NonCachingClient.Create(context.TODO(), dwoNamespace)
assert.NoError(t, err)
exists, err := deploy.Get(deployContext,
types.NamespacedName{Name: DevWorkspaceNamespace, Namespace: DevWorkspaceNamespace},
&corev1.Namespace{})
infrastructure.InitializeForTesting(infrastructure.OpenShiftv4)
err = os.Setenv("ALLOW_DEVWORKSPACE_ENGINE", "true")
assert.NoError(t, err)
devWorkspaceReconciler := NewDevWorkspaceReconciler()
_, done, err := devWorkspaceReconciler.Reconcile(deployContext)
assert.True(t, done, "Reconcile is not triggered")
assert.NoError(t, err, "Reconcile failed")
// check is reconcile updated namespace with according way
exists, err = deploy.Get(deployContext,
types.NamespacedName{Name: DevWorkspaceNamespace},
dwoNamespace)
assert.True(t, exists, "DevWorkspace Namespace does not exist")
assert.Equal(t, "eclipse-che", dwoNamespace.GetAnnotations()[constants.CheEclipseOrgNamespace])
// check that objects are sync
exists, err = deploy.Get(deployContext,
types.NamespacedName{Name: DevWorkspaceDeploymentName, Namespace: DevWorkspaceNamespace},
&appsv1.Deployment{})
assert.True(t, exists, "DevWorkspace deployment is not created in Che managed DWO namespace")
assert.NoError(t, err, "Failed to get devworkspace deployment")
}
func TestReconcileDevWorkspaceIfManagedDWOShouldNotBeTakenUnderControl(t *testing.T) {
cheCluster := &chev2.CheCluster{
ObjectMeta: metav1.ObjectMeta{
Namespace: "eclipse-che",
Name: "che-cluster",
},
}
cheCluster2 := &chev2.CheCluster{
ObjectMeta: metav1.ObjectMeta{
Namespace: "eclipse-che2",
Name: "che-cluster2",
},
}
dwoNamespace := &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: DevWorkspaceNamespace,
Annotations: map[string]string{
constants.CheEclipseOrgNamespace: "eclipse-che2",
},
// no che annotations are there
},
}
deployContext := test.GetDeployContext(cheCluster, []runtime.Object{})
deployContext.ClusterAPI.Scheme.AddKnownTypes(crdv1.SchemeGroupVersion, &crdv1.CustomResourceDefinition{})
err := deployContext.ClusterAPI.NonCachingClient.Create(context.TODO(), dwoNamespace)
assert.NoError(t, err)
err = deployContext.ClusterAPI.NonCachingClient.Create(context.TODO(), cheCluster2)
assert.NoError(t, err)
exists, err := deploy.Get(deployContext,
types.NamespacedName{Name: DevWorkspaceNamespace, Namespace: DevWorkspaceNamespace},
&corev1.Namespace{})
infrastructure.InitializeForTesting(infrastructure.OpenShiftv4)
err = os.Setenv("ALLOW_DEVWORKSPACE_ENGINE", "true")
assert.NoError(t, err)
devWorkspaceReconciler := NewDevWorkspaceReconciler()
_, done, err := devWorkspaceReconciler.Reconcile(deployContext)
assert.True(t, done, "Reconcile is not triggered")
assert.NoError(t, err, "Reconcile failed")
// check is reconcile updated namespace with according way
exists, err = deploy.Get(deployContext,
types.NamespacedName{Name: DevWorkspaceNamespace},
dwoNamespace)
assert.True(t, exists, "DevWorkspace Namespace does not exist")
assert.Equal(t, "eclipse-che2", dwoNamespace.GetAnnotations()[constants.CheEclipseOrgNamespace])
// check that objects are sync
exists, err = deploy.Get(deployContext,
types.NamespacedName{Name: DevWorkspaceDeploymentName, Namespace: DevWorkspaceNamespace},
&appsv1.Deployment{})
assert.False(t, exists, "DevWorkspace deployment is not created in Che managed DWO namespace")
assert.NoError(t, err, "Failed to get devworkspace deployment")
}

View File

@ -14,68 +14,19 @@ package devworkspace
import (
"context"
"strings"
"os"
"strconv"
chev2 "github.com/eclipse-che/che-operator/api/v2"
"github.com/eclipse-che/che-operator/pkg/common/chetypes"
"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"
operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1"
"github.com/sirupsen/logrus"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/labels"
"sigs.k8s.io/controller-runtime/pkg/client"
)
func isDevWorkspaceOperatorCSVExists(deployContext *chetypes.DeployContext) bool {
// If clusterserviceversions resource doesn't exist in cluster DWO as well will not be present
if !utils.IsK8SResourceServed(deployContext.ClusterAPI.DiscoveryClient, ClusterServiceVersionResourceName) {
return false
}
csvList := &operatorsv1alpha1.ClusterServiceVersionList{}
err := deployContext.ClusterAPI.NonCachingClient.List(context.TODO(), csvList, &client.ListOptions{Namespace: OperatorNamespace})
if err != nil {
logrus.Errorf("Failed to list csv: %v", err)
return false
}
for _, csv := range csvList.Items {
if strings.HasPrefix(csv.Name, DevWorkspaceCSVNamePrefix) {
return true
}
}
return false
}
func isWebTerminalSubscriptionExist(deployContext *chetypes.DeployContext) (bool, error) {
// If subscriptions resource doesn't exist in cluster WTO as well will not be present
if !utils.IsK8SResourceServed(deployContext.ClusterAPI.DiscoveryClient, SubscriptionResourceName) {
return false, nil
}
subscription := &operatorsv1alpha1.Subscription{}
if err := deployContext.ClusterAPI.NonCachingClient.Get(
context.TODO(),
types.NamespacedName{
Name: WebTerminalOperatorSubscriptionName,
Namespace: OperatorNamespace,
},
subscription); err != nil {
if apierrors.IsNotFound(err) {
return false, nil
}
return false, err
}
return true, nil
}
func createDwNamespace(deployContext *chetypes.DeployContext) (bool, error) {
namespace := &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
@ -90,12 +41,34 @@ func createDwNamespace(deployContext *chetypes.DeployContext) (bool, error) {
return deploy.CreateIfNotExists(deployContext, namespace)
}
func isOnlyOneOperatorManagesDWResources(deployContext *chetypes.DeployContext) (bool, error) {
cheClusters := &chev2.CheClusterList{}
err := deployContext.ClusterAPI.NonCachingClient.List(context.TODO(), cheClusters)
if err != nil {
func isNoOptDWO() (bool, error) {
value, exists := os.LookupEnv("NO_OPT_DWO")
if !exists {
return false, nil
}
return strconv.ParseBool(value)
}
func isDevWorkspaceOperatorHasOwner(ctx *chetypes.DeployContext) (bool, error) {
deployments := &appsv1.DeploymentList{}
if err := ctx.ClusterAPI.NonCachingClient.List(
context.TODO(),
deployments,
&client.ListOptions{
LabelSelector: labels.SelectorFromSet(map[string]string{
constants.KubernetesPartOfLabelKey: constants.DevWorkspaceOperator,
constants.KubernetesNameLabelKey: constants.DevWorkspaceController,
}),
}); err != nil {
return false, err
}
return len(cheClusters.Items) == 1, nil
for _, deployment := range deployments.Items {
if len(deployment.OwnerReferences) != 0 {
return true, nil
}
}
return false, nil
}