feat(downloader): add oci digest tracking support for helm v4 dependencies

- Update `pkg/chart/interfaces.go` and `dependency.go` to support dynamic dependency digest accessors.
- Expand internal v3 specifications to parse and propagate immutable asset checksums.
- Modify engine routing logic in `pkg/downloader/manager.go` to construct container image references via specific digests during URL mapping.
- Introduce package naming alias (`pkgchart`) in the downloader manager to cleanly sidestep v2/v4 structural namespace collisions.
- Include verification logic and coverage updates inside `manager_test.go`.
pull/32142/head
Momin Huzaifa 5 months ago
parent e65b8666aa
commit fdf9d6a23b

@ -36,6 +36,8 @@ type Dependency struct {
// Appending `index.yaml` to this string should result in a URL that can be
// used to fetch the repository index.
Repository string `json:"repository" yaml:"repository"`
// Digest
Digest string `json: "digest,omitempty" yaml: "digest,omitempty"`
// A yaml path that resolves to a boolean, used for enabling/disabling charts (e.g. subchart1.enabled )
Condition string `json:"condition,omitempty" yaml:"condition,omitempty"`
// Tags can be used to group charts for enabling/disabling together
@ -59,6 +61,7 @@ func (d *Dependency) Validate() error {
d.Name = sanitizeString(d.Name)
d.Version = sanitizeString(d.Version)
d.Repository = sanitizeString(d.Repository)
d.Digest = sanitizeString(d.Digest)
d.Condition = sanitizeString(d.Condition)
for i := range d.Tags {
d.Tags[i] = sanitizeString(d.Tags[i])

@ -62,3 +62,12 @@ func (r *v3DependencyAccessor) Name() string {
func (r *v3DependencyAccessor) Alias() string {
return r.dep.Alias
}
func (r v2DependencyAccessor) Digest() string {
// helm v2 doesn't use digest, return empty sting
return ""
}
func (r v3DependencyAccessor) Digest() string {
return r.dep.Digest
}

@ -41,4 +41,5 @@ type Accessor interface {
type DependencyAccessor interface {
Name() string
Alias() string
Digest() string
}

@ -43,6 +43,7 @@ import (
"helm.sh/helm/v4/pkg/helmpath"
"helm.sh/helm/v4/pkg/registry"
"helm.sh/helm/v4/pkg/repo/v1"
pkgchart "helm.sh/helm/v4/pkg/chart"
)
// ErrRepoNotFound indicates that chart repositories can't be found in local repo cache.
@ -315,7 +316,8 @@ func (m *Manager) downloadAll(deps []*chart.Dependency) error {
// Any failure to resolve/download a chart should fail:
// https://github.com/helm/helm/issues/1439
churl, username, password, insecureSkipTLSVerify, passCredentialsAll, caFile, certFile, keyFile, err := m.findChartURL(dep.Name, dep.Version, dep.Repository, repos)
depAccessor, _ := pkgchart.NewDependencyAccessor(dep)
churl, username, password, insecureSkipTLSVerify, passCredentialsAll, caFile, certFile, keyFile, err := m.findChartURL(dep.Name, dep.Version, depAccessor.Digest(), dep.Repository, repos)
if err != nil {
saveError = fmt.Errorf("could not find %s: %w", churl, err)
break
@ -725,8 +727,11 @@ func (m *Manager) parallelRepoUpdate(repos []*repo.Entry) error {
// repoURL is the repository to search
//
// If it finds a URL that is "relative", it will prepend the repoURL.
func (m *Manager) findChartURL(name, version, repoURL string, repos map[string]*repo.ChartRepository) (url, username, password string, insecureSkipTLSVerify, passCredentialsAll bool, caFile, certFile, keyFile string, err error) {
func (m *Manager) findChartURL(name, version, digest, repoURL string, repos map[string]*repo.ChartRepository) (url, username, password string, insecureSkipTLSVerify, passCredentialsAll bool, caFile, certFile, keyFile string, err error) {
if registry.IsOCI(repoURL) {
if digest != ""{
return fmt.Sprintf("%s/%s@%s", repoURL, name, digest), "", "", false, false, "", "", "", nil
}
return fmt.Sprintf("%s/%s:%s", repoURL, name, version), "", "", false, false, "", "", "", nil
}

@ -71,7 +71,7 @@ func TestFindChartURL(t *testing.T) {
version := "0.1.0"
repoURL := "http://example.com/charts"
churl, username, password, insecureSkipTLSVerify, passcredentialsall, _, _, _, err := m.findChartURL(name, version, repoURL, repos)
churl, username, password, insecureSkipTLSVerify, passcredentialsall, _, _, _, err := m.findChartURL(name, version, "", repoURL, repos)
if err != nil {
t.Fatal(err)
}
@ -96,7 +96,7 @@ func TestFindChartURL(t *testing.T) {
version = "1.2.3"
repoURL = "https://example-https-insecureskiptlsverify.com"
churl, username, password, insecureSkipTLSVerify, passcredentialsall, _, _, _, err = m.findChartURL(name, version, repoURL, repos)
churl, username, password, insecureSkipTLSVerify, passcredentialsall, _, _, _, err = m.findChartURL(name, version, "", repoURL, repos)
if err != nil {
t.Fatal(err)
}
@ -121,7 +121,7 @@ func TestFindChartURL(t *testing.T) {
version = "1.2.3"
repoURL = "http://example.com/helm"
churl, username, password, insecureSkipTLSVerify, passcredentialsall, _, _, _, err = m.findChartURL(name, version, repoURL, repos)
churl, username, password, insecureSkipTLSVerify, passcredentialsall, _, _, _, err = m.findChartURL(name, version, "", repoURL, repos)
if err != nil {
t.Fatal(err)
}

Loading…
Cancel
Save