diff --git a/controllers/k8ssandra/cleanup.go b/controllers/k8ssandra/cleanup.go index 4baedefe2..7f24bad30 100644 --- a/controllers/k8ssandra/cleanup.go +++ b/controllers/k8ssandra/cleanup.go @@ -153,9 +153,144 @@ func (r *K8ssandraClusterReconciler) checkDcDeletion(ctx context.Context, kc *ap } func (r *K8ssandraClusterReconciler) deleteDc(ctx context.Context, kc *api.K8ssandraCluster, dcName string, logger logr.Logger) result.ReconcileResult { + + // delete Stargate + if result := r.deleteStargate(ctx, kc, dcName, logger); result != nil { + return result + } + + // delete Reaper + if result := r.deleteReaper(ctx, kc, dcName, logger); result != nil { + return result + } + + // delete the DC + if result := r.deleteDatacenter(ctx, kc, dcName, logger); result != nil { + return result + } + delete(kc.Status.Datacenters, dcName) + logger.Info("DC deletion finished", "DC", dcName) + return result.Continue() +} + +func (r *K8ssandraClusterReconciler) findStargateForDeletion( + ctx context.Context, + kcKey client.ObjectKey, + dcName string, + remoteClient client.Client) (*stargateapi.Stargate, error) { + + if remoteClient == nil { + return nil, nil + } + stargateName := kcKey.Name + "-" + dcName + "-stargate" + selector := k8ssandralabels.PartOfLabels(kcKey) + options := &client.ListOptions{LabelSelector: labels.SelectorFromSet(selector)} + stargateList := &stargateapi.StargateList{} + + err := remoteClient.List(ctx, stargateList, options) + if err != nil { + return nil, fmt.Errorf("failed to find Stargate (%s) for DC (%s) deletion: %v", stargateName, dcName, err) + } + for _, stargate := range stargateList.Items { + if stargate.Name == stargateName { + return &stargate, nil + } + } + return nil, nil +} + +func (r *K8ssandraClusterReconciler) findReaperForDeletion( + ctx context.Context, + kcKey client.ObjectKey, + dcName string, + remoteClient client.Client) (*reaperapi.Reaper, error) { + + if remoteClient == nil { + return nil, nil + } + reaperName := kcKey.Name + "-" + dcName + "-reaper" + selector := k8ssandralabels.PartOfLabels(kcKey) + options := &client.ListOptions{LabelSelector: labels.SelectorFromSet(selector)} + reaperList := &reaperapi.ReaperList{} + + err := remoteClient.List(ctx, reaperList, options) + if err != nil { + return nil, fmt.Errorf("failed to find Reaper (%s) for DC (%s) deletion: %v", reaperName, dcName, err) + } + for _, reaper := range reaperList.Items { + if reaper.Name == reaperName { + return &reaper, nil + } + } + return nil, nil +} + +func (r *K8ssandraClusterReconciler) findDcForDeletion( + ctx context.Context, + kcKey client.ObjectKey, + dcName string, + remoteClient client.Client) (*cassdcapi.CassandraDatacenter, error) { + + if remoteClient == nil { + return nil, nil + } + selector := k8ssandralabels.PartOfLabels(kcKey) + options := &client.ListOptions{LabelSelector: labels.SelectorFromSet(selector)} + dcList := &cassdcapi.CassandraDatacenterList{} + + err := remoteClient.List(ctx, dcList, options) + if err != nil { + return nil, fmt.Errorf("failed to find CassandraDatacenter (%s) for deletion: %v", dcName, err) + } + + for _, dc := range dcList.Items { + if dc.Name == dcName { + return &dc, nil + } + } + return nil, nil +} + +func (r *K8ssandraClusterReconciler) deleteK8ssandraConfigMaps( + ctx context.Context, + kc *k8ssandraapi.K8ssandraCluster, + dcTemplate k8ssandraapi.CassandraDatacenterTemplate, + namespace string, + remoteClient client.Client, + kcLogger logr.Logger, +) (hasErrors bool) { + selector := k8ssandralabels.PartOfLabels(client.ObjectKey{Namespace: kc.Namespace, Name: kc.SanitizedName()}) + configMaps := &corev1.ConfigMapList{} + options := client.ListOptions{ + Namespace: namespace, + LabelSelector: labels.SelectorFromSet(selector), + } + if err := remoteClient.List(ctx, configMaps, &options); err != nil { + kcLogger.Error(err, "Failed to list ConfigMap objects", "Context", dcTemplate.K8sContext) + return true + } + for _, rp := range configMaps.Items { + if err := remoteClient.Delete(ctx, &rp); err != nil { + key := client.ObjectKey{Namespace: namespace, Name: rp.Name} + if !apierrors.IsNotFound(err) { + kcLogger.Error(err, "Failed to delete configmap", "ConfigMap", key, + "Context", dcTemplate.K8sContext) + hasErrors = true + } + } + } + return +} + +func (r *K8ssandraClusterReconciler) deleteStargate(ctx context.Context, kc *api.K8ssandraCluster, dcName string, logger logr.Logger) result.ReconcileResult { + kcKey := utils.GetKey(kc) + remoteClient, err := r.findRemoteClientForStargate(ctx, kcKey, dcName) + if err != nil { + return result.Error(err) + } - stargate, remoteClient, err := r.findStargateForDeletion(ctx, kcKey, dcName, nil) + stargate, err := r.findStargateForDeletion(ctx, kcKey, dcName, remoteClient) if err != nil { return result.Error(err) } @@ -166,8 +301,18 @@ func (r *K8ssandraClusterReconciler) deleteDc(ctx context.Context, kc *api.K8ssa } logger.Info("Deleted Stargate", "Stargate", utils.GetKey(stargate)) } + return nil +} + +func (r *K8ssandraClusterReconciler) deleteReaper(ctx context.Context, kc *api.K8ssandraCluster, dcName string, logger logr.Logger) result.ReconcileResult { + + kcKey := utils.GetKey(kc) + remoteClient, err := r.findRemoteClientForReaper(ctx, kcKey, dcName) + if err != nil { + return result.Error(err) + } - reaper, remoteClient, err := r.findReaperForDeletion(ctx, kcKey, dcName, remoteClient) + reaper, err := r.findReaperForDeletion(ctx, kcKey, dcName, remoteClient) if err != nil { return result.Error(err) } @@ -178,8 +323,18 @@ func (r *K8ssandraClusterReconciler) deleteDc(ctx context.Context, kc *api.K8ssa } logger.Info("Deleted Reaper", "Reaper", utils.GetKey(reaper)) } + return nil +} + +func (r *K8ssandraClusterReconciler) deleteDatacenter(ctx context.Context, kc *api.K8ssandraCluster, dcName string, logger logr.Logger) result.ReconcileResult { - dc, remoteClient, err := r.findDcForDeletion(ctx, kcKey, dcName, remoteClient) + kcKey := utils.GetKey(kc) + remoteClient, err := r.findRemoteClientForDc(ctx, kcKey, dcName) + if err != nil { + return result.Error(err) + } + + dc, err := r.findDcForDeletion(ctx, kcKey, dcName, remoteClient) if err != nil { return result.Error(err) } @@ -206,154 +361,64 @@ func (r *K8ssandraClusterReconciler) deleteDc(ctx context.Context, kc *api.K8ssa // There is no need to requeue here. Reconciliation will be trigger by updates made by cass-operator. return result.Done() } - - delete(kc.Status.Datacenters, dcName) - logger.Info("DC deletion finished", "DC", dcName) - return result.Continue() + return nil } -func (r *K8ssandraClusterReconciler) findStargateForDeletion( - ctx context.Context, - kcKey client.ObjectKey, - dcName string, - remoteClient client.Client) (*stargateapi.Stargate, client.Client, error) { - +func (r *K8ssandraClusterReconciler) findRemoteClientForReaper(ctx context.Context, kcKey client.ObjectKey, dcName string) (client.Client, error) { + reaperName := kcKey.Name + "-" + dcName + "-reaper" selector := k8ssandralabels.PartOfLabels(kcKey) options := &client.ListOptions{LabelSelector: labels.SelectorFromSet(selector)} - stargateList := &stargateapi.StargateList{} - stargateName := kcKey.Name + "-" + dcName + "-stargate" + reaperList := &reaperapi.ReaperList{} - if remoteClient == nil { - for _, remoteClient := range r.ClientCache.GetAllClients() { - err := remoteClient.List(ctx, stargateList, options) - if err != nil { - return nil, nil, fmt.Errorf("failed to find Stargate (%s) for DC (%s) deletion: %v", stargateName, dcName, err) - } - for _, stargate := range stargateList.Items { - if stargate.Name == stargateName { - return &stargate, remoteClient, nil - } - } - } - } else { - err := remoteClient.List(ctx, stargateList, options) + for _, remoteClient := range r.ClientCache.GetAllClients() { + err := remoteClient.List(ctx, reaperList, options) if err != nil { - return nil, nil, fmt.Errorf("failed to find Stargate (%s) for DC (%s) deletion: %v", stargateName, dcName, err) + return nil, fmt.Errorf("failed to find Reaper (%s) for DC (%s) deletion: %v", reaperName, dcName, err) } - - for _, stargate := range stargateList.Items { - if stargate.Name == stargateName { - return &stargate, remoteClient, nil + for _, reaper := range reaperList.Items { + if reaper.Name == reaperName { + return remoteClient, nil } } } - - return nil, nil, nil + return nil, nil } -func (r *K8ssandraClusterReconciler) findReaperForDeletion( - ctx context.Context, - kcKey client.ObjectKey, - dcName string, - remoteClient client.Client) (*reaperapi.Reaper, client.Client, error) { - +func (r *K8ssandraClusterReconciler) findRemoteClientForStargate(ctx context.Context, kcKey client.ObjectKey, dcName string) (client.Client, error) { + stargateName := kcKey.Name + "-" + dcName + "-stargate" selector := k8ssandralabels.PartOfLabels(kcKey) options := &client.ListOptions{LabelSelector: labels.SelectorFromSet(selector)} - reaperList := &reaperapi.ReaperList{} - reaperName := kcKey.Name + "-" + dcName + "-reaper" + stargateList := &stargateapi.StargateList{} - if remoteClient == nil { - for _, remoteClient := range r.ClientCache.GetAllClients() { - err := remoteClient.List(ctx, reaperList, options) - if err != nil { - return nil, nil, fmt.Errorf("failed to find Reaper (%s) for DC (%s) deletion: %v", reaperName, dcName, err) - } - for _, reaper := range reaperList.Items { - if reaper.Name == reaperName { - return &reaper, remoteClient, nil - } - } - } - } else { - err := remoteClient.List(ctx, reaperList, options) + for _, remoteClient := range r.ClientCache.GetAllClients() { + err := remoteClient.List(ctx, stargateList, options) if err != nil { - return nil, nil, fmt.Errorf("failed to find Reaper (%s) for DC (%s) deletion: %v", reaperName, dcName, err) + return nil, fmt.Errorf("failed to find Stargate (%s) for DC (%s) deletion: %v", stargateName, dcName, err) } - - for _, reaper := range reaperList.Items { - if reaper.Name == reaperName { - return &reaper, remoteClient, nil + for _, stargate := range stargateList.Items { + if stargate.Name == stargateName { + return remoteClient, nil } } } - - return nil, nil, nil + return nil, nil } -func (r *K8ssandraClusterReconciler) findDcForDeletion( - ctx context.Context, - kcKey client.ObjectKey, - dcName string, - remoteClient client.Client) (*cassdcapi.CassandraDatacenter, client.Client, error) { +func (r *K8ssandraClusterReconciler) findRemoteClientForDc(ctx context.Context, kcKey client.ObjectKey, dcName string) (client.Client, error) { selector := k8ssandralabels.PartOfLabels(kcKey) options := &client.ListOptions{LabelSelector: labels.SelectorFromSet(selector)} dcList := &cassdcapi.CassandraDatacenterList{} - if remoteClient == nil { - for _, remoteClient := range r.ClientCache.GetAllClients() { - err := remoteClient.List(ctx, dcList, options) - if err != nil { - return nil, nil, fmt.Errorf("failed to CassandraDatacenter (%s) for DC (%s) deletion: %v", dcName, dcName, err) - } - for _, dc := range dcList.Items { - if dc.Name == dcName { - return &dc, remoteClient, nil - } - } - } - } else { + for _, remoteClient := range r.ClientCache.GetAllClients() { err := remoteClient.List(ctx, dcList, options) if err != nil { - return nil, nil, fmt.Errorf("failed to find CassandraDatacenter (%s) for deletion: %v", dcName, err) + return nil, fmt.Errorf("failed to find CassandraDatacenter (%s) for deletion: %v", dcName, err) } - - for _, dc := range dcList.Items { - if dc.Name == dcName { - return &dc, remoteClient, nil + for _, reaper := range dcList.Items { + if reaper.Name == dcName { + return remoteClient, nil } } } - - return nil, nil, nil -} - -func (r *K8ssandraClusterReconciler) deleteK8ssandraConfigMaps( - ctx context.Context, - kc *k8ssandraapi.K8ssandraCluster, - dcTemplate k8ssandraapi.CassandraDatacenterTemplate, - namespace string, - remoteClient client.Client, - kcLogger logr.Logger, -) (hasErrors bool) { - selector := k8ssandralabels.PartOfLabels(client.ObjectKey{Namespace: kc.Namespace, Name: kc.SanitizedName()}) - configMaps := &corev1.ConfigMapList{} - options := client.ListOptions{ - Namespace: namespace, - LabelSelector: labels.SelectorFromSet(selector), - } - if err := remoteClient.List(ctx, configMaps, &options); err != nil { - kcLogger.Error(err, "Failed to list ConfigMap objects", "Context", dcTemplate.K8sContext) - return true - } - for _, rp := range configMaps.Items { - if err := remoteClient.Delete(ctx, &rp); err != nil { - key := client.ObjectKey{Namespace: namespace, Name: rp.Name} - if !apierrors.IsNotFound(err) { - kcLogger.Error(err, "Failed to delete configmap", "ConfigMap", key, - "Context", dcTemplate.K8sContext) - hasErrors = true - } - } - } - return + return nil, nil }