mirror of
https://github.com/helmfile/helmfile.git
synced 2026-10-04 22:30:39 +02:00
* Adds feature to fetch environment values from remote The releases and environment section allow for values files on the local disk. This enhancement allows for referencing remote (go-getter) files to be fetched, cached and referenced. In addition when fetching a remote git source with a ssh key the ssh key will not be part of the caching folder name. This avoids two problems: 1. Don't leak sensitive information in the name of the caching folder 2. Base64 encoded SSH keys are very long. On some file systems the max lenght of the directory name is hit when using the full base64 information in the path name. The sshkey informations are reducted. Because of this fixed string there is a change of colloding cache names. The likelihood of this collision is very low. The git repo and git reference need to be the same, but the sshkey can change. This will result in the same source to be checkout out and referenced. Signed-off-by: Lüchinger Dominic <dev@snowgarden.ch> * Update pkg/state/storage.go Co-authored-by: Yusuke Kuoka <ykuoka@gmail.com>
312 lines
8.2 KiB
Go
312 lines
8.2 KiB
Go
package remote
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/google/go-cmp/cmp"
|
|
"github.com/helmfile/helmfile/pkg/helmexec"
|
|
"github.com/helmfile/helmfile/pkg/testhelper"
|
|
)
|
|
|
|
func TestRemote_HttpsGitHub(t *testing.T) {
|
|
cleanfs := map[string]string{
|
|
CacheDir(): "",
|
|
}
|
|
cachefs := map[string]string{
|
|
filepath.Join(CacheDir(), "https_github_com_cloudposse_helmfiles_git.ref=0.40.0/releases/kiam.yaml"): "foo: bar",
|
|
}
|
|
|
|
type testcase struct {
|
|
files map[string]string
|
|
expectCacheHit bool
|
|
}
|
|
|
|
testcases := []testcase{
|
|
{files: cleanfs, expectCacheHit: false},
|
|
{files: cachefs, expectCacheHit: true},
|
|
}
|
|
|
|
for i := range testcases {
|
|
testcase := testcases[i]
|
|
|
|
t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) {
|
|
testfs := testhelper.NewTestFs(testcase.files)
|
|
|
|
hit := true
|
|
|
|
get := func(wd, src, dst string) error {
|
|
if wd != CacheDir() {
|
|
return fmt.Errorf("unexpected wd: %s", wd)
|
|
}
|
|
if src != "git::https://github.com/cloudposse/helmfiles.git?ref=0.40.0" {
|
|
return fmt.Errorf("unexpected src: %s", src)
|
|
}
|
|
|
|
hit = false
|
|
|
|
return nil
|
|
}
|
|
|
|
getter := &testGetter{
|
|
get: get,
|
|
}
|
|
remote := &Remote{
|
|
Logger: helmexec.NewLogger(os.Stderr, "debug"),
|
|
Home: CacheDir(),
|
|
Getter: getter,
|
|
ReadFile: testfs.ReadFile,
|
|
FileExists: testfs.FileExistsAt,
|
|
DirExists: testfs.DirectoryExistsAt,
|
|
}
|
|
|
|
// FYI, go-getter in the `dir` mode accepts URL like the below. So helmfile expects URLs similar to it:
|
|
// go-getter -mode dir git::https://github.com/cloudposse/helmfiles.git?ref=0.40.0 gettertest1/b
|
|
|
|
// We use `@` to separate dir and the file path. This is a good idea borrowed from helm-git:
|
|
// https://github.com/aslafy-z/helm-git
|
|
|
|
url := "git::https://github.com/cloudposse/helmfiles.git@releases/kiam.yaml?ref=0.40.0"
|
|
file, err := remote.Locate(url)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
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 {
|
|
t.Errorf("unexpected result: unexpected cache miss")
|
|
}
|
|
if !testcase.expectCacheHit && hit {
|
|
t.Errorf("unexpected result: unexpected cache hit")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestRemote_SShGitHub(t *testing.T) {
|
|
cleanfs := map[string]string{
|
|
CacheDir(): "",
|
|
}
|
|
cachefs := map[string]string{
|
|
filepath.Join(CacheDir(), "ssh_github_com_cloudposse_helmfiles_git.ref=0.40.0/releases/kiam.yaml"): "foo: bar",
|
|
}
|
|
|
|
type testcase struct {
|
|
files map[string]string
|
|
expectCacheHit bool
|
|
}
|
|
|
|
testcases := []testcase{
|
|
{files: cleanfs, expectCacheHit: false},
|
|
{files: cachefs, expectCacheHit: true},
|
|
}
|
|
|
|
for i := range testcases {
|
|
testcase := testcases[i]
|
|
|
|
t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) {
|
|
testfs := testhelper.NewTestFs(testcase.files)
|
|
|
|
hit := true
|
|
|
|
get := func(wd, src, dst string) error {
|
|
if wd != CacheDir() {
|
|
return fmt.Errorf("unexpected wd: %s", wd)
|
|
}
|
|
if src != "git::ssh://git@github.com/cloudposse/helmfiles.git?ref=0.40.0" {
|
|
return fmt.Errorf("unexpected src: %s", src)
|
|
}
|
|
|
|
hit = false
|
|
|
|
return nil
|
|
}
|
|
|
|
getter := &testGetter{
|
|
get: get,
|
|
}
|
|
remote := &Remote{
|
|
Logger: helmexec.NewLogger(os.Stderr, "debug"),
|
|
Home: CacheDir(),
|
|
Getter: getter,
|
|
ReadFile: testfs.ReadFile,
|
|
FileExists: testfs.FileExistsAt,
|
|
DirExists: testfs.DirectoryExistsAt,
|
|
}
|
|
|
|
url := "git::ssh://git@github.com/cloudposse/helmfiles.git@releases/kiam.yaml?ref=0.40.0"
|
|
file, err := remote.Locate(url)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
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 {
|
|
t.Errorf("unexpected result: unexpected cache miss")
|
|
}
|
|
if !testcase.expectCacheHit && hit {
|
|
t.Errorf("unexpected result: unexpected cache hit")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestRemote_SShGitHub_WithSshKey(t *testing.T) {
|
|
cleanfs := map[string]string{
|
|
CacheDir(): "",
|
|
}
|
|
cachefs := map[string]string{
|
|
filepath.Join(CacheDir(), "ssh_github_com_cloudposse_helmfiles_git.ref=0.40.0_sshkey=redacted/releases/kiam.yaml"): "foo: bar",
|
|
}
|
|
|
|
type testcase struct {
|
|
files map[string]string
|
|
expectCacheHit bool
|
|
}
|
|
|
|
testcases := []testcase{
|
|
{files: cleanfs, expectCacheHit: false},
|
|
{files: cachefs, expectCacheHit: true},
|
|
}
|
|
|
|
for i := range testcases {
|
|
testcase := testcases[i]
|
|
|
|
t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) {
|
|
testfs := testhelper.NewTestFs(testcase.files)
|
|
|
|
hit := true
|
|
|
|
get := func(wd, src, dst string) error {
|
|
if wd != CacheDir() {
|
|
return fmt.Errorf("unexpected wd: %s", wd)
|
|
}
|
|
if src != "git::ssh://git@github.com/cloudposse/helmfiles.git?ref=0.40.0&sshkey=ZWNkc2Etc2hhMi1uaXN0cDI1NiBBQUFBRTJWalpITmhMWE5vWVRJdGJtbHpkSEF5TlRZQUFBQUlibWx6ZEhBeU5UWUFBQUJCQkJTU3dOY2xoVzQ2Vm9VR3dMQ3JscVRHYUdOVWdRVUVEUEptc1ZzdUViL2RBNUcrQk9YMWxGaUVMYU9HQ2F6bS9KQkR2V3Y2Y0ZDQUtVRjVocVJOUjdJPSA=" {
|
|
return fmt.Errorf("unexpected src: %s", src)
|
|
}
|
|
|
|
hit = false
|
|
|
|
return nil
|
|
}
|
|
|
|
getter := &testGetter{
|
|
get: get,
|
|
}
|
|
remote := &Remote{
|
|
Logger: helmexec.NewLogger(os.Stderr, "debug"),
|
|
Home: CacheDir(),
|
|
Getter: getter,
|
|
ReadFile: testfs.ReadFile,
|
|
FileExists: testfs.FileExistsAt,
|
|
DirExists: testfs.DirectoryExistsAt,
|
|
}
|
|
|
|
url := "git::ssh://git@github.com/cloudposse/helmfiles.git@releases/kiam.yaml?ref=0.40.0&sshkey=ZWNkc2Etc2hhMi1uaXN0cDI1NiBBQUFBRTJWalpITmhMWE5vWVRJdGJtbHpkSEF5TlRZQUFBQUlibWx6ZEhBeU5UWUFBQUJCQkJTU3dOY2xoVzQ2Vm9VR3dMQ3JscVRHYUdOVWdRVUVEUEptc1ZzdUViL2RBNUcrQk9YMWxGaUVMYU9HQ2F6bS9KQkR2V3Y2Y0ZDQUtVRjVocVJOUjdJPSA="
|
|
file, err := remote.Locate(url)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
expectedFile := filepath.Join(CacheDir(), "ssh_github_com_cloudposse_helmfiles_git.ref=0.40.0_sshkey=redacted/releases/kiam.yaml")
|
|
if file != expectedFile {
|
|
t.Errorf("unexpected file located: %s vs expected: %s", file, expectedFile)
|
|
}
|
|
|
|
if testcase.expectCacheHit && !hit {
|
|
t.Errorf("unexpected result: unexpected cache miss")
|
|
}
|
|
if !testcase.expectCacheHit && hit {
|
|
t.Errorf("unexpected result: unexpected cache hit")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestParse(t *testing.T) {
|
|
type testcase struct {
|
|
input string
|
|
getter, scheme, dir, file, query string
|
|
err string
|
|
}
|
|
|
|
testcases := []testcase{
|
|
{
|
|
input: "raw/incubator",
|
|
err: "parse url: missing scheme - probably this is a local file path? raw/incubator",
|
|
},
|
|
{
|
|
input: "git::https://github.com/stakater/Forecastle.git@deployments/kubernetes/chart/forecastle?ref=v1.0.54",
|
|
getter: "git",
|
|
scheme: "https",
|
|
dir: "/stakater/Forecastle.git",
|
|
file: "deployments/kubernetes/chart/forecastle",
|
|
query: "ref=v1.0.54",
|
|
},
|
|
}
|
|
|
|
for i := range testcases {
|
|
tc := testcases[i]
|
|
|
|
t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) {
|
|
src, err := Parse(tc.input)
|
|
|
|
var errMsg string
|
|
if err != nil {
|
|
errMsg = err.Error()
|
|
}
|
|
|
|
if diff := cmp.Diff(tc.err, errMsg); diff != "" {
|
|
t.Fatalf("Unexpected error:\n%s", diff)
|
|
}
|
|
|
|
var getter, scheme, dir, file, query string
|
|
if src != nil {
|
|
getter = src.Getter
|
|
scheme = src.Scheme
|
|
dir = src.Dir
|
|
file = src.File
|
|
query = src.RawQuery
|
|
}
|
|
|
|
if diff := cmp.Diff(tc.getter, getter); diff != "" {
|
|
t.Fatalf("Unexpected getter:\n%s", diff)
|
|
}
|
|
|
|
if diff := cmp.Diff(tc.scheme, scheme); diff != "" {
|
|
t.Fatalf("Unexpected scheme:\n%s", diff)
|
|
}
|
|
|
|
if diff := cmp.Diff(tc.file, file); diff != "" {
|
|
t.Fatalf("Unexpected file:\n%s", diff)
|
|
}
|
|
|
|
if diff := cmp.Diff(tc.dir, dir); diff != "" {
|
|
t.Fatalf("Unexpected dir:\n%s", diff)
|
|
}
|
|
|
|
if diff := cmp.Diff(tc.query, query); diff != "" {
|
|
t.Fatalf("Unexpected query:\n%s", diff)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
type testGetter struct {
|
|
get func(wd, src, dst string) error
|
|
}
|
|
|
|
func (t *testGetter) Get(wd, src, dst string) error {
|
|
return t.get(wd, src, dst)
|
|
}
|