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:
		
							parent
							
								
									a626664f46
								
							
						
					
					
						commit
						cc33e7b7d8
					
				|  | @ -17,6 +17,7 @@ import ( | |||
| 	"go.uber.org/zap" | ||||
| 
 | ||||
| 	"github.com/helmfile/helmfile/pkg/argparser" | ||||
| 	"github.com/helmfile/helmfile/pkg/filesystem" | ||||
| 	"github.com/helmfile/helmfile/pkg/helmexec" | ||||
| 	"github.com/helmfile/helmfile/pkg/plugins" | ||||
| 	"github.com/helmfile/helmfile/pkg/remote" | ||||
|  | @ -39,16 +40,7 @@ type App struct { | |||
| 
 | ||||
| 	FileOrDir string | ||||
| 
 | ||||
| 	readFile          func(string) ([]byte, error) | ||||
| 	deleteFile        func(string) error | ||||
| 	fileExists        func(string) (bool, error) | ||||
| 	glob              func(string) ([]string, error) | ||||
| 	abs               func(string) (string, error) | ||||
| 	fileExistsAt      func(string) bool | ||||
| 	directoryExistsAt func(string) bool | ||||
| 
 | ||||
| 	getwd func() (string, error) | ||||
| 	chdir func(string) error | ||||
| 	fs *filesystem.FileSystem | ||||
| 
 | ||||
| 	remote *remote.Remote | ||||
| 
 | ||||
|  | @ -81,20 +73,11 @@ func New(conf ConfigProvider) *App { | |||
| 		FileOrDir:           conf.FileOrDir(), | ||||
| 		ValuesFiles:         conf.StateValuesFiles(), | ||||
| 		Set:                 conf.StateValuesSet(), | ||||
| 		fs:                  filesystem.DefaultFileSystem(), | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| func Init(app *App) *App { | ||||
| 	app.readFile = os.ReadFile | ||||
| 	app.deleteFile = os.Remove | ||||
| 	app.glob = filepath.Glob | ||||
| 	app.abs = filepath.Abs | ||||
| 	app.getwd = os.Getwd | ||||
| 	app.chdir = os.Chdir | ||||
| 	app.fileExistsAt = fileExistsAt | ||||
| 	app.fileExists = fileExists | ||||
| 	app.directoryExistsAt = directoryExistsAt | ||||
| 
 | ||||
| 	var err error | ||||
| 	app.valsRuntime, err = plugins.ValsInstance() | ||||
| 	if err != nil { | ||||
|  | @ -619,19 +602,19 @@ func (a *App) within(dir string, do func() error) error { | |||
| 		return do() | ||||
| 	} | ||||
| 
 | ||||
| 	prev, err := a.getwd() | ||||
| 	prev, err := a.fs.Getwd() | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("failed getting current working direcotyr: %v", err) | ||||
| 	} | ||||
| 
 | ||||
| 	absDir, err := a.abs(dir) | ||||
| 	absDir, err := a.fs.Abs(dir) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	a.Logger.Debugf("changing working directory to \"%s\"", absDir) | ||||
| 
 | ||||
| 	if err := a.chdir(absDir); err != nil { | ||||
| 	if err := a.fs.Chdir(absDir); err != nil { | ||||
| 		return fmt.Errorf("failed changing working directory to \"%s\": %v", absDir, err) | ||||
| 	} | ||||
| 
 | ||||
|  | @ -639,7 +622,7 @@ func (a *App) within(dir string, do func() error) error { | |||
| 
 | ||||
| 	a.Logger.Debugf("changing working directory back to \"%s\"", prev) | ||||
| 
 | ||||
| 	if chdirBackErr := a.chdir(prev); chdirBackErr != nil { | ||||
| 	if chdirBackErr := a.fs.Chdir(prev); chdirBackErr != nil { | ||||
| 		if appErr != nil { | ||||
| 			a.Logger.Warnf("%v", appErr) | ||||
| 		} | ||||
|  | @ -658,7 +641,7 @@ func (a *App) visitStateFiles(fileOrDir string, opts LoadOpts, do func(string, s | |||
| 	for _, relPath := range desiredStateFiles { | ||||
| 		var file string | ||||
| 		var dir string | ||||
| 		if a.directoryExistsAt(relPath) { | ||||
| 		if a.fs.DirectoryExistsAt(relPath) { | ||||
| 			file = relPath | ||||
| 			dir = relPath | ||||
| 		} else { | ||||
|  | @ -668,7 +651,7 @@ func (a *App) visitStateFiles(fileOrDir string, opts LoadOpts, do func(string, s | |||
| 
 | ||||
| 		a.Logger.Debugf("processing file \"%s\" in directory \"%s\"", file, dir) | ||||
| 
 | ||||
| 		absd, errAbsDir := a.abs(dir) | ||||
| 		absd, errAbsDir := a.fs.Abs(dir) | ||||
| 		if errAbsDir != nil { | ||||
| 			return errAbsDir | ||||
| 		} | ||||
|  | @ -690,20 +673,15 @@ func (a *App) loadDesiredStateFromYaml(file string, opts ...LoadOpts) (*state.He | |||
| 	} | ||||
| 
 | ||||
| 	ld := &desiredStateLoader{ | ||||
| 		readFile:          a.readFile, | ||||
| 		deleteFile:        a.deleteFile, | ||||
| 		fileExists:        a.fileExists, | ||||
| 		directoryExistsAt: a.directoryExistsAt, | ||||
| 		env:               a.Env, | ||||
| 		namespace:         a.Namespace, | ||||
| 		chart:             a.Chart, | ||||
| 		logger:            a.Logger, | ||||
| 		abs:               a.abs, | ||||
| 		remote:            a.remote, | ||||
| 		fs:        a.fs, | ||||
| 		env:       a.Env, | ||||
| 		namespace: a.Namespace, | ||||
| 		chart:     a.Chart, | ||||
| 		logger:    a.Logger, | ||||
| 		remote:    a.remote, | ||||
| 
 | ||||
| 		overrideKubeContext: a.OverrideKubeContext, | ||||
| 		overrideHelmBinary:  a.OverrideHelmBinary, | ||||
| 		glob:                a.glob, | ||||
| 		getHelm:             a.getHelm, | ||||
| 		valsRuntime:         a.valsRuntime, | ||||
| 	} | ||||
|  | @ -995,7 +973,7 @@ func (a *App) visitStatesWithSelectorsAndRemoteSupport(fileOrDir string, converg | |||
| 		opts.Environment.OverrideValues = envvals | ||||
| 	} | ||||
| 
 | ||||
| 	a.remote = remote.NewRemote(a.Logger, "", a.readFile, a.directoryExistsAt, a.fileExistsAt) | ||||
| 	a.remote = remote.NewRemote(a.Logger, "", a.fs) | ||||
| 
 | ||||
| 	f := converge | ||||
| 	if opts.Filter { | ||||
|  | @ -1095,18 +1073,18 @@ func (a *App) findDesiredStateFiles(specifiedPath string, opts LoadOpts) ([]stri | |||
| 	var helmfileDir string | ||||
| 	if specifiedPath != "" { | ||||
| 		switch { | ||||
| 		case a.fileExistsAt(specifiedPath): | ||||
| 		case a.fs.FileExistsAt(specifiedPath): | ||||
| 			return []string{specifiedPath}, nil | ||||
| 		case a.directoryExistsAt(specifiedPath): | ||||
| 		case a.fs.DirectoryExistsAt(specifiedPath): | ||||
| 			helmfileDir = specifiedPath | ||||
| 		default: | ||||
| 			return []string{}, fmt.Errorf("specified state file %s is not found", specifiedPath) | ||||
| 		} | ||||
| 	} else { | ||||
| 		var defaultFile string | ||||
| 		if a.fileExistsAt(DefaultHelmfile) { | ||||
| 		if a.fs.FileExistsAt(DefaultHelmfile) { | ||||
| 			defaultFile = DefaultHelmfile | ||||
| 		} else if a.fileExistsAt(DeprecatedHelmfile) { | ||||
| 		} else if a.fs.FileExistsAt(DeprecatedHelmfile) { | ||||
| 			log.Printf( | ||||
| 				"warn: %s is being loaded: %s is deprecated in favor of %s. See https://github.com/roboll/helmfile/issues/25 for more information", | ||||
| 				DeprecatedHelmfile, | ||||
|  | @ -1117,7 +1095,7 @@ func (a *App) findDesiredStateFiles(specifiedPath string, opts LoadOpts) ([]stri | |||
| 		} | ||||
| 
 | ||||
| 		switch { | ||||
| 		case a.directoryExistsAt(DefaultHelmfileDirectory): | ||||
| 		case a.fs.DirectoryExistsAt(DefaultHelmfileDirectory): | ||||
| 			if defaultFile != "" { | ||||
| 				return []string{}, fmt.Errorf("configuration conlict error: you can have either %s or %s, but not both", defaultFile, DefaultHelmfileDirectory) | ||||
| 			} | ||||
|  | @ -1130,7 +1108,7 @@ func (a *App) findDesiredStateFiles(specifiedPath string, opts LoadOpts) ([]stri | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	files, err := a.glob(filepath.Join(helmfileDir, "*.y*ml")) | ||||
| 	files, err := a.fs.Glob(filepath.Join(helmfileDir, "*.y*ml")) | ||||
| 	if err != nil { | ||||
| 		return []string{}, err | ||||
| 	} | ||||
|  | @ -1926,28 +1904,6 @@ func (a *App) writeValues(r *Run, c WriteValuesConfigProvider) (bool, []error) { | |||
| 	return true, errs | ||||
| } | ||||
| 
 | ||||
| func fileExistsAt(path string) bool { | ||||
| 	fileInfo, err := os.Stat(path) | ||||
| 	return err == nil && fileInfo.Mode().IsRegular() | ||||
| } | ||||
| 
 | ||||
| func fileExists(path string) (bool, error) { | ||||
| 	_, err := os.Stat(path) | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		if os.IsNotExist(err) { | ||||
| 			return false, nil | ||||
| 		} | ||||
| 		return false, err | ||||
| 	} | ||||
| 	return true, nil | ||||
| } | ||||
| 
 | ||||
| func directoryExistsAt(path string) bool { | ||||
| 	fileInfo, err := os.Stat(path) | ||||
| 	return err == nil && fileInfo.Mode().IsDir() | ||||
| } | ||||
| 
 | ||||
| // Error is a wrapper around an error that adds context to the error.
 | ||||
| type Error struct { | ||||
| 	msg string | ||||
|  | @ -2064,10 +2020,10 @@ func (c context) wrapErrs(errs ...error) error { | |||
| func (a *App) ShowCacheDir(c CacheConfigProvider) error { | ||||
| 	fmt.Printf("Cache directory: %s\n", remote.CacheDir()) | ||||
| 
 | ||||
| 	if !directoryExistsAt(remote.CacheDir()) { | ||||
| 	if !a.fs.DirectoryExistsAt(remote.CacheDir()) { | ||||
| 		return nil | ||||
| 	} | ||||
| 	dirs, err := os.ReadDir(remote.CacheDir()) | ||||
| 	dirs, err := a.fs.ReadDir(remote.CacheDir()) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | @ -2079,7 +2035,7 @@ func (a *App) ShowCacheDir(c CacheConfigProvider) error { | |||
| } | ||||
| 
 | ||||
| func (a *App) CleanCacheDir(c CacheConfigProvider) error { | ||||
| 	if !directoryExistsAt(remote.CacheDir()) { | ||||
| 	if !a.fs.DirectoryExistsAt(remote.CacheDir()) { | ||||
| 		return nil | ||||
| 	} | ||||
| 	fmt.Printf("Cleaning up cache directory: %s\n", remote.CacheDir()) | ||||
|  |  | |||
|  | @ -4,7 +4,6 @@ import ( | |||
| 	"bufio" | ||||
| 	"bytes" | ||||
| 	"io" | ||||
| 	"path/filepath" | ||||
| 	"sync" | ||||
| 	"testing" | ||||
| 
 | ||||
|  | @ -12,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" | ||||
| ) | ||||
|  | @ -90,8 +90,7 @@ func TestApply_3(t *testing.T) { | |||
| 
 | ||||
| 			app := appWithFs(&App{ | ||||
| 				OverrideHelmBinary:  DefaultHelmBinary, | ||||
| 				glob:                filepath.Glob, | ||||
| 				abs:                 filepath.Abs, | ||||
| 				fs:                  filesystem.DefaultFileSystem(), | ||||
| 				OverrideKubeContext: "", | ||||
| 				Env:                 "default", | ||||
| 				Logger:              logger, | ||||
|  |  | |||
|  | @ -4,7 +4,6 @@ import ( | |||
| 	"bufio" | ||||
| 	"bytes" | ||||
| 	"io" | ||||
| 	"path/filepath" | ||||
| 	"sync" | ||||
| 	"testing" | ||||
| 
 | ||||
|  | @ -12,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" | ||||
| ) | ||||
|  | @ -90,8 +90,7 @@ func TestApply_2(t *testing.T) { | |||
| 
 | ||||
| 			app := appWithFs(&App{ | ||||
| 				OverrideHelmBinary:  DefaultHelmBinary, | ||||
| 				glob:                filepath.Glob, | ||||
| 				abs:                 filepath.Abs, | ||||
| 				fs:                  filesystem.DefaultFileSystem(), | ||||
| 				OverrideKubeContext: "default", | ||||
| 				Env:                 "default", | ||||
| 				Logger:              logger, | ||||
|  |  | |||
|  | @ -4,7 +4,6 @@ import ( | |||
| 	"bufio" | ||||
| 	"bytes" | ||||
| 	"io" | ||||
| 	"path/filepath" | ||||
| 	"sync" | ||||
| 	"testing" | ||||
| 
 | ||||
|  | @ -13,6 +12,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" | ||||
| ) | ||||
|  | @ -129,8 +129,7 @@ releases: | |||
| 
 | ||||
| 			app := appWithFs(&App{ | ||||
| 				OverrideHelmBinary:  DefaultHelmBinary, | ||||
| 				glob:                filepath.Glob, | ||||
| 				abs:                 filepath.Abs, | ||||
| 				fs:                  filesystem.DefaultFileSystem(), | ||||
| 				OverrideKubeContext: "default", | ||||
| 				Env:                 "default", | ||||
| 				Logger:              logger, | ||||
|  |  | |||
|  | @ -15,6 +15,7 @@ import ( | |||
| 	"github.com/variantdev/vals" | ||||
| 
 | ||||
| 	"github.com/helmfile/helmfile/pkg/exectest" | ||||
| 	ffs "github.com/helmfile/helmfile/pkg/filesystem" | ||||
| 	"github.com/helmfile/helmfile/pkg/helmexec" | ||||
| 	"github.com/helmfile/helmfile/pkg/testhelper" | ||||
| ) | ||||
|  | @ -131,8 +132,7 @@ releases: | |||
| 
 | ||||
| 			app := appWithFs(&App{ | ||||
| 				OverrideHelmBinary:  DefaultHelmBinary, | ||||
| 				glob:                filepath.Glob, | ||||
| 				abs:                 filepath.Abs, | ||||
| 				fs:                  ffs.DefaultFileSystem(), | ||||
| 				OverrideKubeContext: "default", | ||||
| 				Env:                 "default", | ||||
| 				Logger:              logger, | ||||
|  |  | |||
|  | @ -4,7 +4,6 @@ import ( | |||
| 	"bufio" | ||||
| 	"bytes" | ||||
| 	"io" | ||||
| 	"path/filepath" | ||||
| 	"sync" | ||||
| 	"testing" | ||||
| 
 | ||||
|  | @ -12,6 +11,7 @@ import ( | |||
| 	"github.com/stretchr/testify/assert" | ||||
| 	"github.com/variantdev/vals" | ||||
| 
 | ||||
| 	ffs "github.com/helmfile/helmfile/pkg/filesystem" | ||||
| 	"github.com/helmfile/helmfile/pkg/helmexec" | ||||
| 	"github.com/helmfile/helmfile/pkg/testhelper" | ||||
| 	"github.com/helmfile/helmfile/pkg/testutil" | ||||
|  | @ -145,8 +145,7 @@ releases: | |||
| 
 | ||||
| 			app := appWithFs(&App{ | ||||
| 				OverrideHelmBinary:  DefaultHelmBinary, | ||||
| 				glob:                filepath.Glob, | ||||
| 				abs:                 filepath.Abs, | ||||
| 				fs:                  ffs.DefaultFileSystem(), | ||||
| 				OverrideKubeContext: "default", | ||||
| 				Env:                 tc.environment, | ||||
| 				Logger:              logger, | ||||
|  |  | |||
|  | @ -4,7 +4,6 @@ import ( | |||
| 	"bufio" | ||||
| 	"bytes" | ||||
| 	"io" | ||||
| 	"path/filepath" | ||||
| 	"sync" | ||||
| 	"testing" | ||||
| 
 | ||||
|  | @ -12,6 +11,7 @@ import ( | |||
| 	"github.com/variantdev/vals" | ||||
| 
 | ||||
| 	"github.com/helmfile/helmfile/pkg/exectest" | ||||
| 	ffs "github.com/helmfile/helmfile/pkg/filesystem" | ||||
| 	"github.com/helmfile/helmfile/pkg/helmexec" | ||||
| 	"github.com/helmfile/helmfile/pkg/testhelper" | ||||
| ) | ||||
|  | @ -88,8 +88,7 @@ func TestSync(t *testing.T) { | |||
| 
 | ||||
| 			app := appWithFs(&App{ | ||||
| 				OverrideHelmBinary:  DefaultHelmBinary, | ||||
| 				glob:                filepath.Glob, | ||||
| 				abs:                 filepath.Abs, | ||||
| 				fs:                  ffs.DefaultFileSystem(), | ||||
| 				OverrideKubeContext: "default", | ||||
| 				Env:                 "default", | ||||
| 				Logger:              logger, | ||||
|  |  | |||
|  | @ -15,6 +15,7 @@ import ( | |||
| 	"github.com/variantdev/vals" | ||||
| 
 | ||||
| 	"github.com/helmfile/helmfile/pkg/exectest" | ||||
| 	ffs "github.com/helmfile/helmfile/pkg/filesystem" | ||||
| 	"github.com/helmfile/helmfile/pkg/helmexec" | ||||
| 	"github.com/helmfile/helmfile/pkg/testhelper" | ||||
| ) | ||||
|  | @ -131,8 +132,7 @@ releases: | |||
| 
 | ||||
| 			app := appWithFs(&App{ | ||||
| 				OverrideHelmBinary:  DefaultHelmBinary, | ||||
| 				glob:                filepath.Glob, | ||||
| 				abs:                 filepath.Abs, | ||||
| 				fs:                  &ffs.FileSystem{Glob: filepath.Glob}, | ||||
| 				OverrideKubeContext: "default", | ||||
| 				Env:                 "default", | ||||
| 				Logger:              logger, | ||||
|  |  | |||
|  | @ -21,6 +21,7 @@ import ( | |||
| 
 | ||||
| 	"github.com/helmfile/helmfile/pkg/envvar" | ||||
| 	"github.com/helmfile/helmfile/pkg/exectest" | ||||
| 	ffs "github.com/helmfile/helmfile/pkg/filesystem" | ||||
| 	"github.com/helmfile/helmfile/pkg/helmexec" | ||||
| 	"github.com/helmfile/helmfile/pkg/remote" | ||||
| 	"github.com/helmfile/helmfile/pkg/state" | ||||
|  | @ -40,14 +41,7 @@ func injectFs(app *App, fs *testhelper.TestFs) *App { | |||
| 		app.Set = make(map[string]interface{}) | ||||
| 	} | ||||
| 
 | ||||
| 	app.readFile = fs.ReadFile | ||||
| 	app.glob = fs.Glob | ||||
| 	app.abs = fs.Abs | ||||
| 	app.getwd = fs.Getwd | ||||
| 	app.chdir = fs.Chdir | ||||
| 	app.fileExistsAt = fs.FileExistsAt | ||||
| 	app.fileExists = fs.FileExists | ||||
| 	app.directoryExistsAt = fs.DirectoryExistsAt | ||||
| 	app.fs = fs.ToFileSystem() | ||||
| 	return app | ||||
| } | ||||
| 
 | ||||
|  | @ -1529,12 +1523,11 @@ func TestLoadDesiredStateFromYaml_DuplicateReleaseName(t *testing.T) { | |||
| 		} | ||||
| 		return yamlContent, nil | ||||
| 	} | ||||
| 	fs := ffs.FromFileSystem(ffs.FileSystem{ReadFile: readFile}) | ||||
| 	app := &App{ | ||||
| 		OverrideHelmBinary:  DefaultHelmBinary, | ||||
| 		OverrideKubeContext: "default", | ||||
| 		readFile:            readFile, | ||||
| 		glob:                filepath.Glob, | ||||
| 		abs:                 filepath.Abs, | ||||
| 		fs:                  fs, | ||||
| 		Env:                 "default", | ||||
| 		Logger:              helmexec.NewLogger(os.Stderr, "debug"), | ||||
| 	} | ||||
|  | @ -1593,16 +1586,11 @@ helmDefaults: | |||
| 	app := &App{ | ||||
| 		OverrideHelmBinary:  DefaultHelmBinary, | ||||
| 		OverrideKubeContext: "default", | ||||
| 		readFile:            testFs.ReadFile, | ||||
| 		glob:                testFs.Glob, | ||||
| 		abs:                 testFs.Abs, | ||||
| 		directoryExistsAt:   testFs.DirectoryExistsAt, | ||||
| 		fileExistsAt:        testFs.FileExistsAt, | ||||
| 		fileExists:          testFs.FileExists, | ||||
| 		fs:                  testFs.ToFileSystem(), | ||||
| 		Env:                 "default", | ||||
| 		Logger:              helmexec.NewLogger(os.Stderr, "debug"), | ||||
| 	} | ||||
| 	app.remote = remote.NewRemote(app.Logger, "", app.readFile, app.directoryExistsAt, app.fileExistsAt) | ||||
| 	app.remote = remote.NewRemote(app.Logger, "", app.fs) | ||||
| 
 | ||||
| 	expectNoCallsToHelm(app) | ||||
| 
 | ||||
|  | @ -1683,14 +1671,11 @@ helmDefaults: | |||
| 	}) | ||||
| 	app := &App{ | ||||
| 		OverrideHelmBinary: DefaultHelmBinary, | ||||
| 		readFile:           testFs.ReadFile, | ||||
| 		fileExists:         testFs.FileExists, | ||||
| 		glob:               testFs.Glob, | ||||
| 		abs:                testFs.Abs, | ||||
| 		fs:                 testFs.ToFileSystem(), | ||||
| 		Env:                "default", | ||||
| 		Logger:             helmexec.NewLogger(os.Stderr, "debug"), | ||||
| 	} | ||||
| 	app.remote = remote.NewRemote(app.Logger, testFs.Cwd, testFs.ReadFile, testFs.DirectoryExistsAt, testFs.FileExistsAt) | ||||
| 	app.remote = remote.NewRemote(app.Logger, testFs.Cwd, app.fs) | ||||
| 
 | ||||
| 	expectNoCallsToHelm(app) | ||||
| 
 | ||||
|  | @ -1762,14 +1747,11 @@ foo: FOO | |||
| 	}) | ||||
| 	app := &App{ | ||||
| 		OverrideHelmBinary: DefaultHelmBinary, | ||||
| 		readFile:           testFs.ReadFile, | ||||
| 		fileExists:         testFs.FileExists, | ||||
| 		glob:               testFs.Glob, | ||||
| 		abs:                testFs.Abs, | ||||
| 		fs:                 testFs.ToFileSystem(), | ||||
| 		Env:                "default", | ||||
| 		Logger:             helmexec.NewLogger(os.Stderr, "debug"), | ||||
| 	} | ||||
| 	app.remote = remote.NewRemote(app.Logger, testFs.Cwd, testFs.ReadFile, testFs.DirectoryExistsAt, testFs.FileExistsAt) | ||||
| 	app.remote = remote.NewRemote(app.Logger, testFs.Cwd, app.fs) | ||||
| 
 | ||||
| 	expectNoCallsToHelm(app) | ||||
| 
 | ||||
|  | @ -1828,14 +1810,11 @@ foo: FOO | |||
| 	}) | ||||
| 	app := &App{ | ||||
| 		OverrideHelmBinary: DefaultHelmBinary, | ||||
| 		readFile:           testFs.ReadFile, | ||||
| 		fileExists:         testFs.FileExists, | ||||
| 		glob:               testFs.Glob, | ||||
| 		abs:                testFs.Abs, | ||||
| 		fs:                 testFs.ToFileSystem(), | ||||
| 		Env:                "default", | ||||
| 		Logger:             helmexec.NewLogger(os.Stderr, "debug"), | ||||
| 	} | ||||
| 	app.remote = remote.NewRemote(app.Logger, testFs.Cwd, testFs.ReadFile, testFs.DirectoryExistsAt, testFs.FileExistsAt) | ||||
| 	app.remote = remote.NewRemote(app.Logger, testFs.Cwd, app.fs) | ||||
| 
 | ||||
| 	expectNoCallsToHelm(app) | ||||
| 
 | ||||
|  | @ -1912,14 +1891,11 @@ helmDefaults: | |||
| 	}) | ||||
| 	app := &App{ | ||||
| 		OverrideHelmBinary: DefaultHelmBinary, | ||||
| 		readFile:           testFs.ReadFile, | ||||
| 		fileExists:         testFs.FileExists, | ||||
| 		glob:               testFs.Glob, | ||||
| 		abs:                testFs.Abs, | ||||
| 		fs:                 testFs.ToFileSystem(), | ||||
| 		Env:                "test", | ||||
| 		Logger:             helmexec.NewLogger(os.Stderr, "debug"), | ||||
| 	} | ||||
| 	app.remote = remote.NewRemote(app.Logger, testFs.Cwd, testFs.ReadFile, testFs.DirectoryExistsAt, testFs.FileExistsAt) | ||||
| 	app.remote = remote.NewRemote(app.Logger, testFs.Cwd, app.fs) | ||||
| 
 | ||||
| 	expectNoCallsToHelm(app) | ||||
| 
 | ||||
|  | @ -1988,13 +1964,11 @@ releases: | |||
| 	}) | ||||
| 	app := &App{ | ||||
| 		OverrideHelmBinary: DefaultHelmBinary, | ||||
| 		readFile:           testFs.ReadFile, | ||||
| 		glob:               testFs.Glob, | ||||
| 		abs:                testFs.Abs, | ||||
| 		fs:                 testFs.ToFileSystem(), | ||||
| 		Env:                "default", | ||||
| 		Logger:             helmexec.NewLogger(os.Stderr, "debug"), | ||||
| 	} | ||||
| 	app.remote = remote.NewRemote(app.Logger, testFs.Cwd, testFs.ReadFile, testFs.DirectoryExistsAt, testFs.FileExistsAt) | ||||
| 	app.remote = remote.NewRemote(app.Logger, testFs.Cwd, app.fs) | ||||
| 
 | ||||
| 	expectNoCallsToHelm(app) | ||||
| 
 | ||||
|  | @ -2046,14 +2020,12 @@ releases: | |||
| 	}) | ||||
| 	app := &App{ | ||||
| 		OverrideHelmBinary: DefaultHelmBinary, | ||||
| 		readFile:           testFs.ReadFile, | ||||
| 		glob:               testFs.Glob, | ||||
| 		abs:                testFs.Abs, | ||||
| 		fs:                 testFs.ToFileSystem(), | ||||
| 		Env:                "default", | ||||
| 		Logger:             helmexec.NewLogger(os.Stderr, "debug"), | ||||
| 	} | ||||
| 
 | ||||
| 	app.remote = remote.NewRemote(app.Logger, testFs.Cwd, testFs.ReadFile, testFs.DirectoryExistsAt, testFs.FileExistsAt) | ||||
| 	app.remote = remote.NewRemote(app.Logger, testFs.Cwd, app.fs) | ||||
| 	expectNoCallsToHelm(app) | ||||
| 
 | ||||
| 	st, err := app.loadDesiredStateFromYaml(statePath, LoadOpts{Reverse: true}) | ||||
|  | @ -2103,13 +2075,11 @@ releases: | |||
| 		}) | ||||
| 		app := &App{ | ||||
| 			OverrideHelmBinary: DefaultHelmBinary, | ||||
| 			readFile:           testFs.ReadFile, | ||||
| 			glob:               testFs.Glob, | ||||
| 			abs:                testFs.Abs, | ||||
| 			fs:                 testFs.ToFileSystem(), | ||||
| 			Env:                "default", | ||||
| 			Logger:             helmexec.NewLogger(os.Stderr, "debug"), | ||||
| 		} | ||||
| 		app.remote = remote.NewRemote(app.Logger, testFs.Cwd, testFs.ReadFile, testFs.DirectoryExistsAt, testFs.FileExistsAt) | ||||
| 		app.remote = remote.NewRemote(app.Logger, testFs.Cwd, app.fs) | ||||
| 
 | ||||
| 		opts := LoadOpts{ | ||||
| 			CalleePath: statePath, | ||||
|  | @ -2217,13 +2187,11 @@ services: | |||
| 		}) | ||||
| 		app := &App{ | ||||
| 			OverrideHelmBinary: DefaultHelmBinary, | ||||
| 			readFile:           testFs.ReadFile, | ||||
| 			glob:               testFs.Glob, | ||||
| 			abs:                testFs.Abs, | ||||
| 			fs:                 testFs.ToFileSystem(), | ||||
| 			Env:                "default", | ||||
| 			Logger:             helmexec.NewLogger(os.Stderr, "debug"), | ||||
| 		} | ||||
| 		app.remote = remote.NewRemote(app.Logger, testFs.Cwd, testFs.ReadFile, testFs.DirectoryExistsAt, testFs.FileExistsAt) | ||||
| 		app.remote = remote.NewRemote(app.Logger, testFs.Cwd, app.fs) | ||||
| 
 | ||||
| 		expectNoCallsToHelm(app) | ||||
| 
 | ||||
|  | @ -2656,8 +2624,7 @@ releases: | |||
| 
 | ||||
| 	app := appWithFs(&App{ | ||||
| 		OverrideHelmBinary:  DefaultHelmBinary, | ||||
| 		glob:                filepath.Glob, | ||||
| 		abs:                 filepath.Abs, | ||||
| 		fs:                  ffs.DefaultFileSystem(), | ||||
| 		OverrideKubeContext: "default", | ||||
| 		Env:                 "default", | ||||
| 		Logger:              logger, | ||||
|  | @ -2729,8 +2696,6 @@ releases: | |||
| 
 | ||||
| 	app := appWithFs(&App{ | ||||
| 		OverrideHelmBinary:  DefaultHelmBinary, | ||||
| 		glob:                filepath.Glob, | ||||
| 		abs:                 filepath.Abs, | ||||
| 		OverrideKubeContext: "default", | ||||
| 		Env:                 "default", | ||||
| 		Logger:              logger, | ||||
|  | @ -2741,6 +2706,8 @@ releases: | |||
| 		valsRuntime: valsRuntime, | ||||
| 	}, files) | ||||
| 
 | ||||
| 	fmt.Printf("CRAFTED APP WITH %p\n", app.fs.DirectoryExistsAt) | ||||
| 
 | ||||
| 	if err := app.Template(configImpl{}); err != nil { | ||||
| 		t.Fatalf("%v", err) | ||||
| 	} | ||||
|  | @ -4282,8 +4249,7 @@ changing working directory back to "/path/to" | |||
| 
 | ||||
| 				app := appWithFs(&App{ | ||||
| 					OverrideHelmBinary:  DefaultHelmBinary, | ||||
| 					glob:                filepath.Glob, | ||||
| 					abs:                 filepath.Abs, | ||||
| 					fs:                  ffs.DefaultFileSystem(), | ||||
| 					OverrideKubeContext: "default", | ||||
| 					Env:                 "default", | ||||
| 					Logger:              logger, | ||||
|  | @ -4465,8 +4431,7 @@ changing working directory back to "/path/to" | |||
| 
 | ||||
| 				app := appWithFs(&App{ | ||||
| 					OverrideHelmBinary:  DefaultHelmBinary, | ||||
| 					glob:                filepath.Glob, | ||||
| 					abs:                 filepath.Abs, | ||||
| 					fs:                  ffs.DefaultFileSystem(), | ||||
| 					OverrideKubeContext: "default", | ||||
| 					Env:                 "default", | ||||
| 					Logger:              logger, | ||||
|  | @ -4523,8 +4488,7 @@ releases: | |||
| 
 | ||||
| 	app := appWithFs(&App{ | ||||
| 		OverrideHelmBinary:  DefaultHelmBinary, | ||||
| 		glob:                filepath.Glob, | ||||
| 		abs:                 filepath.Abs, | ||||
| 		fs:                  ffs.DefaultFileSystem(), | ||||
| 		OverrideKubeContext: "default", | ||||
| 		Env:                 "default", | ||||
| 		Logger:              logger, | ||||
|  | @ -4570,8 +4534,7 @@ releases: | |||
| 
 | ||||
| 	app := appWithFs(&App{ | ||||
| 		OverrideHelmBinary:  DefaultHelmBinary, | ||||
| 		glob:                filepath.Glob, | ||||
| 		abs:                 filepath.Abs, | ||||
| 		fs:                  ffs.DefaultFileSystem(), | ||||
| 		OverrideKubeContext: "default", | ||||
| 		Env:                 "default", | ||||
| 		Logger:              logger, | ||||
|  | @ -4631,8 +4594,7 @@ releases: | |||
| 
 | ||||
| 	app := appWithFs(&App{ | ||||
| 		OverrideHelmBinary:  DefaultHelmBinary, | ||||
| 		glob:                filepath.Glob, | ||||
| 		abs:                 filepath.Abs, | ||||
| 		fs:                  ffs.DefaultFileSystem(), | ||||
| 		OverrideKubeContext: "default", | ||||
| 		Env:                 "default", | ||||
| 		Logger:              logger, | ||||
|  | @ -4693,8 +4655,7 @@ releases: | |||
| 
 | ||||
| 	app := appWithFs(&App{ | ||||
| 		OverrideHelmBinary:  DefaultHelmBinary, | ||||
| 		glob:                filepath.Glob, | ||||
| 		abs:                 filepath.Abs, | ||||
| 		fs:                  ffs.DefaultFileSystem(), | ||||
| 		OverrideKubeContext: "default", | ||||
| 		Env:                 "default", | ||||
| 		Logger:              logger, | ||||
|  |  | |||
|  | @ -11,6 +11,7 @@ import ( | |||
| 	"go.uber.org/zap" | ||||
| 
 | ||||
| 	"github.com/helmfile/helmfile/pkg/environment" | ||||
| 	"github.com/helmfile/helmfile/pkg/filesystem" | ||||
| 	"github.com/helmfile/helmfile/pkg/helmexec" | ||||
| 	"github.com/helmfile/helmfile/pkg/remote" | ||||
| 	"github.com/helmfile/helmfile/pkg/state" | ||||
|  | @ -27,14 +28,9 @@ type desiredStateLoader struct { | |||
| 	env       string | ||||
| 	namespace string | ||||
| 	chart     string | ||||
| 	fs        *filesystem.FileSystem | ||||
| 
 | ||||
| 	readFile          func(string) ([]byte, error) | ||||
| 	deleteFile        func(string) error | ||||
| 	fileExists        func(string) (bool, error) | ||||
| 	abs               func(string) (string, error) | ||||
| 	glob              func(string) ([]string, error) | ||||
| 	directoryExistsAt func(string) bool | ||||
| 	getHelm           func(*state.HelmState) helmexec.Interface | ||||
| 	getHelm func(*state.HelmState) helmexec.Interface | ||||
| 
 | ||||
| 	remote      *remote.Remote | ||||
| 	logger      *zap.SugaredLogger | ||||
|  | @ -50,8 +46,8 @@ func (ld *desiredStateLoader) Load(f string, opts LoadOpts) (*state.HelmState, e | |||
| 		if opts.CalleePath == "" { | ||||
| 			return nil, fmt.Errorf("bug: opts.CalleePath was nil: f=%s, opts=%v", f, opts) | ||||
| 		} | ||||
| 		storage := state.NewStorage(opts.CalleePath, ld.logger, ld.glob) | ||||
| 		envld := state.NewEnvironmentValuesLoader(storage, ld.readFile, ld.logger, ld.remote) | ||||
| 		storage := state.NewStorage(opts.CalleePath, ld.logger, ld.fs) | ||||
| 		envld := state.NewEnvironmentValuesLoader(storage, ld.fs, ld.logger, ld.remote) | ||||
| 		handler := state.MissingFileHandlerError | ||||
| 		vals, err := envld.LoadEnvironmentValues(&handler, args, &environment.EmptyEnvironment) | ||||
| 		if err != nil { | ||||
|  | @ -120,7 +116,7 @@ func (ld *desiredStateLoader) loadFileWithOverrides(inheritedEnv, overrodeEnv *e | |||
| 		f = filepath.Join(baseDir, file) | ||||
| 	} | ||||
| 
 | ||||
| 	fileBytes, err := ld.readFile(f) | ||||
| 	fileBytes, err := ld.fs.ReadFile(f) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | @ -166,8 +162,7 @@ func (ld *desiredStateLoader) loadFileWithOverrides(inheritedEnv, overrodeEnv *e | |||
| } | ||||
| 
 | ||||
| func (a *desiredStateLoader) underlying() *state.StateCreator { | ||||
| 	c := state.NewCreator(a.logger, a.readFile, a.fileExists, a.abs, a.glob, a.directoryExistsAt, a.valsRuntime, a.getHelm, a.overrideHelmBinary, a.remote) | ||||
| 	c.DeleteFile = a.deleteFile | ||||
| 	c := state.NewCreator(a.logger, a.fs, a.valsRuntime, a.getHelm, a.overrideHelmBinary, a.remote) | ||||
| 	c.LoadFile = a.loadFile | ||||
| 	return c | ||||
| } | ||||
|  |  | |||
|  | @ -4,13 +4,13 @@ import ( | |||
| 	"bufio" | ||||
| 	"bytes" | ||||
| 	"io" | ||||
| 	"path/filepath" | ||||
| 	"sync" | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"github.com/variantdev/vals" | ||||
| 
 | ||||
| 	"github.com/helmfile/helmfile/pkg/exectest" | ||||
| 	ffs "github.com/helmfile/helmfile/pkg/filesystem" | ||||
| 	"github.com/helmfile/helmfile/pkg/helmexec" | ||||
| 	"github.com/helmfile/helmfile/pkg/testhelper" | ||||
| ) | ||||
|  | @ -83,8 +83,7 @@ func TestDestroy_2(t *testing.T) { | |||
| 
 | ||||
| 			app := appWithFs(&App{ | ||||
| 				OverrideHelmBinary:  DefaultHelmBinary, | ||||
| 				glob:                filepath.Glob, | ||||
| 				abs:                 filepath.Abs, | ||||
| 				fs:                  ffs.DefaultFileSystem(), | ||||
| 				OverrideKubeContext: "", | ||||
| 				Env:                 "default", | ||||
| 				Logger:              logger, | ||||
|  |  | |||
|  | @ -4,7 +4,6 @@ import ( | |||
| 	"bufio" | ||||
| 	"bytes" | ||||
| 	"io" | ||||
| 	"path/filepath" | ||||
| 	"sync" | ||||
| 	"testing" | ||||
| 
 | ||||
|  | @ -12,6 +11,7 @@ import ( | |||
| 	"go.uber.org/zap" | ||||
| 
 | ||||
| 	"github.com/helmfile/helmfile/pkg/exectest" | ||||
| 	ffs "github.com/helmfile/helmfile/pkg/filesystem" | ||||
| 	"github.com/helmfile/helmfile/pkg/helmexec" | ||||
| 	"github.com/helmfile/helmfile/pkg/testhelper" | ||||
| ) | ||||
|  | @ -124,8 +124,7 @@ func TestDestroy(t *testing.T) { | |||
| 
 | ||||
| 			app := appWithFs(&App{ | ||||
| 				OverrideHelmBinary:  DefaultHelmBinary, | ||||
| 				glob:                filepath.Glob, | ||||
| 				abs:                 filepath.Abs, | ||||
| 				fs:                  ffs.DefaultFileSystem(), | ||||
| 				OverrideKubeContext: "default", | ||||
| 				Env:                 "default", | ||||
| 				Logger:              logger, | ||||
|  |  | |||
|  | @ -4,7 +4,6 @@ import ( | |||
| 	"bufio" | ||||
| 	"bytes" | ||||
| 	"io" | ||||
| 	"path/filepath" | ||||
| 	"sync" | ||||
| 	"testing" | ||||
| 
 | ||||
|  | @ -12,6 +11,7 @@ import ( | |||
| 	"github.com/variantdev/vals" | ||||
| 
 | ||||
| 	"github.com/helmfile/helmfile/pkg/exectest" | ||||
| 	ffs "github.com/helmfile/helmfile/pkg/filesystem" | ||||
| 	"github.com/helmfile/helmfile/pkg/helmexec" | ||||
| 	"github.com/helmfile/helmfile/pkg/testhelper" | ||||
| ) | ||||
|  | @ -1060,8 +1060,7 @@ changing working directory back to "/path/to" | |||
| 
 | ||||
| 				app := appWithFs(&App{ | ||||
| 					OverrideHelmBinary:  DefaultHelmBinary, | ||||
| 					glob:                filepath.Glob, | ||||
| 					abs:                 filepath.Abs, | ||||
| 					fs:                  ffs.DefaultFileSystem(), | ||||
| 					OverrideKubeContext: "", | ||||
| 					Env:                 "default", | ||||
| 					Logger:              logger, | ||||
|  |  | |||
|  | @ -4,7 +4,6 @@ import ( | |||
| 	"bufio" | ||||
| 	"bytes" | ||||
| 	"io" | ||||
| 	"path/filepath" | ||||
| 	"sync" | ||||
| 	"testing" | ||||
| 
 | ||||
|  | @ -13,6 +12,7 @@ import ( | |||
| 	"go.uber.org/zap" | ||||
| 
 | ||||
| 	"github.com/helmfile/helmfile/pkg/exectest" | ||||
| 	ffs "github.com/helmfile/helmfile/pkg/filesystem" | ||||
| 	"github.com/helmfile/helmfile/pkg/helmexec" | ||||
| 	"github.com/helmfile/helmfile/pkg/testhelper" | ||||
| ) | ||||
|  | @ -1352,8 +1352,7 @@ changing working directory back to "/path/to" | |||
| 
 | ||||
| 				app := appWithFs(&App{ | ||||
| 					OverrideHelmBinary:  DefaultHelmBinary, | ||||
| 					glob:                filepath.Glob, | ||||
| 					abs:                 filepath.Abs, | ||||
| 					fs:                  ffs.DefaultFileSystem(), | ||||
| 					OverrideKubeContext: overrideKubeContext, | ||||
| 					Env:                 "default", | ||||
| 					Logger:              logger, | ||||
|  |  | |||
|  | @ -124,7 +124,7 @@ func (r *desiredStateLoader) twoPassRenderTemplateToYaml(inherited, overrode *en | |||
| 	} | ||||
| 
 | ||||
| 	tmplData := state.NewEnvironmentTemplateData(*finalEnv, r.namespace, vals) | ||||
| 	secondPassRenderer := tmpl.NewFileRenderer(r.readFile, baseDir, tmplData) | ||||
| 	secondPassRenderer := tmpl.NewFileRenderer(r.fs, baseDir, tmplData) | ||||
| 	yamlBuf, err := secondPassRenderer.RenderTemplateContentToBuffer(content) | ||||
| 	if err != nil { | ||||
| 		if r.logger != nil { | ||||
|  |  | |||
|  | @ -17,16 +17,13 @@ import ( | |||
| func makeLoader(files map[string]string, env string) (*desiredStateLoader, *testhelper.TestFs) { | ||||
| 	testfs := testhelper.NewTestFs(files) | ||||
| 	logger := helmexec.NewLogger(os.Stdout, "debug") | ||||
| 	r := remote.NewRemote(logger, testfs.Cwd, testfs.ReadFile, testfs.DirectoryExistsAt, testfs.FileExistsAt) | ||||
| 	r := remote.NewRemote(logger, testfs.Cwd, testfs.ToFileSystem()) | ||||
| 	return &desiredStateLoader{ | ||||
| 		env:        env, | ||||
| 		namespace:  "namespace", | ||||
| 		logger:     helmexec.NewLogger(os.Stdout, "debug"), | ||||
| 		readFile:   testfs.ReadFile, | ||||
| 		fileExists: testfs.FileExists, | ||||
| 		abs:        testfs.Abs, | ||||
| 		glob:       testfs.Glob, | ||||
| 		remote:     r, | ||||
| 		env:       env, | ||||
| 		namespace: "namespace", | ||||
| 		logger:    helmexec.NewLogger(os.Stdout, "debug"), | ||||
| 		fs:        testfs.ToFileSystem(), | ||||
| 		remote:    r, | ||||
| 	}, testfs | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ import ( | |||
| 	"go.uber.org/zap" | ||||
| 
 | ||||
| 	"github.com/helmfile/helmfile/pkg/environment" | ||||
| 	"github.com/helmfile/helmfile/pkg/filesystem" | ||||
| 	"github.com/helmfile/helmfile/pkg/helmexec" | ||||
| 	"github.com/helmfile/helmfile/pkg/tmpl" | ||||
| ) | ||||
|  | @ -35,9 +36,9 @@ type Bus struct { | |||
| 	Chart         string | ||||
| 
 | ||||
| 	Env environment.Environment | ||||
| 	Fs  *filesystem.FileSystem | ||||
| 
 | ||||
| 	ReadFile func(string) ([]byte, error) | ||||
| 	Logger   *zap.SugaredLogger | ||||
| 	Logger *zap.SugaredLogger | ||||
| } | ||||
| 
 | ||||
| func (bus *Bus) Trigger(evt string, evtErr error, context map[string]interface{}) (bool, error) { | ||||
|  | @ -100,7 +101,7 @@ func (bus *Bus) Trigger(evt string, evtErr error, context map[string]interface{} | |||
| 		for k, v := range context { | ||||
| 			data[k] = v | ||||
| 		} | ||||
| 		render := tmpl.NewTextRenderer(bus.ReadFile, bus.BasePath, data) | ||||
| 		render := tmpl.NewTextRenderer(bus.Fs, bus.BasePath, data) | ||||
| 
 | ||||
| 		bus.Logger.Debugf("hook[%s]: triggered by event \"%s\"\n", name, evt) | ||||
| 
 | ||||
|  |  | |||
|  | @ -9,6 +9,7 @@ import ( | |||
| 	"go.uber.org/zap/zaptest/observer" | ||||
| 
 | ||||
| 	"github.com/helmfile/helmfile/pkg/environment" | ||||
| 	ffs "github.com/helmfile/helmfile/pkg/filesystem" | ||||
| ) | ||||
| 
 | ||||
| type runner struct { | ||||
|  | @ -154,7 +155,7 @@ func TestTrigger(t *testing.T) { | |||
| 			Namespace:     "myns", | ||||
| 			Env:           environment.Environment{Name: "prod"}, | ||||
| 			Logger:        zeLogger, | ||||
| 			ReadFile:      readFile, | ||||
| 			Fs:            &ffs.FileSystem{ReadFile: readFile}, | ||||
| 		} | ||||
| 
 | ||||
| 		bus.Runner = &runner{} | ||||
|  |  | |||
|  | @ -0,0 +1,101 @@ | |||
| package filesystem | ||||
| 
 | ||||
| import ( | ||||
| 	"io/fs" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| ) | ||||
| 
 | ||||
| type FileSystem struct { | ||||
| 	ReadFile          func(string) ([]byte, error) | ||||
| 	ReadDir           func(string) ([]fs.DirEntry, error) | ||||
| 	DeleteFile        func(string) error | ||||
| 	FileExists        func(string) (bool, error) | ||||
| 	Glob              func(string) ([]string, error) | ||||
| 	FileExistsAt      func(string) bool | ||||
| 	DirectoryExistsAt func(string) bool | ||||
| 	Stat              func(string) (os.FileInfo, error) | ||||
| 	Getwd             func() (string, error) | ||||
| 	Chdir             func(string) error | ||||
| 	Abs               func(string) (string, error) | ||||
| } | ||||
| 
 | ||||
| func DefaultFileSystem() *FileSystem { | ||||
| 	dfs := FileSystem{ | ||||
| 		ReadFile:   os.ReadFile, | ||||
| 		ReadDir:    os.ReadDir, | ||||
| 		DeleteFile: os.Remove, | ||||
| 		Stat:       os.Stat, | ||||
| 		Glob:       filepath.Glob, | ||||
| 		Getwd:      os.Getwd, | ||||
| 		Chdir:      os.Chdir, | ||||
| 		Abs:        filepath.Abs, | ||||
| 	} | ||||
| 
 | ||||
| 	dfs.FileExistsAt = dfs.fileExistsAtDefault | ||||
| 	dfs.DirectoryExistsAt = dfs.directoryExistsDefault | ||||
| 	dfs.FileExists = dfs.fileExistsDefault | ||||
| 	return &dfs | ||||
| } | ||||
| 
 | ||||
| func FromFileSystem(params FileSystem) *FileSystem { | ||||
| 	dfs := DefaultFileSystem() | ||||
| 
 | ||||
| 	if params.ReadFile != nil { | ||||
| 		dfs.ReadFile = params.ReadFile | ||||
| 	} | ||||
| 	if params.ReadDir != nil { | ||||
| 		dfs.ReadDir = params.ReadDir | ||||
| 	} | ||||
| 	if params.DeleteFile != nil { | ||||
| 		dfs.DeleteFile = params.DeleteFile | ||||
| 	} | ||||
| 	if params.FileExists != nil { | ||||
| 		dfs.FileExists = params.FileExists | ||||
| 	} | ||||
| 	if params.Glob != nil { | ||||
| 		dfs.Glob = params.Glob | ||||
| 	} | ||||
| 	if params.FileExistsAt != nil { | ||||
| 		dfs.FileExistsAt = params.FileExistsAt | ||||
| 	} | ||||
| 	if params.DirectoryExistsAt != nil { | ||||
| 		dfs.DirectoryExistsAt = params.DirectoryExistsAt | ||||
| 	} | ||||
| 	if params.Stat != nil { | ||||
| 		dfs.Stat = params.Stat | ||||
| 	} | ||||
| 	if params.Getwd != nil { | ||||
| 		dfs.Getwd = params.Getwd | ||||
| 	} | ||||
| 	if params.Chdir != nil { | ||||
| 		dfs.Chdir = params.Chdir | ||||
| 	} | ||||
| 	if params.Abs != nil { | ||||
| 		dfs.Abs = params.Abs | ||||
| 	} | ||||
| 
 | ||||
| 	return dfs | ||||
| } | ||||
| 
 | ||||
| func (filesystem *FileSystem) fileExistsAtDefault(path string) bool { | ||||
| 	fileInfo, err := filesystem.Stat(path) | ||||
| 	return err == nil && fileInfo.Mode().IsRegular() | ||||
| } | ||||
| 
 | ||||
| func (filesystem *FileSystem) fileExistsDefault(path string) (bool, error) { | ||||
| 	_, err := filesystem.Stat(path) | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		if os.IsNotExist(err) { | ||||
| 			return false, nil | ||||
| 		} | ||||
| 		return false, err | ||||
| 	} | ||||
| 	return true, nil | ||||
| } | ||||
| 
 | ||||
| func (filesystem *FileSystem) directoryExistsDefault(path string) bool { | ||||
| 	fileInfo, err := filesystem.Stat(path) | ||||
| 	return err == nil && fileInfo.Mode().IsDir() | ||||
| } | ||||
|  | @ -0,0 +1,98 @@ | |||
| package filesystem | ||||
| 
 | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"io/fs" | ||||
| 	"os" | ||||
| 	"strings" | ||||
| 	"testing" | ||||
| 	"time" | ||||
| ) | ||||
| 
 | ||||
| type TestFileInfo struct { | ||||
| 	mode fs.FileMode | ||||
| } | ||||
| 
 | ||||
| func (tfi TestFileInfo) Name() string       { return "" } | ||||
| func (tfi TestFileInfo) Size() int64        { return 0 } | ||||
| func (tfi TestFileInfo) Mode() fs.FileMode  { return tfi.mode } | ||||
| func (tfi TestFileInfo) ModTime() time.Time { return time.Time{} } | ||||
| func (tfi TestFileInfo) IsDir() bool        { return tfi.mode.IsDir() } | ||||
| func (tfi TestFileInfo) Sys() any           { return nil } | ||||
| 
 | ||||
| func NewTestFileSystem() FileSystem { | ||||
| 	replaceffs := FileSystem{ | ||||
| 		Stat: func(s string) (os.FileInfo, error) { | ||||
| 			if strings.HasPrefix(s, "existing_file") { | ||||
| 				return TestFileInfo{mode: 0}, nil | ||||
| 			} | ||||
| 			if strings.HasPrefix(s, "existing_dir") { | ||||
| 				return TestFileInfo{mode: fs.ModeDir}, nil | ||||
| 			} | ||||
| 			return nil, errors.New("Error") | ||||
| 		}, | ||||
| 	} | ||||
| 	return *FromFileSystem(replaceffs) | ||||
| } | ||||
| 
 | ||||
| func TestFs_fileExistsDefault(t *testing.T) { | ||||
| 	ffs := NewTestFileSystem() | ||||
| 	var exists, _ = ffs.FileExists("existing_file.txt") | ||||
| 	if !exists { | ||||
| 		t.Errorf("Expected file %s, not found", "existing_file.txt") | ||||
| 	} | ||||
| 
 | ||||
| 	exists, _ = ffs.FileExists("non_existing_file.txt") | ||||
| 	if exists { | ||||
| 		t.Errorf("Not expected file %s, found", "non_existing_file.txt") | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestFs_fileExistsAtDefault(t *testing.T) { | ||||
| 	ffs := NewTestFileSystem() | ||||
| 
 | ||||
| 	var exists = ffs.FileExistsAt("existing_file.txt") | ||||
| 	if !exists { | ||||
| 		t.Errorf("Expected file %s, not found", "existing_file.txt") | ||||
| 	} | ||||
| 
 | ||||
| 	exists = ffs.FileExistsAt("non_existing_file.txt") | ||||
| 	if exists { | ||||
| 		t.Errorf("Not expected file %s, found", "non_existing_file.txt") | ||||
| 	} | ||||
| 
 | ||||
| 	exists = ffs.FileExistsAt("existing_dir") | ||||
| 	if exists { | ||||
| 		t.Errorf("Not expected file %s, found", "existing_dir") | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestFs_directoryExistsDefault(t *testing.T) { | ||||
| 	ffs := NewTestFileSystem() | ||||
| 	var exists = ffs.DirectoryExistsAt("existing_dir") | ||||
| 	if !exists { | ||||
| 		t.Errorf("Expected file %s, not found", "existing_dir") | ||||
| 	} | ||||
| 
 | ||||
| 	exists = ffs.DirectoryExistsAt("not_existing_dir") | ||||
| 	if exists { | ||||
| 		t.Errorf("Not expected file %s, found", "existing_dir") | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestFs_DefaultBuilder(t *testing.T) { | ||||
| 	ffs := DefaultFileSystem() | ||||
| 	if ffs.ReadFile == nil || | ||||
| 		ffs.ReadDir == nil || | ||||
| 		ffs.DeleteFile == nil || | ||||
| 		ffs.FileExists == nil || | ||||
| 		ffs.Glob == nil || | ||||
| 		ffs.FileExistsAt == nil || | ||||
| 		ffs.DirectoryExistsAt == nil || | ||||
| 		ffs.Stat == nil || | ||||
| 		ffs.Getwd == nil || | ||||
| 		ffs.Chdir == nil || | ||||
| 		ffs.Abs == nil { | ||||
| 		t.Errorf("Missing functions in DefaultFileSystem") | ||||
| 	} | ||||
| } | ||||
|  | @ -17,6 +17,7 @@ import ( | |||
| 	"gopkg.in/yaml.v2" | ||||
| 
 | ||||
| 	"github.com/helmfile/helmfile/pkg/envvar" | ||||
| 	"github.com/helmfile/helmfile/pkg/filesystem" | ||||
| ) | ||||
| 
 | ||||
| var disableInsecureFeatures bool | ||||
|  | @ -43,11 +44,9 @@ type Remote struct { | |||
| 	// Getter is the underlying implementation of getter used for fetching remote files
 | ||||
| 	Getter Getter | ||||
| 
 | ||||
| 	// ReadFile is the implementation of the file reader that reads a local file from the specified path.
 | ||||
| 	// Filesystem abstraction
 | ||||
| 	// Inject any implementation of your choice, like an im-memory impl for testing, os.ReadFile for the real-world use.
 | ||||
| 	ReadFile   func(string) ([]byte, error) | ||||
| 	DirExists  func(string) bool | ||||
| 	FileExists func(string) bool | ||||
| 	fs *filesystem.FileSystem | ||||
| } | ||||
| 
 | ||||
| func (r *Remote) Unmarshal(src string, dst interface{}) error { | ||||
|  | @ -87,7 +86,7 @@ func (r *Remote) GetBytes(goGetterSrc string) ([]byte, error) { | |||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	bytes, err := r.ReadFile(f) | ||||
| 	bytes, err := r.fs.ReadFile(f) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("read file: %v", err) | ||||
| 	} | ||||
|  | @ -99,7 +98,7 @@ func (r *Remote) GetBytes(goGetterSrc string) ([]byte, error) { | |||
| // If the argument was an URL, it fetches the remote directory contained within the URL,
 | ||||
| // and returns the path to the file in the fetched directory
 | ||||
| func (r *Remote) Locate(urlOrPath string) (string, error) { | ||||
| 	if r.FileExists(urlOrPath) || r.DirExists(urlOrPath) { | ||||
| 	if r.fs.FileExistsAt(urlOrPath) || r.fs.DirectoryExistsAt(urlOrPath) { | ||||
| 		return urlOrPath, nil | ||||
| 	} | ||||
| 	fetched, err := r.Fetch(urlOrPath) | ||||
|  | @ -217,11 +216,11 @@ func (r *Remote) Fetch(goGetterSrc string, cacheDirOpt ...string) (string, error | |||
| 	r.Logger.Debugf("cached dir: %s", cacheDirPath) | ||||
| 
 | ||||
| 	{ | ||||
| 		if r.FileExists(cacheDirPath) { | ||||
| 		if r.fs.FileExistsAt(cacheDirPath) { | ||||
| 			return "", fmt.Errorf("%s is not directory. please remove it so that variant could use it for dependency caching", getterDst) | ||||
| 		} | ||||
| 
 | ||||
| 		if r.DirExists(cacheDirPath) { | ||||
| 		if r.fs.DirectoryExistsAt(cacheDirPath) { | ||||
| 			cached = true | ||||
| 		} | ||||
| 	} | ||||
|  | @ -285,17 +284,15 @@ func (g *GoGetter) Get(wd, src, dst string) error { | |||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func NewRemote(logger *zap.SugaredLogger, homeDir string, readFile func(string) ([]byte, error), dirExists func(string) bool, fileExists func(string) bool) *Remote { | ||||
| func NewRemote(logger *zap.SugaredLogger, homeDir string, fs *filesystem.FileSystem) *Remote { | ||||
| 	if disableInsecureFeatures { | ||||
| 		panic("Remote sources are disabled due to 'DISABLE_INSECURE_FEATURES'") | ||||
| 	} | ||||
| 	remote := &Remote{ | ||||
| 		Logger:     logger, | ||||
| 		Home:       homeDir, | ||||
| 		Getter:     &GoGetter{Logger: logger}, | ||||
| 		ReadFile:   readFile, | ||||
| 		DirExists:  dirExists, | ||||
| 		FileExists: fileExists, | ||||
| 		Logger: logger, | ||||
| 		Home:   homeDir, | ||||
| 		Getter: &GoGetter{Logger: logger}, | ||||
| 		fs:     fs, | ||||
| 	} | ||||
| 
 | ||||
| 	if remote.Home == "" { | ||||
|  |  | |||
|  | @ -55,12 +55,10 @@ func TestRemote_HttpsGitHub(t *testing.T) { | |||
| 				get: get, | ||||
| 			} | ||||
| 			remote := &Remote{ | ||||
| 				Logger:     helmexec.NewLogger(os.Stderr, "debug"), | ||||
| 				Home:       CacheDir(), | ||||
| 				Getter:     getter, | ||||
| 				ReadFile:   testfs.ReadFile, | ||||
| 				FileExists: testfs.FileExistsAt, | ||||
| 				DirExists:  testfs.DirectoryExistsAt, | ||||
| 				Logger: helmexec.NewLogger(os.Stderr, "debug"), | ||||
| 				Home:   CacheDir(), | ||||
| 				Getter: getter, | ||||
| 				fs:     testfs.ToFileSystem(), | ||||
| 			} | ||||
| 
 | ||||
| 			// FYI, go-getter in the `dir` mode accepts URL like the below. So helmfile expects URLs similar to it:
 | ||||
|  | @ -133,12 +131,10 @@ func TestRemote_SShGitHub(t *testing.T) { | |||
| 				get: get, | ||||
| 			} | ||||
| 			remote := &Remote{ | ||||
| 				Logger:     helmexec.NewLogger(os.Stderr, "debug"), | ||||
| 				Home:       CacheDir(), | ||||
| 				Getter:     getter, | ||||
| 				ReadFile:   testfs.ReadFile, | ||||
| 				FileExists: testfs.FileExistsAt, | ||||
| 				DirExists:  testfs.DirectoryExistsAt, | ||||
| 				Logger: helmexec.NewLogger(os.Stderr, "debug"), | ||||
| 				Home:   CacheDir(), | ||||
| 				Getter: getter, | ||||
| 				fs:     testfs.ToFileSystem(), | ||||
| 			} | ||||
| 
 | ||||
| 			url := "git::ssh://git@github.com/cloudposse/helmfiles.git@releases/kiam.yaml?ref=0.40.0" | ||||
|  | @ -205,12 +201,10 @@ func TestRemote_SShGitHub_WithSshKey(t *testing.T) { | |||
| 				get: get, | ||||
| 			} | ||||
| 			remote := &Remote{ | ||||
| 				Logger:     helmexec.NewLogger(os.Stderr, "debug"), | ||||
| 				Home:       CacheDir(), | ||||
| 				Getter:     getter, | ||||
| 				ReadFile:   testfs.ReadFile, | ||||
| 				FileExists: testfs.FileExistsAt, | ||||
| 				DirExists:  testfs.DirectoryExistsAt, | ||||
| 				Logger: helmexec.NewLogger(os.Stderr, "debug"), | ||||
| 				Home:   CacheDir(), | ||||
| 				Getter: getter, | ||||
| 				fs:     testfs.ToFileSystem(), | ||||
| 			} | ||||
| 
 | ||||
| 			url := "git::ssh://git@github.com/cloudposse/helmfiles.git@releases/kiam.yaml?ref=0.40.0&sshkey=ZWNkc2Etc2hhMi1uaXN0cDI1NiBBQUFBRTJWalpITmhMWE5vWVRJdGJtbHpkSEF5TlRZQUFBQUlibWx6ZEhBeU5UWUFBQUJCQkJTU3dOY2xoVzQ2Vm9VR3dMQ3JscVRHYUdOVWdRVUVEUEptc1ZzdUViL2RBNUcrQk9YMWxGaUVMYU9HQ2F6bS9KQkR2V3Y2Y0ZDQUtVRjVocVJOUjdJPSA=" | ||||
|  |  | |||
|  | @ -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) | ||||
|  |  | |||
|  | @ -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 { | ||||
|  |  | |||
|  | @ -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) | ||||
|  |  | |||
|  | @ -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) | ||||
|  |  | |||
|  | @ -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
 | ||||
|  |  | |||
|  | @ -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:
 | ||||
|  |  | |||
|  | @ -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) | ||||
|  |  | |||
|  | @ -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) | ||||
|  |  | |||
|  | @ -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, | ||||
| 			} | ||||
| 
 | ||||
|  |  | |||
|  | @ -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) | ||||
|  |  | |||
|  | @ -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) | ||||
| 	} | ||||
|  |  | |||
|  | @ -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 { | ||||
|  |  | |||
|  | @ -5,6 +5,8 @@ import ( | |||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	ffs "github.com/helmfile/helmfile/pkg/filesystem" | ||||
| ) | ||||
| 
 | ||||
| type TestFs struct { | ||||
|  | @ -13,6 +15,7 @@ type TestFs struct { | |||
| 	files map[string]string | ||||
| 
 | ||||
| 	GlobFixtures map[string][]string | ||||
| 	DeleteFile   func(string) error | ||||
| 
 | ||||
| 	fileReaderCalls int | ||||
| 	successfulReads []string | ||||
|  | @ -34,9 +37,26 @@ func NewTestFs(files map[string]string) *TestFs { | |||
| 		successfulReads: []string{}, | ||||
| 
 | ||||
| 		GlobFixtures: map[string][]string{}, | ||||
| 		DeleteFile:   func(string) (ret error) { return }, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (f *TestFs) ToFileSystem() *ffs.FileSystem { | ||||
| 	curfs := ffs.FileSystem{ | ||||
| 		FileExistsAt:      f.FileExistsAt, | ||||
| 		FileExists:        f.FileExists, | ||||
| 		DirectoryExistsAt: f.DirectoryExistsAt, | ||||
| 		ReadFile:          f.ReadFile, | ||||
| 		Glob:              f.Glob, | ||||
| 		Getwd:             f.Getwd, | ||||
| 		Chdir:             f.Chdir, | ||||
| 		Abs:               f.Abs, | ||||
| 		DeleteFile:        f.DeleteFile, | ||||
| 	} | ||||
| 	trfs := ffs.FromFileSystem(curfs) | ||||
| 	return trfs | ||||
| } | ||||
| 
 | ||||
| func (f *TestFs) FileExistsAt(path string) bool { | ||||
| 	var ok bool | ||||
| 	if strings.HasPrefix(path, "/") { | ||||
|  |  | |||
|  | @ -1,12 +1,13 @@ | |||
| package tmpl | ||||
| 
 | ||||
| import "io/fs" | ||||
| import ( | ||||
| 	"github.com/helmfile/helmfile/pkg/filesystem" | ||||
| ) | ||||
| 
 | ||||
| type Context struct { | ||||
| 	preRender bool | ||||
| 	basePath  string | ||||
| 	readFile  func(string) ([]byte, error) | ||||
| 	readDir   func(string) ([]fs.DirEntry, error) | ||||
| 	fs        *filesystem.FileSystem | ||||
| } | ||||
| 
 | ||||
| // SetBasePath sets the base path for the template
 | ||||
|  | @ -14,10 +15,6 @@ func (c *Context) SetBasePath(path string) { | |||
| 	c.basePath = path | ||||
| } | ||||
| 
 | ||||
| func (c *Context) SetReadFile(f func(string) ([]byte, error)) { | ||||
| 	c.readFile = f | ||||
| } | ||||
| 
 | ||||
| func (c *Context) SetReadDir(f func(string) ([]fs.DirEntry, error)) { | ||||
| 	c.readDir = f | ||||
| func (c *Context) SetFileSystem(fs *filesystem.FileSystem) { | ||||
| 	c.fs = fs | ||||
| } | ||||
|  |  | |||
|  | @ -220,11 +220,11 @@ func (c *Context) ReadFile(filename string) (string, error) { | |||
| 		path = filepath.Join(c.basePath, filename) | ||||
| 	} | ||||
| 
 | ||||
| 	if c.readFile == nil { | ||||
| 	if c.fs.ReadFile == nil { | ||||
| 		return "", fmt.Errorf("readFile is not implemented") | ||||
| 	} | ||||
| 
 | ||||
| 	bytes, err := c.readFile(path) | ||||
| 	bytes, err := c.fs.ReadFile(path) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
|  | @ -239,7 +239,7 @@ func (c *Context) ReadDir(path string) ([]string, error) { | |||
| 		contextPath = filepath.Join(c.basePath, path) | ||||
| 	} | ||||
| 
 | ||||
| 	entries, err := c.readDir(contextPath) | ||||
| 	entries, err := c.fs.ReadDir(contextPath) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("ReadDir %q: %w", contextPath, err) | ||||
| 	} | ||||
|  | @ -262,7 +262,7 @@ func (c *Context) ReadDirEntries(path string) ([]fs.DirEntry, error) { | |||
| 	} else { | ||||
| 		contextPath = filepath.Join(c.basePath, path) | ||||
| 	} | ||||
| 	entries, err := c.readDir(contextPath) | ||||
| 	entries, err := c.fs.ReadDir(contextPath) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("ReadDirEntries %q: %w", contextPath, err) | ||||
| 	} | ||||
|  |  | |||
|  | @ -9,6 +9,8 @@ import ( | |||
| 	"testing" | ||||
| 
 | ||||
| 	"github.com/stretchr/testify/require" | ||||
| 
 | ||||
| 	"github.com/helmfile/helmfile/pkg/filesystem" | ||||
| ) | ||||
| 
 | ||||
| func TestCreateFuncMap(t *testing.T) { | ||||
|  | @ -62,17 +64,23 @@ func TestCreateFuncMap_SkipInsecureTemplateFunctions(t *testing.T) { | |||
| 	skipInsecureTemplateFunctions = currentVal | ||||
| } | ||||
| 
 | ||||
| func newFSExpecting(expectedFilename string, expected string) *filesystem.FileSystem { | ||||
| 	return filesystem.FromFileSystem(filesystem.FileSystem{ | ||||
| 		ReadFile: func(filename string) ([]byte, error) { | ||||
| 			if filename != expectedFilename { | ||||
| 				return nil, fmt.Errorf("unexpected filename: expected=%v, actual=%s", expectedFilename, filename) | ||||
| 			} | ||||
| 			return []byte(expected), nil | ||||
| 		}, | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| func TestReadFile(t *testing.T) { | ||||
| 	expected := `foo: | ||||
|   bar: BAR | ||||
| ` | ||||
| 	expectedFilename := "values.yaml" | ||||
| 	ctx := &Context{basePath: ".", readFile: func(filename string) ([]byte, error) { | ||||
| 		if filename != expectedFilename { | ||||
| 			return nil, fmt.Errorf("unexpected filename: expected=%v, actual=%s", expectedFilename, filename) | ||||
| 		} | ||||
| 		return []byte(expected), nil | ||||
| 	}} | ||||
| 	ctx := &Context{basePath: ".", fs: newFSExpecting(expectedFilename, expected)} | ||||
| 	actual, err := ctx.ReadFile(expectedFilename) | ||||
| 	require.NoError(t, err) | ||||
| 	require.Equal(t, expected, actual) | ||||
|  | @ -125,12 +133,12 @@ func TestReadDir(t *testing.T) { | |||
| 	} | ||||
| 
 | ||||
| 	expectedDirname := "sampleDirectory" | ||||
| 	ctx := &Context{basePath: ".", readDir: func(dirname string) ([]fs.DirEntry, error) { | ||||
| 	ctx := &Context{basePath: ".", fs: filesystem.FromFileSystem(filesystem.FileSystem{ReadDir: func(dirname string) ([]fs.DirEntry, error) { | ||||
| 		if dirname != expectedDirname { | ||||
| 			return nil, fmt.Errorf("unexpected filename: expected=%v, actual=%s", expectedDirname, dirname) | ||||
| 		} | ||||
| 		return result, nil | ||||
| 	}} | ||||
| 	}})} | ||||
| 
 | ||||
| 	actual, err := ctx.ReadDir(expectedDirname) | ||||
| 	require.NoError(t, err) | ||||
|  | @ -146,12 +154,12 @@ func TestReadDirEntries(t *testing.T) { | |||
| 	} | ||||
| 
 | ||||
| 	expectedDirname := "sampleDirectory" | ||||
| 	ctx := &Context{basePath: ".", readDir: func(dirname string) ([]fs.DirEntry, error) { | ||||
| 	ctx := &Context{basePath: ".", fs: filesystem.FromFileSystem(filesystem.FileSystem{ReadDir: func(dirname string) ([]fs.DirEntry, error) { | ||||
| 		if dirname != expectedDirname { | ||||
| 			return nil, fmt.Errorf("unexpected filename: expected=%v, actual=%s", expectedDirname, dirname) | ||||
| 		} | ||||
| 		return result, nil | ||||
| 	}} | ||||
| 	}})} | ||||
| 
 | ||||
| 	actual, err := ctx.ReadDirEntries(expectedDirname) | ||||
| 	require.NoError(t, err) | ||||
|  | @ -163,12 +171,7 @@ func TestReadFile_PassAbsPath(t *testing.T) { | |||
|   bar: BAR | ||||
| ` | ||||
| 	expectedFilename, _ := filepath.Abs("values.yaml") | ||||
| 	ctx := &Context{basePath: ".", readFile: func(filename string) ([]byte, error) { | ||||
| 		if filename != expectedFilename { | ||||
| 			return nil, fmt.Errorf("unexpected filename: expected=%v, actual=%s", expectedFilename, filename) | ||||
| 		} | ||||
| 		return []byte(expected), nil | ||||
| 	}} | ||||
| 	ctx := &Context{basePath: ".", fs: newFSExpecting(expectedFilename, expected)} | ||||
| 	actual, err := ctx.ReadFile(expectedFilename) | ||||
| 	require.NoError(t, err) | ||||
| 	require.Equal(t, actual, expected) | ||||
|  |  | |||
|  | @ -4,6 +4,8 @@ import ( | |||
| 	"fmt" | ||||
| 	"reflect" | ||||
| 	"testing" | ||||
| 
 | ||||
| 	ffs "github.com/helmfile/helmfile/pkg/filesystem" | ||||
| ) | ||||
| 
 | ||||
| func TestRenderTemplate_Values(t *testing.T) { | ||||
|  | @ -14,12 +16,12 @@ func TestRenderTemplate_Values(t *testing.T) { | |||
|   bar: FOO_BAR | ||||
| ` | ||||
| 	expectedFilename := "values.yaml" | ||||
| 	ctx := &Context{readFile: func(filename string) ([]byte, error) { | ||||
| 	ctx := &Context{fs: &ffs.FileSystem{ReadFile: func(filename string) ([]byte, error) { | ||||
| 		if filename != expectedFilename { | ||||
| 			return nil, fmt.Errorf("unexpected filename: expected=%v, actual=%s", expectedFilename, filename) | ||||
| 		} | ||||
| 		return []byte(valuesYamlContent), nil | ||||
| 	}} | ||||
| 	}}} | ||||
| 	buf, err := ctx.RenderTemplateToBuffer(`{{ readFile "values.yaml" | fromYaml | setValueAtPath "foo.bar" "FOO_BAR" | toYaml }}`) | ||||
| 	if err != nil { | ||||
| 		t.Errorf("unexpected error: %v", err) | ||||
|  | @ -43,12 +45,12 @@ func TestRenderTemplate_WithData(t *testing.T) { | |||
| 			"bar": "FOO_BAR", | ||||
| 		}, | ||||
| 	} | ||||
| 	ctx := &Context{readFile: func(filename string) ([]byte, error) { | ||||
| 	ctx := &Context{fs: &ffs.FileSystem{ReadFile: func(filename string) ([]byte, error) { | ||||
| 		if filename != expectedFilename { | ||||
| 			return nil, fmt.Errorf("unexpected filename: expected=%v, actual=%s", expectedFilename, filename) | ||||
| 		} | ||||
| 		return []byte(valuesYamlContent), nil | ||||
| 	}} | ||||
| 	}}} | ||||
| 	buf, err := ctx.RenderTemplateToBuffer(valuesYamlContent, data) | ||||
| 	if err != nil { | ||||
| 		t.Errorf("unexpected error: %v", err) | ||||
|  | @ -68,12 +70,12 @@ func TestRenderTemplate_AccessingMissingKeyWithGetOrNil(t *testing.T) { | |||
| ` | ||||
| 	expectedFilename := "values.yaml" | ||||
| 	data := map[string]interface{}{} | ||||
| 	ctx := &Context{readFile: func(filename string) ([]byte, error) { | ||||
| 	ctx := &Context{fs: &ffs.FileSystem{ReadFile: func(filename string) ([]byte, error) { | ||||
| 		if filename != expectedFilename { | ||||
| 			return nil, fmt.Errorf("unexpected filename: expected=%v, actual=%s", expectedFilename, filename) | ||||
| 		} | ||||
| 		return []byte(valuesYamlContent), nil | ||||
| 	}} | ||||
| 	}}} | ||||
| 	buf, err := ctx.RenderTemplateToBuffer(valuesYamlContent, data) | ||||
| 	if err != nil { | ||||
| 		t.Errorf("unexpected error: %v", err) | ||||
|  | @ -93,12 +95,12 @@ func TestRenderTemplate_Defaulting(t *testing.T) { | |||
| ` | ||||
| 	expectedFilename := "values.yaml" | ||||
| 	data := map[string]interface{}{} | ||||
| 	ctx := &Context{readFile: func(filename string) ([]byte, error) { | ||||
| 	ctx := &Context{fs: &ffs.FileSystem{ReadFile: func(filename string) ([]byte, error) { | ||||
| 		if filename != expectedFilename { | ||||
| 			return nil, fmt.Errorf("unexpected filename: expected=%v, actual=%s", expectedFilename, filename) | ||||
| 		} | ||||
| 		return []byte(valuesYamlContent), nil | ||||
| 	}} | ||||
| 	}}} | ||||
| 	buf, err := ctx.RenderTemplateToBuffer(valuesYamlContent, data) | ||||
| 	if err != nil { | ||||
| 		t.Errorf("unexpected error: %v", err) | ||||
|  | @ -110,9 +112,9 @@ func TestRenderTemplate_Defaulting(t *testing.T) { | |||
| } | ||||
| 
 | ||||
| func renderTemplateToString(s string, data ...interface{}) (string, error) { | ||||
| 	ctx := &Context{readFile: func(filename string) ([]byte, error) { | ||||
| 	ctx := &Context{fs: &ffs.FileSystem{ReadFile: func(filename string) ([]byte, error) { | ||||
| 		return nil, fmt.Errorf("unexpected call to readFile: filename=%s", filename) | ||||
| 	}} | ||||
| 	}}} | ||||
| 	tplString, err := ctx.RenderTemplateToBuffer(s, data...) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
|  |  | |||
|  | @ -3,43 +3,43 @@ package tmpl | |||
| import ( | ||||
| 	"bytes" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	"github.com/helmfile/helmfile/pkg/filesystem" | ||||
| ) | ||||
| 
 | ||||
| type FileRenderer struct { | ||||
| 	ReadFile func(string) ([]byte, error) | ||||
| 	Context  *Context | ||||
| 	Data     interface{} | ||||
| 	fs      *filesystem.FileSystem | ||||
| 	Context *Context | ||||
| 	Data    interface{} | ||||
| } | ||||
| 
 | ||||
| func NewFileRenderer(readFile func(filename string) ([]byte, error), basePath string, data interface{}) *FileRenderer { | ||||
| func NewFileRenderer(fs *filesystem.FileSystem, basePath string, data interface{}) *FileRenderer { | ||||
| 	return &FileRenderer{ | ||||
| 		ReadFile: readFile, | ||||
| 		fs: fs, | ||||
| 		Context: &Context{ | ||||
| 			basePath: basePath, | ||||
| 			readFile: readFile, | ||||
| 			readDir:  os.ReadDir, | ||||
| 			fs:       fs, | ||||
| 		}, | ||||
| 		Data: data, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func NewFirstPassRenderer(basePath string, data interface{}) *FileRenderer { | ||||
| 	fs := filesystem.DefaultFileSystem() | ||||
| 	return &FileRenderer{ | ||||
| 		ReadFile: os.ReadFile, | ||||
| 		fs: fs, | ||||
| 		Context: &Context{ | ||||
| 			preRender: true, | ||||
| 			basePath:  basePath, | ||||
| 			readFile:  os.ReadFile, | ||||
| 			readDir:   os.ReadDir, | ||||
| 			fs:        fs, | ||||
| 		}, | ||||
| 		Data: data, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (r *FileRenderer) RenderTemplateFileToBuffer(file string) (*bytes.Buffer, error) { | ||||
| 	content, err := r.ReadFile(file) | ||||
| 	content, err := r.fs.ReadFile(file) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | @ -60,7 +60,7 @@ func (r *FileRenderer) RenderToBytes(path string) ([]byte, error) { | |||
| 		yamlBytes = yamlBuf.Bytes() | ||||
| 	} else { | ||||
| 		var err error | ||||
| 		yamlBytes, err = r.ReadFile(path) | ||||
| 		yamlBytes, err = r.fs.ReadFile(path) | ||||
| 		if err != nil { | ||||
| 			return nil, fmt.Errorf("failed to load [%s]: %v", path, err) | ||||
| 		} | ||||
|  |  | |||
|  | @ -6,6 +6,7 @@ import ( | |||
| 	"testing" | ||||
| 
 | ||||
| 	"github.com/helmfile/helmfile/pkg/environment" | ||||
| 	"github.com/helmfile/helmfile/pkg/filesystem" | ||||
| ) | ||||
| 
 | ||||
| var emptyEnvTmplData = map[string]interface{}{ | ||||
|  | @ -23,7 +24,7 @@ func TestRenderToBytes_Gotmpl(t *testing.T) { | |||
| ` | ||||
| 	dataFile := "data.txt" | ||||
| 	valuesTmplFile := "values.yaml.gotmpl" | ||||
| 	r := NewFileRenderer(func(filename string) ([]byte, error) { | ||||
| 	r := NewFileRenderer(&filesystem.FileSystem{ReadFile: func(filename string) ([]byte, error) { | ||||
| 		switch filename { | ||||
| 		case valuesTmplFile: | ||||
| 			return []byte(valuesYamlTmplContent), nil | ||||
|  | @ -31,7 +32,7 @@ func TestRenderToBytes_Gotmpl(t *testing.T) { | |||
| 			return []byte(dataFileContent), nil | ||||
| 		} | ||||
| 		return nil, fmt.Errorf("unexpected filename: expected=%v or %v, actual=%s", dataFile, valuesTmplFile, filename) | ||||
| 	}, "", emptyEnvTmplData) | ||||
| 	}}, "", emptyEnvTmplData) | ||||
| 	buf, err := r.RenderToBytes(valuesTmplFile) | ||||
| 	if err != nil { | ||||
| 		t.Errorf("unexpected error: %v", err) | ||||
|  | @ -50,12 +51,12 @@ func TestRenderToBytes_Yaml(t *testing.T) { | |||
|   bar: '{{ readFile "data.txt" }}' | ||||
| ` | ||||
| 	valuesFile := "values.yaml" | ||||
| 	r := NewFileRenderer(func(filename string) ([]byte, error) { | ||||
| 	r := NewFileRenderer(&filesystem.FileSystem{ReadFile: func(filename string) ([]byte, error) { | ||||
| 		if filename == valuesFile { | ||||
| 			return []byte(valuesYamlContent), nil | ||||
| 		} | ||||
| 		return nil, fmt.Errorf("unexpected filename: expected=%v, actual=%s", valuesFile, filename) | ||||
| 	}, "", emptyEnvTmplData) | ||||
| 	}}, "", emptyEnvTmplData) | ||||
| 	buf, err := r.RenderToBytes(valuesFile) | ||||
| 	if err != nil { | ||||
| 		t.Errorf("unexpected error: %v", err) | ||||
|  |  | |||
|  | @ -1,5 +1,9 @@ | |||
| package tmpl | ||||
| 
 | ||||
| import ( | ||||
| 	"github.com/helmfile/helmfile/pkg/filesystem" | ||||
| ) | ||||
| 
 | ||||
| type templateTextRenderer struct { | ||||
| 	ReadText func(string) ([]byte, error) | ||||
| 	Context  *Context | ||||
|  | @ -11,12 +15,12 @@ type TextRenderer interface { | |||
| } | ||||
| 
 | ||||
| // nolint: golint
 | ||||
| func NewTextRenderer(readFile func(filename string) ([]byte, error), basePath string, data interface{}) *templateTextRenderer { | ||||
| func NewTextRenderer(fs *filesystem.FileSystem, basePath string, data interface{}) *templateTextRenderer { | ||||
| 	return &templateTextRenderer{ | ||||
| 		ReadText: readFile, | ||||
| 		ReadText: fs.ReadFile, | ||||
| 		Context: &Context{ | ||||
| 			basePath: basePath, | ||||
| 			readFile: readFile, | ||||
| 			fs:       fs, | ||||
| 		}, | ||||
| 		Data: data, | ||||
| 	} | ||||
|  |  | |||
|  | @ -1,10 +1,11 @@ | |||
| package tmpl | ||||
| 
 | ||||
| import ( | ||||
| 	"os" | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"github.com/stretchr/testify/require" | ||||
| 
 | ||||
| 	"github.com/helmfile/helmfile/pkg/filesystem" | ||||
| ) | ||||
| 
 | ||||
| // TestTextRenderer tests the text renderer.
 | ||||
|  | @ -12,7 +13,7 @@ func TestNewTextRenderer(t *testing.T) { | |||
| 	tData := map[string]interface{}{ | ||||
| 		"foo": "bar", | ||||
| 	} | ||||
| 	tr := NewTextRenderer(os.ReadFile, ".", tData) | ||||
| 	tr := NewTextRenderer(filesystem.DefaultFileSystem(), ".", tData) | ||||
| 	require.Equal(t, tData, tr.Data) | ||||
| 	require.Equal(t, ".", tr.Context.basePath) | ||||
| } | ||||
|  | @ -22,7 +23,7 @@ func TestTextRender(t *testing.T) { | |||
| 	tData := map[string]interface{}{ | ||||
| 		"foot": "bart", | ||||
| 	} | ||||
| 	tr := NewTextRenderer(os.ReadFile, ".", tData) | ||||
| 	tr := NewTextRenderer(filesystem.DefaultFileSystem(), ".", tData) | ||||
| 
 | ||||
| 	tests := []struct { | ||||
| 		text    string | ||||
|  |  | |||
|  | @ -9,6 +9,7 @@ import ( | |||
| 
 | ||||
| 	"github.com/stretchr/testify/require" | ||||
| 
 | ||||
| 	"github.com/helmfile/helmfile/pkg/filesystem" | ||||
| 	"github.com/helmfile/helmfile/pkg/tmpl" | ||||
| ) | ||||
| 
 | ||||
|  | @ -276,7 +277,7 @@ func TestFileRendering(t *testing.T) { | |||
| 
 | ||||
| 			filename := fmt.Sprintf("%s/%s.gotmpl", tempDir, tc.name) | ||||
| 			os.WriteFile(filename, []byte(tc.tmplString), 0644) | ||||
| 			fileRenderer := tmpl.NewFileRenderer(os.ReadFile, ".", tc.data) | ||||
| 			fileRenderer := tmpl.NewFileRenderer(filesystem.DefaultFileSystem(), ".", tc.data) | ||||
| 			tmpl_bytes, err := fileRenderer.RenderToBytes(filename) | ||||
| 
 | ||||
| 			if tc.wantErr { | ||||
|  | @ -294,8 +295,7 @@ func TestFileRendering(t *testing.T) { | |||
| func TestTmplStrings(t *testing.T) { | ||||
| 	c := &tmpl.Context{} | ||||
| 	c.SetBasePath(".") | ||||
| 	c.SetReadFile(os.ReadFile) | ||||
| 	c.SetReadDir(os.ReadDir) | ||||
| 	c.SetFileSystem(filesystem.DefaultFileSystem()) | ||||
| 	tmpl := template.New("stringTemplateTest").Funcs(c.CreateFuncMap()) | ||||
| 
 | ||||
| 	tmplE2eTest.load() | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue