// List lists all of the local charts. func List(homedir string) { md := filepath.Join(homedir, WorkspaceChartPath, "*") charts, err := filepath.Glob(md) if err != nil { log.Warn("Could not find any charts in %q: %s", md, err) } for _, c := range charts { cname := filepath.Base(c) if ch, err := model.Load(filepath.Join(c, "Chart.yaml")); err == nil { log.Info("\t%s (%s %s) - %s", cname, ch.Name, ch.Version, ch.Description) continue } log.Info("\t%s (unknown)", cname) } }
// 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 following order: // // - Namespaces // - Secrets // - Volumes // - Services // - Pods // - ReplicationControllers func Install(chart, home, namespace string, force bool) { if !chartInstalled(chart, home) { log.Info("No installed chart named %q. Installing now.", chart) fetch(chart, chart, home) } cd := filepath.Join(home, WorkspaceChartPath, chart) c, err := model.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, filepath.Join(home, WorkspaceChartPath)) 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.") } } if err := uploadManifests(c, namespace); err != nil { log.Die("Failed to upload manifests: %s", err) } PrintREADME(chart, home) }
// Search looks for packages with 'term' in their name. func Search(term, homedir string) { charts, err := search(term, homedir) if err != nil { log.Die(err.Error()) } log.Info("\n=================") log.Info("Available Charts") log.Info("=================\n") log.Info("") for dir, chart := range charts { log.Info("\t%s (%s %s) - %s", filepath.Base(dir), chart.Name, chart.Version, chart.Description) } }
// kubectlCreate calls `kubectl create` and sends the data via Stdin. func kubectlCreate(data []byte, ns string) error { a := []string{"create", "-f", "-"} if ns != "" { a = append([]string{"--namespace=" + ns}, a...) } 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.Info("File: %s", string(data)) in.Write(data) in.Close() return c.Wait() }
func search(term, homedir string) (map[string]*model.Chartfile, error) { dirs, err := filepath.Glob(filepath.Join(homedir, CacheChartPath, "*")) if err != nil { return nil, fmt.Errorf("No results found. %s", err) } else if len(dirs) == 0 { return nil, errors.New("No results found.") } charts := make(map[string]*model.Chartfile) r, _ := regexp.Compile(term) for _, dir := range dirs { chart, err := model.LoadChartfile(filepath.Join(dir, "Chart.yaml")) if err != nil { log.Info("\t%s - UNKNOWN", filepath.Base(dir)) continue } else if r.MatchString(chart.Name) || r.MatchString(chart.Description) { charts[dir] = chart } } return charts, nil }
// gitUpdate updates a Git repo. func gitUpdate(git *vcs.GitRepo) error { if err := git.Update(); err != nil { return err } log.Info("Updated %s from %s", git.LocalPath(), git.Remote()) return nil }
// gitUpdate updates a Git repo. func gitUpdate(git *vcs.GitRepo) error { if err := git.Update(); err != nil { return err } // TODO: We should make this pretty. log.Info("Updated") return nil }
// 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.Info("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 }
func Install(chart, home, namespace string) { Fetch(chart, chart, home) log.Info("kubectl --namespace=%q create -f %s.yaml", namespace, chart) if !chartInstalled(chart, home) { log.Info("No installed chart named %q. Installing now.", chart) Fetch(chart, chart, home) } d := filepath.Join(home, WorkspaceChartPath, chart, "manifests") log.Debug("Looking for manifests in %q", d) files, err := manifestFiles(d) if err != nil { log.Die("No manifests to install: %s", err) } for _, f := range files { if err := kubectlCreate(f, namespace); err != nil { log.Warn("Failed to install manifest %q: %s", f, err) } } }
func Uninstall(chart, home, namespace string) { if !chartInstalled(chart, home) { log.Info("No installed chart named %q. Nothing to delete.", chart) return } cd := filepath.Join(home, WorkspaceChartPath, chart) c, err := model.Load(cd) if err != nil { log.Die("Failed to load chart: %s", err) } if err := deleteChart(c, namespace); err != nil { log.Die("Failed to completely delete chart: %s", err) } }
func Info(chart, homedir string) { chartPath := filepath.Join(homedir, CacheChartPath, chart, "Chart.yaml") log.Info("%s", chartPath) chartModel, err := model.LoadChartfile(chartPath) if err != nil { log.Die("%s - UNKNOWN", chart) } log.Info("Chart: %s", chartModel.Name) log.Info("Description: %s", chartModel.Description) log.Info("Details: %s", chartModel.Details) log.Info("Version: %s", chartModel.Version) log.Info("Website: %s", chartModel.Home) log.Info("From: %s", chartPath) log.Info("Dependencies: %s", chartModel.Dependencies) }
// ensureHome ensures that a HELM_HOME exists. func ensureHome(home string) { if fi, err := os.Stat(home); err != nil { log.Info("Creating %s", home) for _, p := range helmpaths { pp := filepath.Join(home, p) if err := os.MkdirAll(pp, 0755); err != nil { log.Die("Could not create %q: %s", pp, err) } } } else if !fi.IsDir() { log.Die("%s must be a directory.", home) } if err := os.Chdir(home); err != nil { log.Die("Could not change to directory %q: %s", home, err) } }
// ensureRepo ensures that the repo exists and is checked out. 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) } if !git.CheckLocal() { log.Info("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 }
func fetch(chart, lname, homedir string) { src := filepath.Join(homedir, CacheChartPath, chart) dest := filepath.Join(homedir, WorkspaceChartPath, lname) if fi, err := os.Stat(src); err != nil { } else if !fi.IsDir() { log.Die("Malformed chart %s: Chart must be in a directory.", chart) } if err := os.MkdirAll(dest, 0755); err != nil { log.Die("Could not create %q: %s", dest, err) } log.Info("Fetching %s to %s", src, dest) if err := copyDir(src, dest); err != nil { log.Die("Failed copying %s to %s", src, dest) } }
// ensureHome ensures that a HELM_HOME exists. func ensureHome(home string) { must := []string{home, filepath.Join(home, CachePath), filepath.Join(home, WorkspacePath)} for _, p := range must { if fi, err := os.Stat(p); err != nil { log.Info("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) } } if err := os.Chdir(home); err != nil { log.Die("Could not change to directory %q: %s", home, err) } }
// Search looks for packages with 'term' in their name. func Search(term, homedir string) { dirs, err := search(term, homedir) if err != nil { log.Die(err.Error()) } log.Info("\n=================") log.Info("Available Charts") log.Info("=================\n") for _, d := range dirs { y, err := model.LoadChartfile(filepath.Join(d, "Chart.yaml")) if err != nil { log.Info("\t%s - UNKNOWN", filepath.Base(d)) continue } log.Info("\t%s (%s %s) - %s", filepath.Base(d), y.Name, y.Version, y.Description) } log.Info("") }
// Search looks for packages with 'term' in their name. func Search(term, homedir string) { term = sanitizeTerm(term) sp := filepath.Join(homedir, CacheChartPath, "*"+term+"*") dirs, err := filepath.Glob(sp) if err != nil { log.Die("No results found. %s", err) } log.Info("\n=================") log.Info("Available Charts") log.Info("=================\n") for _, d := range dirs { y, err := model.Load(filepath.Join(d, "Chart.yaml")) if err != nil { log.Info("\t%s - UNKNOWN", filepath.Base(d)) continue } log.Info("\t%s (%s %s) - %s", filepath.Base(d), y.Name, y.Version, y.Description) } log.Info("") }
func Uninstall(chart, home, namespace string) { log.Info("Do something!") }
func Build(chart, homedir string) { log.Info("Rebuilding %s", chart) }