313 lines
13 KiB
Go
313 lines
13 KiB
Go
//
|
|
// Copyright (c) 2019-2023 Red Hat, Inc.
|
|
// This program and the accompanying materials are made
|
|
// available under the terms of the Eclipse Public License 2.0
|
|
// which is available at https://www.eclipse.org/legal/epl-2.0/
|
|
//
|
|
// SPDX-License-Identifier: EPL-2.0
|
|
//
|
|
// Contributors:
|
|
// Red Hat, Inc. - initial API and implementation
|
|
//
|
|
|
|
package usernamespace
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"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/common/utils"
|
|
"github.com/eclipse-che/che-operator/pkg/deploy"
|
|
corev1 "k8s.io/api/core/v1"
|
|
"k8s.io/apimachinery/pkg/api/errors"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/runtime"
|
|
"k8s.io/utils/pointer"
|
|
|
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"k8s.io/apimachinery/pkg/types"
|
|
)
|
|
|
|
const (
|
|
eclipseCheNamespace = "eclipse-che"
|
|
userNamespace = "user-namespace"
|
|
objectName = "che-workspaces-config"
|
|
)
|
|
|
|
var (
|
|
objectKeyInUserNs = types.NamespacedName{Name: objectName, Namespace: userNamespace}
|
|
objectKeyInCheNs = types.NamespacedName{Name: objectName, Namespace: eclipseCheNamespace}
|
|
)
|
|
|
|
func TestSyncConfigMap(t *testing.T) {
|
|
deployContext := test.GetDeployContext(nil, []runtime.Object{
|
|
&corev1.ConfigMap{
|
|
TypeMeta: metav1.TypeMeta{
|
|
Kind: "ConfigMap",
|
|
APIVersion: "v1",
|
|
},
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: objectName,
|
|
Namespace: "eclipse-che",
|
|
Labels: map[string]string{
|
|
constants.KubernetesPartOfLabelKey: constants.CheEclipseOrg,
|
|
constants.KubernetesComponentLabelKey: constants.WorkspacesConfig,
|
|
},
|
|
Annotations: map[string]string{},
|
|
},
|
|
Data: map[string]string{
|
|
"a": "b",
|
|
},
|
|
Immutable: pointer.Bool(false),
|
|
}})
|
|
|
|
workspaceConfigReconciler := NewWorkspacesConfigReconciler(
|
|
deployContext.ClusterAPI.Client,
|
|
deployContext.ClusterAPI.NonCachingClient,
|
|
deployContext.ClusterAPI.Scheme,
|
|
NewNamespaceCache(deployContext.ClusterAPI.NonCachingClient))
|
|
|
|
// Sync ConfigMap
|
|
err := workspaceConfigReconciler.syncWorkspacesConfig(context.TODO(), userNamespace)
|
|
assert.Nil(t, err)
|
|
assertSyncConfig(t, workspaceConfigReconciler, 2, v1ConfigMapGKV)
|
|
|
|
// Check ConfigMap in a user namespace is created
|
|
cm := &corev1.ConfigMap{}
|
|
err = workspaceConfigReconciler.client.Get(context.TODO(), objectKeyInUserNs, cm)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, "b", cm.Data["a"])
|
|
assert.Equal(t, false, *cm.Immutable)
|
|
assert.Equal(t, constants.WorkspacesConfig, cm.Labels[constants.KubernetesComponentLabelKey])
|
|
assert.Equal(t, constants.CheEclipseOrg, cm.Labels[constants.KubernetesPartOfLabelKey])
|
|
assert.Equal(t, "true", cm.Labels["controller.devfile.io/watch-configmap"])
|
|
assert.Equal(t, "true", cm.Labels["controller.devfile.io/mount-to-devworkspace"])
|
|
|
|
// Update src ConfigMap
|
|
cm = &corev1.ConfigMap{}
|
|
err = workspaceConfigReconciler.client.Get(context.TODO(), objectKeyInCheNs, cm)
|
|
assert.Nil(t, err)
|
|
cm.Data["a"] = "c"
|
|
err = workspaceConfigReconciler.client.Update(context.TODO(), cm)
|
|
assert.Nil(t, err)
|
|
|
|
// Sync ConfigMap
|
|
err = workspaceConfigReconciler.syncWorkspacesConfig(context.TODO(), userNamespace)
|
|
assert.Nil(t, err)
|
|
assertSyncConfig(t, workspaceConfigReconciler, 2, v1ConfigMapGKV)
|
|
|
|
// Check that destination ConfigMap is updated
|
|
cm = &corev1.ConfigMap{}
|
|
err = workspaceConfigReconciler.client.Get(context.TODO(), objectKeyInUserNs, cm)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, "c", cm.Data["a"])
|
|
assert.Equal(t, false, *cm.Immutable)
|
|
assert.Equal(t, constants.WorkspacesConfig, cm.Labels[constants.KubernetesComponentLabelKey])
|
|
assert.Equal(t, constants.CheEclipseOrg, cm.Labels[constants.KubernetesPartOfLabelKey])
|
|
assert.Equal(t, "true", cm.Labels["controller.devfile.io/watch-configmap"])
|
|
assert.Equal(t, "true", cm.Labels["controller.devfile.io/mount-to-devworkspace"])
|
|
|
|
// Update dst ConfigMap
|
|
cm = &corev1.ConfigMap{}
|
|
err = workspaceConfigReconciler.client.Get(context.TODO(), objectKeyInUserNs, cm)
|
|
assert.Nil(t, err)
|
|
cm.Data["a"] = "new-c"
|
|
err = workspaceConfigReconciler.client.Update(context.TODO(), cm)
|
|
assert.Nil(t, err)
|
|
|
|
// Sync ConfigMap
|
|
err = workspaceConfigReconciler.syncWorkspacesConfig(context.TODO(), userNamespace)
|
|
assert.Nil(t, err)
|
|
assertSyncConfig(t, workspaceConfigReconciler, 2, v1ConfigMapGKV)
|
|
|
|
// Check that destination ConfigMap is reverted
|
|
cm = &corev1.ConfigMap{}
|
|
err = workspaceConfigReconciler.client.Get(context.TODO(), objectKeyInUserNs, cm)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, "c", cm.Data["a"])
|
|
assert.Equal(t, false, *cm.Immutable)
|
|
assert.Equal(t, constants.WorkspacesConfig, cm.Labels[constants.KubernetesComponentLabelKey])
|
|
assert.Equal(t, constants.CheEclipseOrg, cm.Labels[constants.KubernetesPartOfLabelKey])
|
|
assert.Equal(t, "true", cm.Labels["controller.devfile.io/watch-configmap"])
|
|
assert.Equal(t, "true", cm.Labels["controller.devfile.io/mount-to-devworkspace"])
|
|
|
|
// Update dst ConfigMap in the way that it won't be reverted
|
|
cm = &corev1.ConfigMap{}
|
|
err = workspaceConfigReconciler.client.Get(context.TODO(), objectKeyInUserNs, cm)
|
|
assert.Nil(t, err)
|
|
cm.Annotations = map[string]string{"new-annotation": "new-test"}
|
|
utils.AddMap(cm.Labels, map[string]string{"new-label": "new-test"})
|
|
err = workspaceConfigReconciler.client.Update(context.TODO(), cm)
|
|
assert.Nil(t, err)
|
|
|
|
// Sync ConfigMap
|
|
err = workspaceConfigReconciler.syncWorkspacesConfig(context.TODO(), userNamespace)
|
|
assert.Nil(t, err)
|
|
assertSyncConfig(t, workspaceConfigReconciler, 2, v1ConfigMapGKV)
|
|
|
|
// Check that destination ConfigMap is not reverted
|
|
cm = &corev1.ConfigMap{}
|
|
err = workspaceConfigReconciler.client.Get(context.TODO(), objectKeyInUserNs, cm)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, "c", cm.Data["a"])
|
|
assert.Equal(t, false, *cm.Immutable)
|
|
assert.Equal(t, constants.WorkspacesConfig, cm.Labels[constants.KubernetesComponentLabelKey])
|
|
assert.Equal(t, constants.CheEclipseOrg, cm.Labels[constants.KubernetesPartOfLabelKey])
|
|
assert.Equal(t, "true", cm.Labels["controller.devfile.io/watch-configmap"])
|
|
assert.Equal(t, "true", cm.Labels["controller.devfile.io/mount-to-devworkspace"])
|
|
assert.Equal(t, "new-test", cm.Labels["new-label"])
|
|
assert.Equal(t, "new-test", cm.Annotations["new-annotation"])
|
|
|
|
// Delete dst ConfigMap
|
|
err = deploy.DeleteIgnoreIfNotFound(context.TODO(), deployContext.ClusterAPI.Client, objectKeyInUserNs, &corev1.ConfigMap{})
|
|
assert.Nil(t, err)
|
|
|
|
// Sync ConfigMap
|
|
err = workspaceConfigReconciler.syncWorkspacesConfig(context.TODO(), userNamespace)
|
|
assert.Nil(t, err)
|
|
assertSyncConfig(t, workspaceConfigReconciler, 2, v1ConfigMapGKV)
|
|
|
|
// Check that destination ConfigMap is reverted
|
|
cm = &corev1.ConfigMap{}
|
|
err = workspaceConfigReconciler.client.Get(context.TODO(), objectKeyInUserNs, cm)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, "c", cm.Data["a"])
|
|
assert.Equal(t, false, *cm.Immutable)
|
|
assert.Equal(t, constants.WorkspacesConfig, cm.Labels[constants.KubernetesComponentLabelKey])
|
|
assert.Equal(t, constants.CheEclipseOrg, cm.Labels[constants.KubernetesPartOfLabelKey])
|
|
assert.Equal(t, "true", cm.Labels["controller.devfile.io/watch-configmap"])
|
|
assert.Equal(t, "true", cm.Labels["controller.devfile.io/mount-to-devworkspace"])
|
|
|
|
// Delete src ConfigMap
|
|
err = deploy.DeleteIgnoreIfNotFound(context.TODO(), deployContext.ClusterAPI.Client, objectKeyInCheNs, &corev1.ConfigMap{})
|
|
assert.Nil(t, err)
|
|
|
|
// Sync ConfigMap
|
|
err = workspaceConfigReconciler.syncWorkspacesConfig(context.TODO(), userNamespace)
|
|
assert.Nil(t, err)
|
|
assertSyncConfig(t, workspaceConfigReconciler, 0, v1ConfigMapGKV)
|
|
|
|
// Check that destination ConfigMap in a user namespace is deleted
|
|
cm = &corev1.ConfigMap{}
|
|
err = workspaceConfigReconciler.client.Get(context.TODO(), objectKeyInUserNs, cm)
|
|
assert.NotNil(t, err)
|
|
assert.True(t, errors.IsNotFound(err))
|
|
}
|
|
|
|
func TestSyncConfigMapShouldMergeLabelsAndAnnotationsOnUpdate(t *testing.T) {
|
|
deployContext := test.GetDeployContext(nil, []runtime.Object{
|
|
&corev1.ConfigMap{
|
|
TypeMeta: metav1.TypeMeta{
|
|
Kind: "ConfigMap",
|
|
APIVersion: "v1",
|
|
},
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: objectName,
|
|
Namespace: "eclipse-che",
|
|
Labels: map[string]string{
|
|
"label": "label-value",
|
|
constants.KubernetesPartOfLabelKey: constants.CheEclipseOrg,
|
|
constants.KubernetesComponentLabelKey: constants.WorkspacesConfig,
|
|
},
|
|
Annotations: map[string]string{
|
|
"annotation": "annotation-value",
|
|
},
|
|
},
|
|
Data: map[string]string{
|
|
"a": "b",
|
|
},
|
|
}})
|
|
|
|
workspaceConfigReconciler := NewWorkspacesConfigReconciler(
|
|
deployContext.ClusterAPI.Client,
|
|
deployContext.ClusterAPI.NonCachingClient,
|
|
deployContext.ClusterAPI.Scheme,
|
|
NewNamespaceCache(deployContext.ClusterAPI.NonCachingClient))
|
|
|
|
// Sync ConfigMap
|
|
err := workspaceConfigReconciler.syncWorkspacesConfig(context.TODO(), userNamespace)
|
|
assert.Nil(t, err)
|
|
assertSyncConfig(t, workspaceConfigReconciler, 2, v1ConfigMapGKV)
|
|
|
|
// Check ConfigMap in a user namespace is created
|
|
cm := &corev1.ConfigMap{}
|
|
err = workspaceConfigReconciler.client.Get(context.TODO(), objectKeyInUserNs, cm)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, constants.WorkspacesConfig, cm.Labels[constants.KubernetesComponentLabelKey])
|
|
assert.Equal(t, constants.CheEclipseOrg, cm.Labels[constants.KubernetesPartOfLabelKey])
|
|
assert.Equal(t, "true", cm.Labels["controller.devfile.io/watch-configmap"])
|
|
assert.Equal(t, "true", cm.Labels["controller.devfile.io/mount-to-devworkspace"])
|
|
assert.Equal(t, "label-value", cm.Labels["label"])
|
|
assert.Equal(t, "annotation-value", cm.Annotations["annotation"])
|
|
|
|
// Update labels and annotations on dst ConfigMap
|
|
cm = &corev1.ConfigMap{}
|
|
err = workspaceConfigReconciler.client.Get(context.TODO(), objectKeyInUserNs, cm)
|
|
assert.Nil(t, err)
|
|
utils.AddMap(cm.Labels, map[string]string{"new-label": "new-label-value"})
|
|
utils.AddMap(cm.Annotations, map[string]string{"new-annotation": "new-annotation-value"})
|
|
err = workspaceConfigReconciler.client.Update(context.TODO(), cm)
|
|
assert.Nil(t, err)
|
|
|
|
// Sync ConfigMap
|
|
err = workspaceConfigReconciler.syncWorkspacesConfig(context.TODO(), userNamespace)
|
|
assert.Nil(t, err)
|
|
assertSyncConfig(t, workspaceConfigReconciler, 2, v1ConfigMapGKV)
|
|
|
|
// Check that destination ConfigMap is not reverted
|
|
cm = &corev1.ConfigMap{}
|
|
err = workspaceConfigReconciler.client.Get(context.TODO(), objectKeyInUserNs, cm)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, constants.WorkspacesConfig, cm.Labels[constants.KubernetesComponentLabelKey])
|
|
assert.Equal(t, constants.CheEclipseOrg, cm.Labels[constants.KubernetesPartOfLabelKey])
|
|
assert.Equal(t, "true", cm.Labels["controller.devfile.io/watch-configmap"])
|
|
assert.Equal(t, "true", cm.Labels["controller.devfile.io/mount-to-devworkspace"])
|
|
assert.Equal(t, "label-value", cm.Labels["label"])
|
|
assert.Equal(t, "new-label-value", cm.Labels["new-label"])
|
|
assert.Equal(t, "annotation-value", cm.Annotations["annotation"])
|
|
assert.Equal(t, "new-annotation-value", cm.Annotations["new-annotation"])
|
|
|
|
// Update src ConfigMap
|
|
cm = &corev1.ConfigMap{}
|
|
err = workspaceConfigReconciler.client.Get(context.TODO(), objectKeyInCheNs, cm)
|
|
assert.Nil(t, err)
|
|
cm.Data["a"] = "c"
|
|
utils.AddMap(cm.Labels, map[string]string{"label": "label-value-2"})
|
|
utils.AddMap(cm.Annotations, map[string]string{"annotation": "annotation-value-2"})
|
|
err = workspaceConfigReconciler.client.Update(context.TODO(), cm)
|
|
assert.Nil(t, err)
|
|
|
|
// Sync ConfigMap
|
|
err = workspaceConfigReconciler.syncWorkspacesConfig(context.TODO(), userNamespace)
|
|
assert.Nil(t, err)
|
|
assertSyncConfig(t, workspaceConfigReconciler, 2, v1ConfigMapGKV)
|
|
|
|
// Check that destination ConfigMap is updated but old labels and annotations are preserved
|
|
cm = &corev1.ConfigMap{}
|
|
err = workspaceConfigReconciler.client.Get(context.TODO(), objectKeyInUserNs, cm)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, "c", cm.Data["a"])
|
|
assert.Equal(t, constants.WorkspacesConfig, cm.Labels[constants.KubernetesComponentLabelKey])
|
|
assert.Equal(t, constants.CheEclipseOrg, cm.Labels[constants.KubernetesPartOfLabelKey])
|
|
assert.Equal(t, "true", cm.Labels["controller.devfile.io/watch-configmap"])
|
|
assert.Equal(t, "true", cm.Labels["controller.devfile.io/mount-to-devworkspace"])
|
|
assert.Equal(t, "label-value-2", cm.Labels["label"])
|
|
assert.Equal(t, "new-label-value", cm.Labels["new-label"])
|
|
assert.Equal(t, "annotation-value-2", cm.Annotations["annotation"])
|
|
assert.Equal(t, "new-annotation-value", cm.Annotations["new-annotation"])
|
|
}
|
|
|
|
func assertSyncConfig(t *testing.T, workspaceConfigReconciler *WorkspacesConfigReconciler, expectedNumberOfRecords int, gkv schema.GroupVersionKind) {
|
|
cm, err := workspaceConfigReconciler.getSyncConfig(context.TODO(), userNamespace)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, expectedNumberOfRecords, len(cm.Data))
|
|
if expectedNumberOfRecords == 2 {
|
|
assert.Contains(t, cm.Data, buildKey(gkv, objectName, userNamespace))
|
|
assert.Contains(t, cm.Data, buildKey(gkv, objectName, eclipseCheNamespace))
|
|
}
|
|
}
|