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:
		
						commit
						0341027bc0
					
				|  | @ -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} | ||||
| 	} | ||||
|  |  | |||
|  | @ -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
 | ||||
| `, | ||||
| 		}, | ||||
| 	} | ||||
|  |  | |||
|  | @ -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() | ||||
| 
 | ||||
|  |  | |||
|  | @ -0,0 +1,6 @@ | |||
| localDockerRegistry: | ||||
|   enabled: true | ||||
|   port: 5000 | ||||
| chartifyTempDir: temp2 | ||||
| helmfileArgs: | ||||
| - template | ||||
|  | @ -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 | ||||
|  | @ -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 | ||||
| 
 | ||||
		Loading…
	
		Reference in New Issue