From 0b18c1b166b6bd7e785bd3d923b96576f28ac6b6 Mon Sep 17 00:00:00 2001 From: Christoffer Nissen Date: Thu, 10 Oct 2024 00:57:33 +0200 Subject: [PATCH] add support for embedded dependency charts defined with file:// protocol --- pkg/cosign/chart.go | 15 ++------------ pkg/helm/chart.go | 30 ++++++++++++++++----------- pkg/helm/chartImportOption.go | 18 +++-------------- pkg/helm/chartOption.go | 38 +++++++++++++++-------------------- 4 files changed, 39 insertions(+), 62 deletions(-) diff --git a/pkg/cosign/chart.go b/pkg/cosign/chart.go index e16d551..958ed55 100644 --- a/pkg/cosign/chart.go +++ b/pkg/cosign/chart.go @@ -17,7 +17,6 @@ import ( "github.com/sigstore/cosign/v2/cmd/cosign/cli/options" "github.com/sigstore/cosign/v2/cmd/cosign/cli/sign" "helm.sh/helm/v3/pkg/chart/loader" - "helm.sh/helm/v3/pkg/repo" _ "github.com/sigstore/sigstore/pkg/signature/kms/aws" _ "github.com/sigstore/sigstore/pkg/signature/kms/azure" @@ -148,20 +147,10 @@ func (so SignChartOption) Run() error { } for _, d := range chartRef.Metadata.Dependencies { - if d.Repository != "" { + if !(d.Repository == "" || strings.HasPrefix(d.Repository, "file://")) { v := d.Version if strings.Contains(v, "*") || strings.Contains(v, "x") { - chart := helm.Chart{ - Name: d.Name, - Repo: repo.Entry{ - Name: c.Repo.Name + "/" + d.Name, - URL: d.Repository, - }, - Version: d.Version, - ValuesFilePath: c.ValuesFilePath, - Parent: &c, - PlainHTTP: c.PlainHTTP, - } + chart := helm.DependencyToChart(d, c) // Resolve Globs to latest patch v, err = chart.ResolveVersion() diff --git a/pkg/helm/chart.go b/pkg/helm/chart.go index 4a812e2..24bee36 100644 --- a/pkg/helm/chart.go +++ b/pkg/helm/chart.go @@ -55,6 +55,21 @@ type Chart struct { DepsCount int } +func DependencyToChart(d *chart.Dependency, p Chart) Chart { + return Chart{ + Name: d.Name, + Repo: repo.Entry{ + Name: p.Repo.Name + "/" + d.Name, + URL: d.Repository, + }, + Version: d.Version, + Parent: &p, + ValuesFilePath: p.ValuesFilePath, + DepsCount: 0, + PlainHTTP: p.PlainHTTP, + } +} + // AddChartRepositoryToHelmRepositoryFile adds repository to Helm repository.yml to enable querying/pull func (c Chart) AddToHelmRepositoryFile() (bool, error) { config := cli.New() @@ -603,22 +618,13 @@ func (c Chart) PushAndModify(registry string, insecure bool, plainHTTP bool) (st // Dependencies (Chart.yaml) for _, d := range chartRef.Metadata.Dependencies { - if d.Repository != "" { + if d.Repository != "" || strings.HasPrefix(d.Repository, "file://") { // Change dependency ref to registry being imported to d.Repository = registry - if strings.Contains(d.Version, "*") { - chart := Chart{ - Name: d.Name, - Repo: repo.Entry{ - Name: c.Repo.Name + "/" + d.Name, - URL: d.Repository, - }, - Version: d.Version, - ValuesFilePath: c.ValuesFilePath, - Parent: &c, - } + if strings.Contains(d.Version, "*") || strings.Contains(d.Version, "x") { + chart := DependencyToChart(d, c) // OCI dependencies can not use globs in version // Resolve Globs to latest patch diff --git a/pkg/helm/chartImportOption.go b/pkg/helm/chartImportOption.go index daea0c6..86dfbc5 100644 --- a/pkg/helm/chartImportOption.go +++ b/pkg/helm/chartImportOption.go @@ -11,7 +11,6 @@ import ( "github.com/ChristofferNissen/helmper/pkg/registry" "github.com/k0kubun/go-ansi" "github.com/schollz/progressbar/v3" - "helm.sh/helm/v3/pkg/repo" ) type ChartImportOption struct { @@ -53,25 +52,14 @@ func (opt ChartImportOption) Run(ctx context.Context, setters ...Option) error { // continue // } - // Only import enabled charts - if d.Repository == "" { + // only import remote charts + if d.Repository == "" || strings.HasPrefix(d.Repository, "file://") { // Embedded in parent chart slog.Debug("Skipping embedded chart", slog.String("chart", d.Name), slog.String("parent", c.Name)) continue } - chart := Chart{ - Name: d.Name, - Repo: repo.Entry{ - Name: c.Repo.Name + "/" + d.Name, - URL: d.Repository, - }, - Version: d.Version, - ValuesFilePath: c.ValuesFilePath, - Parent: &c, - DepsCount: 0, - PlainHTTP: c.PlainHTTP, - } + chart := DependencyToChart(d, c) // Resolve Globs to latest patch if strings.Contains(chart.Version, "*") { diff --git a/pkg/helm/chartOption.go b/pkg/helm/chartOption.go index 6b15474..ba9acc0 100644 --- a/pkg/helm/chartOption.go +++ b/pkg/helm/chartOption.go @@ -18,7 +18,6 @@ import ( "helm.sh/helm/v3/pkg/chart/loader" "helm.sh/helm/v3/pkg/chartutil" "helm.sh/helm/v3/pkg/cli" - "helm.sh/helm/v3/pkg/repo" ) type ChartData map[Chart]map[*registry.Image][]string @@ -105,19 +104,23 @@ func determineTag(ctx context.Context, img *registry.Image, plainHTTP bool) bool } func determineSubChartPath(d *chart.Dependency, subChart *Chart, c *Chart, path string, args *Options) (string, error) { - if d.Repository == "" { - p := path - - // Check if path is archive e.g. contains '.tgz' - if strings.Contains(p, ".tgz") { - // Unpack tar - if err := chartutil.ExpandFile(cli.New().EnvVars()["HELM_CACHE_HOME"], p); err != nil { - return "", err - } - p = filepath.Join(cli.New().EnvVars()["HELM_CACHE_HOME"], c.Name) + p := path + + // Check if path is archive e.g. contains '.tgz' + if strings.Contains(p, ".tgz") { + // Unpack tar + if err := chartutil.ExpandFile(cli.New().EnvVars()["HELM_CACHE_HOME"], p); err != nil { + return "", err } + p = filepath.Join(cli.New().EnvVars()["HELM_CACHE_HOME"], c.Name) + } - return fmt.Sprintf("%s/charts/%s", p, subChart.Name), nil + switch { + case strings.HasPrefix(d.Repository, "file://"): // Helm version >2.2.0 + fallthrough + case d.Repository == "": // Embedded + s := fmt.Sprintf("%s/charts/%s", p, subChart.Name) + return s, nil } // Get Dependency Charts to local filesystem @@ -227,15 +230,7 @@ func (co ChartOption) Run(ctx context.Context, setters ...Option) (ChartData, er } // Create chart for dependency - subChart := Chart{ - Name: d.Name, - Repo: repo.Entry{ - Name: c.Repo.Name + "/" + d.Name, - URL: d.Repository, - }, - Version: d.Version, - Parent: &c, - } + subChart := DependencyToChart(d, c) // Determine path to subChart in filesystem scPath, err := determineSubChartPath(d, &subChart, &c, path, args) @@ -311,7 +306,6 @@ func (co ChartOption) Run(ctx context.Context, setters ...Option) (ChartData, er eg, egCtx := errgroup.WithContext(egCtx) for i, helmValuePaths := range imageMap { - func(i *registry.Image, helmValuePaths []string) { eg.Go(func() error {