diff --git a/internal/resolver/resolver.go b/internal/resolver/resolver.go index 5f0c5b148..57350d3c0 100644 --- a/internal/resolver/resolver.go +++ b/internal/resolver/resolver.go @@ -106,7 +106,7 @@ func (r *Resolver) Resolve(reqs []*chart.Dependency, repoNames map[string]string continue } - repoName := repoNames[d.Name] + repoName := repoNames[dependencyKey(d)] // if the repository was not defined, but the dependency defines a repository url, bypass the cache if repoName == "" && d.Repository != "" { locked[i] = &chart.Dependency{ @@ -206,6 +206,13 @@ func (r *Resolver) Resolve(reqs []*chart.Dependency, repoNames map[string]string }, nil } +func dependencyKey(dep *chart.Dependency) string { + if dep.Alias != "" { + return dep.Alias + } + return dep.Name +} + // HashReq generates a hash of the dependencies. // // This should be used only to compare against another hash generated by this diff --git a/pkg/downloader/manager.go b/pkg/downloader/manager.go index a1fa0ddbd..0e601e991 100644 --- a/pkg/downloader/manager.go +++ b/pkg/downloader/manager.go @@ -511,7 +511,7 @@ func (m *Manager) ensureMissingRepos(repoNames map[string]string, deps []*chart. } // When the repoName for a dependency is known we can skip ensuring - if _, ok := repoNames[dd.Name]; ok { + if _, ok := repoNames[dependencyKey(dd)]; ok { continue } @@ -527,7 +527,7 @@ func (m *Manager) ensureMissingRepos(repoNames map[string]string, deps []*chart. } rn = managerKeyPrefix + rn - repoNames[dd.Name] = rn + repoNames[dependencyKey(dd)] = rn // Assuming the repository is generally available. For Helm managed // access controls the repository needs to be added through the user @@ -555,6 +555,13 @@ func (m *Manager) ensureMissingRepos(repoNames map[string]string, deps []*chart. return repoNames, nil } +func dependencyKey(dep *chart.Dependency) string { + if dep.Alias != "" { + return dep.Alias + } + return dep.Name +} + // resolveRepoNames returns the repo names of the referenced deps which can be used to fetch the cached index file // and replaces aliased repository URLs into resolved URLs in dependencies. func (m *Manager) resolveRepoNames(deps []*chart.Dependency) (map[string]string, error) { @@ -586,12 +593,12 @@ func (m *Manager) resolveRepoNames(deps []*chart.Dependency) (map[string]string, if m.Debug { fmt.Fprintf(m.Out, "Repository from local path: %s\n", dd.Repository) } - reposMap[dd.Name] = dd.Repository + reposMap[dependencyKey(dd)] = dd.Repository continue } if registry.IsOCI(dd.Repository) { - reposMap[dd.Name] = dd.Repository + reposMap[dependencyKey(dd)] = dd.Repository continue } @@ -602,11 +609,11 @@ func (m *Manager) resolveRepoNames(deps []*chart.Dependency) (map[string]string, (strings.HasPrefix(dd.Repository, "alias:") && strings.TrimPrefix(dd.Repository, "alias:") == repo.Name) { found = true dd.Repository = repo.URL - reposMap[dd.Name] = repo.Name + reposMap[dependencyKey(dd)] = repo.Name break } else if urlutil.Equal(repo.URL, dd.Repository) { found = true - reposMap[dd.Name] = repo.Name + reposMap[dependencyKey(dd)] = repo.Name break } } diff --git a/pkg/downloader/manager_test.go b/pkg/downloader/manager_test.go index e40bbbac1..d92ae49a2 100644 --- a/pkg/downloader/manager_test.go +++ b/pkg/downloader/manager_test.go @@ -180,6 +180,52 @@ func TestGetRepoNames(t *testing.T) { } } +func TestResolveAliasedChartFromMixedRepositories(t *testing.T) { + srv := repotest.NewTempServer( + t, + repotest.WithChartSourceGlob("testdata/local-subchart-0.1.0.tgz"), + ) + defer srv.Stop() + require.NoError(t, srv.LinkIndices()) + + dir := t.TempDir() + repositoryConfig := filepath.Join(dir, "repositories.yaml") + require.NoError(t, os.WriteFile(repositoryConfig, []byte("apiVersion: v1\nrepositories: []\n"), 0o644)) + + deps := []*chart.Dependency{ + { + Name: "local-subchart", + Alias: "cluster-new", + Version: "0.1.0", + Repository: "oci://registry.example.com/charts", + }, + { + Name: "local-subchart", + Alias: "cluster-old", + Version: "0.1.0", + Repository: srv.URL(), + }, + } + m := &Manager{ + Out: new(bytes.Buffer), + ChartPath: dir, + Getters: getter.Getters(), + RepositoryConfig: repositoryConfig, + RepositoryCache: dir, + } + + repoNames, err := m.resolveRepoNames(deps) + require.NoError(t, err) + repoNames, err = m.ensureMissingRepos(repoNames, deps) + require.NoError(t, err) + + lock, err := m.resolve(deps, repoNames) + require.NoError(t, err) + require.Len(t, lock.Dependencies, 2) + assert.Equal(t, deps[0].Repository, lock.Dependencies[0].Repository) + assert.Equal(t, deps[1].Repository, lock.Dependencies[1].Repository) +} + func TestDownloadAll(t *testing.T) { chartPath := t.TempDir() m := &Manager{