From c8a450fd22f0a3f14c096d6b7d7340e40fd7e3ff Mon Sep 17 00:00:00 2001 From: Florent Seel Date: Fri, 16 May 2025 15:16:55 +0200 Subject: [PATCH 01/11] feat: option to use default nameing scheme with externalclusterref --- api/v1alpha1/kamajicontrolplane_types.go | 3 +++ config/control-plane-components.yaml | 8 ++++++++ ...controlplane.cluster.x-k8s.io_kamajicontrolplanes.yaml | 4 ++++ ...lane.cluster.x-k8s.io_kamajicontrolplanetemplates.yaml | 4 ++++ pkg/externalclusterreference/name_generator.go | 3 +++ 5 files changed, 22 insertions(+) diff --git a/api/v1alpha1/kamajicontrolplane_types.go b/api/v1alpha1/kamajicontrolplane_types.go index d42d8f2..d24a79f 100644 --- a/api/v1alpha1/kamajicontrolplane_types.go +++ b/api/v1alpha1/kamajicontrolplane_types.go @@ -184,6 +184,9 @@ type ExternalClusterReference struct { KubeconfigSecretNamespace string `json:"kubeconfigSecretNamespace,omitempty"` // The Namespace where the resulting TenantControlPlane must be deployed to. DeploymentNamespace string `json:"deploymentNamespace"` + // Set tenantControlPlane name to corresponding kamajiControlPlane's name instead of "kcp-". + // May lead to collisions in external cluster, use with care. + KeepDefaultName bool `json:"keepDefaultName,omitempty"` } // KamajiControlPlaneStatus defines the observed state of KamajiControlPlane. diff --git a/config/control-plane-components.yaml b/config/control-plane-components.yaml index eb4fe56..05405df 100644 --- a/config/control-plane-components.yaml +++ b/config/control-plane-components.yaml @@ -1524,6 +1524,10 @@ spec: When this value is nil, the Cluster API management cluster will be used as a target. The ExternalClusterReference feature gate must be enabled with one of the available flags. properties: + keepDefaultName: + description: Set tenantControlPlane name to corresponding kamajiControlPlane's name instead of "kcp-". + May lead to collisions in external cluster, use with care. + type: bool deploymentNamespace: description: The Namespace where the resulting TenantControlPlane must be deployed to. type: string @@ -8244,6 +8248,10 @@ spec: When this value is nil, the Cluster API management cluster will be used as a target. The ExternalClusterReference feature gate must be enabled with one of the available flags. properties: + keepDefaultName: + description: Set tenantControlPlane name to corresponding kamajiControlPlane's name instead of "kcp-". + May lead to collisions in external cluster, use with care. + type: bool deploymentNamespace: description: The Namespace where the resulting TenantControlPlane must be deployed to. type: string diff --git a/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanes.yaml b/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanes.yaml index 60174fc..09e46b4 100644 --- a/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanes.yaml +++ b/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanes.yaml @@ -1572,6 +1572,10 @@ spec: When this value is nil, the Cluster API management cluster will be used as a target. The ExternalClusterReference feature gate must be enabled with one of the available flags. properties: + keepDefaultName: + description: Set tenantControlPlane name to corresponding kamajiControlPlane's name instead of "kcp-". + May lead to collisions in external cluster, use with care. + type: bool deploymentNamespace: description: The Namespace where the resulting TenantControlPlane must be deployed to. diff --git a/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanetemplates.yaml b/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanetemplates.yaml index ff4cba4..27ebb40 100644 --- a/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanetemplates.yaml +++ b/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanetemplates.yaml @@ -1584,6 +1584,10 @@ spec: When this value is nil, the Cluster API management cluster will be used as a target. The ExternalClusterReference feature gate must be enabled with one of the available flags. properties: + keepDefaultName: + description: Set tenantControlPlane name to corresponding kamajiControlPlane's name instead of "kcp-". + May lead to collisions in external cluster, use with care. + type: bool deploymentNamespace: description: The Namespace where the resulting TenantControlPlane must be deployed to. diff --git a/pkg/externalclusterreference/name_generator.go b/pkg/externalclusterreference/name_generator.go index 4694489..47d5065 100644 --- a/pkg/externalclusterreference/name_generator.go +++ b/pkg/externalclusterreference/name_generator.go @@ -25,6 +25,9 @@ func ParseKamajiControlPlaneUIDFromTenantControlPlane(tcp kamajiv1alpha1.TenantC } func GenerateRemoteTenantControlPlaneNames(kcp v1alpha1.KamajiControlPlane) (name string, namespace string) { //nolint:nonamedreturns + if kcp.Spec.Deployment.ExternalClusterReference.KeepDefaultName == true { + return kcp.GetName(), kcp.Spec.Deployment.ExternalClusterReference.DeploymentNamespace + } return RemoteTCPPrefix + string(kcp.UID), kcp.Spec.Deployment.ExternalClusterReference.DeploymentNamespace } From 9e856daa5694db98ad27e02f4371fea79e9cabf8 Mon Sep 17 00:00:00 2001 From: Florent Seel Date: Mon, 19 May 2025 15:19:06 +0200 Subject: [PATCH 02/11] fix(crd): boolean instead of bool --- config/control-plane-components.yaml | 4 ++-- .../controlplane.cluster.x-k8s.io_kamajicontrolplanes.yaml | 2 +- ...rolplane.cluster.x-k8s.io_kamajicontrolplanetemplates.yaml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/config/control-plane-components.yaml b/config/control-plane-components.yaml index 05405df..5906433 100644 --- a/config/control-plane-components.yaml +++ b/config/control-plane-components.yaml @@ -1527,7 +1527,7 @@ spec: keepDefaultName: description: Set tenantControlPlane name to corresponding kamajiControlPlane's name instead of "kcp-". May lead to collisions in external cluster, use with care. - type: bool + type: boolean deploymentNamespace: description: The Namespace where the resulting TenantControlPlane must be deployed to. type: string @@ -8251,7 +8251,7 @@ spec: keepDefaultName: description: Set tenantControlPlane name to corresponding kamajiControlPlane's name instead of "kcp-". May lead to collisions in external cluster, use with care. - type: bool + type: boolean deploymentNamespace: description: The Namespace where the resulting TenantControlPlane must be deployed to. type: string diff --git a/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanes.yaml b/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanes.yaml index 09e46b4..ca57e1e 100644 --- a/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanes.yaml +++ b/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanes.yaml @@ -1575,7 +1575,7 @@ spec: keepDefaultName: description: Set tenantControlPlane name to corresponding kamajiControlPlane's name instead of "kcp-". May lead to collisions in external cluster, use with care. - type: bool + type: boolean deploymentNamespace: description: The Namespace where the resulting TenantControlPlane must be deployed to. diff --git a/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanetemplates.yaml b/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanetemplates.yaml index 27ebb40..50938cb 100644 --- a/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanetemplates.yaml +++ b/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanetemplates.yaml @@ -1587,7 +1587,7 @@ spec: keepDefaultName: description: Set tenantControlPlane name to corresponding kamajiControlPlane's name instead of "kcp-". May lead to collisions in external cluster, use with care. - type: bool + type: boolean deploymentNamespace: description: The Namespace where the resulting TenantControlPlane must be deployed to. From 8b4aaad519e5abf16691c1c8f2c817591c46c460 Mon Sep 17 00:00:00 2001 From: Florent Seel Date: Tue, 20 May 2025 15:15:33 +0200 Subject: [PATCH 03/11] fix(name_gen): fixes for CI / lint --- pkg/externalclusterreference/name_generator.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/externalclusterreference/name_generator.go b/pkg/externalclusterreference/name_generator.go index 47d5065..6c80dd7 100644 --- a/pkg/externalclusterreference/name_generator.go +++ b/pkg/externalclusterreference/name_generator.go @@ -25,7 +25,8 @@ func ParseKamajiControlPlaneUIDFromTenantControlPlane(tcp kamajiv1alpha1.TenantC } func GenerateRemoteTenantControlPlaneNames(kcp v1alpha1.KamajiControlPlane) (name string, namespace string) { //nolint:nonamedreturns - if kcp.Spec.Deployment.ExternalClusterReference.KeepDefaultName == true { + if kcp.Spec.Deployment.ExternalClusterReference.KeepDefaultName { + return kcp.GetName(), kcp.Spec.Deployment.ExternalClusterReference.DeploymentNamespace } return RemoteTCPPrefix + string(kcp.UID), kcp.Spec.Deployment.ExternalClusterReference.DeploymentNamespace From acb4cc9ad2cfebbe9a0819fe1131a4efbeae0a69 Mon Sep 17 00:00:00 2001 From: Florent Seel Date: Tue, 20 May 2025 15:25:43 +0200 Subject: [PATCH 04/11] fix: minor fixes for CI --- config/control-plane-components.yaml | 6 ++++-- .../controlplane.cluster.x-k8s.io_kamajicontrolplanes.yaml | 3 ++- ...lplane.cluster.x-k8s.io_kamajicontrolplanetemplates.yaml | 3 ++- pkg/externalclusterreference/name_generator.go | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/config/control-plane-components.yaml b/config/control-plane-components.yaml index 5906433..4d6f561 100644 --- a/config/control-plane-components.yaml +++ b/config/control-plane-components.yaml @@ -1525,7 +1525,8 @@ spec: The ExternalClusterReference feature gate must be enabled with one of the available flags. properties: keepDefaultName: - description: Set tenantControlPlane name to corresponding kamajiControlPlane's name instead of "kcp-". + description: |- + Set tenantControlPlane name to corresponding kamajiControlPlane's name instead of "kcp-". May lead to collisions in external cluster, use with care. type: boolean deploymentNamespace: @@ -8249,7 +8250,8 @@ spec: The ExternalClusterReference feature gate must be enabled with one of the available flags. properties: keepDefaultName: - description: Set tenantControlPlane name to corresponding kamajiControlPlane's name instead of "kcp-". + description: |- + Set tenantControlPlane name to corresponding kamajiControlPlane's name instead of "kcp-". May lead to collisions in external cluster, use with care. type: boolean deploymentNamespace: diff --git a/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanes.yaml b/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanes.yaml index ca57e1e..70526ec 100644 --- a/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanes.yaml +++ b/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanes.yaml @@ -1573,7 +1573,8 @@ spec: The ExternalClusterReference feature gate must be enabled with one of the available flags. properties: keepDefaultName: - description: Set tenantControlPlane name to corresponding kamajiControlPlane's name instead of "kcp-". + description: |- + Set tenantControlPlane name to corresponding kamajiControlPlane's name instead of "kcp-". May lead to collisions in external cluster, use with care. type: boolean deploymentNamespace: diff --git a/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanetemplates.yaml b/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanetemplates.yaml index 50938cb..5dddcfb 100644 --- a/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanetemplates.yaml +++ b/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanetemplates.yaml @@ -1585,7 +1585,8 @@ spec: The ExternalClusterReference feature gate must be enabled with one of the available flags. properties: keepDefaultName: - description: Set tenantControlPlane name to corresponding kamajiControlPlane's name instead of "kcp-". + description: |- + Set tenantControlPlane name to corresponding kamajiControlPlane's name instead of "kcp-". May lead to collisions in external cluster, use with care. type: boolean deploymentNamespace: diff --git a/pkg/externalclusterreference/name_generator.go b/pkg/externalclusterreference/name_generator.go index 6c80dd7..af53c33 100644 --- a/pkg/externalclusterreference/name_generator.go +++ b/pkg/externalclusterreference/name_generator.go @@ -26,9 +26,9 @@ func ParseKamajiControlPlaneUIDFromTenantControlPlane(tcp kamajiv1alpha1.TenantC func GenerateRemoteTenantControlPlaneNames(kcp v1alpha1.KamajiControlPlane) (name string, namespace string) { //nolint:nonamedreturns if kcp.Spec.Deployment.ExternalClusterReference.KeepDefaultName { - return kcp.GetName(), kcp.Spec.Deployment.ExternalClusterReference.DeploymentNamespace } + return RemoteTCPPrefix + string(kcp.UID), kcp.Spec.Deployment.ExternalClusterReference.DeploymentNamespace } From 55c07171755fa7b061763f627907aae65bca9c67 Mon Sep 17 00:00:00 2001 From: Florent Seel Date: Tue, 20 May 2025 17:12:38 +0200 Subject: [PATCH 05/11] fix(crds): order of externalClusterReference properties --- config/control-plane-components.yaml | 12 ++++++------ ...olplane.cluster.x-k8s.io_kamajicontrolplanes.yaml | 8 ++++---- ...cluster.x-k8s.io_kamajicontrolplanetemplates.yaml | 8 ++++---- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/config/control-plane-components.yaml b/config/control-plane-components.yaml index 4d6f561..afddbbe 100644 --- a/config/control-plane-components.yaml +++ b/config/control-plane-components.yaml @@ -1524,14 +1524,14 @@ spec: When this value is nil, the Cluster API management cluster will be used as a target. The ExternalClusterReference feature gate must be enabled with one of the available flags. properties: + deploymentNamespace: + description: The Namespace where the resulting TenantControlPlane must be deployed to. + type: string keepDefaultName: description: |- Set tenantControlPlane name to corresponding kamajiControlPlane's name instead of "kcp-". May lead to collisions in external cluster, use with care. type: boolean - deploymentNamespace: - description: The Namespace where the resulting TenantControlPlane must be deployed to. - type: string kubeconfigSecretKey: description: The key used to extract the kubeconfig from the specified Secret. minLength: 1 @@ -8249,14 +8249,14 @@ spec: When this value is nil, the Cluster API management cluster will be used as a target. The ExternalClusterReference feature gate must be enabled with one of the available flags. properties: + deploymentNamespace: + description: The Namespace where the resulting TenantControlPlane must be deployed to. + type: string keepDefaultName: description: |- Set tenantControlPlane name to corresponding kamajiControlPlane's name instead of "kcp-". May lead to collisions in external cluster, use with care. type: boolean - deploymentNamespace: - description: The Namespace where the resulting TenantControlPlane must be deployed to. - type: string kubeconfigSecretKey: description: The key used to extract the kubeconfig from the specified Secret. minLength: 1 diff --git a/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanes.yaml b/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanes.yaml index 70526ec..81bb874 100644 --- a/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanes.yaml +++ b/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanes.yaml @@ -1572,15 +1572,15 @@ spec: When this value is nil, the Cluster API management cluster will be used as a target. The ExternalClusterReference feature gate must be enabled with one of the available flags. properties: + deploymentNamespace: + description: The Namespace where the resulting TenantControlPlane + must be deployed to. + type: string keepDefaultName: description: |- Set tenantControlPlane name to corresponding kamajiControlPlane's name instead of "kcp-". May lead to collisions in external cluster, use with care. type: boolean - deploymentNamespace: - description: The Namespace where the resulting TenantControlPlane - must be deployed to. - type: string kubeconfigSecretKey: description: The key used to extract the kubeconfig from the specified Secret. diff --git a/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanetemplates.yaml b/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanetemplates.yaml index 5dddcfb..d1445cb 100644 --- a/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanetemplates.yaml +++ b/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanetemplates.yaml @@ -1584,15 +1584,15 @@ spec: When this value is nil, the Cluster API management cluster will be used as a target. The ExternalClusterReference feature gate must be enabled with one of the available flags. properties: + deploymentNamespace: + description: The Namespace where the resulting TenantControlPlane + must be deployed to. + type: string keepDefaultName: description: |- Set tenantControlPlane name to corresponding kamajiControlPlane's name instead of "kcp-". May lead to collisions in external cluster, use with care. type: boolean - deploymentNamespace: - description: The Namespace where the resulting TenantControlPlane - must be deployed to. - type: string kubeconfigSecretKey: description: The key used to extract the kubeconfig from the specified Secret. From d50d28a1eb41dbcd71ae83b0bf30819b66fca41f Mon Sep 17 00:00:00 2001 From: Florent Seel Date: Fri, 30 May 2025 17:09:32 +0200 Subject: [PATCH 06/11] feat: replace keepDefaultName with deploymentName --- api/v1alpha1/kamajicontrolplane_types.go | 5 ++--- config/control-plane-components.yaml | 18 ++++++++---------- ...e.cluster.x-k8s.io_kamajicontrolplanes.yaml | 9 ++++----- ...r.x-k8s.io_kamajicontrolplanetemplates.yaml | 9 ++++----- pkg/externalclusterreference/name_generator.go | 4 ++-- 5 files changed, 20 insertions(+), 25 deletions(-) diff --git a/api/v1alpha1/kamajicontrolplane_types.go b/api/v1alpha1/kamajicontrolplane_types.go index d24a79f..24edc2b 100644 --- a/api/v1alpha1/kamajicontrolplane_types.go +++ b/api/v1alpha1/kamajicontrolplane_types.go @@ -184,9 +184,8 @@ type ExternalClusterReference struct { KubeconfigSecretNamespace string `json:"kubeconfigSecretNamespace,omitempty"` // The Namespace where the resulting TenantControlPlane must be deployed to. DeploymentNamespace string `json:"deploymentNamespace"` - // Set tenantControlPlane name to corresponding kamajiControlPlane's name instead of "kcp-". - // May lead to collisions in external cluster, use with care. - KeepDefaultName bool `json:"keepDefaultName,omitempty"` + // The Name of the resulting TenantControlPlane. + DeploymentName string `json:"deploymentName,omitempty"` } // KamajiControlPlaneStatus defines the observed state of KamajiControlPlane. diff --git a/config/control-plane-components.yaml b/config/control-plane-components.yaml index afddbbe..81411e0 100644 --- a/config/control-plane-components.yaml +++ b/config/control-plane-components.yaml @@ -1524,14 +1524,13 @@ spec: When this value is nil, the Cluster API management cluster will be used as a target. The ExternalClusterReference feature gate must be enabled with one of the available flags. properties: + deploymentName: + description: |- + The Name of the resulting TenantControlPlane. + type: string deploymentNamespace: description: The Namespace where the resulting TenantControlPlane must be deployed to. type: string - keepDefaultName: - description: |- - Set tenantControlPlane name to corresponding kamajiControlPlane's name instead of "kcp-". - May lead to collisions in external cluster, use with care. - type: boolean kubeconfigSecretKey: description: The key used to extract the kubeconfig from the specified Secret. minLength: 1 @@ -8249,14 +8248,13 @@ spec: When this value is nil, the Cluster API management cluster will be used as a target. The ExternalClusterReference feature gate must be enabled with one of the available flags. properties: + deploymentName: + description: |- + The Name of the resulting TenantControlPlane. + type: string deploymentNamespace: description: The Namespace where the resulting TenantControlPlane must be deployed to. type: string - keepDefaultName: - description: |- - Set tenantControlPlane name to corresponding kamajiControlPlane's name instead of "kcp-". - May lead to collisions in external cluster, use with care. - type: boolean kubeconfigSecretKey: description: The key used to extract the kubeconfig from the specified Secret. minLength: 1 diff --git a/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanes.yaml b/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanes.yaml index 81bb874..ebd0f82 100644 --- a/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanes.yaml +++ b/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanes.yaml @@ -1572,15 +1572,14 @@ spec: When this value is nil, the Cluster API management cluster will be used as a target. The ExternalClusterReference feature gate must be enabled with one of the available flags. properties: + deploymentName: + description: |- + The Name of the resulting TenantControlPlane. + type: string deploymentNamespace: description: The Namespace where the resulting TenantControlPlane must be deployed to. type: string - keepDefaultName: - description: |- - Set tenantControlPlane name to corresponding kamajiControlPlane's name instead of "kcp-". - May lead to collisions in external cluster, use with care. - type: boolean kubeconfigSecretKey: description: The key used to extract the kubeconfig from the specified Secret. diff --git a/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanetemplates.yaml b/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanetemplates.yaml index d1445cb..012827c 100644 --- a/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanetemplates.yaml +++ b/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanetemplates.yaml @@ -1584,15 +1584,14 @@ spec: When this value is nil, the Cluster API management cluster will be used as a target. The ExternalClusterReference feature gate must be enabled with one of the available flags. properties: + deploymentName: + description: |- + The Name of the resulting TenantControlPlane. + type: string deploymentNamespace: description: The Namespace where the resulting TenantControlPlane must be deployed to. type: string - keepDefaultName: - description: |- - Set tenantControlPlane name to corresponding kamajiControlPlane's name instead of "kcp-". - May lead to collisions in external cluster, use with care. - type: boolean kubeconfigSecretKey: description: The key used to extract the kubeconfig from the specified Secret. diff --git a/pkg/externalclusterreference/name_generator.go b/pkg/externalclusterreference/name_generator.go index af53c33..e205f77 100644 --- a/pkg/externalclusterreference/name_generator.go +++ b/pkg/externalclusterreference/name_generator.go @@ -25,8 +25,8 @@ func ParseKamajiControlPlaneUIDFromTenantControlPlane(tcp kamajiv1alpha1.TenantC } func GenerateRemoteTenantControlPlaneNames(kcp v1alpha1.KamajiControlPlane) (name string, namespace string) { //nolint:nonamedreturns - if kcp.Spec.Deployment.ExternalClusterReference.KeepDefaultName { - return kcp.GetName(), kcp.Spec.Deployment.ExternalClusterReference.DeploymentNamespace + if kcp.Spec.Deployment.ExternalClusterReference.DeploymentName { + return kcp.Spec.Deployment.ExternalClusterReference.DeploymentName, kcp.Spec.Deployment.ExternalClusterReference.DeploymentNamespace } return RemoteTCPPrefix + string(kcp.UID), kcp.Spec.Deployment.ExternalClusterReference.DeploymentNamespace From 2ce99fa3722d3a55978fceca523dd68808e853b0 Mon Sep 17 00:00:00 2001 From: Florent Seel Date: Tue, 3 Jun 2025 15:39:56 +0200 Subject: [PATCH 07/11] feat: make deploymentName immutable --- api/v1alpha1/kamajicontrolplane_types.go | 1 + config/control-plane-components.yaml | 6 ++++++ .../controlplane.cluster.x-k8s.io_kamajicontrolplanes.yaml | 3 +++ ...lplane.cluster.x-k8s.io_kamajicontrolplanetemplates.yaml | 3 +++ 4 files changed, 13 insertions(+) diff --git a/api/v1alpha1/kamajicontrolplane_types.go b/api/v1alpha1/kamajicontrolplane_types.go index 24edc2b..9488dca 100644 --- a/api/v1alpha1/kamajicontrolplane_types.go +++ b/api/v1alpha1/kamajicontrolplane_types.go @@ -185,6 +185,7 @@ type ExternalClusterReference struct { // The Namespace where the resulting TenantControlPlane must be deployed to. DeploymentNamespace string `json:"deploymentNamespace"` // The Name of the resulting TenantControlPlane. + // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="DeploymentName is immutable" DeploymentName string `json:"deploymentName,omitempty"` } diff --git a/config/control-plane-components.yaml b/config/control-plane-components.yaml index 81411e0..4e63b48 100644 --- a/config/control-plane-components.yaml +++ b/config/control-plane-components.yaml @@ -1528,6 +1528,9 @@ spec: description: |- The Name of the resulting TenantControlPlane. type: string + x-kubernetes-validations: + - message: deploymentName is immutable + rule: 'self == oldSelf' deploymentNamespace: description: The Namespace where the resulting TenantControlPlane must be deployed to. type: string @@ -8252,6 +8255,9 @@ spec: description: |- The Name of the resulting TenantControlPlane. type: string + x-kubernetes-validations: + - message: deploymentName is immutable + rule: 'self == oldSelf' deploymentNamespace: description: The Namespace where the resulting TenantControlPlane must be deployed to. type: string diff --git a/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanes.yaml b/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanes.yaml index ebd0f82..54c6e05 100644 --- a/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanes.yaml +++ b/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanes.yaml @@ -1576,6 +1576,9 @@ spec: description: |- The Name of the resulting TenantControlPlane. type: string + x-kubernetes-validations: + - message: deploymentName is immutable. + rule: 'self == oldSelf' deploymentNamespace: description: The Namespace where the resulting TenantControlPlane must be deployed to. diff --git a/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanetemplates.yaml b/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanetemplates.yaml index 012827c..ac15ac9 100644 --- a/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanetemplates.yaml +++ b/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanetemplates.yaml @@ -1588,6 +1588,9 @@ spec: description: |- The Name of the resulting TenantControlPlane. type: string + x-kubernetes-validations: + - message: deploymentName is immutable + rule: 'self == oldSelf' deploymentNamespace: description: The Namespace where the resulting TenantControlPlane must be deployed to. From aec406b373f2507fcaa60437a3335214ca3c43fc Mon Sep 17 00:00:00 2001 From: Florent Seel Date: Fri, 27 Jun 2025 16:19:54 +0200 Subject: [PATCH 08/11] fix: custom TCP deploymentName immutable once set --- api/v1alpha1/kamajicontrolplane_types.go | 1 + config/control-plane-components.yaml | 6 ++++++ ...trolplane.cluster.x-k8s.io_kamajicontrolplanes.yaml | 10 ++++++---- ...e.cluster.x-k8s.io_kamajicontrolplanetemplates.yaml | 10 ++++++---- pkg/externalclusterreference/name_generator.go | 2 +- 5 files changed, 20 insertions(+), 9 deletions(-) diff --git a/api/v1alpha1/kamajicontrolplane_types.go b/api/v1alpha1/kamajicontrolplane_types.go index 9488dca..c115ee0 100644 --- a/api/v1alpha1/kamajicontrolplane_types.go +++ b/api/v1alpha1/kamajicontrolplane_types.go @@ -169,6 +169,7 @@ type KamajiControlPlaneFields struct { Deployment DeploymentComponent `json:"deployment,omitempty"` } +// +kubebuilder:validation:XValidation:rule="!has(oldSelf.deploymentName) || has(self.deploymentName)", message="DeploymentName is required once set" type ExternalClusterReference struct { // The Secret object containing the kubeconfig used to interact with the remote cluster that will host // the Tenant Control Plane resources generated by the Control Plane Provider. diff --git a/config/control-plane-components.yaml b/config/control-plane-components.yaml index 4e63b48..0750a62 100644 --- a/config/control-plane-components.yaml +++ b/config/control-plane-components.yaml @@ -1554,6 +1554,9 @@ spec: - kubeconfigSecretKey - kubeconfigSecretName type: object + x-kubernetes-validations: + - message: DeploymentName is required once set + rule: '!has(oldSelf.deploymentName) || has(self.deploymentName)' extraContainers: items: description: A single application container that you want to run within a pod. @@ -8281,6 +8284,9 @@ spec: - kubeconfigSecretKey - kubeconfigSecretName type: object + x-kubernetes-validations: + - message: DeploymentName is required once set + rule: '!has(oldSelf.deploymentName) || has(self.deploymentName)' extraContainers: items: description: A single application container that you want to run within a pod. diff --git a/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanes.yaml b/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanes.yaml index 54c6e05..83849ab 100644 --- a/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanes.yaml +++ b/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanes.yaml @@ -1573,12 +1573,11 @@ spec: The ExternalClusterReference feature gate must be enabled with one of the available flags. properties: deploymentName: - description: |- - The Name of the resulting TenantControlPlane. + description: The Name of the resulting TenantControlPlane. type: string x-kubernetes-validations: - - message: deploymentName is immutable. - rule: 'self == oldSelf' + - message: DeploymentName is immutable + rule: self == oldSelf deploymentNamespace: description: The Namespace where the resulting TenantControlPlane must be deployed to. @@ -1604,6 +1603,9 @@ spec: - kubeconfigSecretKey - kubeconfigSecretName type: object + x-kubernetes-validations: + - message: DeploymentName is required once set + rule: '!has(oldSelf.deploymentName) || has(self.deploymentName)' extraContainers: items: description: A single application container that you want to diff --git a/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanetemplates.yaml b/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanetemplates.yaml index ac15ac9..b67f0be 100644 --- a/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanetemplates.yaml +++ b/config/crd/bases/controlplane.cluster.x-k8s.io_kamajicontrolplanetemplates.yaml @@ -1585,12 +1585,11 @@ spec: The ExternalClusterReference feature gate must be enabled with one of the available flags. properties: deploymentName: - description: |- - The Name of the resulting TenantControlPlane. + description: The Name of the resulting TenantControlPlane. type: string x-kubernetes-validations: - - message: deploymentName is immutable - rule: 'self == oldSelf' + - message: DeploymentName is immutable + rule: self == oldSelf deploymentNamespace: description: The Namespace where the resulting TenantControlPlane must be deployed to. @@ -1616,6 +1615,9 @@ spec: - kubeconfigSecretKey - kubeconfigSecretName type: object + x-kubernetes-validations: + - message: DeploymentName is required once set + rule: '!has(oldSelf.deploymentName) || has(self.deploymentName)' extraContainers: items: description: A single application container that you diff --git a/pkg/externalclusterreference/name_generator.go b/pkg/externalclusterreference/name_generator.go index e205f77..b36bbf2 100644 --- a/pkg/externalclusterreference/name_generator.go +++ b/pkg/externalclusterreference/name_generator.go @@ -25,7 +25,7 @@ func ParseKamajiControlPlaneUIDFromTenantControlPlane(tcp kamajiv1alpha1.TenantC } func GenerateRemoteTenantControlPlaneNames(kcp v1alpha1.KamajiControlPlane) (name string, namespace string) { //nolint:nonamedreturns - if kcp.Spec.Deployment.ExternalClusterReference.DeploymentName { + if kcp.Spec.Deployment.ExternalClusterReference.DeploymentName != "" { return kcp.Spec.Deployment.ExternalClusterReference.DeploymentName, kcp.Spec.Deployment.ExternalClusterReference.DeploymentNamespace } From 02c2c12163a1f2fe2344475f10ec34e067abec80 Mon Sep 17 00:00:00 2001 From: florent1s <68420585+florent1s@users.noreply.github.com> Date: Tue, 15 Jul 2025 09:42:16 +0000 Subject: [PATCH 09/11] feat: TCP Collision detection with ExternalCluster * feat: add&check kcp-uid label to avoid collisions with externalclusterref * fix: detect collisions on TCP with external cluster * fix(kcp-finalizer): remote TCP collision detection * fix: remote TCP collision detection * fix: indentation * feat: collision detection for ECR working * fix: includes order * fix: newline --------- Co-authored-by: Florent Seel --- api/v1alpha1/kamajicontrolplane_types.go | 4 ++++ .../kamajicontrolplane_controller_tcp.go | 24 ++++++++++++++++--- controllers/kamajicontrolplane_finalizer.go | 17 +++++++++++++ 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/api/v1alpha1/kamajicontrolplane_types.go b/api/v1alpha1/kamajicontrolplane_types.go index c115ee0..395dd39 100644 --- a/api/v1alpha1/kamajicontrolplane_types.go +++ b/api/v1alpha1/kamajicontrolplane_types.go @@ -250,3 +250,7 @@ type KamajiControlPlaneList struct { func init() { SchemeBuilder.Register(&KamajiControlPlane{}, &KamajiControlPlaneList{}) } + +const ( + KamajiControlPlaneUIDLabel = "kamaji.clastix.io/kamajicontrolplane-uid" +) diff --git a/controllers/kamajicontrolplane_controller_tcp.go b/controllers/kamajicontrolplane_controller_tcp.go index 02022cb..44e79d5 100644 --- a/controllers/kamajicontrolplane_controller_tcp.go +++ b/controllers/kamajicontrolplane_controller_tcp.go @@ -9,20 +9,21 @@ import ( "net" "strings" + kcpv1alpha1 "github.com/clastix/cluster-api-control-plane-provider-kamaji/api/v1alpha1" + "github.com/clastix/cluster-api-control-plane-provider-kamaji/pkg/externalclusterreference" kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1" "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/util/retry" "k8s.io/utils/ptr" capiv1beta1 "sigs.k8s.io/cluster-api/api/v1beta1" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - - kcpv1alpha1 "github.com/clastix/cluster-api-control-plane-provider-kamaji/api/v1alpha1" - "github.com/clastix/cluster-api-control-plane-provider-kamaji/pkg/externalclusterreference" ) var ErrUnsupportedCertificateSAN = errors.New("a certificate SAN must be made of host only with no port") +var ErrTCPCollision = errors.New("Collision on remote TenantControlPlanes") //+kubebuilder:rbac:groups=kamaji.clastix.io,resources=tenantcontrolplanes,verbs=get;list;watch;create;update @@ -57,6 +58,23 @@ func (r *KamajiControlPlaneReconciler) createOrUpdateTenantControlPlane(ctx cont tcp.Labels = kcp.Labels + // Check the KCP-UID label to avoid collsions if 2 clusters with the same name + // use the same namespace with externalClusterReference + // if label is not present, it will be added + if isDelegatedExternally && kcp.Spec.Deployment.ExternalClusterReference.DeploymentName != "" { + var tcpInCluster kamajiv1alpha1.TenantControlPlane + remoteClient.Get(ctx, types.NamespacedName{Namespace: tcp.Namespace, Name: tcp.Name}, &tcpInCluster) + + if val := tcpInCluster.Labels[kcpv1alpha1.KamajiControlPlaneUIDLabel]; val != "" { + if val != string(kcp.UID) { + return errors.Wrap(ErrTCPCollision, fmt.Sprintf("Collision on TenantControlPlane %s: Value of label '%s' does not match.", tcp.Name, kcpv1alpha1.KamajiControlPlaneUIDLabel)) + } + // label matches our kcp UID -> update TCP (nothing to do here) + } else { // label not present -> claim this TCP by adding it + tcp.Labels[kcpv1alpha1.KamajiControlPlaneUIDLabel] = string(kcp.UID) + } + } + if kubeconfigSecretKey := kcp.Annotations[kamajiv1alpha1.KubeconfigSecretKeyAnnotation]; kubeconfigSecretKey != "" { tcp.Annotations[kamajiv1alpha1.KubeconfigSecretKeyAnnotation] = kubeconfigSecretKey } else { diff --git a/controllers/kamajicontrolplane_finalizer.go b/controllers/kamajicontrolplane_finalizer.go index 4125e31..e50b107 100644 --- a/controllers/kamajicontrolplane_finalizer.go +++ b/controllers/kamajicontrolplane_finalizer.go @@ -58,6 +58,23 @@ func (r *KamajiControlPlaneReconciler) handleDeletion(ctx context.Context, kcp v var tcp kamajiv1alpha1.TenantControlPlane tcp.Name, tcp.Namespace = externalclusterreference.GenerateRemoteTenantControlPlaneNames(kcp) + // Check KamajiControlPlaneUIDLabel on TCP, to avoid deleting it if it doesn't belong to our KCP + if kcp.Spec.Deployment.ExternalClusterReference.DeploymentName != "" { + + if err := remoteClient.Get(ctx, types.NamespacedName{Namespace: tcp.Namespace, Name: tcp.Name}, &tcp); err != nil { + if errors.IsNotFound(err) { + log.Info("resource may have been deleted") + } + log.Error(err, "unable to get remote TenantControlPlane") + } + + if val := tcp.Labels[v1alpha1.KamajiControlPlaneUIDLabel]; val != "" && val != string(kcp.UID) { + log.Info("Did not delete remote TenantControlPlane as it belongs to another KamajiControlPlane") + + return nil + } + } + if tcpErr := remoteClient.Delete(ctx, &tcp); tcpErr != nil { if errors.IsNotFound(tcpErr) { log.Info("remote TenantControlPlane is already deleted") From 9aaffb4607fd5b8cc499c74e518c1deb568f5607 Mon Sep 17 00:00:00 2001 From: Florent Seel Date: Wed, 23 Jul 2025 15:50:57 +0200 Subject: [PATCH 10/11] feat(kcp_types): explain KCPUID label --- api/v1alpha1/kamajicontrolplane_types.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/api/v1alpha1/kamajicontrolplane_types.go b/api/v1alpha1/kamajicontrolplane_types.go index 395dd39..74e0609 100644 --- a/api/v1alpha1/kamajicontrolplane_types.go +++ b/api/v1alpha1/kamajicontrolplane_types.go @@ -251,6 +251,9 @@ func init() { SchemeBuilder.Register(&KamajiControlPlane{}, &KamajiControlPlaneList{}) } +// This label is used to detect collisions when using ExternalClusterReference.DeploymentName +// It allows to keep track of the KCP owning a given TCP when the TCP name is not the default +// "kcp-" const ( KamajiControlPlaneUIDLabel = "kamaji.clastix.io/kamajicontrolplane-uid" ) From 67688df3d658e4fd27efb7f5451ea523ca9188e8 Mon Sep 17 00:00:00 2001 From: Florent Seel Date: Wed, 23 Jul 2025 16:18:23 +0200 Subject: [PATCH 11/11] feat(kcp_finalizer): use GetLabels --- controllers/kamajicontrolplane_finalizer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controllers/kamajicontrolplane_finalizer.go b/controllers/kamajicontrolplane_finalizer.go index e50b107..1f08954 100644 --- a/controllers/kamajicontrolplane_finalizer.go +++ b/controllers/kamajicontrolplane_finalizer.go @@ -68,7 +68,7 @@ func (r *KamajiControlPlaneReconciler) handleDeletion(ctx context.Context, kcp v log.Error(err, "unable to get remote TenantControlPlane") } - if val := tcp.Labels[v1alpha1.KamajiControlPlaneUIDLabel]; val != "" && val != string(kcp.UID) { + if val := tcp.GetLabels()[v1alpha1.KamajiControlPlaneUIDLabel]; val != "" && val != string(kcp.UID) { log.Info("Did not delete remote TenantControlPlane as it belongs to another KamajiControlPlane") return nil