Skip to content

Commit

Permalink
fix: Support published Helm charts with different name format (#695)
Browse files Browse the repository at this point in the history
Currently `mindthegap create helm-bundle` fails if the chart published
in
the helm repo has a different name to the expected format
`<chartName>-<chartVersion>.tgz`. An example that hit this issue is the
NFD
chart that is published with the name
`<chartName>-chart-<chartVersion>.tgz`.

This commit fixes the issue by first finding the download URL from the
Helm repo index and then using the existing `GetChartFromURL` function
to download the chart. This already correctly uses the basename of the
published chart file and hence doesn't hit the above issue.

Tested to be working:

```bash
$ cat repos.yaml
repositories:
  nfd:
    repoURL: https://kubernetes-sigs.github.io/node-feature-discovery/charts/
    charts:
      node-feature-discovery:
      - 0.15.2

$ ./dist/mindthegap_darwin_arm64/mindthegap create helm-bundle --helm-charts-file=repos.yaml --overwrite
 ✓ Parsing Helm chart bundle config
 ✓ Creating temporary OCI registry directory
 ✓ Starting temporary OCI registry
 ✓ Creating temporary chart storage directory
 ✓ Fetching Helm chart node-feature-discovery (versions [0.15.2]) from nfd
(https://kubernetes-sigs.github.io/node-feature-discovery/charts/)
 ✓ Archiving Helm charts to helm-charts.tar

$ ./dist/mindthegap_darwin_arm64/mindthegap serve bundle --bundle helm-charts.tar &
 ✓ Creating temporary directory
 ✓ Unarchiving image bundle "helm-charts.tar"
 ✓ Parsing Helm charts bundle config
 ✓ Creating Docker registry
Listening on 127.0.0.1:58639

$ crane ls 127.0.0.1:58783/charts/node-feature-discovery
0.15.2
```
  • Loading branch information
jimmidyson authored Apr 24, 2024
1 parent c00edff commit 1313f8c
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 15 deletions.
61 changes: 47 additions & 14 deletions helm/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ import (
"net/url"
"os"
"path/filepath"
"strings"

"github.com/hashicorp/go-getter"
"helm.sh/helm/v3/pkg/action"
"helm.sh/helm/v3/pkg/chart"
"helm.sh/helm/v3/pkg/chart/loader"
"helm.sh/helm/v3/pkg/cli"
helmgetter "helm.sh/helm/v3/pkg/getter"
"helm.sh/helm/v3/pkg/registry"
"helm.sh/helm/v3/pkg/repo"
"k8s.io/klog/v2"
Expand Down Expand Up @@ -141,25 +143,56 @@ func (c *Client) GetChartFromRepo(
)...,
)

helmOutput, err := pull.Run(chartName)
// Charts pulled from OCI registries will have the scheme "oci://" for the chart name.
// We can use the built-in downloader to fetch these charts.
if strings.HasPrefix(chartName, OCIScheme) {
helmOutput, err := pull.Run(chartName)
if err != nil {
return "", fmt.Errorf(
"failed to fetch chart %s:%s from %s: %w, output:\n\n%s",
chartName,
chartVersion,
repoURL,
err,
helmOutput,
)
}
if helmOutput != "" {
c.out.V(4).Info(helmOutput)
}

return filepath.Join(
outputDir,
fmt.Sprintf("%s-%s.tgz", filepath.Base(chartName), chartVersion),
), nil
}

// For non-OCI charts, we need to discover the chart URL first to be able to handle
// different chart names to the expected `<chartName>-<chartVersion>.tgz` format.
chartURL, err := repo.FindChartInAuthAndTLSAndPassRepoURL(
pull.RepoURL,
pull.Username,
pull.Password,
chartName,
chartVersion,
pull.CertFile,
pull.KeyFile,
pull.CaFile,
pull.InsecureSkipTLSverify,
pull.PassCredentialsAll,
helmgetter.All(pull.Settings),
)
if err != nil {
return "", fmt.Errorf(
"failed to fetch chart %s:%s from %s: %w, output:\n\n%s",
"failed to discover chart URL for %s:%s from %s: %w",
chartName,
chartVersion,
repoURL,
err,
helmOutput,
)
}
if helmOutput != "" {
c.out.V(4).Info(helmOutput)
}

return filepath.Join(
outputDir,
fmt.Sprintf("%s-%s.tgz", filepath.Base(chartName), chartVersion),
), nil
return c.GetChartFromURL(outputDir, chartURL, c.tempDir)
}

func (c *Client) GetChartFromURL(outputDir, chartURL, workingDir string) (string, error) {
Expand All @@ -180,11 +213,11 @@ func (c *Client) GetChartFromURL(outputDir, chartURL, workingDir string) (string
u.RawQuery = q.Encode()

dst := filepath.Join(outputDir, filepath.Base(chartURL))
err = getter.GetFile(dst, u.String(), func(c *getter.Client) error {
c.Pwd = workingDir
err = getter.GetFile(dst, u.String(), func(getterClient *getter.Client) error {
getterClient.Pwd = workingDir
return nil
}, func(c *getter.Client) error {
c.Getters = getters
}, func(getterClient *getter.Client) error {
getterClient.Getters = getters
return nil
})
if err != nil {
Expand Down
9 changes: 9 additions & 0 deletions test/e2e/helmbundle/push_bundle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,15 @@ var _ = Describe("Push Bundle", func() {
helm.InsecureSkipTLSverifyOpt(),
)

helpers.ValidateChartIsAvailable(
GinkgoT(),
"127.0.0.1",
port,
"node-feature-discovery",
"0.15.2",
helm.InsecureSkipTLSverifyOpt(),
)

Expect(reg.Shutdown(context.Background())).To((Succeed()))

Eventually(done).Should(BeClosed())
Expand Down
9 changes: 9 additions & 0 deletions test/e2e/helmbundle/serve_bundle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,15 @@ var _ = Describe("Serve Bundle", func() {
helm.InsecureSkipTLSverifyOpt(),
)

helpers.ValidateChartIsAvailable(
GinkgoT(),
"127.0.0.1",
port,
"node-feature-discovery",
"0.15.2",
helm.InsecureSkipTLSverifyOpt(),
)

close(stopCh)

Eventually(done).Should(BeClosed())
Expand Down
7 changes: 6 additions & 1 deletion test/e2e/helmbundle/testdata/create-success.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,14 @@
# SPDX-License-Identifier: Apache-2.0

repositories:
jetstack:
stefanprodan:
repoURL: https://stefanprodan.github.io/podinfo
charts:
podinfo:
- "6.2.0"
- "6.1.0"
nfd:
repoURL: https://kubernetes-sigs.github.io/node-feature-discovery/charts/
charts:
node-feature-discovery:
- "0.15.2"

0 comments on commit 1313f8c

Please sign in to comment.