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:
		
						commit
						35adb8ae22
					
				
							
								
								
									
										102
									
								
								pkg/app/app.go
								
								
								
								
							
							
						
						
									
										102
									
								
								pkg/app/app.go
								
								
								
								
							|  | @ -158,15 +158,15 @@ func (a *App) Status(c StatusesConfigProvider) error { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (a *App) Delete(c DeleteConfigProvider) error { | func (a *App) Delete(c DeleteConfigProvider) error { | ||||||
| 	return a.reverse().ForEachStateFiltered(func(run *Run) []error { | 	return a.reverse().ForEachState(func(run *Run) (bool, []error) { | ||||||
| 		return run.Delete(c) | 		return a.delete(run, c.Purge(), c) | ||||||
| 	}, true) | 	}) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (a *App) Destroy(c DestroyConfigProvider) error { | func (a *App) Destroy(c DestroyConfigProvider) error { | ||||||
| 	return a.reverse().ForEachStateFiltered(func(run *Run) []error { | 	return a.reverse().ForEachState(func(run *Run) (bool, []error) { | ||||||
| 		return run.Destroy(c) | 		return a.delete(run, true, c) | ||||||
| 	}, true) | 	}) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (a *App) Test(c TestConfigProvider) error { | func (a *App) Test(c TestConfigProvider) error { | ||||||
|  | @ -399,13 +399,13 @@ func (a *App) visitStates(fileOrDir string, defOpts LoadOpts, converge func(*sta | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (a *App) ForEachStateFiltered(do func(*Run) []error, dagEnabled ...bool) error { | func (a *App) ForEachStateFiltered(do func(*Run) []error) error { | ||||||
| 	ctx := NewContext() | 	ctx := NewContext() | ||||||
| 	err := a.VisitDesiredStatesWithReleasesFiltered(a.FileOrDir, func(st *state.HelmState, helm helmexec.Interface) []error { | 	err := a.VisitDesiredStatesWithReleasesFiltered(a.FileOrDir, func(st *state.HelmState, helm helmexec.Interface) []error { | ||||||
| 		run := NewRun(st, helm, ctx) | 		run := NewRun(st, helm, ctx) | ||||||
| 
 | 
 | ||||||
| 		return do(run) | 		return do(run) | ||||||
| 	}, dagEnabled...) | 	}) | ||||||
| 
 | 
 | ||||||
| 	if err != nil && a.ErrorHandler != nil { | 	if err != nil && a.ErrorHandler != nil { | ||||||
| 		return a.ErrorHandler(err) | 		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)) | 	logger.Debugf("processing %d groups of releases in this order:\n%s", numBatches, printBatches(batches)) | ||||||
| 
 | 
 | ||||||
| 	all := true | 	any := false | ||||||
| 
 | 
 | ||||||
| 	for i, batch := range batches { | 	for i, batch := range batches { | ||||||
| 		var targets []state.ReleaseSpec | 		var targets []state.ReleaseSpec | ||||||
|  | @ -485,10 +485,10 @@ func withDAG(templated *state.HelmState, helm helmexec.Interface, logger *zap.Su | ||||||
| 			return false, errs | 			return false, errs | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		all = all && processed | 		any = any || processed | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return all, nil | 	return any, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type Opts struct { | 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) | 	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 a.visitStatesWithSelectorsAndRemoteSupport(fileOrDir, func(st *state.HelmState, helm helmexec.Interface) (bool, []error) { | ||||||
| 		return f(st, helm) | 		return f(st, helm) | ||||||
| 	}) | 	}) | ||||||
|  | @ -835,6 +829,78 @@ Do you really want to apply? | ||||||
| 	return true, syncErrs | 	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 { | func fileExistsAt(path string) bool { | ||||||
| 	fileInfo, err := os.Stat(path) | 	fileInfo, err := os.Stat(path) | ||||||
| 	return err == nil && fileInfo.Mode().IsRegular() | 	return err == nil && fileInfo.Mode().IsRegular() | ||||||
|  |  | ||||||
|  | @ -1,9 +1,6 @@ | ||||||
| package app | package app | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"fmt" |  | ||||||
| 	"strings" |  | ||||||
| 
 |  | ||||||
| 	"github.com/roboll/helmfile/pkg/argparser" | 	"github.com/roboll/helmfile/pkg/argparser" | ||||||
| 	"github.com/roboll/helmfile/pkg/helmexec" | 	"github.com/roboll/helmfile/pkg/helmexec" | ||||||
| 	"github.com/roboll/helmfile/pkg/state" | 	"github.com/roboll/helmfile/pkg/state" | ||||||
|  | @ -64,60 +61,6 @@ func (r *Run) Status(c StatusesConfigProvider) []error { | ||||||
| 	return r.state.ReleaseStatuses(r.helm, workers) | 	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 { | func (r *Run) Diff(c DiffConfigProvider) []error { | ||||||
| 	st := r.state | 	st := r.state | ||||||
| 	helm := r.helm | 	helm := r.helm | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue