From f40f2f98f082b654bd2c74a156c8d255c18a5bda Mon Sep 17 00:00:00 2001 From: Dario Tranchitella Date: Mon, 27 May 2024 17:25:16 +0200 Subject: [PATCH] feat: support for externally managed control plane Signed-off-by: Dario Tranchitella --- api/v1alpha1/conditions_consts.go | 3 +++ api/v1alpha1/proxmoxcluster_types.go | 4 ++++ ...ucture.cluster.x-k8s.io_proxmoxclusters.yaml | 5 +++++ ...luster.x-k8s.io_proxmoxclustertemplates.yaml | 6 ++++++ .../controller/proxmoxcluster_controller.go | 17 +++++++++++++++++ internal/webhook/proxmoxcluster_webhook.go | 8 ++++++-- 6 files changed, 41 insertions(+), 2 deletions(-) diff --git a/api/v1alpha1/conditions_consts.go b/api/v1alpha1/conditions_consts.go index 382b6f92..bc23fdd8 100644 --- a/api/v1alpha1/conditions_consts.go +++ b/api/v1alpha1/conditions_consts.go @@ -78,6 +78,9 @@ const ( // UnknownReason (Severity=Warning) documents the ProxmoxVM Unknown. UnknownReason = "Unknown" + + // MissingControlPlaneEndpointReason (Severity=Warning) documents the missing Control Plane endpoint when Cluster is backed by an externally managed Control Plane. + MissingControlPlaneEndpointReason = "MissingControlPlaneEndpoint" ) const ( diff --git a/api/v1alpha1/proxmoxcluster_types.go b/api/v1alpha1/proxmoxcluster_types.go index 722e9275..52a652b5 100644 --- a/api/v1alpha1/proxmoxcluster_types.go +++ b/api/v1alpha1/proxmoxcluster_types.go @@ -40,6 +40,10 @@ type ProxmoxClusterSpec struct { // +kubebuilder:validation:XValidation:rule="self.port > 0 && self.port < 65536",message="port must be within 1-65535" ControlPlaneEndpoint *clusterv1.APIEndpoint `json:"controlPlaneEndpoint"` + // ExternalManagedControlPlane can be enabled to allow externally managed Control Planes to patch the + // Proxmox cluster with the Load Balancer IP provided by Control Plane provider. + ExternalManagedControlPlane bool `json:"externalManagedControlPlane,omitempty"` + // AllowedNodes specifies all Proxmox nodes which will be considered // for operations. This implies that VMs can be cloned on different nodes from // the node which holds the VM template. diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_proxmoxclusters.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_proxmoxclusters.yaml index 1d8cb8a8..2f3da2ed 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_proxmoxclusters.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_proxmoxclusters.yaml @@ -587,6 +587,11 @@ spec: type: string minItems: 1 type: array + externalManagedControlPlane: + description: ExternalManagedControlPlane can be enabled to allow externally + managed Control Planes to patch the Proxmox cluster with the Load + Balancer IP provided by Control Plane provider. + type: boolean ipv4Config: description: IPv4Config contains information about available IPV4 address pools and the gateway. This can be combined with ipv6Config diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_proxmoxclustertemplates.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_proxmoxclustertemplates.yaml index 5183aa5e..98bf1206 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_proxmoxclustertemplates.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_proxmoxclustertemplates.yaml @@ -637,6 +637,12 @@ spec: type: string minItems: 1 type: array + externalManagedControlPlane: + description: ExternalManagedControlPlane can be enabled to + allow externally managed Control Planes to patch the Proxmox + cluster with the Load Balancer IP provided by Control Plane + provider. + type: boolean ipv4Config: description: IPv4Config contains information about available IPV4 address pools and the gateway. This can be combined diff --git a/internal/controller/proxmoxcluster_controller.go b/internal/controller/proxmoxcluster_controller.go index 5cedab9b..93d5dda3 100644 --- a/internal/controller/proxmoxcluster_controller.go +++ b/internal/controller/proxmoxcluster_controller.go @@ -168,6 +168,23 @@ func (r *ProxmoxClusterReconciler) reconcileNormal(ctx context.Context, clusterS // If the ProxmoxCluster doesn't have our finalizer, add it. ctrlutil.AddFinalizer(clusterScope.ProxmoxCluster, infrav1alpha1.ClusterFinalizer) + if clusterScope.ProxmoxCluster.Spec.ExternalManagedControlPlane { + switch { + case clusterScope.ProxmoxCluster.Spec.ControlPlaneEndpoint.Host == "": + clusterScope.Logger.Info("ProxmoxCluster is not ready, missing or waiting for a ControlPlaneEndpoint host") + + conditions.MarkFalse(clusterScope.ProxmoxCluster, infrav1alpha1.ProxmoxClusterReady, infrav1alpha1.MissingControlPlaneEndpointReason, clusterv1.ConditionSeverityWarning, "The ProxmoxCluster is missing or waiting for a ControlPlaneEndpoint host") + + return ctrl.Result{Requeue: true}, nil + case clusterScope.ProxmoxCluster.Spec.ControlPlaneEndpoint.Port == 0: + clusterScope.Logger.Info("ProxmoxCluster is not ready, missing or waiting for a ControlPlaneEndpoint port") + + conditions.MarkFalse(clusterScope.ProxmoxCluster, infrav1alpha1.ProxmoxClusterReady, infrav1alpha1.MissingControlPlaneEndpointReason, clusterv1.ConditionSeverityWarning, "The ProxmoxCluster is missing or waiting for a ControlPlaneEndpoint port") + + return ctrl.Result{Requeue: true}, nil + } + } + res, err := r.reconcileIPAM(ctx, clusterScope) if err != nil { return ctrl.Result{}, err diff --git a/internal/webhook/proxmoxcluster_webhook.go b/internal/webhook/proxmoxcluster_webhook.go index 0456b4ac..fc273b4e 100644 --- a/internal/webhook/proxmoxcluster_webhook.go +++ b/internal/webhook/proxmoxcluster_webhook.go @@ -93,11 +93,15 @@ func (*ProxmoxCluster) ValidateUpdate(_ context.Context, _ runtime.Object, newOb } func validateControlPlaneEndpoint(cluster *infrav1.ProxmoxCluster) error { - ep := cluster.Spec.ControlPlaneEndpoint + // Skipping the validation of the Control Plane endpoint in case of externally managed Control Plane: + // the Cluster API Control Plane provider will eventually provide the LB. + if cluster.Spec.ExternalManagedControlPlane { + return nil + } gk, name := cluster.GroupVersionKind().GroupKind(), cluster.GetName() - endpoint := ep.Host + endpoint := cluster.Spec.ControlPlaneEndpoint.Host addr, err := netip.ParseAddr(endpoint)