From 21edd808b646d283f5a18573a9362d5ac023ca05 Mon Sep 17 00:00:00 2001 From: Sebastien Plisson Date: Tue, 30 Jan 2018 09:29:24 -0800 Subject: [PATCH] #3321 Accept dependency in requirements.yaml from charts directory. Signed-off-by: Sebastien Plisson --- pkg/downloader/manager.go | 91 +++++++++++++++++++++++++++++++++++++-- pkg/resolver/resolver.go | 13 ++++++ 2 files changed, 101 insertions(+), 3 deletions(-) diff --git a/pkg/downloader/manager.go b/pkg/downloader/manager.go index 23a5b587e..cc517424d 100644 --- a/pkg/downloader/manager.go +++ b/pkg/downloader/manager.go @@ -216,6 +216,30 @@ func (m *Manager) downloadAll(deps []*chartutil.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 == "" { + chartPath := filepath.Join(tmpPath, dep.Name) + ch, err := chartutil.LoadDir(chartPath) + if err != nil { + return fmt.Errorf("Unable to load local 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("Chart %s has an invalid version format: %s", dep.Name, err) + } + + if !constraint.Check(v) { + saveError = fmt.Errorf("Can't get a valid version for dependency %s", dep.Name) + 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) @@ -258,8 +282,11 @@ func (m *Manager) downloadAll(deps []*chartutil.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 { @@ -371,8 +398,9 @@ func (m *Manager) getRepoNames(deps []*chartutil.Dependency) (map[string]string, // 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 == "" { - return nil, fmt.Errorf("no 'repository' field specified for dependency: %q", dd.Name) + continue } // if dep chart is from local path, verify the path is valid if strings.HasPrefix(dd.Repository, "file://") { @@ -663,3 +691,60 @@ func move(tmpPath, destPath string) error { } return nil } + +func copyFile(source string, destination string) (err error) { + sourceFile, err := os.Open(source) + if err != nil { + return err + } + defer sourceFile.Close() + destinationFile, err := os.Create(destination) + if err != nil { + return err + } + defer destinationFile.Close() + _, err = io.Copy(destinationFile, sourceFile) + if err == nil { + stats, err := os.Stat(source) + if err == nil { + return os.Chmod(destination, stats.Mode()) + } + } + return err +} + +func copyDir(source string, destination string) (err error) { + fi, err := os.Stat(source) + if err != nil { + return err + } + if !fi.IsDir() { + return fmt.Errorf("Source is not a directory") + } + _, err = os.Open(destination) + if !os.IsNotExist(err) { + return fmt.Errorf("Destination already exists") + } + err = os.MkdirAll(destination, fi.Mode()) + if err != nil { + return err + } + + entries, err := ioutil.ReadDir(source) + for _, entry := range entries { + sourceFile := source + "/" + entry.Name() + destinationFile := destination + "/" + entry.Name() + if entry.IsDir() { + err = copyDir(sourceFile, destinationFile) + if err != nil { + return err + } + } else { + err = copyFile(sourceFile, destinationFile) + if err != nil { + return err + } + } + } + return +} diff --git a/pkg/resolver/resolver.go b/pkg/resolver/resolver.go index 516e9260f..653606df0 100644 --- a/pkg/resolver/resolver.go +++ b/pkg/resolver/resolver.go @@ -53,6 +53,19 @@ func (r *Resolver) Resolve(reqs *chartutil.Requirements, repoNames map[string]st locked := make([]*chartutil.Dependency, len(reqs.Dependencies)) missing := []string{} for i, d := range reqs.Dependencies { + if d.Repository == "" { + // Local chart subfolder + if _, err := GetLocalPath(filepath.Join("charts", d.Name), r.chartpath); err != nil { + return nil, err + } + + locked[i] = &chartutil.Dependency{ + Name: d.Name, + Repository: "", + Version: d.Version, + } + continue + } if strings.HasPrefix(d.Repository, "file://") { if _, err := GetLocalPath(d.Repository, r.chartpath); err != nil {