diff --git a/pkg/remote/remote.go b/pkg/remote/remote.go index 94721586..d50b6028 100644 --- a/pkg/remote/remote.go +++ b/pkg/remote/remote.go @@ -4,23 +4,37 @@ import ( "context" "encoding/json" "fmt" + "os" + "path/filepath" + "strings" + "github.com/hashicorp/go-getter" "github.com/hashicorp/go-getter/helper/url" "go.uber.org/multierr" "go.uber.org/zap" "gopkg.in/yaml.v2" - "os" - "path/filepath" - "strings" ) -const DefaultCacheDir = ".helmfile/cache" +const defaultCacheDir = "helmfile" + +func cacheDir() string { + dir, err := os.UserCacheDir() + if err != nil { + // fall back to relative path with hidden directory + return relativeCacheDir() + } + return filepath.Join(dir, defaultCacheDir) +} + +// TODO remove this function when rework on caching of remote helmfiles +func relativeCacheDir() string { + return fmt.Sprintf(".%s", defaultCacheDir) +} type Remote struct { Logger *zap.SugaredLogger - // Home is the home directory for helmfile. Usually this points to $HOME of the user running helmfile. - // Helmfile saves fetched remote files into .helmfile/cache under home + // Home is the directory in which remote downloads files. If empty, user cache directory is used Home string // Getter is the underlying implementation of getter used for fetching remote files @@ -166,7 +180,7 @@ func (r *Remote) Fetch(goGetterSrc string, cacheDirOpt ...string) (string, error r.Logger.Debugf("file: %s", u.File) // This should be shared across variant commands, so that they can share cache for the shared imports - cacheBaseDir := DefaultCacheDir + cacheBaseDir := "" if len(cacheDirOpt) == 1 { cacheBaseDir = cacheDirOpt[0] } else if len(cacheDirOpt) > 0 { @@ -187,10 +201,10 @@ func (r *Remote) Fetch(goGetterSrc string, cacheDirOpt ...string) (string, error cached := false - // e.g. .helmfile/cache/https_github_com_cloudposse_helmfiles_git.ref=0.xx.0 + // e.g. https_github_com_cloudposse_helmfiles_git.ref=0.xx.0 getterDst := filepath.Join(cacheBaseDir, cacheKey) - // e.g. $PWD/.helmfile/cache/https_github_com_cloudposse_helmfiles_git.ref=0.xx.0 + // e.g. os.cacheDir()/helmfile/https_github_com_cloudposse_helmfiles_git.ref=0.xx.0 cacheDirPath := filepath.Join(r.Home, getterDst) r.Logger.Debugf("home: %s", r.Home) @@ -275,5 +289,14 @@ func NewRemote(logger *zap.SugaredLogger, homeDir string, readFile func(string) DirExists: dirExists, FileExists: fileExists, } + + if remote.Home == "" { + // Use for remote charts + remote.Home = cacheDir() + } else { + // Use for remote helmfiles, this case Home is relative to the processing file + remote.Home = filepath.Join(remote.Home, relativeCacheDir()) + } + return remote } diff --git a/pkg/remote/remote_test.go b/pkg/remote/remote_test.go index 70186c9b..d6f8b620 100644 --- a/pkg/remote/remote_test.go +++ b/pkg/remote/remote_test.go @@ -3,6 +3,7 @@ package remote import ( "fmt" "os" + "path/filepath" "testing" "github.com/google/go-cmp/cmp" @@ -12,10 +13,10 @@ import ( func TestRemote_HttpsGitHub(t *testing.T) { cleanfs := map[string]string{ - "/path/to/home": "", + cacheDir(): "", } cachefs := map[string]string{ - "/path/to/home/.helmfile/cache/https_github_com_cloudposse_helmfiles_git.ref=0.40.0/releases/kiam.yaml": "foo: bar", + filepath.Join(cacheDir(), "https_github_com_cloudposse_helmfiles_git.ref=0.40.0/releases/kiam.yaml"): "foo: bar", } type testcase struct { @@ -37,7 +38,7 @@ func TestRemote_HttpsGitHub(t *testing.T) { hit := true get := func(wd, src, dst string) error { - if wd != "/path/to/home" { + if wd != cacheDir() { return fmt.Errorf("unexpected wd: %s", wd) } if src != "git::https://github.com/cloudposse/helmfiles.git?ref=0.40.0" { @@ -54,7 +55,7 @@ func TestRemote_HttpsGitHub(t *testing.T) { } remote := &Remote{ Logger: helmexec.NewLogger(os.Stderr, "debug"), - Home: "/path/to/home", + Home: cacheDir(), Getter: getter, ReadFile: testfs.ReadFile, FileExists: testfs.FileExistsAt, @@ -73,8 +74,9 @@ func TestRemote_HttpsGitHub(t *testing.T) { t.Fatalf("unexpected error: %v", err) } - if file != "/path/to/home/.helmfile/cache/https_github_com_cloudposse_helmfiles_git.ref=0.40.0/releases/kiam.yaml" { - t.Errorf("unexpected file located: %s", file) + expectedFile := filepath.Join(cacheDir(), "https_github_com_cloudposse_helmfiles_git.ref=0.40.0/releases/kiam.yaml") + if file != expectedFile { + t.Errorf("unexpected file located: %s vs expected: %s", file, expectedFile) } if testcase.expectCacheHit && !hit { @@ -89,10 +91,10 @@ func TestRemote_HttpsGitHub(t *testing.T) { func TestRemote_SShGitHub(t *testing.T) { cleanfs := map[string]string{ - "/path/to/home": "", + cacheDir(): "", } cachefs := map[string]string{ - "/path/to/home/.helmfile/cache/ssh_github_com_cloudposse_helmfiles_git.ref=0.40.0/releases/kiam.yaml": "foo: bar", + filepath.Join(cacheDir(), "ssh_github_com_cloudposse_helmfiles_git.ref=0.40.0/releases/kiam.yaml"): "foo: bar", } type testcase struct { @@ -114,7 +116,7 @@ func TestRemote_SShGitHub(t *testing.T) { hit := true get := func(wd, src, dst string) error { - if wd != "/path/to/home" { + if wd != cacheDir() { return fmt.Errorf("unexpected wd: %s", wd) } if src != "git::ssh://git@github.com/cloudposse/helmfiles.git?ref=0.40.0" { @@ -131,7 +133,7 @@ func TestRemote_SShGitHub(t *testing.T) { } remote := &Remote{ Logger: helmexec.NewLogger(os.Stderr, "debug"), - Home: "/path/to/home", + Home: cacheDir(), Getter: getter, ReadFile: testfs.ReadFile, FileExists: testfs.FileExistsAt, @@ -144,8 +146,9 @@ func TestRemote_SShGitHub(t *testing.T) { t.Fatalf("unexpected error: %v", err) } - if file != "/path/to/home/.helmfile/cache/ssh_github_com_cloudposse_helmfiles_git.ref=0.40.0/releases/kiam.yaml" { - t.Errorf("unexpected file located: %s", file) + expectedFile := filepath.Join(cacheDir(), "ssh_github_com_cloudposse_helmfiles_git.ref=0.40.0/releases/kiam.yaml") + if file != expectedFile { + t.Errorf("unexpected file located: %s vs expected: %s", file, expectedFile) } if testcase.expectCacheHit && !hit { diff --git a/pkg/state/helmx.go b/pkg/state/helmx.go index 3dcc7872..a69e3c18 100644 --- a/pkg/state/helmx.go +++ b/pkg/state/helmx.go @@ -40,9 +40,7 @@ type Chartify struct { } func (st *HelmState) downloadChartWithGoGetter(r *ReleaseSpec) (string, error) { - pathElems := []string{ - remote.DefaultCacheDir, - } + var pathElems []string if r.Namespace != "" { pathElems = append(pathElems, r.Namespace) @@ -70,7 +68,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.basePath, st.readFile, directoryExistsAt, fileExistsAt) + r := remote.NewRemote(st.logger, "", st.readFile, directoryExistsAt, fileExistsAt) fetchedDir, err := r.Fetch(chart, cacheDir) if err != nil {