Introduce Helmfile's own filesystem abstraction to correctly unit test some components (#307)

Use abstracted FS

Signed-off-by: Arkaitz Jimenez <arkaitzj@gmail.com>

Signed-off-by: Arkaitz Jimenez <arkaitzj@gmail.com>
This commit is contained in:
Arkaitz Jimenez
2022-08-24 12:58:43 +09:00
committed by GitHub
parent a626664f46
commit cc33e7b7d8
44 changed files with 513 additions and 425 deletions
+2 -2
View File
@@ -146,8 +146,8 @@ func (st *HelmState) mergeLockedDependencies() (*HelmState, error) {
depMan := NewChartDependencyManager(filename, st.logger)
if st.readFile != nil {
depMan.readFile = st.readFile
if st.fs.ReadFile != nil {
depMan.readFile = st.fs.ReadFile
}
return resolveDependencies(st, depMan, unresolved)
+12 -27
View File
@@ -5,7 +5,6 @@ import (
"errors"
"fmt"
"io"
"os"
"github.com/imdario/mergo"
"github.com/variantdev/vals"
@@ -13,6 +12,7 @@ import (
"gopkg.in/yaml.v2"
"github.com/helmfile/helmfile/pkg/environment"
"github.com/helmfile/helmfile/pkg/filesystem"
"github.com/helmfile/helmfile/pkg/helmexec"
"github.com/helmfile/helmfile/pkg/maputil"
"github.com/helmfile/helmfile/pkg/remote"
@@ -43,12 +43,7 @@ func (e *UndefinedEnvError) Error() string {
type StateCreator struct {
logger *zap.SugaredLogger
readFile func(string) ([]byte, error)
fileExists func(string) (bool, error)
abs func(string) (string, error)
glob func(string) ([]string, error)
DeleteFile func(string) error
directoryExistsAt func(string) bool
fs *filesystem.FileSystem
valsRuntime vals.Evaluator
@@ -63,17 +58,12 @@ type StateCreator struct {
remote *remote.Remote
}
func NewCreator(logger *zap.SugaredLogger, readFile func(string) ([]byte, error), fileExists func(string) (bool, error), abs func(string) (string, error), glob func(string) ([]string, error), directoryExistsAt func(string) bool, valsRuntime vals.Evaluator, getHelm func(*HelmState) helmexec.Interface, overrideHelmBinary string, remote *remote.Remote) *StateCreator {
func NewCreator(logger *zap.SugaredLogger, fs *filesystem.FileSystem, valsRuntime vals.Evaluator, getHelm func(*HelmState) helmexec.Interface, overrideHelmBinary string, remote *remote.Remote) *StateCreator {
return &StateCreator{
logger: logger,
readFile: readFile,
fileExists: fileExists,
abs: abs,
glob: glob,
directoryExistsAt: directoryExistsAt,
Strict: true,
fs: fs,
valsRuntime: valsRuntime,
getHelm: getHelm,
@@ -87,6 +77,7 @@ func NewCreator(logger *zap.SugaredLogger, readFile func(string) ([]byte, error)
func (c *StateCreator) Parse(content []byte, baseDir, file string) (*HelmState, error) {
var state HelmState
state.fs = c.fs
state.FilePath = file
state.basePath = baseDir
@@ -132,12 +123,6 @@ func (c *StateCreator) Parse(content []byte, baseDir, file string) (*HelmState,
}
state.logger = c.logger
state.readFile = c.readFile
state.removeFile = os.Remove
state.fileExists = c.fileExists
state.glob = c.glob
state.directoryExistsAt = c.directoryExistsAt
state.valsRuntime = c.valsRuntime
return &state, nil
@@ -147,7 +132,7 @@ func (c *StateCreator) Parse(content []byte, baseDir, file string) (*HelmState,
func (c *StateCreator) LoadEnvValues(target *HelmState, env string, ctxEnv *environment.Environment, failOnMissingEnv bool) (*HelmState, error) {
state := *target
e, err := c.loadEnvValues(&state, env, failOnMissingEnv, ctxEnv, c.readFile, c.glob)
e, err := c.loadEnvValues(&state, env, failOnMissingEnv, ctxEnv)
if err != nil {
return nil, &StateLoadError{fmt.Sprintf("failed to read %s", state.FilePath), err}
}
@@ -222,7 +207,7 @@ func (c *StateCreator) loadBases(envValues *environment.Environment, st *HelmSta
}
// nolint: unparam
func (c *StateCreator) loadEnvValues(st *HelmState, name string, failOnMissingEnv bool, ctxEnv *environment.Environment, readFile func(string) ([]byte, error), glob func(string) ([]string, error)) (*environment.Environment, error) {
func (c *StateCreator) loadEnvValues(st *HelmState, name string, failOnMissingEnv bool, ctxEnv *environment.Environment) (*environment.Environment, error) {
envVals := map[string]interface{}{}
envSpec, ok := st.Environments[name]
if ok {
@@ -245,7 +230,7 @@ func (c *StateCreator) loadEnvValues(st *HelmState, name string, failOnMissingEn
envSecretFiles = append(envSecretFiles, resolved...)
}
if err = c.scatterGatherEnvSecretFiles(st, envSecretFiles, envVals, readFile); err != nil {
if err = c.scatterGatherEnvSecretFiles(st, envSecretFiles, envVals); err != nil {
return nil, err
}
}
@@ -268,7 +253,7 @@ func (c *StateCreator) loadEnvValues(st *HelmState, name string, failOnMissingEn
return newEnv, nil
}
func (c *StateCreator) scatterGatherEnvSecretFiles(st *HelmState, envSecretFiles []string, envVals map[string]interface{}, readFile func(string) ([]byte, error)) error {
func (c *StateCreator) scatterGatherEnvSecretFiles(st *HelmState, envSecretFiles []string, envVals map[string]interface{}) error {
var errs []error
helm := c.getHelm(st)
@@ -308,11 +293,11 @@ func (c *StateCreator) scatterGatherEnvSecretFiles(st *HelmState, envSecretFiles
}
// nolint: staticcheck
defer func() {
if err := c.DeleteFile(decFile); err != nil {
if err := c.fs.DeleteFile(decFile); err != nil {
c.logger.Warnf("removing decrypted file %s: %w", decFile, err)
}
}()
bytes, err := readFile(decFile)
bytes, err := c.fs.ReadFile(decFile)
if err != nil {
results <- secretResult{secret.id, nil, fmt.Errorf("failed to load environment secrets file \"%s\": %v", secret.path, err), secret.path}
continue
@@ -367,7 +352,7 @@ func (st *HelmState) loadValuesEntries(missingFileHandler *string, entries []int
var envVals map[string]interface{}
valuesEntries := append([]interface{}{}, entries...)
ld := NewEnvironmentValuesLoader(st.storage(), st.readFile, st.logger, remote)
ld := NewEnvironmentValuesLoader(st.storage(), st.fs, st.logger, remote)
var err error
envVals, err = ld.LoadEnvironmentValues(missingFileHandler, valuesEntries, ctxEnv)
if err != nil {
+10 -13
View File
@@ -1,7 +1,6 @@
package state
import (
"os"
"path/filepath"
"reflect"
"testing"
@@ -10,18 +9,16 @@ import (
"go.uber.org/zap"
"github.com/helmfile/helmfile/pkg/environment"
"github.com/helmfile/helmfile/pkg/filesystem"
"github.com/helmfile/helmfile/pkg/remote"
"github.com/helmfile/helmfile/pkg/testhelper"
)
func createFromYaml(content []byte, file string, env string, logger *zap.SugaredLogger) (*HelmState, error) {
c := &StateCreator{
logger: logger,
readFile: os.ReadFile,
abs: filepath.Abs,
DeleteFile: os.Remove,
Strict: true,
logger: logger,
fs: filesystem.DefaultFileSystem(),
Strict: true,
}
return c.ParseAndLoad(content, filepath.Dir(file), file, env, true, nil)
}
@@ -81,8 +78,8 @@ func (testEnv stateTestEnv) MustLoadState(t *testing.T, file, envName string) *H
t.Fatalf("no file named %q registered", file)
}
r := remote.NewRemote(logger, testFs.Cwd, testFs.ReadFile, testFs.DirectoryExistsAt, testFs.FileExistsAt)
state, err := NewCreator(logger, testFs.ReadFile, testFs.FileExists, testFs.Abs, testFs.Glob, testFs.DirectoryExistsAt, nil, nil, "", r).
r := remote.NewRemote(logger, testFs.Cwd, testFs.ToFileSystem())
state, err := NewCreator(logger, testFs.ToFileSystem(), nil, nil, "", r).
ParseAndLoad([]byte(yamlContent), filepath.Dir(file), file, envName, true, nil)
if err != nil {
t.Fatalf("unexpected error: %v", err)
@@ -148,11 +145,11 @@ releaseNamespace: mynamespace
})
testFs.Cwd = "/example/path/to"
r := remote.NewRemote(logger, testFs.Cwd, testFs.ReadFile, testFs.DirectoryExistsAt, testFs.FileExistsAt)
r := remote.NewRemote(logger, testFs.Cwd, testFs.ToFileSystem())
env := environment.Environment{
Name: "production",
}
state, err := NewCreator(logger, testFs.ReadFile, testFs.FileExists, testFs.Abs, testFs.Glob, testFs.DirectoryExistsAt, nil, nil, "", r).
state, err := NewCreator(logger, testFs.ToFileSystem(), nil, nil, "", r).
ParseAndLoad(yamlContent, filepath.Dir(yamlFile), yamlFile, "production", true, &env)
if err != nil {
t.Fatalf("unexpected error: %v", err)
@@ -238,8 +235,8 @@ overrideNamespace: myns
})
testFs.Cwd = "/example/path/to"
r := remote.NewRemote(logger, testFs.Cwd, testFs.ReadFile, testFs.DirectoryExistsAt, testFs.FileExistsAt)
state, err := NewCreator(logger, testFs.ReadFile, testFs.FileExists, testFs.Abs, testFs.Glob, testFs.DirectoryExistsAt, nil, nil, "", r).
r := remote.NewRemote(logger, testFs.Cwd, testFs.ToFileSystem())
state, err := NewCreator(logger, testFs.ToFileSystem(), nil, nil, "", r).
ParseAndLoad(yamlContent, filepath.Dir(yamlFile), yamlFile, "production", true, nil)
if err != nil {
t.Fatalf("unexpected error: %v", err)
+8 -7
View File
@@ -9,6 +9,7 @@ import (
"gopkg.in/yaml.v2"
"github.com/helmfile/helmfile/pkg/environment"
"github.com/helmfile/helmfile/pkg/filesystem"
"github.com/helmfile/helmfile/pkg/maputil"
"github.com/helmfile/helmfile/pkg/remote"
"github.com/helmfile/helmfile/pkg/tmpl"
@@ -17,19 +18,19 @@ import (
type EnvironmentValuesLoader struct {
storage *Storage
readFile func(string) ([]byte, error)
fs *filesystem.FileSystem
logger *zap.SugaredLogger
remote *remote.Remote
}
func NewEnvironmentValuesLoader(storage *Storage, readFile func(string) ([]byte, error), logger *zap.SugaredLogger, remote *remote.Remote) *EnvironmentValuesLoader {
func NewEnvironmentValuesLoader(storage *Storage, fs *filesystem.FileSystem, logger *zap.SugaredLogger, remote *remote.Remote) *EnvironmentValuesLoader {
return &EnvironmentValuesLoader{
storage: storage,
readFile: readFile,
logger: logger,
remote: remote,
storage: storage,
fs: fs,
logger: logger,
remote: remote,
}
}
@@ -64,7 +65,7 @@ func (ld *EnvironmentValuesLoader) LoadEnvironmentValues(missingFileHandler *str
}
tmplData := NewEnvironmentTemplateData(env, "", map[string]interface{}{})
r := tmpl.NewFileRenderer(ld.readFile, filepath.Dir(f), tmplData)
r := tmpl.NewFileRenderer(ld.fs, filepath.Dir(f), tmplData)
bytes, err := r.RenderToBytes(f)
if err != nil {
return nil, fmt.Errorf("failed to load environment values file \"%s\": %v", f, err)
+3 -7
View File
@@ -1,13 +1,12 @@
package state
import (
"os"
"path/filepath"
"testing"
"github.com/google/go-cmp/cmp"
"go.uber.org/zap"
ffs "github.com/helmfile/helmfile/pkg/filesystem"
"github.com/helmfile/helmfile/pkg/remote"
)
@@ -22,14 +21,11 @@ func newLoader() *EnvironmentValuesLoader {
storage := &Storage{
FilePath: "./helmfile.yaml",
basePath: ".",
glob: filepath.Glob,
fs: ffs.DefaultFileSystem(),
logger: sugar,
}
readFile := func(s string) ([]byte, error) { return []byte{}, nil }
dirExists := func(d string) bool { return false }
fileExists := func(f string) bool { return false }
return NewEnvironmentValuesLoader(storage, os.ReadFile, sugar, remote.NewRemote(sugar, "/tmp", readFile, dirExists, fileExists))
return NewEnvironmentValuesLoader(storage, storage.fs, sugar, remote.NewRemote(sugar, "/tmp", storage.fs))
}
// See https://github.com/roboll/helmfile/pull/1169
+3 -13
View File
@@ -26,16 +26,6 @@ func (st *HelmState) appendHelmXFlags(flags []string, release *ReleaseSpec) ([]s
return flags, nil
}
func fileExistsAt(path string) bool {
fileInfo, err := os.Stat(path)
return err == nil && fileInfo.Mode().IsRegular()
}
func directoryExistsAt(path string) bool {
fileInfo, err := os.Stat(path)
return err == nil && fileInfo.Mode().IsDir()
}
type Chartify struct {
Opts *chartify.ChartifyOpts
Clean func()
@@ -70,7 +60,7 @@ func (st *HelmState) goGetterChart(chart, dir, cacheDir string, force bool) (str
return "", fmt.Errorf("Parsing url from dir failed due to error %q.\nContinuing the process assuming this is a regular Helm chart or a local dir.", err.Error())
}
} else {
r := remote.NewRemote(st.logger, "", st.readFile, directoryExistsAt, fileExistsAt)
r := remote.NewRemote(st.logger, "", st.fs)
fetchedDir, err := r.Fetch(chart, cacheDir)
if err != nil {
@@ -107,14 +97,14 @@ func (st *HelmState) PrepareChartify(helm helmexec.Interface, release *ReleaseSp
dir = filepath.Join(st.basePath, chart)
}
if stat, _ := os.Stat(dir); stat != nil && stat.IsDir() {
if exists, err := st.fileExists(filepath.Join(dir, "Chart.yaml")); err == nil && !exists {
if exists, err := st.fs.FileExists(filepath.Join(dir, "Chart.yaml")); err == nil && !exists {
shouldRun = true
}
}
for _, d := range release.Dependencies {
chart := d.Chart
if st.directoryExistsAt(chart) {
if st.fs.DirectoryExistsAt(chart) {
var err error
// Otherwise helm-dependency-up on the temporary chart generated by chartify ends up errors like:
+15 -19
View File
@@ -26,6 +26,7 @@ import (
"github.com/helmfile/helmfile/pkg/environment"
"github.com/helmfile/helmfile/pkg/event"
"github.com/helmfile/helmfile/pkg/filesystem"
"github.com/helmfile/helmfile/pkg/helmexec"
"github.com/helmfile/helmfile/pkg/remote"
"github.com/helmfile/helmfile/pkg/tmpl"
@@ -92,14 +93,9 @@ type HelmState struct {
ReleaseSetSpec `yaml:",inline"`
logger *zap.SugaredLogger
readFile func(string) ([]byte, error)
removeFile func(string) error
fileExists func(string) (bool, error)
glob func(string) ([]string, error)
tempDir func(string, string) (string, error)
directoryExistsAt func(string) bool
logger *zap.SugaredLogger
fs *filesystem.FileSystem
tempDir func(string, string) (string, error)
valsRuntime vals.Evaluator
@@ -553,7 +549,7 @@ func (st *HelmState) prepareSyncReleases(helm helmexec.Interface, additionalValu
errs = append(errs, newReleaseFailedError(release, err))
}
ok, err := st.fileExists(valfile)
ok, err := st.fs.FileExists(valfile)
if err != nil {
errs = append(errs, newReleaseFailedError(release, err))
} else if !ok {
@@ -1118,7 +1114,7 @@ func (st *HelmState) PrepareCharts(helm helmexec.Interface, dir string, concurre
}
}
isLocal := st.directoryExistsAt(normalizeChart(st.basePath, chartName))
isLocal := st.fs.DirectoryExistsAt(normalizeChart(st.basePath, chartName))
chartification, clean, err := st.PrepareChartify(helm, release, chartPath, workerIndex)
if !opts.SkipCleanup {
@@ -1172,7 +1168,7 @@ func (st *HelmState) PrepareCharts(helm helmexec.Interface, dir string, concurre
// Skip `helm dep build` and `helm dep up` altogether when the chart is from remote or the dep is
// explicitly skipped.
buildDeps = !skipDeps
} else if normalizedChart := normalizeChart(st.basePath, chartPath); st.directoryExistsAt(normalizedChart) {
} else if normalizedChart := normalizeChart(st.basePath, chartPath); st.fs.DirectoryExistsAt(normalizedChart) {
// 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
@@ -1505,7 +1501,7 @@ func (st *HelmState) WriteReleasesValues(helm helmexec.Interface, additionalValu
for _, f := range append(generatedFiles, additionalValues...) {
src := map[string]interface{}{}
srcBytes, err := st.readFile(f)
srcBytes, err := st.fs.ReadFile(f)
if err != nil {
return []error{fmt.Errorf("reading %s: %w", f, err)}
}
@@ -2236,7 +2232,7 @@ func (st *HelmState) triggerGlobalReleaseEvent(evt string, evtErr error, helmfil
Chart: st.OverrideChart,
Env: st.Env,
Logger: st.logger,
ReadFile: st.readFile,
Fs: st.fs,
}
data := map[string]interface{}{
"HelmfileCommand": helmfileCmd,
@@ -2269,7 +2265,7 @@ func (st *HelmState) triggerReleaseEvent(evt string, evtErr error, r *ReleaseSpe
Chart: st.OverrideChart,
Env: st.Env,
Logger: st.logger,
ReadFile: st.readFile,
Fs: st.fs,
}
vals := st.Values()
data := map[string]interface{}{
@@ -2307,7 +2303,7 @@ func (st *HelmState) UpdateDeps(helm helmexec.Interface, includeTransitiveNeeds
var errs []error
for _, release := range releases {
if st.directoryExistsAt(release.ChartPathOrName()) {
if st.fs.DirectoryExistsAt(release.ChartPathOrName()) {
if err := helm.UpdateDeps(release.ChartPathOrName()); err != nil {
errs = append(errs, err)
}
@@ -2631,7 +2627,7 @@ func (st *HelmState) newReleaseTemplateData(release *ReleaseSpec) releaseTemplat
}
func (st *HelmState) newReleaseTemplateFuncMap(dir string) template.FuncMap {
r := tmpl.NewFileRenderer(st.readFile, dir, nil)
r := tmpl.NewFileRenderer(st.fs, dir, nil)
return r.Context.CreateFuncMap()
}
@@ -2639,7 +2635,7 @@ func (st *HelmState) newReleaseTemplateFuncMap(dir string) template.FuncMap {
func (st *HelmState) RenderReleaseValuesFileToBytes(release *ReleaseSpec, path string) ([]byte, error) {
templateData := st.newReleaseTemplateData(release)
r := tmpl.NewFileRenderer(st.readFile, filepath.Dir(path), templateData)
r := tmpl.NewFileRenderer(st.fs, filepath.Dir(path), templateData)
rawBytes, err := r.RenderToBytes(path)
if err != nil {
return nil, err
@@ -2673,8 +2669,8 @@ func (st *HelmState) storage() *Storage {
return &Storage{
FilePath: st.FilePath,
basePath: st.basePath,
glob: st.glob,
logger: st.logger,
fs: st.fs,
}
}
@@ -2710,7 +2706,7 @@ func (st *HelmState) ExpandedHelmfiles() ([]SubHelmfileSpec, error) {
func (st *HelmState) removeFiles(files []string) {
for _, f := range files {
if err := st.removeFile(f); err != nil {
if err := st.fs.DeleteFile(f); err != nil {
st.logger.Warnf("Removing %s: %v", err)
} else {
st.logger.Debugf("Removed %s", f)
+1 -1
View File
@@ -110,7 +110,7 @@ func (st *HelmState) ExecuteTemplates() (*HelmState, error) {
successFlag := false
for it, prev := 0, &release; it < 6; it++ {
tmplData := st.createReleaseTemplateData(prev, vals)
renderer := tmpl.NewFileRenderer(st.readFile, st.basePath, tmplData)
renderer := tmpl.NewFileRenderer(st.fs, st.basePath, tmplData)
r, err := release.ExecuteTemplateExpressions(renderer)
if err != nil {
return nil, fmt.Errorf("failed executing templates in release \"%s\".\"%s\": %v", st.FilePath, release.Name, err)
+2 -1
View File
@@ -7,6 +7,7 @@ import (
"github.com/google/go-cmp/cmp"
"github.com/helmfile/helmfile/pkg/filesystem"
"github.com/helmfile/helmfile/pkg/helmexec"
)
@@ -39,7 +40,7 @@ func TestGoGetter(t *testing.T) {
st := &HelmState{
logger: logger,
readFile: os.ReadFile,
fs: filesystem.DefaultFileSystem(),
basePath: d,
}
+34 -32
View File
@@ -11,6 +11,7 @@ import (
"github.com/variantdev/vals"
"github.com/helmfile/helmfile/pkg/exectest"
"github.com/helmfile/helmfile/pkg/filesystem"
"github.com/helmfile/helmfile/pkg/helmexec"
"github.com/helmfile/helmfile/pkg/testhelper"
)
@@ -19,10 +20,7 @@ var logger = helmexec.NewLogger(os.Stdout, "warn")
var valsRuntime, _ = vals.New(vals.Options{CacheSize: 32})
func injectFs(st *HelmState, fs *testhelper.TestFs) *HelmState {
st.glob = fs.Glob
st.readFile = fs.ReadFile
st.fileExists = fs.FileExists
st.directoryExistsAt = fs.DirectoryExistsAt
st.fs = fs.ToFileSystem()
return st
}
@@ -1715,17 +1713,17 @@ func TestHelmState_SyncReleasesCleanup(t *testing.T) {
ReleaseSetSpec: ReleaseSetSpec{
Releases: tt.releases,
},
logger: logger,
valsRuntime: valsRuntime,
removeFile: func(f string) error {
numRemovedFiles += 1
return nil
},
logger: logger,
valsRuntime: valsRuntime,
RenderedValues: map[string]interface{}{},
}
testfs := testhelper.NewTestFs(map[string]string{
"/path/to/someFile": `foo: FOO`,
})
testfs.DeleteFile = func(f string) error {
numRemovedFiles += 1
return nil
}
state = injectFs(state, testfs)
if errs := state.SyncReleases(&AffectedReleases{}, tt.helm, []string{}, 1); len(errs) > 0 {
t.Errorf("unexpected errors: %v", errs)
@@ -1802,18 +1800,18 @@ func TestHelmState_DiffReleasesCleanup(t *testing.T) {
ReleaseSetSpec: ReleaseSetSpec{
Releases: tt.releases,
},
logger: logger,
valsRuntime: valsRuntime,
removeFile: func(f string) error {
numRemovedFiles += 1
return nil
},
logger: logger,
valsRuntime: valsRuntime,
RenderedValues: map[string]interface{}{},
}
testfs := testhelper.NewTestFs(map[string]string{
"/path/to/someFile": `foo: bar
`,
})
testfs.DeleteFile = func(f string) error {
numRemovedFiles += 1
return nil
}
state = injectFs(state, testfs)
if _, errs := state.DiffReleases(tt.helm, []string{}, 1, false, false, []string{}, false, false, false, false); len(errs) > 0 {
t.Errorf("unexpected errors: %v", errs)
@@ -1960,11 +1958,13 @@ func TestHelmState_ResolveDeps_NoLockFile(t *testing.T) {
},
},
logger: logger,
readFile: func(f string) ([]byte, error) {
if f != "helmfile.lock" {
return nil, fmt.Errorf("stub: unexpected file: %s", f)
}
return nil, os.ErrNotExist
fs: &filesystem.FileSystem{
ReadFile: func(f string) ([]byte, error) {
if f != "helmfile.lock" {
return nil, fmt.Errorf("stub: unexpected file: %s", f)
}
return nil, os.ErrNotExist
},
},
}
@@ -2053,17 +2053,19 @@ func TestHelmState_ReleaseStatuses(t *testing.T) {
Releases: tt.releases,
},
logger: logger,
fileExists: func(f string) (bool, error) {
if f != "foo.yaml" {
return false, fmt.Errorf("unexpected file: %s", f)
}
return true, nil
},
readFile: func(f string) ([]byte, error) {
if f != "foo.yaml" {
return nil, fmt.Errorf("unexpected file: %s", f)
}
return []byte{}, nil
fs: &filesystem.FileSystem{
FileExists: func(f string) (bool, error) {
if f != "foo.yaml" {
return false, fmt.Errorf("unexpected file: %s", f)
}
return true, nil
},
ReadFile: func(f string) ([]byte, error) {
if f != "foo.yaml" {
return nil, fmt.Errorf("unexpected file: %s", f)
}
return []byte{}, nil
},
},
}
errs := state.ReleaseStatuses(tt.helm, 1)
+7 -7
View File
@@ -8,6 +8,7 @@ import (
"go.uber.org/zap"
"github.com/helmfile/helmfile/pkg/filesystem"
"github.com/helmfile/helmfile/pkg/remote"
)
@@ -16,17 +17,16 @@ type Storage struct {
FilePath string
readFile func(string) ([]byte, error)
basePath string
glob func(string) ([]string, error)
fs *filesystem.FileSystem
}
func NewStorage(forFile string, logger *zap.SugaredLogger, glob func(string) ([]string, error)) *Storage {
func NewStorage(forFile string, logger *zap.SugaredLogger, fs *filesystem.FileSystem) *Storage {
return &Storage{
FilePath: forFile,
basePath: filepath.Dir(forFile),
logger: logger,
glob: glob,
fs: fs,
}
}
@@ -36,14 +36,14 @@ func (st *Storage) resolveFile(missingFileHandler *string, tpe, path string) ([]
var files []string
var err error
if remote.IsRemote(path) {
r := remote.NewRemote(st.logger, "", st.readFile, directoryExistsAt, fileExistsAt)
r := remote.NewRemote(st.logger, "", st.fs)
fetchedFilePath, err := r.Fetch(path, "values")
if err != nil {
return nil, false, err
}
if fileExistsAt(fetchedFilePath) {
if st.fs.FileExistsAt(fetchedFilePath) {
files = []string{fetchedFilePath}
}
} else {
@@ -92,7 +92,7 @@ func (st *Storage) resolveFile(missingFileHandler *string, tpe, path string) ([]
func (st *Storage) ExpandPaths(globPattern string) ([]string, error) {
result := []string{}
absPathPattern := st.normalizePath(globPattern)
matches, err := st.glob(absPathPattern)
matches, err := st.fs.Glob(absPathPattern)
if err != nil {
return nil, fmt.Errorf("failed processing %s: %v", globPattern, err)
}
+2 -2
View File
@@ -3,10 +3,10 @@ package state
import (
"fmt"
"os"
"path/filepath"
"reflect"
"testing"
"github.com/helmfile/helmfile/pkg/filesystem"
"github.com/helmfile/helmfile/pkg/helmexec"
"github.com/helmfile/helmfile/pkg/remote"
)
@@ -73,7 +73,7 @@ func TestStorage_resolveFile(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
st := NewStorage(cacheDir, helmexec.NewLogger(os.Stderr, "debug"), filepath.Glob)
st := NewStorage(cacheDir, helmexec.NewLogger(os.Stderr, "debug"), filesystem.DefaultFileSystem())
files, skipped, err := st.resolveFile(tt.args.missingFileHandler, tt.args.title, tt.args.path)
if (err != nil) != tt.wantErr {