Skip to content

Commit

Permalink
✨ Allow credentials in multiple clusters (#114)
Browse files Browse the repository at this point in the history
**What is the purpose of this pull request/Why do we need it?**

As we would like to allow referencing the same secret in multiple
clusters, we need to make sure to not delete it when it is still in use
and set the owner references accordingly.

**Description of changes:**

Updates the finalizer logic to ensure that a finalizer is not removed as
long as the secret is referenced by multiple owners.

**Special notes for your reviewer:**

* An object in Kubernetes can only have one controller reference, but
multiple owner references.

**Checklist:**
- [x] Includes
[emojis](https://github.com/kubernetes-sigs/kubebuilder-release-tools?tab=readme-ov-file#kubebuilder-project-versioning)

---------

Co-authored-by: Jonas Riedel <[email protected]>
  • Loading branch information
lubedacht and jriedel-ionos authored May 13, 2024
1 parent b6f9c86 commit 91e64ed
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 15 deletions.
4 changes: 0 additions & 4 deletions api/v1alpha1/ionoscloudcluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,6 @@ const (
// associated with the IonosCloudCluster before removing it from the API server.
ClusterFinalizer = "ionoscloudcluster.infrastructure.cluster.x-k8s.io"

// ClusterCredentialsFinalizer allows cleanup of resources, which are
// associated with the IonosCloudCluster credentials before removing it from the API server.
ClusterCredentialsFinalizer = ClusterFinalizer + "/credentials"

// IonosCloudClusterReady is the condition for the IonosCloudCluster, which indicates that the cluster is ready.
IonosCloudClusterReady clusterv1.ConditionType = "ClusterReady"

Expand Down
23 changes: 12 additions & 11 deletions internal/controller/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"time"

"github.com/go-logr/logr"
"github.com/google/go-cmp/cmp"
sdk "github.com/ionos-cloud/sdk-go/v6"
corev1 "k8s.io/api/core/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
Expand Down Expand Up @@ -97,30 +98,30 @@ func createServiceFromCluster(
return cloud.NewService(ionosClient, log)
}

// ensureSecretControlledByCluster ensures that the secrets will contain a finalizer and a controller reference.
// The secret should only be deleted when there are no resources left in the IONOS Cloud environment.
// ensureSecretControlledByCluster ensures that the secrets will contain a cluster-specific finalizer and an owner reference.
// The secret will be deleted automatically with its last owner.
func ensureSecretControlledByCluster(
ctx context.Context, c client.Client,
cluster *infrav1.IonosCloudCluster,
secret *corev1.Secret,
) error {
requireUpdate := controllerutil.AddFinalizer(secret, infrav1.ClusterCredentialsFinalizer)
old := secret.DeepCopy()

if !controllerutil.HasControllerReference(secret) {
if err := controllerutil.SetControllerReference(cluster, secret, c.Scheme()); err != nil {
return err
}
requireUpdate = true
finalizerAdded := controllerutil.AddFinalizer(secret, fmt.Sprintf("%s/%s", infrav1.ClusterFinalizer, cluster.GetUID()))
// We want to allow using the secret in multiple clusters.
// Using owner references because Kubernetes only allows us to have one controller reference.
if err := controllerutil.SetOwnerReference(cluster, secret, c.Scheme()); err != nil {
return err
}

if requireUpdate {
if finalizerAdded || !cmp.Equal(old.GetOwnerReferences(), secret.GetOwnerReferences()) {
return c.Update(ctx, secret)
}

return nil
}

// removeCredentialsFinalizer removes the finalizer from the credential secret.
// removeCredentialsFinalizer removes the cluster-specific finalizer from the credentials secret.
func removeCredentialsFinalizer(ctx context.Context, c client.Client, cluster *infrav1.IonosCloudCluster) error {
secretKey := client.ObjectKey{
Namespace: cluster.Namespace,
Expand All @@ -133,6 +134,6 @@ func removeCredentialsFinalizer(ctx context.Context, c client.Client, cluster *i
return client.IgnoreNotFound(err)
}

controllerutil.RemoveFinalizer(&secret, infrav1.ClusterCredentialsFinalizer)
controllerutil.RemoveFinalizer(&secret, fmt.Sprintf("%s/%s", infrav1.ClusterFinalizer, cluster.GetUID()))
return c.Update(ctx, &secret)
}

0 comments on commit 91e64ed

Please sign in to comment.