From 1135392b482f26f244c3c69f51511a1d82590eb7 Mon Sep 17 00:00:00 2001 From: Matt Farina Date: Wed, 6 Jan 2021 09:55:10 -0500 Subject: [PATCH] Fix dep build with OCI based charts The recent addition of oci:// to specify dependencies in the Chart.yaml dependencies and with helm pull missed handling for the dependency build command. This command was failing to handle OCI. This change adds support for the dep build command following the same pattern used to add oci:// functionality. Signed-off-by: Matt Farina --- cmd/helm/dependency.go | 2 +- cmd/helm/dependency_build.go | 3 ++- cmd/helm/dependency_build_test.go | 38 +++++++++++++++++++++++++++++++ pkg/downloader/manager.go | 7 +++--- 4 files changed, 45 insertions(+), 5 deletions(-) diff --git a/cmd/helm/dependency.go b/cmd/helm/dependency.go index 3de3ef014..6bb82e217 100644 --- a/cmd/helm/dependency.go +++ b/cmd/helm/dependency.go @@ -93,7 +93,7 @@ func newDependencyCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { cmd.AddCommand(newDependencyListCmd(out)) cmd.AddCommand(newDependencyUpdateCmd(cfg, out)) - cmd.AddCommand(newDependencyBuildCmd(out)) + cmd.AddCommand(newDependencyBuildCmd(cfg, out)) return cmd } diff --git a/cmd/helm/dependency_build.go b/cmd/helm/dependency_build.go index a0b63f038..1ee46d3d2 100644 --- a/cmd/helm/dependency_build.go +++ b/cmd/helm/dependency_build.go @@ -41,7 +41,7 @@ If no lock file is found, 'helm dependency build' will mirror the behavior of 'helm dependency update'. ` -func newDependencyBuildCmd(out io.Writer) *cobra.Command { +func newDependencyBuildCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { client := action.NewDependency() cmd := &cobra.Command{ @@ -60,6 +60,7 @@ func newDependencyBuildCmd(out io.Writer) *cobra.Command { Keyring: client.Keyring, SkipUpdate: client.SkipRefresh, Getters: getter.All(settings), + RegistryClient: cfg.RegistryClient, RepositoryConfig: settings.RepositoryConfig, RepositoryCache: settings.RepositoryCache, Debug: settings.Debug, diff --git a/cmd/helm/dependency_build_test.go b/cmd/helm/dependency_build_test.go index 8e5f24af7..33198a9dd 100644 --- a/cmd/helm/dependency_build_test.go +++ b/cmd/helm/dependency_build_test.go @@ -22,6 +22,7 @@ import ( "strings" "testing" + "helm.sh/helm/v3/pkg/chartutil" "helm.sh/helm/v3/pkg/provenance" "helm.sh/helm/v3/pkg/repo" "helm.sh/helm/v3/pkg/repo/repotest" @@ -37,6 +38,27 @@ func TestDependencyBuildCmd(t *testing.T) { rootDir := srv.Root() srv.LinkIndices() + ociSrv, err := repotest.NewOCIServer(t, srv.Root()) + if err != nil { + t.Fatal(err) + } + + ociChartName := "oci-depending-chart" + c := createTestingMetadataForOCI(ociChartName, ociSrv.RegistryURL) + if err := chartutil.SaveDir(c, ociSrv.Dir); err != nil { + t.Fatal(err) + } + ociSrv.Run(t, repotest.WithDependingChart(c)) + + err = os.Setenv("HELM_EXPERIMENTAL_OCI", "1") + if err != nil { + t.Fatal("failed to set environment variable enabling OCI support") + } + + dir := func(p ...string) string { + return filepath.Join(append([]string{srv.Root()}, p...)...) + } + chartname := "depbuild" createTestingChart(t, rootDir, chartname, srv.URL()) repoFile := filepath.Join(rootDir, "repositories.yaml") @@ -112,6 +134,22 @@ func TestDependencyBuildCmd(t *testing.T) { if strings.Contains(out, `update from the "test" chart repository`) { t.Errorf("Repo did get updated\n%s", out) } + + // OCI dependencies + cmd = fmt.Sprintf("dependency build '%s' --repository-config %s --repository-cache %s --registry-config %s/config.json", + dir(ociChartName), + dir("repositories.yaml"), + dir(), + dir()) + _, out, err = executeActionCommand(cmd) + if err != nil { + t.Logf("Output: %s", out) + t.Fatal(err) + } + expect = dir(ociChartName, "charts/oci-dependent-chart-0.1.0.tgz") + if _, err := os.Stat(expect); err != nil { + t.Fatal(err) + } } func TestDependencyBuildCmdWithHelmV2Hash(t *testing.T) { diff --git a/pkg/downloader/manager.go b/pkg/downloader/manager.go index 38ed04279..d2d3e9f31 100644 --- a/pkg/downloader/manager.go +++ b/pkg/downloader/manager.go @@ -453,8 +453,8 @@ func (m *Manager) hasAllRepos(deps []*chart.Dependency) error { missing := []string{} Loop: for _, dd := range deps { - // If repo is from local path, continue - if strings.HasPrefix(dd.Repository, "file://") { + // If repo is from local path or OCI, continue + if strings.HasPrefix(dd.Repository, "file://") || strings.HasPrefix(dd.Repository, "oci://") { continue } @@ -555,7 +555,8 @@ func (m *Manager) resolveRepoNames(deps []*chart.Dependency) (map[string]string, missing := []string{} for _, dd := range deps { // Don't map the repository, we don't need to download chart from charts directory - if dd.Repository == "" { + // When OCI is used there is no Helm repository + if dd.Repository == "" || strings.HasPrefix(dd.Repository, "oci://") { continue } // if dep chart is from local path, verify the path is valid