From e8a7e23d4d7d52089779e5dd2c8125c11bdfe07a Mon Sep 17 00:00:00 2001 From: Tsubasa Nagasawa Date: Sun, 18 Sep 2022 17:17:08 +0900 Subject: [PATCH] chore: add e2e test case for helm template with oci based helm chart Signed-off-by: Tsubasa Nagasawa --- test/e2e/template/helmfile/snapshot_test.go | 70 ++++++++++++++++++- .../snapshot/oci_chart_pull/config.yaml | 6 ++ .../snapshot/oci_chart_pull/input.yaml | 19 +++++ .../snapshot/oci_chart_pull/output.yaml | 15 ++++ 4 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 test/e2e/template/helmfile/testdata/snapshot/oci_chart_pull/config.yaml create mode 100644 test/e2e/template/helmfile/testdata/snapshot/oci_chart_pull/input.yaml create mode 100644 test/e2e/template/helmfile/testdata/snapshot/oci_chart_pull/output.yaml diff --git a/test/e2e/template/helmfile/snapshot_test.go b/test/e2e/template/helmfile/snapshot_test.go index eb565f79..cc94e0c3 100644 --- a/test/e2e/template/helmfile/snapshot_test.go +++ b/test/e2e/template/helmfile/snapshot_test.go @@ -1,6 +1,7 @@ package helmfile import ( + "bufio" "context" "fmt" "os" @@ -16,6 +17,12 @@ import ( "gopkg.in/yaml.v3" ) +type ociChart struct { + name string + version string + digest string +} + func TestHelmfileTemplateWithBuildCommand(t *testing.T) { type Config struct { LocalDockerRegistry struct { @@ -95,6 +102,8 @@ func TestHelmfileTemplateWithBuildCommand(t *testing.T) { } }) + // ociCharts holds a list of chart name, version and digest distributed by local oci registry. + ociCharts := []ociChart{} // If localDockerRegistry.enabled is set to `true`, // run the docker registry v2 and push the test charts to the registry // so that it can be accessed by helm and helmfile as a oci registry based chart repository. @@ -126,7 +135,20 @@ func TestHelmfileTemplateWithBuildCommand(t *testing.T) { t.Fatalf("%s is not a directory", c) } tgzFile := execHelmPackage(t, chartPath) - _ = execHelm(t, "push", tgzFile, fmt.Sprintf("oci://localhost:%d/myrepo", hostPort)) + + // Extract chart version from the name of chart package archival + chartName := c.Name() + chartNameWithVersion := strings.TrimSuffix(filepath.Base(tgzFile), filepath.Ext(tgzFile)) + chartVersion := strings.TrimPrefix(chartNameWithVersion, fmt.Sprintf("%s-", chartName)) + + chartDigest, err := execHelmPush(t, tgzFile, fmt.Sprintf("oci://localhost:%d/myrepo", hostPort)) + require.NoError(t, err, "Unable to run helm push to local registry: %v", err) + + ociCharts = append(ociCharts, ociChart{ + name: chartName, + version: chartVersion, + digest: chartDigest, + }) } } @@ -155,6 +177,37 @@ func TestHelmfileTemplateWithBuildCommand(t *testing.T) { gotStr := string(got) gotStr = strings.ReplaceAll(gotStr, fmt.Sprintf("chart=%s", wd), "chart=$WD") + // OCI based helm charts are pulled and exported under temporary directory. + // We are not sure the exact name of the temporary directory generated by helmfile, + // so redact its base directory name with $TMP. + if config.LocalDockerRegistry.Enabled { + var releaseName, chartPath string + sc := bufio.NewScanner(strings.NewReader(gotStr)) + for sc.Scan() { + if !strings.HasPrefix(sc.Text(), "Templating ") { + continue + } + releaseChartStr := strings.TrimPrefix(sc.Text(), "Templating ") + releaseChartParts := strings.Split(releaseChartStr, ", ") + if len(releaseChartParts) != 2 { + t.Fatal("Found unexpected log output of templating oci based helm chart, want=\"Templating release=, chart=\"") + } + releaseNamePart, chartPathPart := releaseChartParts[0], releaseChartParts[1] + releaseName = strings.TrimPrefix(releaseNamePart, "release=") + chartPath = chartPathPart + } + for _, ociChart := range ociCharts { + chartPathWithoutTempDirBase := fmt.Sprintf("/%s/%s/%s/%s", releaseName, ociChart.name, ociChart.version, ociChart.name) + var chartPathBase string + if strings.HasSuffix(chartPath, chartPathWithoutTempDirBase) { + chartPathBase = strings.TrimSuffix(chartPath, chartPathWithoutTempDirBase) + } + if len(chartPathBase) != 0 { + gotStr = strings.ReplaceAll(gotStr, chartPathBase, "chart=$TMP") + } + gotStr = strings.ReplaceAll(gotStr, fmt.Sprintf("Digest: %s", ociChart.digest), "Digest: $DIGEST") + } + } if stat, _ := os.Stat(outputFile); stat != nil { want, err := os.ReadFile(outputFile) @@ -191,6 +244,21 @@ func execHelmPackage(t *testing.T, localChart string) string { return strings.TrimSpace(tgzAbsPath) } +// execHelmPush pushes helm package to oci based helm repository, +// then returns its digest. +func execHelmPush(t *testing.T, tgzPath, remoteUrl string) (string, error) { + t.Helper() + + out := execHelm(t, "push", tgzPath, remoteUrl) + sc := bufio.NewScanner(strings.NewReader(out)) + for sc.Scan() { + if strings.HasPrefix(sc.Text(), "Digest:") { + return strings.TrimPrefix(sc.Text(), "Digest: "), nil + } + } + return "", fmt.Errorf("Unable to find chart digest from output string of helm push") +} + func execHelm(t *testing.T, args ...string) string { t.Helper() diff --git a/test/e2e/template/helmfile/testdata/snapshot/oci_chart_pull/config.yaml b/test/e2e/template/helmfile/testdata/snapshot/oci_chart_pull/config.yaml new file mode 100644 index 00000000..55a14538 --- /dev/null +++ b/test/e2e/template/helmfile/testdata/snapshot/oci_chart_pull/config.yaml @@ -0,0 +1,6 @@ +localDockerRegistry: + enabled: true + port: 5000 +chartifyTempDir: temp2 +helmfileArgs: +- template diff --git a/test/e2e/template/helmfile/testdata/snapshot/oci_chart_pull/input.yaml b/test/e2e/template/helmfile/testdata/snapshot/oci_chart_pull/input.yaml new file mode 100644 index 00000000..2bb1dcc7 --- /dev/null +++ b/test/e2e/template/helmfile/testdata/snapshot/oci_chart_pull/input.yaml @@ -0,0 +1,19 @@ +repositories: +- name: myrepo + url: localhost:5000/myrepo + oci: true + +releases: +- name: foo + chart: myrepo/raw + version: 0.1.0 + values: + - templates: + - | + apiVersion: v1 + kind: ConfigMap + metadata: + name: {{`{{ .Release.Name }}`}} + namespace: {{`{{ .Release.Namespace }}`}} + data: + foo: FOO diff --git a/test/e2e/template/helmfile/testdata/snapshot/oci_chart_pull/output.yaml b/test/e2e/template/helmfile/testdata/snapshot/oci_chart_pull/output.yaml new file mode 100644 index 00000000..10ccf024 --- /dev/null +++ b/test/e2e/template/helmfile/testdata/snapshot/oci_chart_pull/output.yaml @@ -0,0 +1,15 @@ +Pulling localhost:5000/myrepo/raw:0.1.0 +Pulled: localhost:5000/myrepo/raw:0.1.0 +Digest: $DIGEST + +Templating release=foo, chart=$TMP/foo/raw/0.1.0/raw +--- +# Source: raw/templates/resources.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: foo + namespace: default +data: + foo: FOO +