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
parent
0d79ca94b0
commit
954e5a64f6
3
Makefile
3
Makefile
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -120,8 +120,9 @@ const (
|
|||
GatewayAuthenticationContainerName = "oauth-proxy"
|
||||
GatewayAuthorizationContainerName = "kube-rbac-proxy"
|
||||
|
||||
//
|
||||
// common
|
||||
CheEclipseOrg = "che.eclipse.org"
|
||||
DevWorkspaceOperator = "devworkspace-operator"
|
||||
InstallOrUpdateFailed = "InstallOrUpdateFailed"
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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{})
|
||||
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue