Beispiel #1
0
// uploadManifests sends manifests to Kubectl in a particular order.
func uploadManifests(c *chart.Chart, namespace string, client kubectl.Runner) error {

	// Install known kinds in a predictable order.
	for _, k := range InstallOrder {
		for _, m := range c.Kind[k] {
			o := m.VersionedObject
			o.AddAnnotations(map[string]string{
				chart.AnnFile:         m.Source,
				chart.AnnChartVersion: c.Chartfile.Version,
				chart.AnnChartDesc:    c.Chartfile.Description,
				chart.AnnChartName:    c.Chartfile.Name,
			})
			var data []byte
			var err error
			if data, err = o.JSON(); err != nil {
				return err
			}

			var action = client.Create
			// If it's a keeper manifest, do "kubectl apply" instead of "create."
			if manifest.IsKeeper(data) {
				action = client.Apply
			}
			log.Debug("File: %s", string(data))
			out, err := action(data, namespace)
			log.Msg(string(out))
			if err != nil {
				return err
			}
		}
	}

	// Install unknown kinds afterward. Order here is not predictable.
	for _, k := range c.UnknownKinds(InstallOrder) {
		for _, o := range c.Kind[k] {
			o.VersionedObject.AddAnnotations(map[string]string{chart.AnnFile: o.Source})
			data, err := o.VersionedObject.JSON()
			if err != nil {
				return err
			}
			out, err := client.Create(data, namespace)
			log.Msg(string(out))
			if err != nil {
				return err
			}
		}
	}

	return nil
}
Beispiel #2
0
// Target displays information about the cluster
func Target(client kubectl.Runner) {
	out, err := client.ClusterInfo()
	if err != nil {
		log.Err(err.Error())
	}
	log.Msg(string(out))
}
Beispiel #3
0
// Fetch gets a chart from the source repo and copies to the workdir.
//
// - chartName is the source
// - lname is the local name for that chart (chart-name); if blank, it is set to the chart.
// - homedir is the home directory for the user
func Fetch(chartName, lname, homedir string) {

	r := mustConfig(homedir).Repos
	repository, chartName := r.RepoChart(chartName)

	if lname == "" {
		lname = chartName
	}

	fetch(chartName, lname, homedir, repository)

	chartFilePath := helm.WorkspaceChartDirectory(homedir, lname, Chartfile)
	cfile, err := chart.LoadChartfile(chartFilePath)
	if err != nil {
		log.Die("Source is not a valid chart. Missing Chart.yaml: %s", err)
	}

	deps, err := dependency.Resolve(cfile, helm.WorkspaceChartDirectory(homedir))
	if err != nil {
		log.Warn("Could not check dependencies: %s", err)
		return
	}

	if len(deps) > 0 {
		log.Warn("Unsatisfied dependencies:")
		for _, d := range deps {
			log.Msg("\t%s %s", d.Name, d.Version)
		}
	}

	log.Info("Fetched chart into workspace %s", helm.WorkspaceChartDirectory(homedir, lname))
	log.Info("Done")
}
Beispiel #4
0
// PrintREADME prints the README file (if it exists) to the console.
func PrintREADME(chart, home string) {
	p := helm.WorkspaceChartDirectory(home, 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()

}
Beispiel #5
0
// ListRepos lists the repositories.
func ListRepos(homedir string) {
	rf := mustConfig(homedir).Repos

	for _, t := range rf.Tables {
		n := t.Name
		if t.Name == rf.Default {
			n += "*"
		}
		log.Msg("\t%s\t%s", n, t.Repo)
	}
}
Beispiel #6
0
// Install loads a chart into Kubernetes.
//
// If the chart is not found in the workspace, it is fetched and then installed.
//
// During install, manifests are sent to Kubernetes in the ordered specified by InstallOrder.
func Install(chartName, home, namespace string, force bool, generate bool, exclude []string, client kubectl.Runner) {
	ochart := chartName
	r := mustConfig(home).Repos
	table, chartName := r.RepoChart(chartName)

	if !chartFetched(chartName, home) {
		log.Info("No chart named %q in your workspace. Fetching now.", ochart)
		fetch(chartName, chartName, home, table)
	}

	cd := helm.WorkspaceChartDirectory(home, chartName)
	c, err := chart.Load(cd)
	if err != nil {
		log.Die("Failed to load chart: %s", err)
	}

	// Give user the option to bale if dependencies are not satisfied.
	nope, err := dependency.Resolve(c.Chartfile, helm.WorkspaceChartDirectory(home))

	if err != nil {
		log.Warn("Failed to check dependencies: %s", err)
		if !force {
			log.Die("Re-run with --force to install anyway.")
		}
	} else if len(nope) > 0 {
		log.Warn("Unsatisfied dependencies:")
		for _, d := range nope {
			log.Msg("\t%s %s", d.Name, d.Version)
		}
		if !force {
			log.Die("Stopping install. Re-run with --force to install anyway.")
		}
	}

	// Run the generator if -g is set.
	if generate {
		Generate(chartName, home, exclude, force)
	}

	CheckKubePrereqs()

	log.Info("Running `kubectl create -f` ...")
	if err := uploadManifests(c, namespace, client); err != nil {
		log.Die("Failed to upload manifests: %s", err)
	}
	log.Info("Done")

	PrintREADME(chartName, home)
}
Beispiel #7
0
// printSummary prints a diff of charts after upate
func printSummary(diff string) {
	if len(diff) == 0 {
		log.Msg("Already up-to-date.")
		return
	}

	s := make(repoSummary)

	// parse git diff-tree
	for _, line := range strings.Split(diff, "\n") {
		kv := strings.Split(line, "\t")
		st, chart := kv[0], kv[1]

		s.add(st, chart)
	}

	// width of columns
	colwidth := 29

	// get console width
	maxwidth := 118
	if w, _, err := terminal.GetSize(int(os.Stdout.Fd())); err == nil {
		maxwidth = w
	}

	// print results
	for st, charts := range s {
		switch st {
		case "A":
			log.Msg("Added %d charts", len(charts))
		case "D":
			log.Msg("Sent %d charts to the depths", len(charts))
		case "M":
			log.Msg("Updated %d charts", len(charts))
		}

		line := ""
		for _, ch := range charts {
			// if adding this column passes the max
			// print and reset to zero
			if len(line)+colwidth > maxwidth {
				log.Msg(line)
				line = ""
			}
			// append to line with padding
			line = fmt.Sprintf("%s%-29s", line, ch)
		}
		log.Msg(line)
	}
}
Beispiel #8
0
func uninstallKind(kind []*manifest.Manifest, ns, ktype string, dry bool, client kubectl.Runner) {
	for _, o := range kind {
		if dry {
			log.Msg("%s/%s", ktype, o.Name)
		} else {
			// If it's a keeper manifest, skip uninstall.
			if data, err := o.VersionedObject.JSON(); err == nil {
				if manifest.IsKeeper(data) {
					log.Warn("Not uninstalling %s %s because of \"helm-keep\" annotation.\n"+
						"---> Use kubectl to uninstall keeper manifests.\n", ktype, o.Name)
					continue
				}
			}
			out, err := client.Delete(o.Name, ktype, ns)
			if err != nil {
				log.Warn("Could not delete %s %s (Skipping): %s", ktype, o.Name, err)
			}
			log.Info(string(out))
		}
	}
}
Beispiel #9
0
// Search looks for packages with 'term' in their name.
func Search(term, homedir string, regexp bool) {
	cfg := mustConfig(homedir)
	cdir := helm.CacheDirectory(homedir)

	i := search.NewIndex(cfg, cdir)
	res, err := i.Search(term, 5, regexp)
	if err != nil {
		log.Die("Failed to search: %s", err)
	}

	if len(res) == 0 {
		log.Err("No results found. Try using '--regexp'.")
		return
	}

	search.SortScore(res)

	for _, r := range res {
		c, _ := i.Chart(r.Name)
		log.Msg("%s - %s", r.Name, c.Description)
	}
}
Beispiel #10
0
package cli

import (
	"github.com/codegangsta/cli"
	"github.com/helm/helm-classic/log"
)

var homeCmd = cli.Command{
	Name:      "home",
	Usage:     "Displays the location of the Helm Classic home.",
	ArgsUsage: "",
	Action: func(c *cli.Context) {
		log.Msg(home(c))
	},
}