diff --git a/controllers/cks_cluster_controller.go b/controllers/cks_cluster_controller.go index c7b4a982..39f7d1e1 100644 --- a/controllers/cks_cluster_controller.go +++ b/controllers/cks_cluster_controller.go @@ -91,19 +91,25 @@ func (r *CksClusterReconciliationRunner) Reconcile() (res ctrl.Result, reterr er // ReconcileDelete cleans up resources used by the cluster and finally removes the CloudStackCluster's finalizers. func (r *CksClusterReconciliationRunner) ReconcileDelete() (ctrl.Result, error) { - if r.ReconciliationSubject.Status.CloudStackClusterID != "" { + // Only attempt CKS deletion if SyncWithACS was enabled and CloudStackClusterID is set + if r.CSCluster.Spec.SyncWithACS != nil && *r.CSCluster.Spec.SyncWithACS && r.ReconciliationSubject.Status.CloudStackClusterID != "" { if len(r.FailureDomains.Items) == 0 { - return ctrl.Result{}, fmt.Errorf("no failure domains found") + return ctrl.Result{}, fmt.Errorf("cannot delete CKS cluster: no failure domains found (CloudStackClusterID: %s)", r.ReconciliationSubject.Status.CloudStackClusterID) } + res, err := r.AsFailureDomainUser(&r.FailureDomains.Items[0].Spec)() if r.ShouldReturn(res, err) { return res, err } + + r.Log.Info("Deleting CKS cluster from CloudStack", "CloudStackClusterID", r.ReconciliationSubject.Status.CloudStackClusterID) err = r.CSUser.DeleteCksCluster(r.ReconciliationSubject) if err != nil && !strings.Contains(err.Error(), " not found") { return r.RequeueWithMessage(fmt.Sprintf("Deleting cks cluster on CloudStack failed. error: %s", err.Error())) } + r.Log.Info("Successfully deleted CKS cluster from CloudStack", "CloudStackClusterID", r.ReconciliationSubject.Status.CloudStackClusterID) } + controllerutil.RemoveFinalizer(r.ReconciliationSubject, CksClusterFinalizer) return ctrl.Result{}, nil } diff --git a/controllers/cloudstackcluster_controller.go b/controllers/cloudstackcluster_controller.go index 19268c10..bf01bd66 100644 --- a/controllers/cloudstackcluster_controller.go +++ b/controllers/cloudstackcluster_controller.go @@ -140,6 +140,13 @@ func (r *CloudStackClusterReconciliationRunner) SetFailureDomainsStatusMap() (ct // ReconcileDelete cleans up resources used by the cluster and finally removes the CloudStackCluster's finalizers. func (r *CloudStackClusterReconciliationRunner) ReconcileDelete() (ctrl.Result, error) { r.Log.Info("Deleting CloudStackCluster.") + + // Wait for CKS cluster cleanup to complete before deleting FailureDomains + const cksClusterFinalizer = "ckscluster.infrastructure.cluster.x-k8s.io" + if controllerutil.ContainsFinalizer(r.ReconciliationSubject, cksClusterFinalizer) { + return r.RequeueWithMessage("Waiting for CKS cluster cleanup to complete before deleting FailureDomains.") + } + if res, err := r.GetFailureDomains(r.FailureDomains)(); r.ShouldReturn(res, err) { return res, err } diff --git a/pkg/cloud/cks_cluster.go b/pkg/cloud/cks_cluster.go index acf870e0..130d8832 100644 --- a/pkg/cloud/cks_cluster.go +++ b/pkg/cloud/cks_cluster.go @@ -53,15 +53,18 @@ func (c *client) GetOrCreateCksCluster(cluster *clusterv1.Cluster, csCluster *in if csCluster.Status.CloudStackClusterID != "" { externalManagedCluster, count, err := c.cs.Kubernetes.GetKubernetesClusterByID(csCluster.Status.CloudStackClusterID, withExternalManaged(), cloudstack.WithProject(c.user.Project.ID)) if err != nil { - return err + return fmt.Errorf("failed to get CKS cluster by ID %s: %w", csCluster.Status.CloudStackClusterID, err) } else if count > 0 { csCluster.Status.CloudStackClusterID = externalManagedCluster.Id return nil } + // Cluster ID is set in status but not found in CloudStack + // This could mean the cluster was deleted externally or doesn't have ExternalManaged type + return fmt.Errorf("CKS cluster with ID %s not found in CloudStack (expected ExternalManaged type)", csCluster.Status.CloudStackClusterID) } // Check if a cluster exists with the same name - clusterName := fmt.Sprintf("%s - %s - %s", cluster.GetName(), csCluster.GetName(), csCluster.GetUID()) + clusterName := cluster.GetName() externalManagedCluster, count, err := c.cs.Kubernetes.GetKubernetesClusterByName(clusterName, withExternalManaged(), cloudstack.WithProject(c.user.Project.ID)) if err != nil && !strings.Contains(err.Error(), "No match found for ") { return err @@ -81,7 +84,7 @@ func (c *client) GetOrCreateCksCluster(cluster *clusterv1.Cluster, csCluster *in } } // NewCreateKubernetesClusterParams(description string, kubernetesversionid string, name string, serviceofferingid string, size int64, zoneid string) *CreateKubernetesClusterParams - params := c.cs.Kubernetes.NewCreateKubernetesClusterParams(fmt.Sprintf("%s managed by CAPC", clusterName), "", clusterName, "", 0, fd.Zone.ID) + params := c.cs.Kubernetes.NewCreateKubernetesClusterParams(fmt.Sprintf("Cluster %s managed by CAPC", clusterName), "", clusterName, "", 0, fd.Zone.ID) setIfNotEmpty(c.user.Project.ID, params.SetProjectid) setIfNotEmpty(accountName, params.SetAccount)