diff --git a/pkg/handlers/generic/lifecycle/config/cm.go b/pkg/handlers/generic/lifecycle/config/cm.go index bbba7015e..7e2a6088d 100644 --- a/pkg/handlers/generic/lifecycle/config/cm.go +++ b/pkg/handlers/generic/lifecycle/config/cm.go @@ -123,6 +123,9 @@ func (h *HelmChartGetter) getInfoFor( return &settings, err } +// For returns the HelmChart info for the given component from the configmap referenced in the cluster variables. +// It first checks the configmap referenced in the cluster variables. +// If not found, it returns the HelmChart info from the default configmap. func (h *HelmChartGetter) For( ctx context.Context, log logr.Logger, diff --git a/pkg/webhook/cluster/addons_validator.go b/pkg/webhook/cluster/addons_validator.go index eb42e5924..50cdbf520 100644 --- a/pkg/webhook/cluster/addons_validator.go +++ b/pkg/webhook/cluster/addons_validator.go @@ -10,7 +10,7 @@ import ( v1 "k8s.io/api/admission/v1" corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" + apierrors "k8s.io/apimachinery/pkg/api/errors" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" ctrlclient "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" @@ -91,7 +91,7 @@ func validateCustomHelmChartConfigMapExists( Name: name, }, configMap) if err != nil { - if errors.IsNotFound(err) { + if apierrors.IsNotFound(err) { return fmt.Errorf( "HelmChart ConfigMap %q referenced in the cluster variables not found: %w", name, diff --git a/pkg/webhook/cluster/addons_validator_webhook_test.go b/pkg/webhook/cluster/addons_validator_webhook_test.go new file mode 100644 index 000000000..a80a23f58 --- /dev/null +++ b/pkg/webhook/cluster/addons_validator_webhook_test.go @@ -0,0 +1,97 @@ +// Copyright 2024 Nutanix. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +package cluster + +import ( + "strings" + "testing" + + . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" + + "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/api/v1alpha1" + apivariables "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/api/variables" +) + +func TestBlockWithNonExistentHelmChartConfig(t *testing.T) { + g := NewWithT(t) + + cluster := &clusterv1.Cluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "cluster-with-non-existent-helm-chart-configmap", + Namespace: metav1.NamespaceDefault, + }, + Spec: clusterv1.ClusterSpec{ + Topology: &clusterv1.Topology{ + Variables: []clusterv1.ClusterVariable{ + *helmChartConfigVariable(t, "non-existent-helm-chart-configmap"), + }, + }, + }, + } + err := env.Client.Create(ctx, cluster) + g.Expect(err).To(HaveOccurred()) + g.Expect(strings.Contains( + err.Error(), + "HelmChart ConfigMap \"non-existent-helm-chart-configmap\" referenced in the cluster variables not found", + )). + To(BeTrue(), "Expected error to be of type IsNotFound") +} + +func TestAllowWithExistingHelmChartConfig(t *testing.T) { + g := NewWithT(t) + + configmap := &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "custom-helm-chart-configmap", + Namespace: metav1.NamespaceDefault, + }, + Data: map[string]string{ + "ccm": "test chart config data", + }, + } + g.Expect(env.Client.Create(ctx, configmap)).ToNot(HaveOccurred()) + + cluster := &clusterv1.Cluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "custom-helm-chart-configmap", + Namespace: metav1.NamespaceDefault, + }, + Spec: clusterv1.ClusterSpec{ + Topology: &clusterv1.Topology{ + Variables: []clusterv1.ClusterVariable{ + *helmChartConfigVariable(t, "non-existent-helm-chart-configmap"), + }, + }, + }, + } + g.Expect(env.Client.Create(ctx, cluster)).ToNot(HaveOccurred()) +} + +func helmChartConfigVariable( + t *testing.T, + name string, +) *clusterv1.ClusterVariable { + t.Helper() + hv, err := apivariables.MarshalToClusterVariable( + "clusterConfig", + &apivariables.ClusterConfigSpec{ + Addons: &apivariables.Addons{ + GenericAddons: v1alpha1.GenericAddons{ + HelmChartConfig: &v1alpha1.HelmChartConfig{ + ConfigMapRef: v1alpha1.LocalObjectReference{ + Name: name, + }, + }, + }, + }, + }, + ) + if err != nil { + t.Fatalf("failed to create addon variable: %s", err) + } + return hv +}