Skip to content

Fix various issues in chart preparation #1400

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 6, 2020
Merged
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
32 changes: 4 additions & 28 deletions pkg/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,9 @@ func (a *App) Diff(c DiffConfigProvider) error {

func (a *App) Template(c TemplateConfigProvider) error {
return a.ForEachState(func(run *Run) (ok bool, errs []error) {
prepErr := run.withPreparedCharts(true, c.SkipDeps(), "template", func() {
// `helm template` in helm v2 does not support local chart.
// So, we set forceDownload=true for helm v2 only
prepErr := run.withPreparedCharts(!run.helm.IsHelm3(), c.SkipDeps(), "template", func() {
ok, errs = a.template(run, c)
})

Expand All @@ -230,6 +232,7 @@ func (a *App) Template(c TemplateConfigProvider) error {

func (a *App) Lint(c LintConfigProvider) error {
return a.ForEachState(func(run *Run) (_ bool, errs []error) {
// `helm lint` on helm v2 and v3 does not support remote charts, that we need to set `forceDownload=true` here
prepErr := run.withPreparedCharts(true, c.SkipDeps(), "lint", func() {
errs = run.Lint(c)
})
Expand Down Expand Up @@ -970,15 +973,6 @@ func (a *App) apply(r *Run, c ApplyConfigProvider) (bool, bool, []error) {
// on running various helm commands on unnecessary releases
st.Releases = toApply

if !c.SkipDeps() {
if errs := st.BuildDeps(helm); errs != nil && len(errs) > 0 {
return false, false, errs
}
}
if errs := st.PrepareReleases(helm, "apply"); errs != nil && len(errs) > 0 {
return false, false, errs
}

// helm must be 2.11+ and helm-diff should be provided `--detailed-exitcode` in order for `helmfile apply` to work properly
detailedExitCode := true

Expand Down Expand Up @@ -1157,15 +1151,6 @@ func (a *App) sync(r *Run, c SyncConfigProvider) (bool, []error) {
// on running various helm commands on unnecessary releases
st.Releases = toSync

if !c.SkipDeps() {
if errs := st.BuildDeps(helm); errs != nil && len(errs) > 0 {
return false, errs
}
}
if errs := st.PrepareReleases(helm, "sync"); errs != nil && len(errs) > 0 {
return false, errs
}

toDelete, err := st.DetectReleasesToBeDeletedForSync(helm, toSync)
if err != nil {
return false, []error{err}
Expand Down Expand Up @@ -1279,15 +1264,6 @@ func (a *App) template(r *Run, c TemplateConfigProvider) (bool, []error) {
// on running various helm commands on unnecessary releases
st.Releases = toRender

if !c.SkipDeps() {
if errs := st.BuildDeps(helm); errs != nil && len(errs) > 0 {
return false, errs
}
}
if errs := st.PrepareReleases(helm, "template"); errs != nil && len(errs) > 0 {
return false, errs
}

releasesToRender := map[string]state.ReleaseSpec{}
for _, r := range toRender {
id := state.ReleaseToID(&r)
Expand Down
20 changes: 1 addition & 19 deletions pkg/app/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func (r *Run) withPreparedCharts(forceDownload, skipRepos bool, helmfileCommand
return err
}

releaseToChart, errs := r.state.PrepareCharts(r.helm, dir, 2, helmfileCommand, forceDownload)
releaseToChart, errs := r.state.PrepareCharts(r.helm, dir, 2, helmfileCommand, forceDownload, skipRepos)

if len(errs) > 0 {
return fmt.Errorf("%v", errs)
Expand Down Expand Up @@ -114,7 +114,6 @@ func (r *Run) Status(c StatusesConfigProvider) []error {

func (a *App) diff(r *Run, c DiffConfigProvider) (*string, bool, bool, []error) {
st := r.state
helm := r.helm

allReleases := st.GetReleasesWithOverrides()

Expand All @@ -131,15 +130,6 @@ func (a *App) diff(r *Run, c DiffConfigProvider) (*string, bool, bool, []error)
// on running various helm commands on unnecessary releases
st.Releases = toDiff

if !c.SkipDeps() {
if errs := st.BuildDeps(helm); errs != nil && len(errs) > 0 {
return nil, false, false, errs
}
}
if errs := st.PrepareReleases(helm, "diff"); errs != nil && len(errs) > 0 {
return nil, false, false, errs
}

r.helm.SetExtraArgs(argparser.GetArgs(c.Args(), r.state)...)

opts := &state.DiffOpts{
Expand Down Expand Up @@ -188,14 +178,6 @@ func (r *Run) Lint(c LintConfigProvider) []error {
values := c.Values()
args := argparser.GetArgs(c.Args(), st)
workers := c.Concurrency()
if !c.SkipDeps() {
if errs := st.BuildDeps(helm); errs != nil && len(errs) > 0 {
return errs
}
}
if errs := st.PrepareReleases(helm, "lint"); errs != nil && len(errs) > 0 {
return errs
}
opts := &state.LintOpts{
Set: c.Set(),
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/state/chart_dependency.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ func updateDependencies(st *HelmState, shell helmexec.DependencyUpdater, unresol

_, err := depMan.Update(shell, wd, unresolved)
if err != nil {
return nil, fmt.Errorf("unable to resolve %d deps: %v", len(unresolved.deps), err)
return nil, fmt.Errorf("unable to update %d deps: %v", len(unresolved.deps), err)
}

return resolveDependencies(st, depMan, unresolved)
Expand Down
85 changes: 26 additions & 59 deletions pkg/state/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -805,12 +805,13 @@ func releasesNeedCharts(releases []ReleaseSpec) []ReleaseSpec {
// (2) temporary local chart generated from kustomization or manifests
// (3) remote chart
//
// When running `helmfile lint` or `helmfile template`, PrepareCharts will download and untar charts for linting and templating.
// When running `helmfile template` on helm v2, or `helmfile lint` on both helm v2 and v3,
// PrepareCharts will download and untar charts for linting and templating.
//
// Otheriwse, if a chart is not a helm chart, it will call "chartify" to turn it into a chart.
//
// If exists, it will also patch resources by json patches, strategic-merge patches, and injectors.
func (st *HelmState) PrepareCharts(helm helmexec.Interface, dir string, concurrency int, helmfileCommand string, forceDownload bool) (map[string]string, []error) {
func (st *HelmState) PrepareCharts(helm helmexec.Interface, dir string, concurrency int, helmfileCommand string, forceDownload, skipDeps bool) (map[string]string, []error) {
releases := releasesNeedCharts(st.Releases)

temp := make(map[string]string, len(releases))
Expand All @@ -831,6 +832,12 @@ func (st *HelmState) PrepareCharts(helm helmexec.Interface, dir string, concurre
helm3 = helm.IsHelm3()
}

updated, err := st.ResolveDeps()
if err != nil {
return nil, []error{err}
}
*st = *updated

st.scatterGather(
concurrency,
len(releases),
Expand All @@ -842,6 +849,16 @@ func (st *HelmState) PrepareCharts(helm helmexec.Interface, dir string, concurre
},
func(workerIndex int) {
for release := range jobQueue {
// Call user-defined `prepare` hooks to create/modify local charts to be used by
// the later process.
//
// If it wasn't called here, Helmfile can end up an issue like
// https://github.com/roboll/helmfile/issues/1328
if _, err := st.triggerPrepareEvent(release, helmfileCommand); err != nil {
results <- &downloadResults{err: err}
return
}

var chartPath string

chartification, clean, err := st.PrepareChartify(helm, release, workerIndex)
Expand Down Expand Up @@ -869,6 +886,13 @@ func (st *HelmState) PrepareCharts(helm helmexec.Interface, dir string, concurre
chartPath = release.Chart
} else if pathExists(normalizeChart(st.basePath, release.Chart)) {
chartPath = normalizeChart(st.basePath, release.Chart)

if !skipDeps {
if err := helm.BuildDeps(release.Name, chartPath); err != nil {
results <- &downloadResults{err: err}
return
}
}
} else {
fetchFlags := []string{}

Expand Down Expand Up @@ -1540,35 +1564,6 @@ func (st *HelmState) FilterReleases() error {
return nil
}

func (st *HelmState) PrepareReleases(helm helmexec.Interface, helmfileCommand string) []error {
errs := []error{}

for i := range st.Releases {
release := st.Releases[i]

if release.Installed != nil && !*release.Installed {
continue
}

if _, err := st.triggerPrepareEvent(&release, helmfileCommand); err != nil {
errs = append(errs, newReleaseFailedError(&release, err))
continue
}
}
if len(errs) != 0 {
return errs
}

updated, err := st.ResolveDeps()
if err != nil {
return []error{err}
}

*st = *updated

return nil
}

func (st *HelmState) TriggerGlobalPrepareEvent(helmfileCommand string) (bool, error) {
return st.triggerGlobalReleaseEvent("prepare", nil, helmfileCommand)
}
Expand Down Expand Up @@ -1660,34 +1655,6 @@ func (st *HelmState) UpdateDeps(helm helmexec.Interface) []error {
return nil
}

// BuildDeps wrapper for building dependencies on the releases
func (st *HelmState) BuildDeps(helm helmexec.Interface) []error {
errs := []error{}

releases := releasesNeedCharts(st.Releases)

for _, release := range releases {
if len(release.Chart) == 0 {
errs = append(errs, errors.New("chart is required for: "+release.Name))
continue
}

if release.Installed != nil && !*release.Installed {
continue
}

if isLocalChart(release.Chart) {
if err := helm.BuildDeps(release.Name, normalizeChart(st.basePath, release.Chart)); err != nil {
errs = append(errs, err)
}
}
}
if len(errs) != 0 {
return errs
}
return nil
}

func pathExists(chart string) bool {
_, err := os.Stat(chart)
return err == nil
Expand Down
2 changes: 1 addition & 1 deletion pkg/testhelper/testfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func (f *TestFs) ReadFile(filename string) ([]byte, error) {
str, ok = f.files[filepath.Join(f.Cwd, filename)]
}
if !ok {
return []byte(nil), fmt.Errorf("no registered file found: %s", filename)
return []byte(nil), os.ErrNotExist
}

f.fileReaderCalls += 1
Expand Down