feat: pull charts by specifying the SHA256 checksum as the version.

This worked in version 3.7, but seems to have been lost or removed in
the upgrade to 3.8.

It is useful because not all repositories have immutable tags.

This is tangentially related to this comment:

https://github.com/helm/helm/issues/10312#issuecomment-961396434

Signed-off-by: Eric Wollesen <ewwolles@amazon.com>
pull/10799/head
Eric Wollesen 4 years ago
parent 2cf845424a
commit 3b9d0462a8

@ -21,6 +21,7 @@ import (
"net/url" "net/url"
"os" "os"
"path/filepath" "path/filepath"
"regexp"
"strings" "strings"
"github.com/Masterminds/semver/v3" "github.com/Masterminds/semver/v3"
@ -141,36 +142,41 @@ func (c *ChartDownloader) DownloadTo(ref, version, dest string) (string, *proven
return destfile, ver, nil return destfile, ver, nil
} }
var sha256re = regexp.MustCompile(`^sha256:[0-9a-fA-F]{64}$`)
func (c *ChartDownloader) getOciURI(ref, version string, u *url.URL) (*url.URL, error) { func (c *ChartDownloader) getOciURI(ref, version string, u *url.URL) (*url.URL, error) {
var tag string
var err error var err error
// Evaluate whether an explicit version has been provided. Otherwise, determine version to use // Evaluate whether an explicit version has been provided. Otherwise, determine version to use
_, errSemVer := semver.NewVersion(version) if sha256re.MatchString(version) {
if errSemVer == nil { u.Path = fmt.Sprintf("%s@%s", u.Path, version)
tag = version
} else { } else {
// Retrieve list of repository tags var tag string
tags, err := c.RegistryClient.Tags(strings.TrimPrefix(ref, fmt.Sprintf("%s://", registry.OCIScheme))) _, errSemVer := semver.NewVersion(version)
if err != nil { if errSemVer == nil {
return nil, err tag = version
} } else {
if len(tags) == 0 { // Retrieve list of repository tags
return nil, errors.Errorf("Unable to locate any tags in provided repository: %s", ref) tags, err := c.RegistryClient.Tags(strings.TrimPrefix(ref, fmt.Sprintf("%s://", registry.OCIScheme)))
} if err != nil {
return nil, err
}
if len(tags) == 0 {
return nil, errors.Errorf("Unable to locate any tags in provided repository: %s", ref)
}
// Determine if version provided // Determine if version provided
// If empty, try to get the highest available tag // If empty, try to get the highest available tag
// If exact version, try to find it // If exact version, try to find it
// If semver constraint string, try to find a match // If semver constraint string, try to find a match
tag, err = registry.GetTagMatchingVersionOrConstraint(tags, version) tag, err = registry.GetTagMatchingVersionOrConstraint(tags, version)
if err != nil { if err != nil {
return nil, err return nil, err
}
} }
u.Path = fmt.Sprintf("%s:%s", u.Path, tag)
} }
u.Path = fmt.Sprintf("%s:%s", u.Path, tag)
return u, err return u, err
} }
@ -182,7 +188,9 @@ func (c *ChartDownloader) getOciURI(ref, version string, u *url.URL) (*url.URL,
// A reference may be an HTTP URL, an oci reference URL, a 'reponame/chartname' // A reference may be an HTTP URL, an oci reference URL, a 'reponame/chartname'
// reference, or a local path. // reference, or a local path.
// //
// A version is a SemVer string (1.2.3-beta.1+f334a6789). // A version is a SemVer string (1.2.3-beta.1+f334a6789) or a SHA256 digest of
// the chart's manifest
// (sha256:d234555386402a5867ef0169fefe5486858b6d8d209eaf32fd26d29b16807fd6).
// //
// - For fully qualified URLs, the version will be ignored (since URLs aren't versioned) // - For fully qualified URLs, the version will be ignored (since URLs aren't versioned)
// - For a chart reference // - For a chart reference

@ -40,6 +40,7 @@ func TestResolveChartRef(t *testing.T) {
{name: "full URL", ref: "http://example.com/foo-1.2.3.tgz", expect: "http://example.com/foo-1.2.3.tgz"}, {name: "full URL", ref: "http://example.com/foo-1.2.3.tgz", expect: "http://example.com/foo-1.2.3.tgz"},
{name: "full URL, HTTPS", ref: "https://example.com/foo-1.2.3.tgz", expect: "https://example.com/foo-1.2.3.tgz"}, {name: "full URL, HTTPS", ref: "https://example.com/foo-1.2.3.tgz", expect: "https://example.com/foo-1.2.3.tgz"},
{name: "full URL, with authentication", ref: "http://username:password@example.com/foo-1.2.3.tgz", expect: "http://username:password@example.com/foo-1.2.3.tgz"}, {name: "full URL, with authentication", ref: "http://username:password@example.com/foo-1.2.3.tgz", expect: "http://username:password@example.com/foo-1.2.3.tgz"},
{name: "full URL, with sha256", ref: "oci://example.com/foo/bar", version: "sha256:d234555386402a5867ef0169fefe5486858b6d8d209eaf32fd26d29b16807fd6", expect: "oci://example.com/foo/bar@sha256:d234555386402a5867ef0169fefe5486858b6d8d209eaf32fd26d29b16807fd6"},
{name: "reference, testing repo", ref: "testing/alpine", expect: "http://example.com/alpine-1.2.3.tgz"}, {name: "reference, testing repo", ref: "testing/alpine", expect: "http://example.com/alpine-1.2.3.tgz"},
{name: "reference, version, testing repo", ref: "testing/alpine", version: "0.2.0", expect: "http://example.com/alpine-0.2.0.tgz"}, {name: "reference, version, testing repo", ref: "testing/alpine", version: "0.2.0", expect: "http://example.com/alpine-0.2.0.tgz"},
{name: "reference, version, malformed repo", ref: "malformed/alpine", version: "1.2.3", expect: "http://dl.example.com/alpine-1.2.3.tgz"}, {name: "reference, version, malformed repo", ref: "malformed/alpine", version: "1.2.3", expect: "http://dl.example.com/alpine-1.2.3.tgz"},

Loading…
Cancel
Save