Esempio n. 1
0
// Resolve takes a chart and a location and checks whether the chart's dependencies are satisfied.
//
// The `installdir` is the location where installed charts are located. Typically
// this is in $HELM_HOME/workspace/charts.
//
// This returns a list of unsatisfied dependencies (NOT an error condition).
//
// It returns an error only if it cannot perform the task of resolving dependencies.
// Failed dependencies to not constitute an error.
func Resolve(cf *chart.Chartfile, installdir string) ([]*chart.Dependency, error) {
	if len(cf.Dependencies) == 0 {
		log.Debug("No dependencies to check. :achievement-unlocked:")
		return []*chart.Dependency{}, nil
	}

	cache, err := dependencyCache(installdir)
	if err != nil {
		log.Debug("Failed to build dependency cache: %s", err)
		return []*chart.Dependency{}, err
	}

	res := []*chart.Dependency{}

	// TODO: This could be made more efficient.
	for _, check := range cf.Dependencies {
		resolved := false
		for n, chart := range cache {
			log.Debug("Checking if %s (%s) %s meets %s %s", chart.Name, n, chart.Version, check.Name, check.Version)
			if chart.Name == check.Name && check.VersionOK(chart.Version) {
				log.Debug("✔︎")
				resolved = true
				break
			}
		}
		if !resolved {
			log.Debug("No matches found for %s %s", check.Name, check.Version)
			res = append(res, check)
		}
	}
	return res, nil
}
Esempio n. 2
0
// Check by chart directory name whether a chart is fetched into the workspace.
//
// This does NOT check the Chart.yaml file.
func chartFetched(chartName, home string) bool {
	p := filepath.Join(home, WorkspaceChartPath, chartName, "Chart.yaml")
	log.Debug("Looking for %q", p)
	if fi, err := os.Stat(p); err != nil || fi.IsDir() {
		log.Debug("No chart: %s", err)
		return false
	}
	return true
}
Esempio n. 3
0
// ensureHome ensures that a HELM_HOME exists.
func ensureHome(home string) {

	must := []string{home, filepath.Join(home, CachePath), filepath.Join(home, WorkspacePath), filepath.Join(home, CacheChartPath)}

	for _, p := range must {
		if fi, err := os.Stat(p); err != nil {
			log.Debug("Creating %s", p)
			if err := os.MkdirAll(p, 0755); err != nil {
				log.Die("Could not create %q: %s", p, err)
			}
		} else if !fi.IsDir() {
			log.Die("%s must be a directory.", home)
		}
	}

	refi := filepath.Join(home, Configfile)
	if _, err := os.Stat(refi); err != nil {
		log.Info("Creating %s", refi)
		// Attempt to create a Repos.yaml
		if err := ioutil.WriteFile(refi, []byte(config.DefaultConfigfile), 0755); err != nil {
			log.Die("Could not create %s: %s", refi, err)
		}
	}

	if err := os.Chdir(home); err != nil {
		log.Die("Could not change to directory %q: %s", home, err)
	}
}
Esempio n. 4
0
// gitUpdate updates a Git repo.
func gitUpdate(git *vcs.GitRepo) error {
	if err := git.Update(); err != nil {
		return err
	}

	log.Debug("Updated %s from %s", git.LocalPath(), git.Remote())
	return nil
}
Esempio n. 5
0
// Copy a directory and its subdirectories.
func copyDir(src, dst string) error {

	var failure error

	walker := func(fname string, fi os.FileInfo, e error) error {
		if e != nil {
			log.Warn("Encounter error walking %q: %s", fname, e)
			failure = e
			return nil
		}

		log.Debug("Copying %s", fname)
		rf, err := filepath.Rel(src, fname)
		if err != nil {
			log.Warn("Could not find relative path: %s", err)
			return nil
		}
		df := filepath.Join(dst, rf)

		// Handle directories by creating mirrors.
		if fi.IsDir() {
			if err := os.MkdirAll(df, fi.Mode()); err != nil {
				log.Warn("Could not create %q: %s", df, err)
				failure = err
			}
			return nil
		}

		// Otherwise, copy files.
		in, err := os.Open(fname)
		if err != nil {
			log.Warn("Skipping file %s: %s", fname, err)
			return nil
		}
		out, err := os.Create(df)
		if err != nil {
			in.Close()
			log.Warn("Skipping file copy %s: %s", fname, err)
			return nil
		}
		if _, err = io.Copy(out, in); err != nil {
			log.Warn("Copy from %s to %s failed: %s", fname, df, err)
		}

		if err := out.Close(); err != nil {
			log.Warn("Failed to close %q: %s", df, err)
		}
		if err := in.Close(); err != nil {
			log.Warn("Failed to close reader %q: %s", fname, err)
		}

		return nil
	}
	filepath.Walk(src, walker)
	return failure
}
Esempio n. 6
0
func (r *Repos) deleteRepo(name string) error {
	rpath := filepath.Join(r.Dir, name)
	if fi, err := os.Stat(rpath); err != nil || !fi.IsDir() {
		log.Info("Deleted nothing. No repo named %s", name)
		return nil
	}

	log.Debug("Deleting %s", rpath)
	return os.RemoveAll(rpath)
}
Esempio n. 7
0
func kubectlDelete(name, ktype, ns string) error {
	log.Debug("Deleting %s (%s)", name, ktype)
	a := []string{"delete", ktype, name}
	if ns != "" {
		a = append([]string{fmt.Sprintf("--namespace=%q", ns)}, a...)
	}

	cmd := exec.Command("kubectl", a...)

	if d, err := cmd.CombinedOutput(); err != nil {
		return fmt.Errorf("%s: %s", string(d), err)
	}
	return nil
}
Esempio n. 8
0
// ParseDir parses all of the manifests inside of a chart directory.
//
// The directory should be the Chart directory (contains Chart.yaml and manifests/)
//
// This will return an error if the directory does not exist, or if there is an
// error parsing or decoding any yaml files.
func ParseDir(chartDir string) ([]*Manifest, error) {
	dir := filepath.Join(chartDir, "manifests")
	files := []*Manifest{}

	if _, err := os.Stat(dir); err != nil {
		return files, err
	}

	// add manifest files
	walker := func(fname string, fi os.FileInfo, e error) error {
		log.Debug("Parsing %s", fname)
		// Chauncey was right.
		if e != nil {
			return e
		}

		if fi.IsDir() {
			return nil
		}

		if filepath.Ext(fname) != ".yaml" {
			log.Debug("Skipping %s. Not a YAML file.", fname)
			return nil
		}

		m, err := Parse(fname)
		if err != nil {
			return err
		}

		files = append(files, m...)

		return nil
	}

	return files, filepath.Walk(dir, walker)
}
Esempio n. 9
0
func fetch(chartName, lname, homedir, chartpath string) {
	src := filepath.Join(homedir, CachePath, chartpath, chartName)
	dest := filepath.Join(homedir, WorkspaceChartPath, lname)

	if fi, err := os.Stat(src); err != nil {
		log.Die("Chart %s not found in %s", lname, src)
	} else if !fi.IsDir() {
		log.Die("Malformed chart %s: Chart must be in a directory.", chartName)
	}

	if err := os.MkdirAll(dest, 0755); err != nil {
		log.Die("Could not create %q: %s", dest, err)
	}

	log.Debug("Fetching %s to %s", src, dest)
	if err := copyDir(src, dest); err != nil {
		log.Die("Failed copying %s to %s", src, dest)
	}
}
Esempio n. 10
0
// PrintREADME prints the README file (if it exists) to the console.
func PrintREADME(chart, home string) {
	p := filepath.Join(home, WorkspaceChartPath, chart, "README.*")
	files, err := filepath.Glob(p)
	if err != nil || len(files) == 0 {
		// No README. Skip.
		log.Debug("No readme in %s", p)
		return
	}

	f, err := os.Open(files[0])
	if err != nil {
		log.Warn("Could not read README: %s", err)
		return
	}
	log.Msg(strings.Repeat("=", 40))
	io.Copy(log.Stdout, f)
	log.Msg(strings.Repeat("=", 40))
	f.Close()

}
Esempio n. 11
0
// ensureRepo ensures that the repo exists and is checked out.
// DEPRECATED: You should use the functions in package `repo` instead.
func ensureRepo(repo, home string) *vcs.GitRepo {
	if err := os.Chdir(home); err != nil {
		log.Die("Could not change to directory %q: %s", home, err)
	}
	git, err := vcs.NewGitRepo(repo, home)
	if err != nil {
		log.Die("Could not get repository %q: %s", repo, err)
	}

	git.Logger = log.New()

	if !git.CheckLocal() {
		log.Debug("Cloning repo into %q. Please wait.", home)
		if err := git.Get(); err != nil {
			log.Die("Could not create repository in %q: %s", home, err)
		}
	}

	return git
}
Esempio n. 12
0
// kubectlCreate calls `kubectl create` and sends the data via Stdin.
//
// If dryRun is set to true, then we just output the command that was
// going to be run to os.Stdout and return nil.
func kubectlCreate(data []byte, ns string, dryRun bool) error {
	a := []string{"create", "-f", "-"}

	if ns != "" {
		a = append([]string{"--namespace=" + ns}, a...)
	}

	if dryRun {
		cmd := "kubectl"
		for _, arg := range a {
			cmd = fmt.Sprintf("%s %s", cmd, arg)
		}
		cmd = fmt.Sprintf("%s < %s", cmd, data)
		log.Info(cmd)
		return nil
	}

	c := exec.Command("kubectl", a...)
	in, err := c.StdinPipe()
	if err != nil {
		return err
	}

	c.Stdout = os.Stdout
	c.Stderr = os.Stderr

	if err := c.Start(); err != nil {
		return err
	}

	log.Debug("File: %s", string(data))
	in.Write(data)
	in.Close()

	return c.Wait()
}