diff --git a/pkg/uninstall/uninstall.go b/pkg/uninstall/uninstall.go index ee3f678c43..1a6091b296 100644 --- a/pkg/uninstall/uninstall.go +++ b/pkg/uninstall/uninstall.go @@ -35,11 +35,13 @@ import ( kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2" notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1" sourcev1 "github.com/fluxcd/source-controller/api/v1beta2" + "github.com/hashicorp/go-multierror" ) // Components removes all Kubernetes components that are part of Flux excluding the CRDs and namespace. -func Components(ctx context.Context, logger log.Logger, kubeClient client.Client, namespace string, dryRun bool) { - opts, dryRunStr := getDeleteOptions(dryRun) +func Components(ctx context.Context, logger log.Logger, kubeClient client.Client, namespace string, dryRun bool) error { + var aggregateErr error + opts, dryRunStr := getDeleteOptions(dryRun) selector := client.MatchingLabels{manifestgen.PartOfLabelKey: manifestgen.PartOfLabelValue} { var list appsv1.DeploymentList @@ -47,6 +49,7 @@ func Components(ctx context.Context, logger log.Logger, kubeClient client.Client for _, r := range list.Items { if err := kubeClient.Delete(ctx, &r, opts); err != nil { logger.Failuref("Deployment/%s/%s deletion failed: %s", r.Namespace, r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("Deployment/%s/%s deleted %s", r.Namespace, r.Name, dryRunStr) } @@ -59,6 +62,7 @@ func Components(ctx context.Context, logger log.Logger, kubeClient client.Client for _, r := range list.Items { if err := kubeClient.Delete(ctx, &r, opts); err != nil { logger.Failuref("Service/%s/%s deletion failed: %s", r.Namespace, r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("Service/%s/%s deleted %s", r.Namespace, r.Name, dryRunStr) } @@ -71,6 +75,7 @@ func Components(ctx context.Context, logger log.Logger, kubeClient client.Client for _, r := range list.Items { if err := kubeClient.Delete(ctx, &r, opts); err != nil { logger.Failuref("NetworkPolicy/%s/%s deletion failed: %s", r.Namespace, r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("NetworkPolicy/%s/%s deleted %s", r.Namespace, r.Name, dryRunStr) } @@ -83,6 +88,7 @@ func Components(ctx context.Context, logger log.Logger, kubeClient client.Client for _, r := range list.Items { if err := kubeClient.Delete(ctx, &r, opts); err != nil { logger.Failuref("ServiceAccount/%s/%s deletion failed: %s", r.Namespace, r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("ServiceAccount/%s/%s deleted %s", r.Namespace, r.Name, dryRunStr) } @@ -95,6 +101,7 @@ func Components(ctx context.Context, logger log.Logger, kubeClient client.Client for _, r := range list.Items { if err := kubeClient.Delete(ctx, &r, opts); err != nil { logger.Failuref("ClusterRole/%s deletion failed: %s", r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("ClusterRole/%s deleted %s", r.Name, dryRunStr) } @@ -107,17 +114,21 @@ func Components(ctx context.Context, logger log.Logger, kubeClient client.Client for _, r := range list.Items { if err := kubeClient.Delete(ctx, &r, opts); err != nil { logger.Failuref("ClusterRoleBinding/%s deletion failed: %s", r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("ClusterRoleBinding/%s deleted %s", r.Name, dryRunStr) } } } } + + return aggregateErr } // Finalizers removes all finalizes on Kubernetes components that have been added by a Flux controller. -func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client, dryRun bool) { - opts, dryRunStr := getUpdateOptions(dryRun) +func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client, dryRun bool) error { + var aggregateErr error + opts, dryRunStr := getUpdateOptions(dryRun) { var list sourcev1.GitRepositoryList if err := kubeClient.List(ctx, &list, client.InNamespace("")); err == nil { @@ -125,6 +136,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } @@ -138,6 +150,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } @@ -151,6 +164,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } @@ -164,6 +178,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } @@ -177,6 +192,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } @@ -190,6 +206,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } @@ -203,6 +220,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } @@ -216,6 +234,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } @@ -229,6 +248,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } @@ -242,6 +262,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } @@ -255,6 +276,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } @@ -268,6 +290,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } @@ -281,17 +304,20 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } } } } + return aggregateErr } // CustomResourceDefinitions removes all Kubernetes CRDs that are a part of Flux. -func CustomResourceDefinitions(ctx context.Context, logger log.Logger, kubeClient client.Client, dryRun bool) { - opts, dryRunStr := getDeleteOptions(dryRun) +func CustomResourceDefinitions(ctx context.Context, logger log.Logger, kubeClient client.Client, dryRun bool) error { + var aggregateErr error + opts, dryRunStr := getDeleteOptions(dryRun) selector := client.MatchingLabels{manifestgen.PartOfLabelKey: manifestgen.PartOfLabelValue} { var list apiextensionsv1.CustomResourceDefinitionList @@ -299,23 +325,28 @@ func CustomResourceDefinitions(ctx context.Context, logger log.Logger, kubeClien for _, r := range list.Items { if err := kubeClient.Delete(ctx, &r, opts); err != nil { logger.Failuref("CustomResourceDefinition/%s deletion failed: %s", r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("CustomResourceDefinition/%s deleted %s", r.Name, dryRunStr) } } } } + return aggregateErr } // Namespace removes the namespace Flux is installed in. -func Namespace(ctx context.Context, logger log.Logger, kubeClient client.Client, namespace string, dryRun bool) { - opts, dryRunStr := getDeleteOptions(dryRun) +func Namespace(ctx context.Context, logger log.Logger, kubeClient client.Client, namespace string, dryRun bool) error { + var aggregateErr error + opts, dryRunStr := getDeleteOptions(dryRun) ns := corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: namespace}} if err := kubeClient.Delete(ctx, &ns, opts); err != nil { logger.Failuref("Namespace/%s deletion failed: %s", namespace, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("Namespace/%s deleted %s", namespace, dryRunStr) } + return aggregateErr } func getDeleteOptions(dryRun bool) (*client.DeleteOptions, string) {