Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
5 changes: 0 additions & 5 deletions controllers/clusterprofile_predicates.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,6 @@ func ClusterProfilePredicates(logger logr.Logger) predicate.Predicate {
return true
}

// Skip reconciliation when only finalizers changed (e.g., we added/removed our own).
if !reflect.DeepEqual(newCP.Finalizers, oldCP.Finalizers) {
return false
}

// React when access providers change.
if !reflect.DeepEqual(newCP.Status.AccessProviders, oldCP.Status.AccessProviders) {
logger.V(logs.LogVerbose).Info("ClusterProfile access providers changed, will reconcile")
Expand Down
24 changes: 22 additions & 2 deletions controllers/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"fmt"
"os"
"os/exec"
"reflect"
"time"

"github.com/go-logr/logr"
Expand Down Expand Up @@ -246,13 +247,28 @@ func reconcileKubeconfigSecret(ctx context.Context, c client.Client,
return c.Update(ctx, existing)
}

// sveltosClusterLabels returns the labels to set on the SveltosCluster.
// All labels from the ClusterProfile are copied so that Sveltos selectors can
// match the SveltosCluster using the same labels. The managed-by label is
// always added (and takes precedence) so the controller can identify its own objects.
func sveltosClusterLabels(cp *clusterinventoryv1alpha1.ClusterProfile) map[string]string {
labels := make(map[string]string, len(cp.Labels)+1)
for k, v := range cp.Labels {
labels[k] = v
}
labels[managedByLabel] = managedByValue
return labels
}

// reconcileSveltosCluster creates or updates the SveltosCluster for cp.
func reconcileSveltosCluster(ctx context.Context, c client.Client,
cp *clusterinventoryv1alpha1.ClusterProfile, logger logr.Logger) error {

secretName := kubeconfigSecretName(cp.Name)
logger = logger.WithValues("sveltoscluster", fmt.Sprintf("%s/%s", cp.Namespace, cp.Name))

desiredLabels := sveltosClusterLabels(cp)

existing := &libsveltosv1beta1.SveltosCluster{}
err := c.Get(ctx, types.NamespacedName{Namespace: cp.Namespace, Name: cp.Name}, existing)
if err != nil {
Expand All @@ -263,7 +279,7 @@ func reconcileSveltosCluster(ctx context.Context, c client.Client,
ObjectMeta: metav1.ObjectMeta{
Name: cp.Name,
Namespace: cp.Namespace,
Labels: map[string]string{managedByLabel: managedByValue},
Labels: desiredLabels,
},
Spec: libsveltosv1beta1.SveltosClusterSpec{
KubeconfigName: secretName,
Expand All @@ -284,12 +300,16 @@ func reconcileSveltosCluster(ctx context.Context, c client.Client,
}
}

if existing.Spec.KubeconfigName == secretName && existing.Spec.KubeconfigKeyName == kubeconfigKey {
if existing.Spec.KubeconfigName == secretName &&
existing.Spec.KubeconfigKeyName == kubeconfigKey &&
reflect.DeepEqual(existing.Labels, desiredLabels) {

return nil
}

existing.Spec.KubeconfigName = secretName
existing.Spec.KubeconfigKeyName = kubeconfigKey
existing.Labels = desiredLabels
logger.V(logs.LogDebug).Info("updating SveltosCluster")
return c.Update(ctx, existing)
}
Expand Down
40 changes: 40 additions & 0 deletions controllers/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,46 @@ var _ = Describe("Utils", func() {
Expect(sc.Labels[controller.ManagedByLabel]).To(Equal(controller.ManagedByValue))
})

It("copies ClusterProfile labels onto the SveltosCluster at creation", func() {
cpName := randomString()
cp := buildClusterProfile(cpName, namespace, "", nil)
cp.Labels = map[string]string{"env": "prod", "region": "us-east-1"}

Expect(controller.ReconcileSveltosCluster(context.TODO(), testEnv.Client, cp, logger)).To(Succeed())

sc := &libsveltosv1beta1.SveltosCluster{}
Eventually(func() error {
return testEnv.Get(context.TODO(),
types.NamespacedName{Namespace: namespace, Name: cpName}, sc)
}, timeout, pollingInterval).Should(Succeed())
Expect(sc.Labels["env"]).To(Equal("prod"))
Expect(sc.Labels["region"]).To(Equal("us-east-1"))
Expect(sc.Labels[controller.ManagedByLabel]).To(Equal(controller.ManagedByValue))
})

It("updates SveltosCluster labels when ClusterProfile labels change", func() {
cpName := randomString()
cp := buildClusterProfile(cpName, namespace, "", nil)
cp.Labels = map[string]string{"env": "staging"}

Expect(controller.ReconcileSveltosCluster(context.TODO(), testEnv.Client, cp, logger)).To(Succeed())
Expect(waitForObject(context.TODO(), testEnv.Client, &libsveltosv1beta1.SveltosCluster{
ObjectMeta: metav1.ObjectMeta{Name: cpName, Namespace: namespace},
})).To(Succeed())

cp.Labels = map[string]string{"env": "prod"}
Expect(controller.ReconcileSveltosCluster(context.TODO(), testEnv.Client, cp, logger)).To(Succeed())

sc := &libsveltosv1beta1.SveltosCluster{}
Eventually(func() string {
if err := testEnv.Get(context.TODO(),
types.NamespacedName{Namespace: namespace, Name: cpName}, sc); err != nil {
return ""
}
return sc.Labels["env"]
}, timeout, pollingInterval).Should(Equal("prod"))
})

It("is idempotent on repeated calls", func() {
cpName := randomString()
cp := buildClusterProfile(cpName, namespace, "", nil)
Expand Down