Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 50 additions & 28 deletions pkg/skaffold/deploy/helm/helm.go
Original file line number Diff line number Diff line change
Expand Up @@ -295,15 +295,7 @@ func (h *Deployer) Deploy(ctx context.Context, out io.Writer, builds []graph.Art
releaseNameToRelease[r.Name] = r
}

levels := make([]int, 0, len(levelByLevelReleases))
for level := range levelByLevelReleases {
levels = append(levels, level)
}
// Sort levels in ascending order
sort.Ints(levels)

// Process each level in order
for _, level := range levels {
for level := 0; level < len(levelByLevelReleases); level++ {
releases := levelByLevelReleases[level]
if len(levelByLevelReleases) > 1 {
olog.Entry(ctx).Infof("Installing level %d/%d releases (%d releases)", level+1, len(levelByLevelReleases), len(releases))
Expand Down Expand Up @@ -450,30 +442,41 @@ func (h *Deployer) Cleanup(ctx context.Context, out io.Writer, dryRun bool, _ ma
"DeployerType": "helm",
})

var errMsgs []string
dependencyGraph, err := NewDependencyGraph(h.Releases)
if err != nil {
return fmt.Errorf("unable to create dependency graph: %w", err)
}

levelByLevelReleases, err := dependencyGraph.GetReleasesByLevel()
if err != nil {
return fmt.Errorf("unable to get releases by level: %w", err)
}

releaseNameToRelease := make(map[string]latest.HelmRelease)
for _, r := range h.Releases {
releaseName, err := util.ExpandEnvTemplateOrFail(r.Name, nil)
if err != nil {
return fmt.Errorf("cannot parse the release name template: %w", err)
}
releaseNameToRelease[r.Name] = r
}

namespace, err := helm.ReleaseNamespace(h.namespace, r)
if err != nil {
return err
}
args := []string{}
if dryRun {
args = append(args, "get", "manifest")
var errMsgs []string
for level := len(levelByLevelReleases) - 1; level >= 0; level-- {
releases := levelByLevelReleases[level]
if len(levelByLevelReleases) > 1 {
olog.Entry(ctx).Infof("Cleaning up level %d/%d releases (%d releases)", level+1, len(levelByLevelReleases), len(releases))
} else {
args = append(args, "delete")
olog.Entry(ctx).Infof("Cleaning up releases (%d releases)", len(releases))
}
args = append(args, releaseName)

if namespace != "" {
args = append(args, "--namespace", namespace)
}
if err := helm.Exec(ctx, h, out, false, nil, args...); err != nil {
errMsgs = append(errMsgs, err.Error())
for _, name := range releases {
olog.Entry(ctx).Infof("Cleaning up release: %s", name)
release := releaseNameToRelease[name]
releaseName, err := util.ExpandEnvTemplateOrFail(release.Name, nil)
if err != nil {
return fmt.Errorf("cannot parse the release name template: %w", err)
}

if err := h.deleteRelease(ctx, out, releaseName, release, dryRun); err != nil {
errMsgs = append(errMsgs, err.Error())
}
}
}

Expand Down Expand Up @@ -616,6 +619,25 @@ func (h *Deployer) deployRelease(ctx context.Context, out io.Writer, releaseName
return b, artifacts, nil
}

func (h *Deployer) deleteRelease(ctx context.Context, out io.Writer, releaseName string, r latest.HelmRelease, dryRun bool) error {
namespace, err := helm.ReleaseNamespace(h.namespace, r)
if err != nil {
return err
}
args := []string{}
if dryRun {
args = append(args, "get", "manifest")
} else {
args = append(args, "delete")
}
args = append(args, releaseName)

if namespace != "" {
args = append(args, "--namespace", namespace)
}
return helm.Exec(ctx, h, out, false, nil, args...)
}

func getPostRendererFlag(flags []string) []string {
for i, ele := range flags {
if strings.HasPrefix(ele, "--post-renderer") {
Expand Down
19 changes: 19 additions & 0 deletions pkg/skaffold/deploy/helm/helm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ var testDeployPreservingOrderWithDependsOnConfig = latest.LegacyHelmDeploy{
* level 1: B, D
* level 2: A, E
*/
/** Expected order of deletion:
* level 2: E, A
* level 1: D, B
* level 0: F, C
*/
Releases: []latest.HelmRelease{{
Name: "A",
ChartPath: "examples/test",
Expand Down Expand Up @@ -1282,6 +1287,20 @@ func TestHelmCleanup(t *testing.T) {
namespace: kubectl.TestNamespace,
builds: testBuilds,
},
{
description: "helm3 ordered cleanup success",
commands: testutil.
CmdRunWithOutput("helm version --client", version31).
AndRun("helm --kube-context kubecontext delete E --namespace testNamespace --kubeconfig kubeconfig").
AndRun("helm --kube-context kubecontext delete A --namespace testNamespace --kubeconfig kubeconfig").
AndRun("helm --kube-context kubecontext delete D --namespace testNamespace --kubeconfig kubeconfig").
AndRun("helm --kube-context kubecontext delete B --namespace testNamespace --kubeconfig kubeconfig").
AndRun("helm --kube-context kubecontext delete F --namespace testNamespace --kubeconfig kubeconfig").
AndRun("helm --kube-context kubecontext delete C --namespace testNamespace --kubeconfig kubeconfig"),
helm: testDeployPreservingOrderWithDependsOnConfig,
namespace: kubectl.TestNamespace,
builds: testBuilds,
},
}
for _, test := range tests {
testutil.Run(t, test.description, func(t *testutil.T) {
Expand Down
Loading