feat: least frequent repository update (#356)
Prevents helmfile from consuming unnecessarily much time in running `helm repo update` over and over. helmfile now marks which repository was updated, and skip second and further `helm repo update` when all the `repositories` found in a helmfile.yaml was marked as already updated. Let's say you had two helmfiles, the first one with repositories `foo` and `bar`, an the second one with only `bar`. `helmfile repos` will run `helm update repo` for the first helmfile, marking `foo` and `bar` as already updated. The second helmfile.yaml contains only `bar`, which is marked as already updated. So helmfile won't run `helm repo update` for the second. This applies to all the helmfile command that results in `helm repo update`, like `repos`, `sync`, `diff` and so on. Resolves #335
This commit is contained in:
parent
f2b610afdf
commit
b94265122f
93
main.go
93
main.go
|
|
@ -114,13 +114,13 @@ func main() {
|
|||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
return visitAllDesiredStates(c, func(state *state.HelmState, helm helmexec.Interface) (bool, []error) {
|
||||
return visitAllDesiredStates(c, func(state *state.HelmState, helm helmexec.Interface, ctx context) (bool, []error) {
|
||||
args := args.GetArgs(c.String("args"), state)
|
||||
if len(args) > 0 {
|
||||
helm.SetExtraArgs(args...)
|
||||
}
|
||||
|
||||
errs := state.SyncRepos(helm)
|
||||
errs := ctx.SyncReposOnce(state, helm)
|
||||
|
||||
ok := len(state.Repositories) > 0 && len(errs) == 0
|
||||
|
||||
|
|
@ -148,7 +148,7 @@ func main() {
|
|||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
return findAndIterateOverDesiredStatesUsingFlags(c, func(state *state.HelmState, helm helmexec.Interface) []error {
|
||||
return findAndIterateOverDesiredStatesUsingFlags(c, func(state *state.HelmState, helm helmexec.Interface, _ context) []error {
|
||||
return executeSyncCommand(c, state, helm)
|
||||
})
|
||||
},
|
||||
|
|
@ -185,9 +185,11 @@ func main() {
|
|||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
return findAndIterateOverDesiredStatesUsingFlags(c, func(state *state.HelmState, helm helmexec.Interface) []error {
|
||||
if errs := state.PrepareRelease(helm, "diff"); errs != nil && len(errs) > 0 {
|
||||
return errs
|
||||
return findAndIterateOverDesiredStatesUsingFlags(c, func(state *state.HelmState, helm helmexec.Interface, ctx context) []error {
|
||||
if c.Bool("sync-repos") {
|
||||
if errs := ctx.SyncReposOnce(state, helm); errs != nil && len(errs) > 0 {
|
||||
return errs
|
||||
}
|
||||
}
|
||||
|
||||
_, errs := executeDiffCommand(c, state, helm, c.Bool("detailed-exitcode"), c.Bool("suppress-secrets"))
|
||||
|
|
@ -215,10 +217,17 @@ func main() {
|
|||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
return findAndIterateOverDesiredStatesUsingFlags(c, func(state *state.HelmState, helm helmexec.Interface) []error {
|
||||
return findAndIterateOverDesiredStatesUsingFlags(c, func(state *state.HelmState, helm helmexec.Interface, ctx context) []error {
|
||||
if errs := state.PrepareRelease(helm, "template"); errs != nil && len(errs) > 0 {
|
||||
return errs
|
||||
}
|
||||
if errs := ctx.SyncReposOnce(state, helm); errs != nil && len(errs) > 0 {
|
||||
return errs
|
||||
}
|
||||
|
||||
if errs := state.UpdateDeps(helm); errs != nil && len(errs) > 0 {
|
||||
return errs
|
||||
}
|
||||
|
||||
return executeTemplateCommand(c, state, helm)
|
||||
})
|
||||
|
|
@ -244,11 +253,11 @@ func main() {
|
|||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
return findAndIterateOverDesiredStatesUsingFlags(c, func(state *state.HelmState, helm helmexec.Interface) []error {
|
||||
return findAndIterateOverDesiredStatesUsingFlags(c, func(state *state.HelmState, helm helmexec.Interface, ctx context) []error {
|
||||
values := c.StringSlice("values")
|
||||
args := args.GetArgs(c.String("args"), state)
|
||||
workers := c.Int("concurrency")
|
||||
if errs := state.SyncRepos(helm); errs != nil && len(errs) > 0 {
|
||||
if errs := ctx.SyncReposOnce(state, helm); errs != nil && len(errs) > 0 {
|
||||
return errs
|
||||
}
|
||||
if errs := state.PrepareRelease(helm, "lint"); errs != nil && len(errs) > 0 {
|
||||
|
|
@ -278,8 +287,8 @@ func main() {
|
|||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
return findAndIterateOverDesiredStatesUsingFlags(c, func(state *state.HelmState, helm helmexec.Interface) []error {
|
||||
if errs := state.SyncRepos(helm); errs != nil && len(errs) > 0 {
|
||||
return findAndIterateOverDesiredStatesUsingFlags(c, func(state *state.HelmState, helm helmexec.Interface, ctx context) []error {
|
||||
if errs := ctx.SyncReposOnce(state, helm); errs != nil && len(errs) > 0 {
|
||||
return errs
|
||||
}
|
||||
if errs := state.PrepareRelease(helm, "sync"); errs != nil && len(errs) > 0 {
|
||||
|
|
@ -324,9 +333,9 @@ func main() {
|
|||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
return findAndIterateOverDesiredStatesUsingFlags(c, func(st *state.HelmState, helm helmexec.Interface) []error {
|
||||
return findAndIterateOverDesiredStatesUsingFlags(c, func(st *state.HelmState, helm helmexec.Interface, ctx context) []error {
|
||||
if !c.Bool("skip-repo-update") {
|
||||
if errs := st.SyncRepos(helm); errs != nil && len(errs) > 0 {
|
||||
if errs := ctx.SyncReposOnce(st, helm); errs != nil && len(errs) > 0 {
|
||||
return errs
|
||||
}
|
||||
}
|
||||
|
|
@ -413,7 +422,7 @@ Do you really want to apply?
|
|||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
return findAndIterateOverDesiredStatesUsingFlags(c, func(state *state.HelmState, helm helmexec.Interface) []error {
|
||||
return findAndIterateOverDesiredStatesUsingFlags(c, func(state *state.HelmState, helm helmexec.Interface, _ context) []error {
|
||||
workers := c.Int("concurrency")
|
||||
|
||||
args := args.GetArgs(c.String("args"), state)
|
||||
|
|
@ -444,7 +453,7 @@ Do you really want to apply?
|
|||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
return findAndIterateOverDesiredStatesUsingFlagsWithReverse(c, true, func(state *state.HelmState, helm helmexec.Interface) []error {
|
||||
return findAndIterateOverDesiredStatesUsingFlagsWithReverse(c, true, func(state *state.HelmState, helm helmexec.Interface, _ context) []error {
|
||||
purge := c.Bool("purge")
|
||||
|
||||
args := args.GetArgs(c.String("args"), state)
|
||||
|
|
@ -492,7 +501,7 @@ Do you really want to delete?
|
|||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
return findAndIterateOverDesiredStatesUsingFlags(c, func(state *state.HelmState, helm helmexec.Interface) []error {
|
||||
return findAndIterateOverDesiredStatesUsingFlags(c, func(state *state.HelmState, helm helmexec.Interface, _ context) []error {
|
||||
cleanup := c.Bool("cleanup")
|
||||
timeout := c.Int("timeout")
|
||||
|
||||
|
|
@ -527,14 +536,6 @@ func executeSyncCommand(c *cli.Context, state *state.HelmState, helm helmexec.In
|
|||
}
|
||||
|
||||
func executeTemplateCommand(c *cli.Context, state *state.HelmState, helm helmexec.Interface) []error {
|
||||
if errs := state.SyncRepos(helm); errs != nil && len(errs) > 0 {
|
||||
return errs
|
||||
}
|
||||
|
||||
if errs := state.UpdateDeps(helm); errs != nil && len(errs) > 0 {
|
||||
return errs
|
||||
}
|
||||
|
||||
args := args.GetArgs(c.String("args"), state)
|
||||
values := c.StringSlice("values")
|
||||
workers := c.Int("concurrency")
|
||||
|
|
@ -548,12 +549,6 @@ func executeDiffCommand(c *cli.Context, st *state.HelmState, helm helmexec.Inter
|
|||
helm.SetExtraArgs(args...)
|
||||
}
|
||||
|
||||
if c.Bool("sync-repos") {
|
||||
if errs := st.SyncRepos(helm); errs != nil && len(errs) > 0 {
|
||||
return []*state.ReleaseSpec{}, errs
|
||||
}
|
||||
}
|
||||
|
||||
values := c.StringSlice("values")
|
||||
workers := c.Int("concurrency")
|
||||
|
||||
|
|
@ -574,7 +569,7 @@ type app struct {
|
|||
selectors []string
|
||||
}
|
||||
|
||||
func findAndIterateOverDesiredStatesUsingFlags(c *cli.Context, converge func(*state.HelmState, helmexec.Interface) []error) error {
|
||||
func findAndIterateOverDesiredStatesUsingFlags(c *cli.Context, converge func(*state.HelmState, helmexec.Interface, context) []error) error {
|
||||
return findAndIterateOverDesiredStatesUsingFlagsWithReverse(c, false, converge)
|
||||
}
|
||||
|
||||
|
|
@ -612,17 +607,43 @@ func initAppEntry(c *cli.Context, reverse bool) (*app, string, error) {
|
|||
return app, fileOrDir, nil
|
||||
}
|
||||
|
||||
func visitAllDesiredStates(c *cli.Context, converge func(*state.HelmState, helmexec.Interface) (bool, []error)) error {
|
||||
type context struct {
|
||||
updatedRepos map[string]struct{}
|
||||
}
|
||||
|
||||
func (ctx context) SyncReposOnce(st *state.HelmState, helm state.RepoUpdater) []error {
|
||||
var errs []error
|
||||
|
||||
allUpdated := true
|
||||
for _, r := range st.Repositories {
|
||||
_, exists := ctx.updatedRepos[r.Name]
|
||||
allUpdated = allUpdated && exists
|
||||
}
|
||||
|
||||
if !allUpdated {
|
||||
errs = st.SyncRepos(helm)
|
||||
|
||||
for _, r := range st.Repositories {
|
||||
ctx.updatedRepos[r.Name] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
func visitAllDesiredStates(c *cli.Context, converge func(*state.HelmState, helmexec.Interface, context) (bool, []error)) error {
|
||||
app, fileOrDir, err := initAppEntry(c, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx := context{}
|
||||
|
||||
convergeWithHelmBinary := func(st *state.HelmState, helm helmexec.Interface) (bool, []error) {
|
||||
if c.GlobalString("helm-binary") != "" {
|
||||
helm.SetHelmBinary(c.GlobalString("helm-binary"))
|
||||
}
|
||||
return converge(st, helm)
|
||||
return converge(st, helm, ctx)
|
||||
}
|
||||
|
||||
err = app.VisitDesiredStates(fileOrDir, convergeWithHelmBinary)
|
||||
|
|
@ -648,17 +669,19 @@ func toCliError(err error) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func findAndIterateOverDesiredStatesUsingFlagsWithReverse(c *cli.Context, reverse bool, converge func(*state.HelmState, helmexec.Interface) []error) error {
|
||||
func findAndIterateOverDesiredStatesUsingFlagsWithReverse(c *cli.Context, reverse bool, converge func(*state.HelmState, helmexec.Interface, context) []error) error {
|
||||
app, fileOrDir, err := initAppEntry(c, reverse)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx := context{}
|
||||
|
||||
convergeWithHelmBinary := func(st *state.HelmState, helm helmexec.Interface) []error {
|
||||
if c.GlobalString("helm-binary") != "" {
|
||||
helm.SetHelmBinary(c.GlobalString("helm-binary"))
|
||||
}
|
||||
return converge(st, helm)
|
||||
return converge(st, helm, ctx)
|
||||
}
|
||||
|
||||
err = app.VisitDesiredStatesWithReleasesFiltered(fileOrDir, convergeWithHelmBinary)
|
||||
|
|
|
|||
|
|
@ -128,8 +128,13 @@ func (state *HelmState) applyDefaultsTo(spec *ReleaseSpec) {
|
|||
}
|
||||
}
|
||||
|
||||
type RepoUpdater interface {
|
||||
AddRepo(name, repository, certfile, keyfile, username, password string) error
|
||||
UpdateRepo() error
|
||||
}
|
||||
|
||||
// SyncRepos will update the given helm releases
|
||||
func (state *HelmState) SyncRepos(helm helmexec.Interface) []error {
|
||||
func (state *HelmState) SyncRepos(helm RepoUpdater) []error {
|
||||
errs := []error{}
|
||||
|
||||
for _, repo := range state.Repositories {
|
||||
|
|
@ -828,6 +833,7 @@ func (state *HelmState) PrepareRelease(helm helmexec.Interface, helmfileCommand
|
|||
for _, release := range state.Releases {
|
||||
if _, err := state.triggerPrepareEvent(&release, helmfileCommand); err != nil {
|
||||
errs = append(errs, &ReleaseError{&release, err})
|
||||
continue
|
||||
}
|
||||
}
|
||||
if len(errs) != 0 {
|
||||
|
|
|
|||
Loading…
Reference in New Issue