Merge pull request #939 from roboll/fix-needs-ported-to-delete

Port the `needs` fix for `helmfile apply` to `delete` and `destroy`
This commit is contained in:
KUOKA Yusuke 2019-11-06 22:41:37 +09:00 committed by GitHub
commit 35adb8ae22
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 84 additions and 75 deletions

View File

@ -158,15 +158,15 @@ func (a *App) Status(c StatusesConfigProvider) error {
}
func (a *App) Delete(c DeleteConfigProvider) error {
return a.reverse().ForEachStateFiltered(func(run *Run) []error {
return run.Delete(c)
}, true)
return a.reverse().ForEachState(func(run *Run) (bool, []error) {
return a.delete(run, c.Purge(), c)
})
}
func (a *App) Destroy(c DestroyConfigProvider) error {
return a.reverse().ForEachStateFiltered(func(run *Run) []error {
return run.Destroy(c)
}, true)
return a.reverse().ForEachState(func(run *Run) (bool, []error) {
return a.delete(run, true, c)
})
}
func (a *App) Test(c TestConfigProvider) error {
@ -399,13 +399,13 @@ func (a *App) visitStates(fileOrDir string, defOpts LoadOpts, converge func(*sta
return nil
}
func (a *App) ForEachStateFiltered(do func(*Run) []error, dagEnabled ...bool) error {
func (a *App) ForEachStateFiltered(do func(*Run) []error) error {
ctx := NewContext()
err := a.VisitDesiredStatesWithReleasesFiltered(a.FileOrDir, func(st *state.HelmState, helm helmexec.Interface) []error {
run := NewRun(st, helm, ctx)
return do(run)
}, dagEnabled...)
})
if err != nil && a.ErrorHandler != nil {
return a.ErrorHandler(err)
@ -460,7 +460,7 @@ func withDAG(templated *state.HelmState, helm helmexec.Interface, logger *zap.Su
logger.Debugf("processing %d groups of releases in this order:\n%s", numBatches, printBatches(batches))
all := true
any := false
for i, batch := range batches {
var targets []state.ReleaseSpec
@ -485,10 +485,10 @@ func withDAG(templated *state.HelmState, helm helmexec.Interface, logger *zap.Su
return false, errs
}
all = all && processed
any = any || processed
}
return all, nil
return any, nil
}
type Opts struct {
@ -572,15 +572,9 @@ func (a *App) Wrap(converge func(*state.HelmState, helmexec.Interface) []error)
}
}
func (a *App) VisitDesiredStatesWithReleasesFiltered(fileOrDir string, converge func(*state.HelmState, helmexec.Interface) []error, dagEnabled ...bool) error {
func (a *App) VisitDesiredStatesWithReleasesFiltered(fileOrDir string, converge func(*state.HelmState, helmexec.Interface) []error) error {
f := a.Wrap(converge)
if len(dagEnabled) > 0 && dagEnabled[0] {
return a.visitStatesWithSelectorsAndRemoteSupport(fileOrDir, func(st *state.HelmState, helm helmexec.Interface) (bool, []error) {
return withDAG(st, helm, a.Logger, a.Reverse, f)
})
}
return a.visitStatesWithSelectorsAndRemoteSupport(fileOrDir, func(st *state.HelmState, helm helmexec.Interface) (bool, []error) {
return f(st, helm)
})
@ -835,6 +829,78 @@ Do you really want to apply?
return true, syncErrs
}
func (a *App) delete(r *Run, purge bool, c DestroyConfigProvider) (bool, []error) {
st := r.state
helm := r.helm
affectedReleases := state.AffectedReleases{}
var deletingReleases []state.ReleaseSpec
if len(st.Selectors) > 0 {
var err error
deletingReleases, err = st.GetFilteredReleases()
if err != nil {
return false, []error{err}
}
if len(deletingReleases) == 0 {
return false, nil
}
} else {
deletingReleases = st.Releases
}
releasesToBeDeleted := map[string]state.ReleaseSpec{}
for _, r := range deletingReleases {
id := state.ReleaseToID(&r)
releasesToBeDeleted[id] = r
}
names := make([]string, len(deletingReleases))
for i, r := range deletingReleases {
names[i] = fmt.Sprintf(" %s (%s)", r.Name, r.Chart)
}
var errs []error
var any bool
msg := fmt.Sprintf(`Affected releases are:
%s
Do you really want to delete?
Helmfile will delete all your releases, as shown above.
`, strings.Join(names, "\n"))
interactive := c.Interactive()
if !interactive || interactive && r.askForConfirmation(msg) {
r.helm.SetExtraArgs(argparser.GetArgs(c.Args(), r.state)...)
if len(releasesToBeDeleted) > 0 {
deleted, deletionErrs := withDAG(st, helm, a.Logger, true, a.Wrap(func(subst *state.HelmState, helm helmexec.Interface) []error {
var rs []state.ReleaseSpec
for _, r := range subst.Releases {
if _, ok := releasesToBeDeleted[state.ReleaseToID(&r)]; ok {
rs = append(rs, r)
}
}
subst.Releases = rs
return subst.DeleteReleases(&affectedReleases, helm, c.Concurrency(), purge)
}))
any = any || deleted
if deletionErrs != nil && len(deletionErrs) > 0 {
errs = append(errs, deletionErrs...)
}
}
}
affectedReleases.DisplayAffectedReleases(c.Logger())
return any, errs
}
func fileExistsAt(path string) bool {
fileInfo, err := os.Stat(path)
return err == nil && fileInfo.Mode().IsRegular()

View File

@ -1,9 +1,6 @@
package app
import (
"fmt"
"strings"
"github.com/roboll/helmfile/pkg/argparser"
"github.com/roboll/helmfile/pkg/helmexec"
"github.com/roboll/helmfile/pkg/state"
@ -64,60 +61,6 @@ func (r *Run) Status(c StatusesConfigProvider) []error {
return r.state.ReleaseStatuses(r.helm, workers)
}
func (r *Run) Delete(c DeleteConfigProvider) []error {
affectedReleases := state.AffectedReleases{}
purge := c.Purge()
errs := []error{}
names := make([]string, len(r.state.Releases))
for i, r := range r.state.Releases {
names[i] = fmt.Sprintf(" %s (%s)", r.Name, r.Chart)
}
msg := fmt.Sprintf(`Affected releases are:
%s
Do you really want to delete?
Helmfile will delete all your releases, as shown above.
`, strings.Join(names, "\n"))
interactive := c.Interactive()
if !interactive || interactive && r.askForConfirmation(msg) {
r.helm.SetExtraArgs(argparser.GetArgs(c.Args(), r.state)...)
errs = r.state.DeleteReleases(&affectedReleases, r.helm, c.Concurrency(), purge)
}
affectedReleases.DisplayAffectedReleases(c.Logger())
return errs
}
func (r *Run) Destroy(c DestroyConfigProvider) []error {
errs := []error{}
affectedReleases := state.AffectedReleases{}
names := make([]string, len(r.state.Releases))
for i, r := range r.state.Releases {
names[i] = fmt.Sprintf(" %s (%s)", r.Name, r.Chart)
}
msg := fmt.Sprintf(`Affected releases are:
%s
Do you really want to delete?
Helmfile will delete all your releases, as shown above.
`, strings.Join(names, "\n"))
interactive := c.Interactive()
if !interactive || interactive && r.askForConfirmation(msg) {
r.helm.SetExtraArgs(argparser.GetArgs(c.Args(), r.state)...)
errs = r.state.DeleteReleases(&affectedReleases, r.helm, c.Concurrency(), true)
}
affectedReleases.DisplayAffectedReleases(c.Logger())
return errs
}
func (r *Run) Diff(c DiffConfigProvider) []error {
st := r.state
helm := r.helm