Merge pull request #371 from toVersus/fix/oci-pull-bug

fix: add missing untar flag to pull chart from oci registry
This commit is contained in:
yxxhero 2022-09-18 19:36:39 +08:00 committed by GitHub
commit 0341027bc0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 111 additions and 3 deletions

View File

@ -466,7 +466,7 @@ func (helm *execer) ChartPull(chart string, path string, flags ...string) error
// in the 3.7.0 version, the chart pull has been replaced with helm pull
// https://github.com/helm/helm/releases/tag/v3.7.0
ociChartURL, ociChartTag := resolveOciChart(chart)
helmArgs = []string{"pull", ociChartURL, "--version", ociChartTag, "--destination", path}
helmArgs = []string{"pull", ociChartURL, "--version", ociChartTag, "--destination", path, "--untar"}
} else {
helmArgs = []string{"chart", "pull", chart}
}

View File

@ -733,7 +733,7 @@ exec: helm --kube-context dev chart pull chart --untar --untardir /tmp/dir
chartPath: "path1",
chartFlags: []string{"--untardir", "/tmp/dir"},
listResult: `Pulling repo/helm-charts:0.14.0
exec: helm --kube-context dev pull oci://repo/helm-charts --version 0.14.0 --destination path1 --untardir /tmp/dir
exec: helm --kube-context dev pull oci://repo/helm-charts --version 0.14.0 --destination path1 --untar --untardir /tmp/dir
`,
},
}

View File

@ -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=<release_name>, chart=<chart_name>\"")
}
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()

View File

@ -0,0 +1,6 @@
localDockerRegistry:
enabled: true
port: 5000
chartifyTempDir: temp2
helmfileArgs:
- template

View File

@ -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

View File

@ -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