parent
4d7fcd846e
commit
2710cb382f
|
|
@ -2,6 +2,7 @@ package remote
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
"github.com/roboll/helmfile/pkg/helmexec"
|
"github.com/roboll/helmfile/pkg/helmexec"
|
||||||
"github.com/roboll/helmfile/pkg/testhelper"
|
"github.com/roboll/helmfile/pkg/testhelper"
|
||||||
"os"
|
"os"
|
||||||
|
|
@ -156,6 +157,75 @@ func TestRemote_SShGitHub(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
type testGetter struct {
|
||||||
get func(wd, src, dst string) error
|
get func(wd, src, dst string) error
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,11 +36,34 @@ func directoryExistsAt(path string) bool {
|
||||||
|
|
||||||
type Chartify struct {
|
type Chartify struct {
|
||||||
Opts *chartify.ChartifyOpts
|
Opts *chartify.ChartifyOpts
|
||||||
Chart string
|
|
||||||
Clean func()
|
Clean func()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *HelmState) PrepareChartify(helm helmexec.Interface, release *ReleaseSpec, workerIndex int) (*Chartify, func(), error) {
|
func (st *HelmState) goGetterChart(chart, dir string, force bool) (string, error) {
|
||||||
|
if dir != "" && chart == "" {
|
||||||
|
chart = dir
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := remote.Parse(chart)
|
||||||
|
if err != nil {
|
||||||
|
if force {
|
||||||
|
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)
|
||||||
|
|
||||||
|
fetchedDir, err := r.Fetch(chart)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("fetching %q: %v", chart, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
chart = fetchedDir
|
||||||
|
}
|
||||||
|
|
||||||
|
return chart, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (st *HelmState) PrepareChartify(helm helmexec.Interface, release *ReleaseSpec, chart string, workerIndex int) (*Chartify, func(), error) {
|
||||||
chartify := &Chartify{
|
chartify := &Chartify{
|
||||||
Opts: &chartify.ChartifyOpts{
|
Opts: &chartify.ChartifyOpts{
|
||||||
WorkaroundOutputDirIssue: true,
|
WorkaroundOutputDirIssue: true,
|
||||||
|
|
@ -58,31 +81,6 @@ func (st *HelmState) PrepareChartify(helm helmexec.Interface, release *ReleaseSp
|
||||||
|
|
||||||
var shouldRun bool
|
var shouldRun bool
|
||||||
|
|
||||||
chart := release.Chart
|
|
||||||
if release.Directory != "" && chart == "" {
|
|
||||||
chart = release.Directory
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := remote.Parse(chart)
|
|
||||||
if err != nil {
|
|
||||||
if release.ForceGoGetter {
|
|
||||||
return nil, clean, fmt.Errorf("Parsing url from directory of release %q failed due to error %q.\nContinuing the process assuming this is a regular Helm chart or a local directory.", release.Name, err.Error())
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
r := remote.NewRemote(st.logger, st.basePath, st.readFile, directoryExistsAt, fileExistsAt)
|
|
||||||
|
|
||||||
fetchedDir, err := r.Fetch(chart)
|
|
||||||
if err != nil {
|
|
||||||
return nil, clean, fmt.Errorf("fetching %q: %v", chart, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
chart = fetchedDir
|
|
||||||
|
|
||||||
filesNeedCleaning = append(filesNeedCleaning, fetchedDir)
|
|
||||||
}
|
|
||||||
|
|
||||||
chartify.Chart = chart
|
|
||||||
|
|
||||||
dir := filepath.Join(st.basePath, chart)
|
dir := filepath.Join(st.basePath, chart)
|
||||||
if stat, _ := os.Stat(dir); stat != nil && stat.IsDir() {
|
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.fileExists(filepath.Join(dir, "Chart.yaml")); err == nil && !exists {
|
||||||
|
|
|
||||||
|
|
@ -859,9 +859,15 @@ func (st *HelmState) PrepareCharts(helm helmexec.Interface, dir string, concurre
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var chartPath string
|
chartName := release.Chart
|
||||||
|
|
||||||
chartification, clean, err := st.PrepareChartify(helm, release, workerIndex)
|
chartPath, err := st.goGetterChart(chartName, release.Directory, release.ForceGoGetter)
|
||||||
|
if err != nil {
|
||||||
|
results <- &downloadResults{err: fmt.Errorf("release %q: %w", release.Name, err)}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
chartification, clean, err := st.PrepareChartify(helm, release, chartPath, workerIndex)
|
||||||
defer clean()
|
defer clean()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
results <- &downloadResults{err: err}
|
results <- &downloadResults{err: err}
|
||||||
|
|
@ -874,7 +880,7 @@ func (st *HelmState) PrepareCharts(helm helmexec.Interface, dir string, concurre
|
||||||
chartify.UseHelm3(helm3),
|
chartify.UseHelm3(helm3),
|
||||||
)
|
)
|
||||||
|
|
||||||
out, err := c.Chartify(release.Name, chartification.Chart, chartify.WithChartifyOpts(chartification.Opts))
|
out, err := c.Chartify(release.Name, chartPath, chartify.WithChartifyOpts(chartification.Opts))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
results <- &downloadResults{err: err}
|
results <- &downloadResults{err: err}
|
||||||
return
|
return
|
||||||
|
|
@ -883,9 +889,14 @@ func (st *HelmState) PrepareCharts(helm helmexec.Interface, dir string, concurre
|
||||||
chartPath = out
|
chartPath = out
|
||||||
}
|
}
|
||||||
} else if !forceDownload {
|
} else if !forceDownload {
|
||||||
chartPath = release.Chart
|
// At this point, we are sure that either:
|
||||||
} else if pathExists(normalizeChart(st.basePath, release.Chart)) {
|
// 1. It is a local chart and we can use it in later process (helm upgrade/template/lint/etc)
|
||||||
chartPath = normalizeChart(st.basePath, release.Chart)
|
// without any modification, or
|
||||||
|
// 2. It is a remote chart which can be safely handed over to helm,
|
||||||
|
// because the version of Helm used in this transaction support downloading the chart instead,
|
||||||
|
// and we don't need any modification to the chart
|
||||||
|
} else if pathExists(normalizeChart(st.basePath, chartPath)) {
|
||||||
|
chartPath = normalizeChart(st.basePath, chartPath)
|
||||||
|
|
||||||
if !skipDeps {
|
if !skipDeps {
|
||||||
if err := helm.BuildDeps(release.Name, chartPath); err != nil {
|
if err := helm.BuildDeps(release.Name, chartPath); err != nil {
|
||||||
|
|
@ -914,7 +925,7 @@ func (st *HelmState) PrepareCharts(helm helmexec.Interface, dir string, concurre
|
||||||
fetchFlags = append(fetchFlags, "--version", release.Version)
|
fetchFlags = append(fetchFlags, "--version", release.Version)
|
||||||
}
|
}
|
||||||
|
|
||||||
pathElems = append(pathElems, release.Name, release.Chart, chartVersion)
|
pathElems = append(pathElems, release.Name, chartName, chartVersion)
|
||||||
|
|
||||||
chartPath = path.Join(pathElems...)
|
chartPath = path.Join(pathElems...)
|
||||||
|
|
||||||
|
|
@ -925,7 +936,7 @@ func (st *HelmState) PrepareCharts(helm helmexec.Interface, dir string, concurre
|
||||||
// only fetch chart if it is not already fetched
|
// only fetch chart if it is not already fetched
|
||||||
if _, err := os.Stat(chartPath); os.IsNotExist(err) {
|
if _, err := os.Stat(chartPath); os.IsNotExist(err) {
|
||||||
fetchFlags = append(fetchFlags, "--untar", "--untardir", chartPath)
|
fetchFlags = append(fetchFlags, "--untar", "--untardir", chartPath)
|
||||||
if err := helm.Fetch(release.Chart, fetchFlags...); err != nil {
|
if err := helm.Fetch(chartName, fetchFlags...); err != nil {
|
||||||
results <- &downloadResults{err: err}
|
results <- &downloadResults{err: err}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
package state
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
|
"github.com/roboll/helmfile/pkg/helmexec"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGoGetter(t *testing.T) {
|
||||||
|
logger := helmexec.NewLogger(os.Stderr, "warn")
|
||||||
|
|
||||||
|
testcases := []struct {
|
||||||
|
chart, dir string
|
||||||
|
force bool
|
||||||
|
|
||||||
|
out, err string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
chart: "raw/incubator",
|
||||||
|
dir: "",
|
||||||
|
force: false,
|
||||||
|
out: "raw/incubator",
|
||||||
|
err: "",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tc := range testcases {
|
||||||
|
t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) {
|
||||||
|
d, err := ioutil.TempDir("", "testgogetter")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(d)
|
||||||
|
|
||||||
|
st := &HelmState{
|
||||||
|
logger: logger,
|
||||||
|
readFile: ioutil.ReadFile,
|
||||||
|
basePath: d,
|
||||||
|
}
|
||||||
|
|
||||||
|
out, err := st.goGetterChart(tc.chart, tc.dir, false)
|
||||||
|
|
||||||
|
if diff := cmp.Diff(tc.out, out); diff != "" {
|
||||||
|
t.Fatalf("Unexpected out:\n%s", diff)
|
||||||
|
}
|
||||||
|
|
||||||
|
var errMsg string
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
errMsg = err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
if diff := cmp.Diff(tc.err, errMsg); diff != "" {
|
||||||
|
t.Fatalf("Unexpected err:\n%s", diff)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue