Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion api/v2/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

51 changes: 5 additions & 46 deletions controllers/usernamespace/usernamespace_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -310,57 +310,16 @@ func (r *CheUserNamespaceReconciler) reconcileTrustedCerts(ctx context.Context,
if err := deleteLegacyObject("trusted-ca-certs", &corev1.ConfigMap{}, targetNs, checluster, deployContext); err != nil {
return err
}
targetConfigMapName := prefixedName("trusted-ca-certs")

delConfigMap := func() error {
_, err := deploy.Delete(deployContext, client.ObjectKey{Name: targetConfigMapName, Namespace: targetNs}, &corev1.ConfigMap{})
return err
}

sourceMap := &corev1.ConfigMap{}
if err := r.client.Get(ctx, client.ObjectKey{Name: tls.CheMergedCABundleCertsCMName, Namespace: checluster.Namespace}, sourceMap); err != nil {
if !errors.IsNotFound(err) {
return err
}

return delConfigMap()
}

targetMap := &corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{
Kind: "ConfigMap",
APIVersion: "v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: targetConfigMapName,
Namespace: targetNs,
Labels: defaults.AddStandardLabelsForComponent(checluster, userSettingsComponentLabelValue, map[string]string{
dwconstants.DevWorkspaceMountLabel: "true",
dwconstants.DevWorkspaceWatchConfigMapLabel: "true",
}),
Annotations: addToFirst(sourceMap.Annotations, map[string]string{
dwconstants.DevWorkspaceMountAsAnnotation: "file",
dwconstants.DevWorkspaceMountPathAnnotation: "/public-certs",
}),
},
Data: sourceMap.Data,
}
// Remove trusted-ca-certs ConfigMap from the target namespace to reduce the number of ConfigMaps
// and avoid mounting the same certificates under different paths.
// See cerificates#syncCheCABundleCerts
trustedCACertsCMKey := client.ObjectKey{Name: prefixedName("trusted-ca-certs"), Namespace: targetNs}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

on dogfooding, I see there is che-trusted-ca-certs, is it going to be removed by prefix?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, testing configuration of 3.19, am I correct that che-trusted-ca-certs and ca-certs-merged are pretty much identical?

Screenshot 2025-03-19 at 14 21 37

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. che-trusted-ca-certs will be removed completedly
  2. yes, those CMs are identical

_, err := deploy.Delete(deployContext, trustedCACertsCMKey, &corev1.ConfigMap{})

_, err := deploy.Sync(deployContext, targetMap, deploy.ConfigMapDiffOpts)
return err
}

func addToFirst(first map[string]string, second map[string]string) map[string]string {
if first == nil {
first = map[string]string{}
}
for k, v := range second {
first[k] = v
}

return first
}

func (r *CheUserNamespaceReconciler) reconcileProxySettings(ctx context.Context, targetNs string, checluster *chev2.CheCluster, deployContext *chetypes.DeployContext) error {
if err := deleteLegacyObject("proxy-settings", &corev1.ConfigMap{}, targetNs, checluster, deployContext); err != nil {
return err
Expand Down
9 changes: 0 additions & 9 deletions controllers/usernamespace/usernamespace_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,15 +268,6 @@ func TestCreatesDataInNamespace(t *testing.T) {
assert.Equal(t, corev1.SecretTypeOpaque, cert.Type, "Unexpected secret type")
assert.Equal(t, true, *cert.Immutable, "Unexpected mutability of the secret")

caCerts := corev1.ConfigMap{}
assert.NoError(t, cl.Get(ctx, client.ObjectKey{Name: "che-trusted-ca-certs", Namespace: namespace.GetName()}, &caCerts))
assert.Equal(t, "file", caCerts.GetAnnotations()[dwconstants.DevWorkspaceMountAsAnnotation], "trusted certs should be annotated as mount as 'file'")
assert.Equal(t, "/public-certs", caCerts.GetAnnotations()[dwconstants.DevWorkspaceMountPathAnnotation], "trusted certs annotated as mounted to an unexpected path")
assert.Equal(t, "true", caCerts.GetLabels()[dwconstants.DevWorkspaceMountLabel], "trusted certs should be labeled as mounted")
assert.Equal(t, 2, len(caCerts.Data), "Expecting exactly 2 data entries in the trusted cert config map")
assert.Equal(t, "trusted cert 1", string(caCerts.Data["trusted1"]), "Unexpected trusted cert 1 value")
assert.Equal(t, "trusted cert 2", string(caCerts.Data["trusted2"]), "Unexpected trusted cert 2 value")

gitTlsConfig := corev1.ConfigMap{}
assert.NoError(t, cl.Get(ctx, client.ObjectKey{Name: "che-git-tls-creds", Namespace: namespace.GetName()}, &gitTlsConfig))
assert.Equal(t, "true", gitTlsConfig.Labels[dwconstants.DevWorkspaceGitTLSLabel])
Expand Down
3 changes: 3 additions & 0 deletions pkg/common/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ const (
CheEclipseOrgScmServerEndpoint = "che.eclipse.org/scm-server-endpoint"
CheEclipseOrgManagedAnnotationsDigest = "che.eclipse.org/managed-annotations-digest"
CheEclipseOrgScmGitHubDisableSubdomainIsolation = "che.eclipse.org/scm-github-disable-subdomain-isolation"
OpenShiftIOOwningComponent = "openshift.io/owning-component"
ConfigOpenShiftIOInjectTrustedCaBundle = "config.openshift.io/inject-trusted-cabundle"

// DevEnvironments
PerUserPVCStorageStrategy = "per-user"
Expand Down Expand Up @@ -128,6 +130,7 @@ const (
WorkspacesConfig = "workspaces-config"
InstallOrUpdateFailed = "InstallOrUpdateFailed"
FinalizerSuffix = "finalizers.che.eclipse.org"
PublicCertsDir = "/public-certs"

// DevWorkspace
DevWorkspaceServiceAccountName = "devworkspace-controller-serviceaccount"
Expand Down
42 changes: 22 additions & 20 deletions pkg/common/test/utils.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright (c) 2019-2023 Red Hat, Inc.
// Copyright (c) 2019-2025 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/
Expand All @@ -18,6 +18,8 @@ import (
"strings"
"testing"

"sigs.k8s.io/controller-runtime/pkg/reconcile"

securityv1 "github.com/openshift/api/security/v1"

controllerv1alpha1 "github.com/devfile/devworkspace-operator/apis/controller/v1alpha1"
Expand Down Expand Up @@ -85,26 +87,9 @@ func CompareResources(actualDeployment *appsv1.Deployment, expected TestExpected
)
}

func AssertEqualEnvVars(t *testing.T, expected []corev1.EnvVar, actual []corev1.EnvVar) {
assert.Equal(t, len(expected), len(actual))
for _, expectedEnvVar := range expected {
found := true
for _, actualEnvVar := range actual {
if expectedEnvVar.Name == actualEnvVar.Name && expectedEnvVar.Value == actualEnvVar.Value {
found = true
break
}
}

if !found {
t.Errorf("Expected env var %s=%s not found", expectedEnvVar.Name, expectedEnvVar.Value)
}
}
}

func ValidateSecurityContext(actualDeployment *appsv1.Deployment, t *testing.T) {
assert.Equal(t, corev1.Capability("ALL"), actualDeployment.Spec.Template.Spec.Containers[0].SecurityContext.Capabilities.Drop[0])
assert.Equal(t, pointer.BoolPtr(false), actualDeployment.Spec.Template.Spec.Containers[0].SecurityContext.AllowPrivilegeEscalation)
assert.Equal(t, pointer.Bool(false), actualDeployment.Spec.Template.Spec.Containers[0].SecurityContext.AllowPrivilegeEscalation)
}

func compareQuantity(resource string, actualQuantity *resource.Quantity, expected string, t *testing.T) {
Expand Down Expand Up @@ -164,7 +149,7 @@ func GetResourceQuantity(value string, defaultValue string) resource.Quantity {
}

func EnableTestMode() {
os.Setenv("MOCK_API", "1")
_ = os.Setenv("MOCK_API", "1")
}

func IsTestMode() bool {
Expand Down Expand Up @@ -216,3 +201,20 @@ func GetDeployContext(cheCluster *chev2.CheCluster, initObjs []runtime.Object) *
CheHost: strings.TrimPrefix(cheCluster.Status.CheURL, "https://"),
}
}

// EnsureReconcile runs the testReconcileFunc until it returns done=true or 10 iterations
func EnsureReconcile(
t *testing.T,
ctx *chetypes.DeployContext,
testReconcileFunc func(ctx *chetypes.DeployContext) (result reconcile.Result, done bool, err error)) {

for i := 0; i < 10; i++ {
_, done, err := testReconcileFunc(ctx)
assert.NoError(t, err)
if done {
return
}
}

assert.Fail(t, "Reconcile did not finish in 10 iterations")
}
5 changes: 4 additions & 1 deletion pkg/common/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ func GetPullPolicyFromDockerImage(dockerImage string) string {
return "IfNotPresent"
}

func GetMap(value map[string]string, defaultValue map[string]string) map[string]string {
func GetMapOrDefault(value map[string]string, defaultValue map[string]string) map[string]string {
ret := value
if len(value) < 1 {
ret = defaultValue
Expand Down Expand Up @@ -224,6 +224,9 @@ func AddMap(a map[string]string, b map[string]string) {
func MergeMaps(maps []map[string]string) map[string]string {
result := make(map[string]string)
for _, m := range maps {
//if m == nil {
// continue
//}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

leftover?

for k, v := range m {
result[k] = v
}
Expand Down
70 changes: 50 additions & 20 deletions pkg/deploy/configmap.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright (c) 2019-2023 Red Hat, Inc.
// Copyright (c) 2019-2025 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/
Expand Down Expand Up @@ -29,13 +29,35 @@ var ConfigMapDiffOpts = cmp.Options{
}),
}

// InitConfigMap returns a new ConfigMap Kubernetes object.
func InitConfigMap(
ctx *chetypes.DeployContext,
name string,
data map[string]string,
component string) *corev1.ConfigMap {

return &corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{
Kind: "ConfigMap",
APIVersion: "v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: ctx.CheCluster.Namespace,
Labels: GetLabels(component),
Annotations: map[string]string{},
},
Data: data,
}
}

func SyncConfigMapDataToCluster(
deployContext *chetypes.DeployContext,
name string,
data map[string]string,
component string) (bool, error) {

configMapSpec := GetConfigMapSpec(deployContext, name, data, component)
configMapSpec := InitConfigMap(deployContext, name, data, component)
return Sync(deployContext, configMapSpec, ConfigMapDiffOpts)
}

Expand All @@ -46,25 +68,33 @@ func SyncConfigMapSpecToCluster(
return Sync(deployContext, configMapSpec, ConfigMapDiffOpts)
}

func GetConfigMapSpec(
deployContext *chetypes.DeployContext,
name string,
data map[string]string,
component string) *corev1.ConfigMap {
// SyncConfigMap synchronizes the ConfigMap with the cluster.
func SyncConfigMap(
ctx *chetypes.DeployContext,
cm *corev1.ConfigMap,
ensuredLabels []string,
ensuredAnnotations []string) (bool, error) {

configMap := &corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{
Kind: "ConfigMap",
APIVersion: "v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: deployContext.CheCluster.Namespace,
Labels: GetLabels(component),
Annotations: map[string]string{},
},
Data: data,
diffs := cmp.Options{
cmpopts.IgnoreFields(corev1.ConfigMap{}, "TypeMeta"),
GetLabelsAndAnnotationsComparator(ensuredLabels, ensuredAnnotations),
}

return Sync(ctx, cm, diffs)
}

// SyncConfigMapIgnoreData synchronizes the ConfigMap with the cluster ignoring the data field.
func SyncConfigMapIgnoreData(
ctx *chetypes.DeployContext,
cm *corev1.ConfigMap,
ensuredLabels []string,
ensuredAnnotations []string) (bool, error) {

diffs := cmp.Options{
cmpopts.IgnoreFields(corev1.ConfigMap{}, "TypeMeta"),
cmpopts.IgnoreFields(corev1.ConfigMap{}, "Data"),
GetLabelsAndAnnotationsComparator(ensuredLabels, ensuredAnnotations),
}

return configMap
return Sync(ctx, cm, diffs)
}
4 changes: 2 additions & 2 deletions pkg/deploy/configmap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,14 @@ func TestSyncConfigMapSpecDataToCluster(t *testing.T) {
},
}

spec := GetConfigMapSpec(deployContext, "test", map[string]string{"a": "b"}, "che")
spec := InitConfigMap(deployContext, "test", map[string]string{"a": "b"}, "che")
done, err := SyncConfigMapSpecToCluster(deployContext, spec)
if !done || err != nil {
t.Fatalf("Failed to sync config map: %v", err)
}

// check if labels
spec = GetConfigMapSpec(deployContext, "test", map[string]string{"a": "b"}, "che")
spec = InitConfigMap(deployContext, "test", map[string]string{"a": "b"}, "che")
spec.ObjectMeta.Labels = map[string]string{"l": "v"}
_, err = SyncConfigMapSpecToCluster(deployContext, spec)
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions pkg/deploy/gateway/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ func GetConfigmapForGatewayConfig(
Namespace: deployContext.CheCluster.Namespace,
Labels: labels.Merge(
deploy.GetLabels(gatewayConfigComponentName),
utils.GetMap(deployContext.CheCluster.Spec.Networking.Auth.Gateway.ConfigLabels, constants.DefaultSingleHostGatewayConfigMapLabels)),
utils.GetMapOrDefault(deployContext.CheCluster.Spec.Networking.Auth.Gateway.ConfigLabels, constants.DefaultSingleHostGatewayConfigMapLabels)),
},
Data: map[string]string{
componentName + ".yml": string(gatewayConfigContent),
Expand Down Expand Up @@ -499,7 +499,7 @@ func getGatewayDeploymentSpec(ctx *chetypes.DeployContext) (*appsv1.Deployment,
}

func getContainersSpec(ctx *chetypes.DeployContext) []corev1.Container {
configLabelsMap := utils.GetMap(ctx.CheCluster.Spec.Networking.Auth.Gateway.ConfigLabels, constants.DefaultSingleHostGatewayConfigMapLabels)
configLabelsMap := utils.GetMapOrDefault(ctx.CheCluster.Spec.Networking.Auth.Gateway.ConfigLabels, constants.DefaultSingleHostGatewayConfigMapLabels)
gatewayImage := defaults.GetGatewayImage(ctx.CheCluster)
configSidecarImage := defaults.GetGatewayConfigSidecarImage(ctx.CheCluster)
configLabels := labels.FormatLabels(configLabelsMap)
Expand Down
15 changes: 14 additions & 1 deletion pkg/deploy/labels.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright (c) 2019-2023 Red Hat, Inc.
// Copyright (c) 2019-2025 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/
Expand Down Expand Up @@ -27,6 +27,19 @@ func GetLabels(component string) map[string]string {
}
}

func GetDefaultKubernetesLabelsWith(labels ...string) []string {
defaultK8sLabels := append(
[]string{
constants.KubernetesNameLabelKey,
constants.KubernetesInstanceLabelKey,
constants.KubernetesPartOfLabelKey,
constants.KubernetesComponentLabelKey,
constants.KubernetesManagedByLabelKey,
}, labels...)

return defaultK8sLabels
}

func GetManagedByLabel() string {
return defaults.GetCheFlavor() + "-operator"
}
Expand Down
21 changes: 21 additions & 0 deletions pkg/deploy/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,27 @@ func DeleteIgnoreIfNotFound(
return err
}

func GetLabelsAndAnnotationsComparator(
ensuredLabels []string,
ensuredAnnotations []string) cmp.Option {

return cmp.Comparer(func(x, y metav1.ObjectMeta) bool {
for _, label := range ensuredLabels {
if x.Labels[label] != y.Labels[label] {
return false
}
}

for _, annotation := range ensuredAnnotations {
if x.Annotations[annotation] != y.Annotations[annotation] {
return false
}
}

return true
})
}

// doCreate creates object.
// Return error if object cannot be created otherwise returns nil.
func doCreate(
Expand Down
Loading
Loading