Skip to content

feat: adds cluster's ownerref on cilium helm values source object #1034

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Feb 5, 2025
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
2 changes: 0 additions & 2 deletions docs/content/addons/cni.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,6 @@ data:
mode: kubernetes
kind: ConfigMap
metadata:
labels:
clusterctl.cluster.x-k8s.io/move: ""
name: <CLUSTER_NAME>-cilium-cni-helm-values-template
namespace: <CLUSTER_NAMESPACE>
```
Expand Down
8 changes: 6 additions & 2 deletions pkg/handlers/generic/lifecycle/ccm/nutanix/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

"github.com/go-logr/logr"
"github.com/spf13/pflag"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
ctrlclient "sigs.k8s.io/controller-runtime/pkg/client"
Expand Down Expand Up @@ -84,10 +85,13 @@ func (p *provider) Apply(
// However, that would leave the credentials visible in the HelmChartProxy.
// Instead, we'll create the Secret on the remote cluster and reference it in the Helm values.
if clusterConfig.Addons.CCM.Credentials != nil {
err := handlersutils.EnsureOwnerReferenceForSecret(
err := handlersutils.EnsureClusterOwnerReferenceForObject(
ctx,
p.client,
clusterConfig.Addons.CCM.Credentials.SecretRef.Name,
corev1.TypedLocalObjectReference{
Kind: "Secret",
Name: clusterConfig.Addons.CCM.Credentials.SecretRef.Name,
},
cluster,
)
if err != nil {
Expand Down
29 changes: 29 additions & 0 deletions pkg/handlers/generic/lifecycle/cni/cilium/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"fmt"

"github.com/spf13/pflag"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/ptr"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
Expand All @@ -22,6 +23,7 @@ import (
"github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/lifecycle/addons"
"github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/lifecycle/config"
"github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/pkg/handlers/options"
handlersutils "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/pkg/handlers/utils"
)

type CNIConfig struct {
Expand Down Expand Up @@ -183,6 +185,33 @@ func (c *CiliumCNI) apply(
helmValuesSourceRefName = cniVar.Values.SourceRef.Name
// Use cluster's namespace since Values.SourceRef is always a LocalObjectReference
targetNamespace = cluster.Namespace

err := handlersutils.EnsureClusterOwnerReferenceForObject(
ctx,
c.client,
corev1.TypedLocalObjectReference{
Kind: cniVar.Values.SourceRef.Kind,
Name: cniVar.Values.SourceRef.Name,
},
cluster,
)
if err != nil {
log.Error(
err,
"error updating Cluster's owner reference on Cilium helm values source object",
"name",
cniVar.Values.SourceRef.Name,
"kind",
cniVar.Values.SourceRef.Kind,
)
resp.SetStatus(runtimehooksv1.ResponseStatusFailure)
resp.SetMessage(
fmt.Sprintf(
"failed to set Cluster's owner reference on Cilium helm values source object: %v",
err,
),
)
}
}

strategy = addons.NewHelmAddonApplier(
Expand Down
8 changes: 6 additions & 2 deletions pkg/handlers/generic/lifecycle/csi/nutanix/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

"github.com/go-logr/logr"
"github.com/spf13/pflag"
corev1 "k8s.io/api/core/v1"
"k8s.io/utils/ptr"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
ctrlclient "sigs.k8s.io/controller-runtime/pkg/client"
Expand Down Expand Up @@ -108,10 +109,13 @@ func (n *NutanixCSI) Apply(
}

if provider.Credentials != nil {
err := handlersutils.EnsureOwnerReferenceForSecret(
err := handlersutils.EnsureClusterOwnerReferenceForObject(
ctx,
n.client,
provider.Credentials.SecretRef.Name,
corev1.TypedLocalObjectReference{
Kind: "Secret",
Name: provider.Credentials.SecretRef.Name,
},
cluster,
)
if err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"errors"
"fmt"

corev1 "k8s.io/api/core/v1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
Expand Down Expand Up @@ -287,10 +288,13 @@ func ensureOwnerReferenceOnCredentialsSecrets(
if secretName := handlersutils.SecretNameForImageRegistryCredentials(credential); secretName != "" {
// Ensure the Secret is owned by the Cluster so it is correctly moved and deleted with the Cluster.
// This code assumes that Secret exists and that was validated before calling this function.
err := handlersutils.EnsureOwnerReferenceForSecret(
err := handlersutils.EnsureClusterOwnerReferenceForObject(
ctx,
c,
secretName,
corev1.TypedLocalObjectReference{
Kind: "Secret",
Name: secretName,
},
cluster,
)
if err != nil {
Expand Down
50 changes: 42 additions & 8 deletions pkg/handlers/utils/secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import (

corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
"sigs.k8s.io/cluster-api/controllers/external"
"sigs.k8s.io/cluster-api/controllers/remote"
ctrlclient "sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
Expand Down Expand Up @@ -64,30 +66,62 @@ func CopySecretToRemoteCluster(
return nil
}

// EnsureOwnerReferenceForSecret will ensure that the secretName Secret has an OwnerReference of the cluster.
func EnsureOwnerReferenceForSecret(
// EnsureClusterOwnerReferenceForObject ensures that OwnerReference of the cluster is added on provided object.
func EnsureClusterOwnerReferenceForObject(
ctx context.Context,
cl ctrlclient.Client,
secretName string,
objectRef corev1.TypedLocalObjectReference,
cluster *clusterv1.Cluster,
) error {
secret, err := getSecretForCluster(ctx, cl, secretName, cluster)
targetObj, err := GetResourceFromTypedLocalObjectReference(
ctx,
cl,
objectRef,
cluster.Namespace,
)
if err != nil {
return err
}

err = controllerutil.SetOwnerReference(cluster, secret, cl.Scheme())
err = controllerutil.SetOwnerReference(cluster, targetObj, cl.Scheme())
if err != nil {
return fmt.Errorf("failed to set owner reference on Secret: %w", err)
return fmt.Errorf("failed to set cluster's owner reference on object: %w", err)
}

err = cl.Update(ctx, secret)
err = cl.Update(ctx, targetObj)
if err != nil {
return fmt.Errorf("failed to update Secret with owner references: %w", err)
return fmt.Errorf("failed to update object with cluster's owner reference: %w", err)
}
return nil
}

// GetResourceFromTypedLocalObjectReference gets the resource from the provided TypedLocalObjectReference.
func GetResourceFromTypedLocalObjectReference(
ctx context.Context,
cl ctrlclient.Client,
typedLocalObjectRef corev1.TypedLocalObjectReference,
ns string,
) (*unstructured.Unstructured, error) {
apiVersion := corev1.SchemeGroupVersion.String()
if typedLocalObjectRef.APIGroup != nil {
apiVersion = *typedLocalObjectRef.APIGroup
}

objectRef := &corev1.ObjectReference{
APIVersion: apiVersion,
Kind: typedLocalObjectRef.Kind,
Name: typedLocalObjectRef.Name,
Namespace: ns,
}

targetObj, err := external.Get(ctx, cl, objectRef)
if err != nil {
return nil, fmt.Errorf("failed to get resource from object reference: %w", err)
}

return targetObj, nil
}

func getSecretForCluster(
ctx context.Context,
c ctrlclient.Client,
Expand Down
27 changes: 22 additions & 5 deletions pkg/handlers/utils/secrets_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ package utils

import (
"context"
"fmt"
"testing"

"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
apiErrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
Expand Down Expand Up @@ -97,23 +99,38 @@ func Test_EnsureOwnerReferenceForSecret(t *testing.T) {
client: buildFakeClient(t, testSecret, testCluster),
secretName: "missing-secret",
cluster: testCluster,
wantErr: errors.NewNotFound(corev1.Resource("secrets"), "missing-secret"),
wantErr: fmt.Errorf(
"failed to get resource from object reference: %w",
errors.Wrapf(
apiErrors.NewNotFound(corev1.Resource("secrets"), "missing-secret"),
"failed to retrieve %s %s",
"Secret",
"missing-secret",
),
),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()

err := EnsureOwnerReferenceForSecret(
err := EnsureClusterOwnerReferenceForObject(
context.Background(),
tt.client,
tt.secretName,
corev1.TypedLocalObjectReference{
Kind: "Secret",
Name: tt.secretName,
},
tt.cluster,
)
require.Equal(t, tt.wantErr, err)

if tt.wantErr != nil {
assert.Equal(t, tt.wantErr.Error(), err.Error())
return
} else {
require.NoError(t, err)
}

// verify that the owner reference was added
secret := &corev1.Secret{}
err = tt.client.Get(
Expand Down
Loading