feat: Add missingFileHandlerConfig.ignoreMissingGitBranch (#645)
This commit is contained in:
parent
60e024ee3b
commit
ec60ac815b
|
|
@ -236,6 +236,10 @@ releases:
|
||||||
version: ~1.24.1 # the semver of the chart. range constraint is supported
|
version: ~1.24.1 # the semver of the chart. range constraint is supported
|
||||||
condition: vault.enabled # The values lookup key for filtering releases. Corresponds to the boolean value of `vault.enabled`, where `vault` is an arbitrary value
|
condition: vault.enabled # The values lookup key for filtering releases. Corresponds to the boolean value of `vault.enabled`, where `vault` is an arbitrary value
|
||||||
missingFileHandler: Warn # set to either "Error" or "Warn". "Error" instructs helmfile to fail when unable to find a values or secrets file. When "Warn", it prints the file and continues.
|
missingFileHandler: Warn # set to either "Error" or "Warn". "Error" instructs helmfile to fail when unable to find a values or secrets file. When "Warn", it prints the file and continues.
|
||||||
|
missingFileHandlerConfig:
|
||||||
|
# Ignores missing git branch error so that the Debug/Info/Warn handler can treat a missing branch as non-error.
|
||||||
|
# See https://github.com/helmfile/helmfile/issues/392
|
||||||
|
ignoreMissingGitBranch: true
|
||||||
# Values files used for rendering the chart
|
# Values files used for rendering the chart
|
||||||
values:
|
values:
|
||||||
# Value files passed via --values
|
# Value files passed via --values
|
||||||
|
|
@ -400,6 +404,10 @@ environments:
|
||||||
# Use "Warn", "Info", or "Debug" if you want helmfile to not fail when a values file is missing, while just leaving
|
# Use "Warn", "Info", or "Debug" if you want helmfile to not fail when a values file is missing, while just leaving
|
||||||
# a message about the missing file at the log-level.
|
# a message about the missing file at the log-level.
|
||||||
missingFileHandler: Error
|
missingFileHandler: Error
|
||||||
|
missingFileHandlerConfig:
|
||||||
|
# Ignores missing git branch error so that the Debug/Info/Warn handler can treat a missing branch as non-error.
|
||||||
|
# See https://github.com/helmfile/helmfile/issues/392
|
||||||
|
ignoreMissingGitBranch: true
|
||||||
# kubeContext to use for this environment
|
# kubeContext to use for this environment
|
||||||
kubeContext: kube-context
|
kubeContext: kube-context
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -227,7 +227,7 @@ func (c *StateCreator) loadEnvValues(st *HelmState, name string, failOnMissingEn
|
||||||
if len(envSpec.Secrets) > 0 {
|
if len(envSpec.Secrets) > 0 {
|
||||||
var envSecretFiles []string
|
var envSecretFiles []string
|
||||||
for _, urlOrPath := range envSpec.Secrets {
|
for _, urlOrPath := range envSpec.Secrets {
|
||||||
resolved, skipped, err := st.storage().resolveFile(envSpec.MissingFileHandler, "environment values", urlOrPath)
|
resolved, skipped, err := st.storage().resolveFile(envSpec.MissingFileHandler, "environment values", urlOrPath, envSpec.MissingFileHandlerConfig.resolveFileOptions()...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,4 +13,6 @@ type EnvironmentSpec struct {
|
||||||
// Use "Warn", "Info", or "Debug" if you want helmfile to not fail when a values file is missing, while just leaving
|
// Use "Warn", "Info", or "Debug" if you want helmfile to not fail when a values file is missing, while just leaving
|
||||||
// a message about the missing file at the log-level.
|
// a message about the missing file at the log-level.
|
||||||
MissingFileHandler *string `yaml:"missingFileHandler,omitempty"`
|
MissingFileHandler *string `yaml:"missingFileHandler,omitempty"`
|
||||||
|
// MissingFileHandlerConfig is composed of various settings for the MissingFileHandler
|
||||||
|
MissingFileHandlerConfig MissingFileHandlerConfig `yaml:"missingFileHandlerConfig,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -82,10 +82,19 @@ type ReleaseSetSpec struct {
|
||||||
// non-existent path. The default behavior is to print a warning. Note the
|
// non-existent path. The default behavior is to print a warning. Note the
|
||||||
// differing default compared to other MissingFileHandlers.
|
// differing default compared to other MissingFileHandlers.
|
||||||
MissingFileHandler string `yaml:"missingFileHandler,omitempty"`
|
MissingFileHandler string `yaml:"missingFileHandler,omitempty"`
|
||||||
|
// MissingFileHandlerConfig is composed of various settings for the MissingFileHandler
|
||||||
|
MissingFileHandlerConfig MissingFileHandlerConfig `yaml:"missingFileHandlerConfig,omitempty"`
|
||||||
|
|
||||||
LockFile string `yaml:"lockFilePath,omitempty"`
|
LockFile string `yaml:"lockFilePath,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type MissingFileHandlerConfig struct {
|
||||||
|
// IgnoreMissingGitBranch is set to true in order to let the missing file handler
|
||||||
|
// treat missing git branch errors like `pathspec 'develop' did not match any file(s) known to git` safe
|
||||||
|
// and ignored when the handler is set to Warn or Info.
|
||||||
|
IgnoreMissingGitBranch bool `yaml:"ignoreMissingGitBranch,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// helmStateAlias is helm state alias
|
// helmStateAlias is helm state alias
|
||||||
type helmStateAlias HelmState
|
type helmStateAlias HelmState
|
||||||
|
|
||||||
|
|
@ -2721,13 +2730,19 @@ func (st *HelmState) removeFiles(files []string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c MissingFileHandlerConfig) resolveFileOptions() []resolveFileOption {
|
||||||
|
return []resolveFileOption{
|
||||||
|
ignoreMissingGitBranch(c.IgnoreMissingGitBranch),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (st *HelmState) generateTemporaryReleaseValuesFiles(release *ReleaseSpec, values []interface{}, missingFileHandler *string) ([]string, error) {
|
func (st *HelmState) generateTemporaryReleaseValuesFiles(release *ReleaseSpec, values []interface{}, missingFileHandler *string) ([]string, error) {
|
||||||
generatedFiles := []string{}
|
generatedFiles := []string{}
|
||||||
|
|
||||||
for _, value := range values {
|
for _, value := range values {
|
||||||
switch typedValue := value.(type) {
|
switch typedValue := value.(type) {
|
||||||
case string:
|
case string:
|
||||||
paths, skip, err := st.storage().resolveFile(missingFileHandler, "values", typedValue)
|
paths, skip, err := st.storage().resolveFile(missingFileHandler, "values", typedValue, st.MissingFileHandlerConfig.resolveFileOptions()...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return generatedFiles, err
|
return generatedFiles, err
|
||||||
}
|
}
|
||||||
|
|
@ -2828,7 +2843,7 @@ func (st *HelmState) generateSecretValuesFiles(helm helmexec.Interface, release
|
||||||
|
|
||||||
switch value := v.(type) {
|
switch value := v.(type) {
|
||||||
case string:
|
case string:
|
||||||
paths, skip, err = st.storage().resolveFile(release.MissingFileHandler, "secrets", release.ValuesPathPrefix+value)
|
paths, skip, err = st.storage().resolveFile(release.MissingFileHandler, "secrets", release.ValuesPathPrefix+value, st.MissingFileHandlerConfig.resolveFileOptions()...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -3282,7 +3297,7 @@ func (st *HelmState) LoadYAMLForEmbedding(release *ReleaseSpec, entries []interf
|
||||||
case string:
|
case string:
|
||||||
var values map[string]interface{}
|
var values map[string]interface{}
|
||||||
|
|
||||||
paths, skip, err := st.storage().resolveFile(missingFileHandler, "values", pathPrefix+t)
|
paths, skip, err := st.storage().resolveFile(missingFileHandler, "values", pathPrefix+t, st.MissingFileHandlerConfig.resolveFileOptions()...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"net/url"
|
"net/url"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
|
||||||
|
|
@ -30,17 +31,42 @@ func NewStorage(forFile string, logger *zap.SugaredLogger, fs *filesystem.FileSy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *Storage) resolveFile(missingFileHandler *string, tpe, path string) ([]string, bool, error) {
|
type resolveFileConfig struct {
|
||||||
|
IgnoreMissingGitBranch bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type resolveFileOption func(*resolveFileConfig)
|
||||||
|
|
||||||
|
func ignoreMissingGitBranch(v bool) func(c *resolveFileConfig) {
|
||||||
|
return func(c *resolveFileConfig) {
|
||||||
|
c.IgnoreMissingGitBranch = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (st *Storage) resolveFile(missingFileHandler *string, tpe, path string, opts ...resolveFileOption) ([]string, bool, error) {
|
||||||
title := fmt.Sprintf("%s file", tpe)
|
title := fmt.Sprintf("%s file", tpe)
|
||||||
|
|
||||||
var files []string
|
var (
|
||||||
var err error
|
files []string
|
||||||
|
err error
|
||||||
|
conf resolveFileConfig
|
||||||
|
)
|
||||||
|
|
||||||
|
for _, o := range opts {
|
||||||
|
o(&conf)
|
||||||
|
}
|
||||||
|
|
||||||
if remote.IsRemote(path) {
|
if remote.IsRemote(path) {
|
||||||
r := remote.NewRemote(st.logger, "", st.fs)
|
r := remote.NewRemote(st.logger, "", st.fs)
|
||||||
|
|
||||||
fetchedFilePath, err := r.Fetch(path, "values")
|
fetchedFilePath, err := r.Fetch(path, "values")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, err
|
// https://github.com/helmfile/helmfile/issues/392
|
||||||
|
if conf.IgnoreMissingGitBranch && strings.Contains(err.Error(), "' did not match any file(s) known to git") {
|
||||||
|
st.logger.Debugf("Ignored missing git branch error: %v", err)
|
||||||
|
} else {
|
||||||
|
return nil, false, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if st.fs.FileExistsAt(fetchedFilePath) {
|
if st.fs.FileExistsAt(fetchedFilePath) {
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,12 @@ func TestStorage_resolveFile(t *testing.T) {
|
||||||
missingFileHandler *string
|
missingFileHandler *string
|
||||||
title string
|
title string
|
||||||
path string
|
path string
|
||||||
|
opts []resolveFileOption
|
||||||
}
|
}
|
||||||
|
|
||||||
cacheDir := remote.CacheDir()
|
cacheDir := remote.CacheDir()
|
||||||
infoHandler := MissingFileHandlerInfo
|
infoHandler := MissingFileHandlerInfo
|
||||||
|
warnHandler := MissingFileHandlerWarn
|
||||||
errorHandler := MissingFileHandlerError
|
errorHandler := MissingFileHandlerError
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
|
|
@ -49,6 +51,55 @@ func TestStorage_resolveFile(t *testing.T) {
|
||||||
wantSkipped: false,
|
wantSkipped: false,
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "non existing branch in repo produce error",
|
||||||
|
args: args{
|
||||||
|
path: "git::https://github.com/helmfile/helmfile.git@examples/values/non-existing-file.yaml?ref=inexistent-branch-for-test",
|
||||||
|
title: "values",
|
||||||
|
missingFileHandler: &infoHandler,
|
||||||
|
},
|
||||||
|
wantSkipped: false,
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "non existing branch in repo produce info when ignoreMissingGitBranch=true",
|
||||||
|
args: args{
|
||||||
|
path: "git::https://github.com/helmfile/helmfile.git@examples/values/non-existing-file.yaml?ref=inexistent-branch-for-test",
|
||||||
|
title: "values",
|
||||||
|
missingFileHandler: &infoHandler,
|
||||||
|
opts: []resolveFileOption{
|
||||||
|
ignoreMissingGitBranch(true),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantSkipped: true,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "non existing branch in repo produce warn when ignoreMissingGitBranch=true",
|
||||||
|
args: args{
|
||||||
|
path: "git::https://github.com/helmfile/helmfile.git@examples/values/non-existing-file.yaml?ref=inexistent-branch-for-test",
|
||||||
|
title: "values",
|
||||||
|
missingFileHandler: &warnHandler,
|
||||||
|
opts: []resolveFileOption{
|
||||||
|
ignoreMissingGitBranch(true),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantSkipped: true,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "non existing branch in repo produce error with error handler even if ignoreMissingGitBranch=true",
|
||||||
|
args: args{
|
||||||
|
path: "git::https://github.com/helmfile/helmfile.git@examples/values/non-existing-file.yaml?ref=inexistent-branch-for-test",
|
||||||
|
title: "values",
|
||||||
|
missingFileHandler: &errorHandler,
|
||||||
|
opts: []resolveFileOption{
|
||||||
|
ignoreMissingGitBranch(true),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantSkipped: false,
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "existing remote value fetched",
|
name: "existing remote value fetched",
|
||||||
args: args{
|
args: args{
|
||||||
|
|
@ -75,7 +126,7 @@ func TestStorage_resolveFile(t *testing.T) {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
st := NewStorage(cacheDir, helmexec.NewLogger(io.Discard, "debug"), filesystem.DefaultFileSystem())
|
st := NewStorage(cacheDir, helmexec.NewLogger(io.Discard, "debug"), filesystem.DefaultFileSystem())
|
||||||
|
|
||||||
files, skipped, err := st.resolveFile(tt.args.missingFileHandler, tt.args.title, tt.args.path)
|
files, skipped, err := st.resolveFile(tt.args.missingFileHandler, tt.args.title, tt.args.path, tt.args.opts...)
|
||||||
if (err != nil) != tt.wantErr {
|
if (err != nil) != tt.wantErr {
|
||||||
t.Errorf("resolveFile() error = %v, wantErr %v", err, tt.wantErr)
|
t.Errorf("resolveFile() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
return
|
return
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue