From 43313e3ec727b6656dbb4aabf2cc78526052b38f Mon Sep 17 00:00:00 2001 From: Kit Patella Date: Wed, 30 Oct 2024 08:02:38 -0700 Subject: [PATCH] chore: add logger to zarf destroy (#3162) Signed-off-by: Kit Patella --- src/cmd/destroy.go | 10 ++++++++-- src/internal/packager/helm/chart.go | 4 +++- src/internal/packager/helm/destroy.go | 15 +++++++++++++-- src/pkg/cluster/cluster.go | 2 ++ src/pkg/cluster/namespace.go | 6 ++++++ src/pkg/cluster/state.go | 10 +++++++--- src/pkg/cluster/zarf.go | 12 ++++++++++++ src/pkg/packager/remove.go | 2 +- 8 files changed, 52 insertions(+), 9 deletions(-) diff --git a/src/cmd/destroy.go b/src/cmd/destroy.go index 6951efd96b..eeca2ce3f3 100644 --- a/src/cmd/destroy.go +++ b/src/cmd/destroy.go @@ -16,6 +16,7 @@ import ( "github.com/zarf-dev/zarf/src/config/lang" "github.com/zarf-dev/zarf/src/internal/packager/helm" "github.com/zarf-dev/zarf/src/pkg/cluster" + "github.com/zarf-dev/zarf/src/pkg/logger" "github.com/zarf-dev/zarf/src/pkg/message" "github.com/zarf-dev/zarf/src/pkg/utils/exec" @@ -33,7 +34,9 @@ var destroyCmd = &cobra.Command{ // TODO(mkcp): refactor and de-nest this function. RunE: func(cmd *cobra.Command, _ []string) error { ctx := cmd.Context() - timeoutCtx, cancel := context.WithTimeout(cmd.Context(), cluster.DefaultTimeout) + l := logger.From(ctx) + + timeoutCtx, cancel := context.WithTimeout(ctx, cluster.DefaultTimeout) defer cancel() c, err := cluster.NewClusterWithWait(timeoutCtx) if err != nil { @@ -46,6 +49,7 @@ var destroyCmd = &cobra.Command{ state, err := c.LoadZarfState(ctx) if err != nil { message.WarnErr(err, err.Error()) + l.Warn(err.Error()) } // If Zarf deployed the cluster, burn it all down @@ -68,6 +72,7 @@ var destroyCmd = &cobra.Command{ err := exec.CmdWithPrint(script) if errors.Is(err, os.ErrPermission) { message.Warnf(lang.CmdDestroyErrScriptPermissionDenied, script) + l.Warn("received 'permission denied' when trying to execute script. Please double-check you have the correct kube-context.", "script", script) // Don't remove scripts we can't execute so the user can try to manually run continue @@ -79,11 +84,12 @@ var destroyCmd = &cobra.Command{ err = os.Remove(script) if err != nil { message.WarnErr(err, fmt.Sprintf("Unable to remove script. script=%s", script)) + l.Warn("unable to remove script", "script", script, "error", err.Error()) } } } else { // Perform chart uninstallation - helm.Destroy(removeComponents) + helm.Destroy(ctx, removeComponents) // If Zarf didn't deploy the cluster, only delete the ZarfNamespace if err := c.DeleteZarfNamespace(ctx); err != nil { diff --git a/src/internal/packager/helm/chart.go b/src/internal/packager/helm/chart.go index 954b1d6144..35e1e5625c 100644 --- a/src/internal/packager/helm/chart.go +++ b/src/internal/packager/helm/chart.go @@ -9,6 +9,7 @@ import ( "context" "errors" "fmt" + "github.com/zarf-dev/zarf/src/pkg/logger" "time" "github.com/Masterminds/semver/v3" @@ -213,12 +214,13 @@ func (h *Helm) TemplateChart(ctx context.Context) (manifest string, chartValues } // RemoveChart removes a chart from the cluster. -func (h *Helm) RemoveChart(namespace string, name string, spinner *message.Spinner) error { +func (h *Helm) RemoveChart(ctx context.Context, namespace string, name string, spinner *message.Spinner) error { // Establish a new actionConfig for the namespace. _ = h.createActionConfig(namespace, spinner) // Perform the uninstall. response, err := h.uninstallChart(name) message.Debug(response) + logger.From(ctx).Debug("chart uninstalled", "response", response) return err } diff --git a/src/internal/packager/helm/destroy.go b/src/internal/packager/helm/destroy.go index 44c519a00a..21693aaa92 100644 --- a/src/internal/packager/helm/destroy.go +++ b/src/internal/packager/helm/destroy.go @@ -5,17 +5,23 @@ package helm import ( + "context" "regexp" + "time" "github.com/zarf-dev/zarf/src/pkg/cluster" + "github.com/zarf-dev/zarf/src/pkg/logger" "github.com/zarf-dev/zarf/src/pkg/message" "helm.sh/helm/v3/pkg/action" ) // Destroy removes ZarfInitPackage charts from the cluster and optionally all Zarf-installed charts. -func Destroy(purgeAllZarfInstallations bool) { +func Destroy(ctx context.Context, purgeAllZarfInstallations bool) { + start := time.Now() + l := logger.From(ctx) spinner := message.NewProgressSpinner("Removing Zarf-installed charts") defer spinner.Stop() + l.Info("removing Zarf-installed charts") h := Helm{} @@ -24,6 +30,7 @@ func Destroy(purgeAllZarfInstallations bool) { if err != nil { // Don't fatal since this is a removal action spinner.Errorf(err, "Unable to initialize the K8s client") + l.Error("unable to initialize the K8s client", "error", err.Error()) return } @@ -42,6 +49,7 @@ func Destroy(purgeAllZarfInstallations bool) { if err != nil { // Don't fatal since this is a removal action spinner.Errorf(err, "Unable to get the list of installed charts") + l.Error("unable to get the list of installed charts", "error", err.Error()) } // Iterate over all releases @@ -53,12 +61,15 @@ func Destroy(purgeAllZarfInstallations bool) { // Filter on zarf releases if zarfPrefix.MatchString(release.Name) { spinner.Updatef("Uninstalling helm chart %s/%s", release.Namespace, release.Name) - if err = h.RemoveChart(release.Namespace, release.Name, spinner); err != nil { + l.Info("uninstalling helm chart", "namespace", release.Namespace, "name", release.Name) + if err = h.RemoveChart(ctx, release.Namespace, release.Name, spinner); err != nil { // Don't fatal since this is a removal action spinner.Errorf(err, "Unable to uninstall the chart") + l.Error("unable to uninstall the chart", "error", err.Error()) } } } spinner.Success() + l.Debug("done uninstalling charts", "duration", time.Since(start)) } diff --git a/src/pkg/cluster/cluster.go b/src/pkg/cluster/cluster.go index 73557c4ce2..4686deed76 100644 --- a/src/pkg/cluster/cluster.go +++ b/src/pkg/cluster/cluster.go @@ -41,6 +41,7 @@ type Cluster struct { // NewClusterWithWait creates a new Cluster instance and waits for the given timeout for the cluster to be ready. func NewClusterWithWait(ctx context.Context) (*Cluster, error) { + start := time.Now() l := logger.From(ctx) spinner := message.NewProgressSpinner("Waiting for cluster connection") defer spinner.Stop() @@ -74,6 +75,7 @@ func NewClusterWithWait(ctx context.Context) (*Cluster, error) { } spinner.Success() + l.Debug("done waiting for cluster, connected", "duration", time.Since(start)) return c, nil } diff --git a/src/pkg/cluster/namespace.go b/src/pkg/cluster/namespace.go index 99d50a5f5e..24525dc6b1 100644 --- a/src/pkg/cluster/namespace.go +++ b/src/pkg/cluster/namespace.go @@ -14,13 +14,17 @@ import ( kerrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "github.com/zarf-dev/zarf/src/pkg/logger" "github.com/zarf-dev/zarf/src/pkg/message" ) // DeleteZarfNamespace deletes the Zarf namespace from the connected cluster. func (c *Cluster) DeleteZarfNamespace(ctx context.Context) error { + start := time.Now() + l := logger.From(ctx) spinner := message.NewProgressSpinner("Deleting the zarf namespace from this cluster") defer spinner.Stop() + l.Info("deleting the zarf namespace from this cluster") err := c.Clientset.CoreV1().Namespaces().Delete(ctx, ZarfNamespaceName, metav1.DeleteOptions{}) if kerrors.IsNotFound(err) { @@ -42,6 +46,8 @@ func (c *Cluster) DeleteZarfNamespace(ctx context.Context) error { if err != nil { return err } + + l.Debug("done deleting the zarf namespace from this cluster", "duration", time.Since(start)) return nil } diff --git a/src/pkg/cluster/state.go b/src/pkg/cluster/state.go index f2279b0221..a6274356a0 100644 --- a/src/pkg/cluster/state.go +++ b/src/pkg/cluster/state.go @@ -20,6 +20,7 @@ import ( "github.com/defenseunicorns/pkg/helpers/v2" "github.com/zarf-dev/zarf/src/config" "github.com/zarf-dev/zarf/src/config/lang" + "github.com/zarf-dev/zarf/src/pkg/logger" "github.com/zarf-dev/zarf/src/pkg/message" "github.com/zarf-dev/zarf/src/pkg/pki" "github.com/zarf-dev/zarf/src/types" @@ -205,7 +206,7 @@ func (c *Cluster) LoadZarfState(ctx context.Context) (*types.ZarfState, error) { if err != nil { return nil, fmt.Errorf("%w: %w", stateErr, err) } - c.debugPrintZarfState(state) + c.debugPrintZarfState(ctx, state) return state, nil } @@ -230,10 +231,11 @@ func (c *Cluster) sanitizeZarfState(state *types.ZarfState) *types.ZarfState { return state } -func (c *Cluster) debugPrintZarfState(state *types.ZarfState) { +func (c *Cluster) debugPrintZarfState(ctx context.Context, state *types.ZarfState) { if state == nil { return } + // this is a shallow copy, nested pointers WILL NOT be copied oldState := *state sanitized := c.sanitizeZarfState(&oldState) @@ -242,11 +244,13 @@ func (c *Cluster) debugPrintZarfState(state *types.ZarfState) { return } message.Debugf("ZarfState - %s", string(b)) + + logger.From(ctx).Debug("cluster.debugPrintZarfState", "state", sanitized) } // SaveZarfState takes a given state and persists it to the Zarf/zarf-state secret. func (c *Cluster) SaveZarfState(ctx context.Context, state *types.ZarfState) error { - c.debugPrintZarfState(state) + c.debugPrintZarfState(ctx, state) data, err := json.Marshal(&state) if err != nil { diff --git a/src/pkg/cluster/zarf.go b/src/pkg/cluster/zarf.go index 3f12381e38..906a7bc166 100644 --- a/src/pkg/cluster/zarf.go +++ b/src/pkg/cluster/zarf.go @@ -10,6 +10,7 @@ import ( "errors" "fmt" "strings" + "time" autoscalingV2 "k8s.io/api/autoscaling/v2" corev1 "k8s.io/api/core/v1" @@ -19,6 +20,7 @@ import ( "github.com/zarf-dev/zarf/src/api/v1alpha1" "github.com/zarf-dev/zarf/src/config" "github.com/zarf-dev/zarf/src/internal/gitea" + "github.com/zarf-dev/zarf/src/pkg/logger" "github.com/zarf-dev/zarf/src/pkg/message" "github.com/zarf-dev/zarf/src/types" ) @@ -133,41 +135,51 @@ func (c *Cluster) DeleteDeployedPackage(ctx context.Context, packageName string) // StripZarfLabelsAndSecretsFromNamespaces removes metadata and secrets from existing namespaces no longer manged by Zarf. func (c *Cluster) StripZarfLabelsAndSecretsFromNamespaces(ctx context.Context) { + start := time.Now() + l := logger.From(ctx) spinner := message.NewProgressSpinner("Removing zarf metadata & secrets from existing namespaces not managed by Zarf") defer spinner.Stop() + l.Info("removing zarf metadata & secrets from existing namespaces not managed by Zarf") deleteOptions := metav1.DeleteOptions{} listOptions := metav1.ListOptions{ LabelSelector: ZarfManagedByLabel + "=zarf", } + // TODO(mkcp): Remove unnecessary nesting w/ else namespaceList, err := c.Clientset.CoreV1().Namespaces().List(ctx, metav1.ListOptions{}) if err != nil { spinner.Errorf(err, "Unable to get k8s namespaces") + l.Error("unable to get k8s namespaces", "error", err) } else { for _, namespace := range namespaceList.Items { if _, ok := namespace.Labels[AgentLabel]; ok { spinner.Updatef("Removing Zarf Agent label for namespace %s", namespace.Name) + l.Info("removing Zarf Agent label", "namespace", namespace.Name) delete(namespace.Labels, AgentLabel) namespaceCopy := namespace _, err := c.Clientset.CoreV1().Namespaces().Update(ctx, &namespaceCopy, metav1.UpdateOptions{}) if err != nil { // This is not a hard failure, but we should log it spinner.Errorf(err, "Unable to update the namespace labels for %s", namespace.Name) + l.Warn("unable to update the namespace labels", "namespace", namespace.Name, "error", err) } } spinner.Updatef("Removing Zarf secrets for namespace %s", namespace.Name) + l.Info("removing Zarf secrets", "namespace", namespace.Name) err := c.Clientset.CoreV1(). Secrets(namespace.Name). DeleteCollection(ctx, deleteOptions, listOptions) if err != nil { spinner.Errorf(err, "Unable to delete secrets from namespace %s", namespace.Name) + l.Error("unable to delete secrets", "namespace", namespace.Name, "error", err) } } } spinner.Success() + l.Debug("done stripping zarf labels and secrets from namespaces", "duration", time.Since(start)) } // RecordPackageDeployment saves metadata about a package that has been deployed to the cluster. diff --git a/src/pkg/packager/remove.go b/src/pkg/packager/remove.go index 322db5570f..b1149e343d 100644 --- a/src/pkg/packager/remove.go +++ b/src/pkg/packager/remove.go @@ -185,7 +185,7 @@ func (p *Packager) removeComponent(ctx context.Context, deployedPackage *types.D spinner.Updatef("Uninstalling chart '%s' from the '%s' component", chart.ChartName, deployedComponent.Name) helmCfg := helm.NewClusterOnly(p.cfg, p.variableConfig, p.state, p.cluster) - if err := helmCfg.RemoveChart(chart.Namespace, chart.ChartName, spinner); err != nil { + if err := helmCfg.RemoveChart(ctx, chart.Namespace, chart.ChartName, spinner); err != nil { if !errors.Is(err, driver.ErrReleaseNotFound) { onFailure() return deployedPackage, fmt.Errorf("unable to uninstall the helm chart %s in the namespace %s: %w",