From f2aa97e31389ff2acb0aab007ce1418768eda866 Mon Sep 17 00:00:00 2001 From: Martin Hickey Date: Wed, 9 Oct 2019 16:35:55 +0100 Subject: [PATCH] fix(helm): Port accept dependency in requirements.yaml from charts directory (#6611) * Port #6578 to Helm 3 Signed-off-by: Martin Hickey * Update after reviw Review comments: - https://github.com/helm/helm/pull/6611#discussion_r332745703 Signed-off-by: Martin Hickey --- internal/resolver/resolver.go | 13 +++++++ internal/resolver/resolver_test.go | 23 ++++++++++++ .../charts/localdependency/Chart.yaml | 3 ++ pkg/downloader/manager.go | 36 +++++++++++++++++-- pkg/downloader/manager_test.go | 7 ++++ .../testdata/local-subchart/Chart.yaml | 3 ++ 6 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 internal/resolver/testdata/chartpath/charts/localdependency/Chart.yaml create mode 100644 pkg/downloader/testdata/local-subchart/Chart.yaml diff --git a/internal/resolver/resolver.go b/internal/resolver/resolver.go index c902b0134..79238b22f 100644 --- a/internal/resolver/resolver.go +++ b/internal/resolver/resolver.go @@ -53,6 +53,19 @@ func (r *Resolver) Resolve(reqs []*chart.Dependency, repoNames map[string]string locked := make([]*chart.Dependency, len(reqs)) missing := []string{} for i, d := range reqs { + if d.Repository == "" { + // Local chart subfolder + if _, err := GetLocalPath(filepath.Join("charts", d.Name), r.chartpath); err != nil { + return nil, err + } + + locked[i] = &chart.Dependency{ + Name: d.Name, + Repository: "", + Version: d.Version, + } + continue + } if strings.HasPrefix(d.Repository, "file://") { if _, err := GetLocalPath(d.Repository, r.chartpath); err != nil { diff --git a/internal/resolver/resolver_test.go b/internal/resolver/resolver_test.go index 3c402aaea..6bb29ba9a 100644 --- a/internal/resolver/resolver_test.go +++ b/internal/resolver/resolver_test.go @@ -85,6 +85,29 @@ func TestResolve(t *testing.T) { }, err: true, }, + { + name: "repo from valid path under charts path", + req: []*chart.Dependency{ + {Name: "localdependency", Repository: "", Version: "0.1.0"}, + }, + expect: &chart.Lock{ + Dependencies: []*chart.Dependency{ + {Name: "localdependency", Repository: "", Version: "0.1.0"}, + }, + }, + }, + { + name: "repo from invalid path under charts path", + req: []*chart.Dependency{ + {Name: "nonexistentdependency", Repository: "", Version: "0.1.0"}, + }, + expect: &chart.Lock{ + Dependencies: []*chart.Dependency{ + {Name: "nonexistentlocaldependency", Repository: "", Version: "0.1.0"}, + }, + }, + err: true, + }, } repoNames := map[string]string{"alpine": "kubernetes-charts", "redis": "kubernetes-charts"} diff --git a/internal/resolver/testdata/chartpath/charts/localdependency/Chart.yaml b/internal/resolver/testdata/chartpath/charts/localdependency/Chart.yaml new file mode 100644 index 000000000..083c51ee5 --- /dev/null +++ b/internal/resolver/testdata/chartpath/charts/localdependency/Chart.yaml @@ -0,0 +1,3 @@ +description: A Helm chart for Kubernetes +name: localdependency +version: 0.1.0 diff --git a/pkg/downloader/manager.go b/pkg/downloader/manager.go index 4b49a7911..f1dea342f 100644 --- a/pkg/downloader/manager.go +++ b/pkg/downloader/manager.go @@ -203,6 +203,31 @@ func (m *Manager) downloadAll(deps []*chart.Dependency) error { fmt.Fprintf(m.Out, "Saving %d charts\n", len(deps)) var saveError error for _, dep := range deps { + // No repository means the chart is in charts directory + if dep.Repository == "" { + fmt.Fprintf(m.Out, "Dependency %s did not declare a repository. Assuming it exists in the charts directory\n", dep.Name) + chartPath := filepath.Join(tmpPath, dep.Name) + ch, err := loader.LoadDir(chartPath) + if err != nil { + return fmt.Errorf("Unable to load chart: %v", err) + } + + constraint, err := semver.NewConstraint(dep.Version) + if err != nil { + return fmt.Errorf("Dependency %s has an invalid version/constraint format: %s", dep.Name, err) + } + + v, err := semver.NewVersion(ch.Metadata.Version) + if err != nil { + return fmt.Errorf("Invalid version %s for dependency %s: %s", dep.Version, dep.Name, err) + } + + if !constraint.Check(v) { + saveError = fmt.Errorf("Dependency %s at version %s does not satisfy the constraint %s", dep.Name, ch.Metadata.Version, dep.Version) + break + } + continue + } if strings.HasPrefix(dep.Repository, "file://") { if m.Debug { fmt.Fprintf(m.Out, "Archiving %s from repo %s\n", dep.Name, dep.Repository) @@ -247,8 +272,11 @@ func (m *Manager) downloadAll(deps []*chart.Dependency) error { if saveError == nil { fmt.Fprintln(m.Out, "Deleting outdated charts") for _, dep := range deps { - if err := m.safeDeleteDep(dep.Name, tmpPath); err != nil { - return err + // Chart from local charts directory stays in place + if dep.Repository != "" { + if err := m.safeDeleteDep(dep.Name, tmpPath); err != nil { + return err + } } } if err := move(tmpPath, destPath); err != nil { @@ -360,6 +388,10 @@ func (m *Manager) getRepoNames(deps []*chart.Dependency) (map[string]string, err // by Helm. missing := []string{} for _, dd := range deps { + // Don't map the repository, we don't need to download chart from charts directory + if dd.Repository == "" { + continue + } // if dep chart is from local path, verify the path is valid if strings.HasPrefix(dd.Repository, "file://") { if _, err := resolver.GetLocalPath(dd.Repository, m.ChartPath); err != nil { diff --git a/pkg/downloader/manager_test.go b/pkg/downloader/manager_test.go index 06c62ecaa..7939771c9 100644 --- a/pkg/downloader/manager_test.go +++ b/pkg/downloader/manager_test.go @@ -147,6 +147,13 @@ func TestGetRepoNames(t *testing.T) { }, expect: map[string]string{"oedipus-rex": "testing"}, }, + { + name: "repo from local chart under charts path", + req: []*chart.Dependency{ + {Name: "local-subchart", Repository: ""}, + }, + expect: map[string]string{}, + }, } for _, tt := range tests { diff --git a/pkg/downloader/testdata/local-subchart/Chart.yaml b/pkg/downloader/testdata/local-subchart/Chart.yaml new file mode 100644 index 000000000..1e17203e5 --- /dev/null +++ b/pkg/downloader/testdata/local-subchart/Chart.yaml @@ -0,0 +1,3 @@ +description: A Helm chart for Kubernetes +name: local-subchart +version: 0.1.0