Fix chart fetched by go-getter not to fail due to missing dependencies (#1408)
Ref https://github.com/roboll/helmfile/issues/1401#issuecomment-670915272
This commit is contained in:
parent
0ef7e65f02
commit
9a03d79a84
|
|
@ -819,6 +819,7 @@ func (st *HelmState) PrepareCharts(helm helmexec.Interface, dir string, concurre
|
||||||
releaseName string
|
releaseName string
|
||||||
chartPath string
|
chartPath string
|
||||||
err error
|
err error
|
||||||
|
diagnostic string
|
||||||
}
|
}
|
||||||
|
|
||||||
errs := []error{}
|
errs := []error{}
|
||||||
|
|
@ -838,6 +839,8 @@ func (st *HelmState) PrepareCharts(helm helmexec.Interface, dir string, concurre
|
||||||
}
|
}
|
||||||
*st = *updated
|
*st = *updated
|
||||||
|
|
||||||
|
var diagnostics []string
|
||||||
|
|
||||||
st.scatterGather(
|
st.scatterGather(
|
||||||
concurrency,
|
concurrency,
|
||||||
len(releases),
|
len(releases),
|
||||||
|
|
@ -867,6 +870,8 @@ func (st *HelmState) PrepareCharts(helm helmexec.Interface, dir string, concurre
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chartFetchedByGoGetter := chartPath != chartName
|
||||||
|
|
||||||
chartification, clean, err := st.PrepareChartify(helm, release, chartPath, workerIndex)
|
chartification, clean, err := st.PrepareChartify(helm, release, chartPath, workerIndex)
|
||||||
defer clean()
|
defer clean()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -874,6 +879,8 @@ func (st *HelmState) PrepareCharts(helm helmexec.Interface, dir string, concurre
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var diagnostic string
|
||||||
|
|
||||||
if chartification != nil {
|
if chartification != nil {
|
||||||
c := chartify.New(
|
c := chartify.New(
|
||||||
chartify.HelmBin(st.DefaultHelmBinary),
|
chartify.HelmBin(st.DefaultHelmBinary),
|
||||||
|
|
@ -888,6 +895,50 @@ func (st *HelmState) PrepareCharts(helm helmexec.Interface, dir string, concurre
|
||||||
// TODO Chartify
|
// TODO Chartify
|
||||||
chartPath = out
|
chartPath = out
|
||||||
}
|
}
|
||||||
|
} else if pathExists(normalizeChart(st.basePath, chartPath)) {
|
||||||
|
// At this point, we are sure that chartPath is a local directory containing either:
|
||||||
|
// - A remote chart fetched by go-getter or
|
||||||
|
// - A local chart
|
||||||
|
//
|
||||||
|
// The chart may have Chart.yaml(and requirements.yaml for Helm 2), and optionally Chart.lock/requirements.lock,
|
||||||
|
// but no `charts/` directory populated at all, or a subet of chart dependencies are missing in the directory.
|
||||||
|
//
|
||||||
|
// In such situation, Helm fails with an error like:
|
||||||
|
// Error: found in Chart.yaml, but missing in charts/ directory: cert-manager, prometheus, postgresql, gitlab-runner, grafana, redis
|
||||||
|
//
|
||||||
|
// (See also https://github.com/roboll/helmfile/issues/1401#issuecomment-670854495)
|
||||||
|
//
|
||||||
|
// To avoid it, we need to call a `helm dep build` command on the chart.
|
||||||
|
// But the command may consistently fail when an outdated Chart.lock exists.
|
||||||
|
//
|
||||||
|
// (I've mentioned about such case in https://github.com/roboll/helmfile/pull/1400.)
|
||||||
|
//
|
||||||
|
// Trying to run `helm dep build` on the chart regardless of if it's from local or remote is
|
||||||
|
// problematic, as usually the user would have no way to fix the remote chart on their own.
|
||||||
|
//
|
||||||
|
// Given that, we always run `helm dep build` on the chart here, but tolerate any error caused by it
|
||||||
|
// for a remote chart, so that the user can notice/fix the issue in a local chart while
|
||||||
|
// a broken remote chart won't completely block their job.
|
||||||
|
chartPath = normalizeChart(st.basePath, chartPath)
|
||||||
|
|
||||||
|
if !skipDeps {
|
||||||
|
if err := helm.BuildDeps(release.Name, chartPath); err != nil {
|
||||||
|
if chartFetchedByGoGetter {
|
||||||
|
diagnostic = fmt.Sprintf(
|
||||||
|
"WARN: `helm dep build` failed. While processing release %q, Helmfile observed that remote chart %q fetched by go-getter is seemingly broken. "+
|
||||||
|
"One of well-known causes of this is that the chart has outdated Chart.lock, which needs the chart maintainer needs to run `helm dep up`. "+
|
||||||
|
"Helmfile is tolerating the error to avoid blocking you until the remote chart gets fixed. "+
|
||||||
|
"But this may result in any failure later if the chart is broken badly. FYI, the tolerated error was: %v",
|
||||||
|
release.Name,
|
||||||
|
chartName,
|
||||||
|
err.Error(),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
results <- &downloadResults{err: err}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if !forceDownload {
|
} else if !forceDownload {
|
||||||
// At this point, we are sure that either:
|
// At this point, we are sure that either:
|
||||||
// 1. It is a local chart and we can use it in later process (helm upgrade/template/lint/etc)
|
// 1. It is a local chart and we can use it in later process (helm upgrade/template/lint/etc)
|
||||||
|
|
@ -895,15 +946,6 @@ func (st *HelmState) PrepareCharts(helm helmexec.Interface, dir string, concurre
|
||||||
// 2. It is a remote chart which can be safely handed over to helm,
|
// 2. It is a remote chart which can be safely handed over to helm,
|
||||||
// because the version of Helm used in this transaction support downloading the chart instead,
|
// because the version of Helm used in this transaction support downloading the chart instead,
|
||||||
// and we don't need any modification to the chart
|
// and we don't need any modification to the chart
|
||||||
} else if pathExists(normalizeChart(st.basePath, chartPath)) {
|
|
||||||
chartPath = normalizeChart(st.basePath, chartPath)
|
|
||||||
|
|
||||||
if !skipDeps {
|
|
||||||
if err := helm.BuildDeps(release.Name, chartPath); err != nil {
|
|
||||||
results <- &downloadResults{err: err}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
pathElems := []string{
|
pathElems := []string{
|
||||||
dir,
|
dir,
|
||||||
|
|
@ -943,13 +985,17 @@ func (st *HelmState) PrepareCharts(helm helmexec.Interface, dir string, concurre
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
results <- &downloadResults{releaseName: release.Name, chartPath: chartPath}
|
results <- &downloadResults{releaseName: release.Name, chartPath: chartPath, diagnostic: diagnostic}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
func() {
|
func() {
|
||||||
for i := 0; i < len(releases); i++ {
|
for i := 0; i < len(releases); i++ {
|
||||||
downloadRes := <-results
|
downloadRes := <-results
|
||||||
|
|
||||||
|
if d := downloadRes.diagnostic; d != "" {
|
||||||
|
diagnostics = append(diagnostics, d)
|
||||||
|
}
|
||||||
|
|
||||||
if downloadRes.err != nil {
|
if downloadRes.err != nil {
|
||||||
errs = append(errs, downloadRes.err)
|
errs = append(errs, downloadRes.err)
|
||||||
|
|
||||||
|
|
@ -960,6 +1006,11 @@ func (st *HelmState) PrepareCharts(helm helmexec.Interface, dir string, concurre
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
sort.Strings(diagnostics)
|
||||||
|
for _, d := range diagnostics {
|
||||||
|
st.logger.Warn(d)
|
||||||
|
}
|
||||||
|
|
||||||
if len(errs) > 0 {
|
if len(errs) > 0 {
|
||||||
return nil, errs
|
return nil, errs
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue