Skip to content

Commit

Permalink
[bug] add support for embedded dependency charts defined with file://…
Browse files Browse the repository at this point in the history
… protocol (#111)

* add support for embedded dependency charts defined with file:// protocol
* add logic to PushAndModify for Helm Charts with file:// dependencies
  • Loading branch information
ChristofferNissen authored Oct 10, 2024
1 parent 5e0b56c commit c39ac28
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 72 deletions.
15 changes: 2 additions & 13 deletions pkg/cosign/chart.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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()
Expand Down
52 changes: 30 additions & 22 deletions pkg/helm/chart.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -583,42 +598,35 @@ func (c Chart) PushAndModify(registry string, insecure bool, plainHTTP bool) (st
}
defer os.Remove(path)

dname, err := os.MkdirTemp("", "sampledir")
dir, err := os.MkdirTemp("", "sampledir")
if err != nil {
return "", err
}
// fmt.Println("Temp dir name:", dname)
defer os.RemoveAll(dname)
defer os.RemoveAll(dir)

err = chartutil.ExpandFile(dname, path)
err = chartutil.ExpandFile(dir, path)
if err != nil {
return "", err
}

// modify chart contents here before pushing
chartRef, err := loader.Load(dname + "/" + c.Name)
chartRef, err := loader.Load(dir + "/" + c.Name)
if err != nil {
return "", err
}

// Dependencies (Chart.yaml)
for _, d := range chartRef.Metadata.Dependencies {
if d.Repository != "" {
switch {
case strings.HasPrefix(d.Repository, "file://"):
slog.Debug("Leaving embedded chart as is", slog.String("Chart", d.Name))
case d.Repository != "":

// 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
Expand All @@ -631,7 +639,7 @@ func (c Chart) PushAndModify(registry string, insecure bool, plainHTTP bool) (st

}

err = chartutil.SaveChartfile(dname+"/"+c.Name+"/Chart.yaml", chartRef.Metadata)
err = chartutil.SaveChartfile(dir+"/"+c.Name+"/Chart.yaml", chartRef.Metadata)
if err != nil {
return "", err
}
Expand All @@ -640,14 +648,14 @@ func (c Chart) PushAndModify(registry string, insecure bool, plainHTTP bool) (st
// https://github.com/helm/helm/blob/main/cmd/helm/dependency_update.go
var buf bytes.Buffer
ma := getManager(&buf, true, true)
ma.ChartPath = dname + "/" + c.Name
ma.ChartPath = dir + "/" + c.Name
err = ma.Update()
if err != nil {
return "", err
slog.Debug("Error occurred trying to update Helm Chart on filesystem, skipping update of chart dependencies", slog.String("error", err.Error()))
}

// Reload Helm Chart from filesystem
chartRef, err = loader.Load(dname + "/" + c.Name)
chartRef, err = loader.Load(dir + "/" + c.Name)
if err != nil {
return "", err
}
Expand Down Expand Up @@ -802,8 +810,8 @@ func (c Chart) Locate() (string, error) {
}

return fmt.Sprintf("%s/%s-%s.tgz", helmCacheHome, c.Name, c.Version), nil
default:

default:
u, err := url.Parse(c.Repo.URL)
if err != nil {
return "", err
Expand Down
18 changes: 3 additions & 15 deletions pkg/helm/chartImportOption.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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, "*") {
Expand Down
38 changes: 16 additions & 22 deletions pkg/helm/chartOption.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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 {

Expand Down

0 comments on commit c39ac28

Please sign in to comment.