Merge pull request #4027 from adamreese/dev-v3-ref-cmd

ref(cmd): consistent naming of cmd variables
pull/4029/head
Adam Reese 6 years ago committed by GitHub
commit b5f52905df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -37,16 +37,11 @@ For example, 'helm create foo' will create a directory structure that looks
something like this:
foo/
|
|- .helmignore # Contains patterns to ignore when packaging Helm charts.
|
|- Chart.yaml # Information about your chart
|
|- values.yaml # The default values for your templates
|
|- charts/ # Charts that this chart depends on
|
|- templates/ # The template files
.helmignore # Contains patterns to ignore when packaging Helm charts.
Chart.yaml # Information about your chart
values.yaml # The default values for your templates
charts/ # Charts that this chart depends on
templates/ # The template files
'helm create' takes a path for an argument. If directories in the given path
do not exist, Helm will attempt to create them as it goes. If the given
@ -54,38 +49,40 @@ destination exists and there are files in that directory, conflicting files
will be overwritten, but other files will be left alone.
`
type createCmd struct {
home helmpath.Home
name string
out io.Writer
starter string
type createOptions struct {
starter string // --starter
// args
name string
home helmpath.Home
}
func newCreateCmd(out io.Writer) *cobra.Command {
cc := &createCmd{out: out}
o := &createOptions{}
cmd := &cobra.Command{
Use: "create NAME",
Short: "create a new chart with the given name",
Long: createDesc,
RunE: func(cmd *cobra.Command, args []string) error {
cc.home = settings.Home
o.home = settings.Home
if len(args) == 0 {
return errors.New("the name of the new chart is required")
}
cc.name = args[0]
return cc.run()
o.name = args[0]
return o.run(out)
},
}
cmd.Flags().StringVarP(&cc.starter, "starter", "p", "", "the named Helm starter scaffold")
cmd.Flags().StringVarP(&o.starter, "starter", "p", "", "the named Helm starter scaffold")
return cmd
}
func (c *createCmd) run() error {
fmt.Fprintf(c.out, "Creating %s\n", c.name)
func (o *createOptions) run(out io.Writer) error {
fmt.Fprintf(out, "Creating %s\n", o.name)
chartname := filepath.Base(c.name)
chartname := filepath.Base(o.name)
cfile := &chart.Metadata{
Name: chartname,
Description: "A Helm chart for Kubernetes",
@ -94,12 +91,12 @@ func (c *createCmd) run() error {
APIVersion: chartutil.APIVersionv1,
}
if c.starter != "" {
if o.starter != "" {
// Create from the starter
lstarter := filepath.Join(c.home.Starters(), c.starter)
return chartutil.CreateFrom(cfile, filepath.Dir(c.name), lstarter)
lstarter := filepath.Join(o.home.Starters(), o.starter)
return chartutil.CreateFrom(cfile, filepath.Dir(o.name), lstarter)
}
_, err := chartutil.Create(cfile, filepath.Dir(c.name))
_, err := chartutil.Create(cfile, filepath.Dir(o.name))
return err
}

@ -34,22 +34,20 @@ Use the '--dry-run' flag to see which releases will be deleted without actually
deleting them.
`
type deleteCmd struct {
name string
dryRun bool
disableHooks bool
purge bool
timeout int64
out io.Writer
type deleteOptions struct {
disableHooks bool // --no-hooks
dryRun bool // --dry-run
purge bool // --purge
timeout int64 // --timeout
// args
name string
client helm.Interface
}
func newDeleteCmd(c helm.Interface, out io.Writer) *cobra.Command {
del := &deleteCmd{
out: out,
client: c,
}
o := &deleteOptions{client: c}
cmd := &cobra.Command{
Use: "delete [flags] RELEASE_NAME [...]",
@ -61,39 +59,39 @@ func newDeleteCmd(c helm.Interface, out io.Writer) *cobra.Command {
if len(args) == 0 {
return errors.New("command 'delete' requires a release name")
}
del.client = ensureHelmClient(del.client, false)
o.client = ensureHelmClient(o.client, false)
for i := 0; i < len(args); i++ {
del.name = args[i]
if err := del.run(); err != nil {
o.name = args[i]
if err := o.run(out); err != nil {
return err
}
fmt.Fprintf(out, "release \"%s\" deleted\n", del.name)
fmt.Fprintf(out, "release \"%s\" deleted\n", o.name)
}
return nil
},
}
f := cmd.Flags()
f.BoolVar(&del.dryRun, "dry-run", false, "simulate a delete")
f.BoolVar(&del.disableHooks, "no-hooks", false, "prevent hooks from running during deletion")
f.BoolVar(&del.purge, "purge", false, "remove the release from the store and make its name free for later use")
f.Int64Var(&del.timeout, "timeout", 300, "time in seconds to wait for any individual Kubernetes operation (like Jobs for hooks)")
f.BoolVar(&o.dryRun, "dry-run", false, "simulate a delete")
f.BoolVar(&o.disableHooks, "no-hooks", false, "prevent hooks from running during deletion")
f.BoolVar(&o.purge, "purge", false, "remove the release from the store and make its name free for later use")
f.Int64Var(&o.timeout, "timeout", 300, "time in seconds to wait for any individual Kubernetes operation (like Jobs for hooks)")
return cmd
}
func (d *deleteCmd) run() error {
func (o *deleteOptions) run(out io.Writer) error {
opts := []helm.DeleteOption{
helm.DeleteDryRun(d.dryRun),
helm.DeleteDisableHooks(d.disableHooks),
helm.DeletePurge(d.purge),
helm.DeleteTimeout(d.timeout),
helm.DeleteDryRun(o.dryRun),
helm.DeleteDisableHooks(o.disableHooks),
helm.DeletePurge(o.purge),
helm.DeleteTimeout(o.timeout),
}
res, err := d.client.DeleteRelease(d.name, opts...)
res, err := o.client.DeleteRelease(o.name, opts...)
if res != nil && res.Info != "" {
fmt.Fprintln(d.out, res.Info)
fmt.Fprintln(out, res.Info)
}
return err

@ -102,13 +102,14 @@ func newDependencyCmd(out io.Writer) *cobra.Command {
return cmd
}
type dependencyListCmd struct {
out io.Writer
type dependencyLisOptions struct {
chartpath string
}
func newDependencyListCmd(out io.Writer) *cobra.Command {
dlc := &dependencyListCmd{out: out}
o := &dependencyLisOptions{
chartpath: ".",
}
cmd := &cobra.Command{
Use: "list [flags] CHART",
@ -116,20 +117,17 @@ func newDependencyListCmd(out io.Writer) *cobra.Command {
Short: "list the dependencies for the given chart",
Long: dependencyListDesc,
RunE: func(cmd *cobra.Command, args []string) error {
cp := "."
if len(args) > 0 {
cp = args[0]
o.chartpath = filepath.Clean(args[0])
}
dlc.chartpath = filepath.Clean(cp)
return dlc.run()
return o.run(out)
},
}
return cmd
}
func (l *dependencyListCmd) run() error {
c, err := chartutil.Load(l.chartpath)
func (o *dependencyLisOptions) run(out io.Writer) error {
c, err := chartutil.Load(o.chartpath)
if err != nil {
return err
}
@ -137,21 +135,21 @@ func (l *dependencyListCmd) run() error {
r, err := chartutil.LoadRequirements(c)
if err != nil {
if err == chartutil.ErrRequirementsNotFound {
fmt.Fprintf(l.out, "WARNING: no requirements at %s/charts\n", l.chartpath)
fmt.Fprintf(out, "WARNING: no requirements at %s/charts\n", o.chartpath)
return nil
}
return err
}
l.printRequirements(r, l.out)
fmt.Fprintln(l.out)
l.printMissing(r)
o.printRequirements(out, r)
fmt.Fprintln(out)
o.printMissing(out, r)
return nil
}
func (l *dependencyListCmd) dependencyStatus(dep *chartutil.Dependency) string {
func (o *dependencyLisOptions) dependencyStatus(dep *chartutil.Dependency) string {
filename := fmt.Sprintf("%s-%s.tgz", dep.Name, "*")
archives, err := filepath.Glob(filepath.Join(l.chartpath, "charts", filename))
archives, err := filepath.Glob(filepath.Join(o.chartpath, "charts", filename))
if err != nil {
return "bad pattern"
} else if len(archives) > 1 {
@ -187,7 +185,7 @@ func (l *dependencyListCmd) dependencyStatus(dep *chartutil.Dependency) string {
}
}
folder := filepath.Join(l.chartpath, "charts", dep.Name)
folder := filepath.Join(o.chartpath, "charts", dep.Name)
if fi, err := os.Stat(folder); err != nil {
return "missing"
} else if !fi.IsDir() {
@ -224,29 +222,29 @@ func (l *dependencyListCmd) dependencyStatus(dep *chartutil.Dependency) string {
}
// printRequirements prints all of the requirements in the yaml file.
func (l *dependencyListCmd) printRequirements(reqs *chartutil.Requirements, out io.Writer) {
func (o *dependencyLisOptions) printRequirements(out io.Writer, reqs *chartutil.Requirements) {
table := uitable.New()
table.MaxColWidth = 80
table.AddRow("NAME", "VERSION", "REPOSITORY", "STATUS")
for _, row := range reqs.Dependencies {
table.AddRow(row.Name, row.Version, row.Repository, l.dependencyStatus(row))
table.AddRow(row.Name, row.Version, row.Repository, o.dependencyStatus(row))
}
fmt.Fprintln(out, table)
}
// printMissing prints warnings about charts that are present on disk, but are not in the requirements.
func (l *dependencyListCmd) printMissing(reqs *chartutil.Requirements) {
folder := filepath.Join(l.chartpath, "charts/*")
func (o *dependencyLisOptions) printMissing(out io.Writer, reqs *chartutil.Requirements) {
folder := filepath.Join(o.chartpath, "charts/*")
files, err := filepath.Glob(folder)
if err != nil {
fmt.Fprintln(l.out, err)
fmt.Fprintln(out, err)
return
}
for _, f := range files {
fi, err := os.Stat(f)
if err != nil {
fmt.Fprintf(l.out, "Warning: %s\n", err)
fmt.Fprintf(out, "Warning: %s\n", err)
}
// Skip anything that is not a directory and not a tgz file.
if !fi.IsDir() && filepath.Ext(f) != ".tgz" {
@ -254,7 +252,7 @@ func (l *dependencyListCmd) printMissing(reqs *chartutil.Requirements) {
}
c, err := chartutil.Load(f)
if err != nil {
fmt.Fprintf(l.out, "WARNING: %q is not a chart.\n", f)
fmt.Fprintf(out, "WARNING: %q is not a chart.\n", f)
continue
}
found := false
@ -265,7 +263,7 @@ func (l *dependencyListCmd) printMissing(reqs *chartutil.Requirements) {
}
}
if !found {
fmt.Fprintf(l.out, "WARNING: %q is not in requirements.yaml.\n", f)
fmt.Fprintf(out, "WARNING: %q is not in requirements.yaml.\n", f)
}
}

@ -36,48 +36,50 @@ If no lock file is found, 'helm dependency build' will mirror the behavior
of 'helm dependency update'.
`
type dependencyBuildCmd struct {
out io.Writer
type dependencyBuildOptions struct {
keyring string // --keyring
verify bool // --verify
// args
chartpath string
verify bool
keyring string
helmhome helmpath.Home
helmhome helmpath.Home
}
func newDependencyBuildCmd(out io.Writer) *cobra.Command {
dbc := &dependencyBuildCmd{out: out}
o := &dependencyBuildOptions{
chartpath: ".",
}
cmd := &cobra.Command{
Use: "build [flags] CHART",
Short: "rebuild the charts/ directory based on the requirements.lock file",
Long: dependencyBuildDesc,
RunE: func(cmd *cobra.Command, args []string) error {
dbc.helmhome = settings.Home
dbc.chartpath = "."
o.helmhome = settings.Home
if len(args) > 0 {
dbc.chartpath = args[0]
o.chartpath = args[0]
}
return dbc.run()
return o.run(out)
},
}
f := cmd.Flags()
f.BoolVar(&dbc.verify, "verify", false, "verify the packages against signatures")
f.StringVar(&dbc.keyring, "keyring", defaultKeyring(), "keyring containing public keys")
f.BoolVar(&o.verify, "verify", false, "verify the packages against signatures")
f.StringVar(&o.keyring, "keyring", defaultKeyring(), "keyring containing public keys")
return cmd
}
func (d *dependencyBuildCmd) run() error {
func (o *dependencyBuildOptions) run(out io.Writer) error {
man := &downloader.Manager{
Out: d.out,
ChartPath: d.chartpath,
HelmHome: d.helmhome,
Keyring: d.keyring,
Out: out,
ChartPath: o.chartpath,
HelmHome: o.helmhome,
Keyring: o.keyring,
Getters: getter.All(settings),
}
if d.verify {
if o.verify {
man.Verify = downloader.VerifyIfPossible
}

@ -41,19 +41,23 @@ reason, an update command will not remove charts unless they are (a) present
in the requirements.yaml file, but (b) at the wrong version.
`
// dependencyUpdateCmd describes a 'helm dependency update'
type dependencyUpdateCmd struct {
out io.Writer
chartpath string
helmhome helmpath.Home
verify bool
keyring string
skipRefresh bool
// dependencyUpdateOptions describes a 'helm dependency update'
type dependencyUpdateOptions struct {
keyring string // --keyring
skipRefresh bool // --skip-refresh
verify bool // --verify
// args
chartpath string
helmhome helmpath.Home
}
// newDependencyUpdateCmd creates a new dependency update command.
func newDependencyUpdateCmd(out io.Writer) *cobra.Command {
duc := &dependencyUpdateCmd{out: out}
o := &dependencyUpdateOptions{
chartpath: ".",
}
cmd := &cobra.Command{
Use: "update [flags] CHART",
@ -61,42 +65,33 @@ func newDependencyUpdateCmd(out io.Writer) *cobra.Command {
Short: "update charts/ based on the contents of requirements.yaml",
Long: dependencyUpDesc,
RunE: func(cmd *cobra.Command, args []string) error {
cp := "."
if len(args) > 0 {
cp = args[0]
o.chartpath = filepath.Clean(args[0])
}
var err error
duc.chartpath, err = filepath.Abs(cp)
if err != nil {
return err
}
duc.helmhome = settings.Home
return duc.run()
o.helmhome = settings.Home
return o.run(out)
},
}
f := cmd.Flags()
f.BoolVar(&duc.verify, "verify", false, "verify the packages against signatures")
f.StringVar(&duc.keyring, "keyring", defaultKeyring(), "keyring containing public keys")
f.BoolVar(&duc.skipRefresh, "skip-refresh", false, "do not refresh the local repository cache")
f.BoolVar(&o.verify, "verify", false, "verify the packages against signatures")
f.StringVar(&o.keyring, "keyring", defaultKeyring(), "keyring containing public keys")
f.BoolVar(&o.skipRefresh, "skip-refresh", false, "do not refresh the local repository cache")
return cmd
}
// run runs the full dependency update process.
func (d *dependencyUpdateCmd) run() error {
func (o *dependencyUpdateOptions) run(out io.Writer) error {
man := &downloader.Manager{
Out: d.out,
ChartPath: d.chartpath,
HelmHome: d.helmhome,
Keyring: d.keyring,
SkipUpdate: d.skipRefresh,
Out: out,
ChartPath: o.chartpath,
HelmHome: o.helmhome,
Keyring: o.keyring,
SkipUpdate: o.skipRefresh,
Getters: getter.All(settings),
}
if d.verify {
if o.verify {
man.Verify = downloader.VerifyAlways
}
if settings.Debug {

@ -190,11 +190,11 @@ func TestDependencyUpdateCmd_DontDeleteOldChartsOnError(t *testing.T) {
}
out := bytes.NewBuffer(nil)
duc := &dependencyUpdateCmd{out: out}
duc.helmhome = helmpath.Home(hh)
duc.chartpath = hh.Path(chartname)
o := &dependencyUpdateOptions{}
o.helmhome = helmpath.Home(hh)
o.chartpath = hh.Path(chartname)
if err := duc.run(); err != nil {
if err := o.run(out); err != nil {
output := out.String()
t.Logf("Output: %s", output)
t.Fatal(err)
@ -203,14 +203,14 @@ func TestDependencyUpdateCmd_DontDeleteOldChartsOnError(t *testing.T) {
// Chart repo is down
srv.Stop()
if err := duc.run(); err == nil {
if err := o.run(out); err == nil {
output := out.String()
t.Logf("Output: %s", output)
t.Fatal("Expected error, got nil")
}
// Make sure charts dir still has dependencies
files, err := ioutil.ReadDir(filepath.Join(duc.chartpath, "charts"))
files, err := ioutil.ReadDir(filepath.Join(o.chartpath, "charts"))
if err != nil {
t.Fatal(err)
}
@ -226,7 +226,7 @@ func TestDependencyUpdateCmd_DontDeleteOldChartsOnError(t *testing.T) {
}
// Make sure tmpcharts is deleted
if _, err := os.Stat(filepath.Join(duc.chartpath, "tmpcharts")); !os.IsNotExist(err) {
if _, err := os.Stat(filepath.Join(o.chartpath, "tmpcharts")); !os.IsNotExist(err) {
t.Fatalf("tmpcharts dir still exists")
}
}

@ -37,15 +37,14 @@ It can also generate bash autocompletions.
$ helm docs markdown -dir mydocs/
`
type docsCmd struct {
out io.Writer
type docsOptions struct {
dest string
docTypeString string
topCmd *cobra.Command
}
func newDocsCmd(out io.Writer) *cobra.Command {
dc := &docsCmd{out: out}
o := &docsOptions{}
cmd := &cobra.Command{
Use: "docs",
@ -53,28 +52,28 @@ func newDocsCmd(out io.Writer) *cobra.Command {
Long: docsDesc,
Hidden: true,
RunE: func(cmd *cobra.Command, args []string) error {
dc.topCmd = cmd.Root()
return dc.run()
o.topCmd = cmd.Root()
return o.run(out)
},
}
f := cmd.Flags()
f.StringVar(&dc.dest, "dir", "./", "directory to which documentation is written")
f.StringVar(&dc.docTypeString, "type", "markdown", "the type of documentation to generate (markdown, man, bash)")
f.StringVar(&o.dest, "dir", "./", "directory to which documentation is written")
f.StringVar(&o.docTypeString, "type", "markdown", "the type of documentation to generate (markdown, man, bash)")
return cmd
}
func (d *docsCmd) run() error {
switch d.docTypeString {
func (o *docsOptions) run(out io.Writer) error {
switch o.docTypeString {
case "markdown", "mdown", "md":
return doc.GenMarkdownTree(d.topCmd, d.dest)
return doc.GenMarkdownTree(o.topCmd, o.dest)
case "man":
manHdr := &doc.GenManHeader{Title: "HELM", Section: "1"}
return doc.GenManTree(d.topCmd, manHdr, d.dest)
return doc.GenManTree(o.topCmd, manHdr, o.dest)
case "bash":
return d.topCmd.GenBashCompletionFile(filepath.Join(d.dest, "completions.bash"))
return o.topCmd.GenBashCompletionFile(filepath.Join(o.dest, "completions.bash"))
default:
return fmt.Errorf("unknown doc type %q. Try 'markdown' or 'man'", d.docTypeString)
return fmt.Errorf("unknown doc type %q. Try 'markdown' or 'man'", o.docTypeString)
}
}

@ -24,6 +24,7 @@ import (
"path/filepath"
"github.com/spf13/cobra"
"k8s.io/helm/pkg/chartutil"
"k8s.io/helm/pkg/downloader"
"k8s.io/helm/pkg/getter"
@ -45,31 +46,27 @@ file, and MUST pass the verification process. Failure in any part of this will
result in an error, and the chart will not be saved locally.
`
type fetchCmd struct {
untar bool
untardir string
chartRef string
destdir string
version string
repoURL string
username string
password string
verify bool
verifyLater bool
keyring string
type fetchOptions struct {
caFile string // --ca-file
certFile string // --cert-file
destdir string // --destination
devel bool // --devel
keyFile string // --key-file
keyring string // --keyring
password string // --password
repoURL string // --repo
untar bool // --untar
untardir string // --untardir
username string // --username
verify bool // --verify
verifyLater bool // --prov
version string // --version
certFile string
keyFile string
caFile string
devel bool
out io.Writer
chartRef string
}
func newFetchCmd(out io.Writer) *cobra.Command {
fch := &fetchCmd{out: out}
o := &fetchOptions{}
cmd := &cobra.Command{
Use: "fetch [flags] [chart URL | repo/chartname] [...]",
@ -80,14 +77,14 @@ func newFetchCmd(out io.Writer) *cobra.Command {
return fmt.Errorf("need at least one argument, url or repo/name of the chart")
}
if fch.version == "" && fch.devel {
if o.version == "" && o.devel {
debug("setting version to >0.0.0-0")
fch.version = ">0.0.0-0"
o.version = ">0.0.0-0"
}
for i := 0; i < len(args); i++ {
fch.chartRef = args[i]
if err := fch.run(); err != nil {
o.chartRef = args[i]
if err := o.run(out); err != nil {
return err
}
}
@ -96,45 +93,45 @@ func newFetchCmd(out io.Writer) *cobra.Command {
}
f := cmd.Flags()
f.BoolVar(&fch.untar, "untar", false, "if set to true, will untar the chart after downloading it")
f.StringVar(&fch.untardir, "untardir", ".", "if untar is specified, this flag specifies the name of the directory into which the chart is expanded")
f.BoolVar(&fch.verify, "verify", false, "verify the package against its signature")
f.BoolVar(&fch.verifyLater, "prov", false, "fetch the provenance file, but don't perform verification")
f.StringVar(&fch.version, "version", "", "specific version of a chart. Without this, the latest version is fetched")
f.StringVar(&fch.keyring, "keyring", defaultKeyring(), "keyring containing public keys")
f.StringVarP(&fch.destdir, "destination", "d", ".", "location to write the chart. If this and tardir are specified, tardir is appended to this")
f.StringVar(&fch.repoURL, "repo", "", "chart repository url where to locate the requested chart")
f.StringVar(&fch.certFile, "cert-file", "", "identify HTTPS client using this SSL certificate file")
f.StringVar(&fch.keyFile, "key-file", "", "identify HTTPS client using this SSL key file")
f.StringVar(&fch.caFile, "ca-file", "", "verify certificates of HTTPS-enabled servers using this CA bundle")
f.BoolVar(&fch.devel, "devel", false, "use development versions, too. Equivalent to version '>0.0.0-0'. If --version is set, this is ignored.")
f.StringVar(&fch.username, "username", "", "chart repository username")
f.StringVar(&fch.password, "password", "", "chart repository password")
f.BoolVar(&o.devel, "devel", false, "use development versions, too. Equivalent to version '>0.0.0-0'. If --version is set, this is ignored.")
f.BoolVar(&o.untar, "untar", false, "if set to true, will untar the chart after downloading it")
f.BoolVar(&o.verify, "verify", false, "verify the package against its signature")
f.BoolVar(&o.verifyLater, "prov", false, "fetch the provenance file, but don't perform verification")
f.StringVar(&o.caFile, "ca-file", "", "verify certificates of HTTPS-enabled servers using this CA bundle")
f.StringVar(&o.certFile, "cert-file", "", "identify HTTPS client using this SSL certificate file")
f.StringVar(&o.keyFile, "key-file", "", "identify HTTPS client using this SSL key file")
f.StringVar(&o.keyring, "keyring", defaultKeyring(), "keyring containing public keys")
f.StringVar(&o.password, "password", "", "chart repository password")
f.StringVar(&o.repoURL, "repo", "", "chart repository url where to locate the requested chart")
f.StringVar(&o.untardir, "untardir", ".", "if untar is specified, this flag specifies the name of the directory into which the chart is expanded")
f.StringVar(&o.username, "username", "", "chart repository username")
f.StringVar(&o.version, "version", "", "specific version of a chart. Without this, the latest version is fetched")
f.StringVarP(&o.destdir, "destination", "d", ".", "location to write the chart. If this and tardir are specified, tardir is appended to this")
return cmd
}
func (f *fetchCmd) run() error {
func (o *fetchOptions) run(out io.Writer) error {
c := downloader.ChartDownloader{
HelmHome: settings.Home,
Out: f.out,
Keyring: f.keyring,
Out: out,
Keyring: o.keyring,
Verify: downloader.VerifyNever,
Getters: getter.All(settings),
Username: f.username,
Password: f.password,
Username: o.username,
Password: o.password,
}
if f.verify {
if o.verify {
c.Verify = downloader.VerifyAlways
} else if f.verifyLater {
} else if o.verifyLater {
c.Verify = downloader.VerifyLater
}
// If untar is set, we fetch to a tempdir, then untar and copy after
// verification.
dest := f.destdir
if f.untar {
dest := o.destdir
if o.untar {
var err error
dest, err = ioutil.TempDir("", "helm-")
if err != nil {
@ -143,28 +140,28 @@ func (f *fetchCmd) run() error {
defer os.RemoveAll(dest)
}
if f.repoURL != "" {
chartURL, err := repo.FindChartInAuthRepoURL(f.repoURL, f.username, f.password, f.chartRef, f.version, f.certFile, f.keyFile, f.caFile, getter.All(settings))
if o.repoURL != "" {
chartURL, err := repo.FindChartInAuthRepoURL(o.repoURL, o.username, o.password, o.chartRef, o.version, o.certFile, o.keyFile, o.caFile, getter.All(settings))
if err != nil {
return err
}
f.chartRef = chartURL
o.chartRef = chartURL
}
saved, v, err := c.DownloadTo(f.chartRef, f.version, dest)
saved, v, err := c.DownloadTo(o.chartRef, o.version, dest)
if err != nil {
return err
}
if f.verify {
fmt.Fprintf(f.out, "Verification: %v\n", v)
if o.verify {
fmt.Fprintf(out, "Verification: %v\n", v)
}
// After verification, untar the chart into the requested directory.
if f.untar {
ud := f.untardir
if o.untar {
ud := o.untardir
if !filepath.IsAbs(ud) {
ud = filepath.Join(f.destdir, ud)
ud = filepath.Join(o.destdir, ud)
}
if fi, err := os.Stat(ud); err != nil {
if err := os.MkdirAll(ud, 0755); err != nil {

@ -40,19 +40,16 @@ chart, the supplied values, and the generated manifest file.
var errReleaseRequired = errors.New("release name is required")
type getCmd struct {
type getOptions struct {
version int // --revision
release string
version int
out io.Writer
client helm.Interface
}
func newGetCmd(client helm.Interface, out io.Writer) *cobra.Command {
get := &getCmd{
out: out,
client: client,
}
o := &getOptions{client: client}
cmd := &cobra.Command{
Use: "get [flags] RELEASE_NAME",
@ -62,13 +59,13 @@ func newGetCmd(client helm.Interface, out io.Writer) *cobra.Command {
if len(args) == 0 {
return errReleaseRequired
}
get.release = args[0]
get.client = ensureHelmClient(get.client, false)
return get.run()
o.release = args[0]
o.client = ensureHelmClient(o.client, false)
return o.run(out)
},
}
cmd.Flags().IntVar(&get.version, "revision", 0, "get the named release with revision")
cmd.Flags().IntVar(&o.version, "revision", 0, "get the named release with revision")
cmd.AddCommand(newGetValuesCmd(client, out))
cmd.AddCommand(newGetManifestCmd(client, out))
@ -77,11 +74,10 @@ func newGetCmd(client helm.Interface, out io.Writer) *cobra.Command {
return cmd
}
// getCmd is the command that implements 'helm get'
func (g *getCmd) run() error {
func (g *getOptions) run(out io.Writer) error {
res, err := g.client.ReleaseContent(g.release, g.version)
if err != nil {
return err
}
return printRelease(g.out, res)
return printRelease(out, res)
}

@ -31,18 +31,15 @@ This command downloads hooks for a given release.
Hooks are formatted in YAML and separated by the YAML '---\n' separator.
`
type getHooksCmd struct {
type getHooksOptions struct {
release string
out io.Writer
client helm.Interface
version int
}
func newGetHooksCmd(client helm.Interface, out io.Writer) *cobra.Command {
ghc := &getHooksCmd{
out: out,
client: client,
}
o := &getHooksOptions{client: client}
cmd := &cobra.Command{
Use: "hooks [flags] RELEASE_NAME",
Short: "download all hooks for a named release",
@ -51,24 +48,24 @@ func newGetHooksCmd(client helm.Interface, out io.Writer) *cobra.Command {
if len(args) == 0 {
return errReleaseRequired
}
ghc.release = args[0]
ghc.client = ensureHelmClient(ghc.client, false)
return ghc.run()
o.release = args[0]
o.client = ensureHelmClient(o.client, false)
return o.run(out)
},
}
cmd.Flags().IntVar(&ghc.version, "revision", 0, "get the named release with revision")
cmd.Flags().IntVar(&o.version, "revision", 0, "get the named release with revision")
return cmd
}
func (g *getHooksCmd) run() error {
res, err := g.client.ReleaseContent(g.release, g.version)
func (o *getHooksOptions) run(out io.Writer) error {
res, err := o.client.ReleaseContent(o.release, o.version)
if err != nil {
fmt.Fprintln(g.out, g.release)
fmt.Fprintln(out, o.release)
return err
}
for _, hook := range res.Hooks {
fmt.Fprintf(g.out, "---\n# %s\n%s", hook.Name, hook.Manifest)
fmt.Fprintf(out, "---\n# %s\n%s", hook.Name, hook.Manifest)
}
return nil
}

@ -33,18 +33,17 @@ were generated from this release's chart(s). If a chart is dependent on other
charts, those resources will also be included in the manifest.
`
type getManifestCmd struct {
type getManifestOptions struct {
version int // --revision
release string
out io.Writer
client helm.Interface
version int
client helm.Interface
}
func newGetManifestCmd(client helm.Interface, out io.Writer) *cobra.Command {
get := &getManifestCmd{
out: out,
client: client,
}
o := &getManifestOptions{client: client}
cmd := &cobra.Command{
Use: "manifest [flags] RELEASE_NAME",
Short: "download the manifest for a named release",
@ -53,22 +52,22 @@ func newGetManifestCmd(client helm.Interface, out io.Writer) *cobra.Command {
if len(args) == 0 {
return errReleaseRequired
}
get.release = args[0]
get.client = ensureHelmClient(get.client, false)
return get.run()
o.release = args[0]
o.client = ensureHelmClient(o.client, false)
return o.run(out)
},
}
cmd.Flags().IntVar(&get.version, "revision", 0, "get the named release with revision")
cmd.Flags().IntVar(&o.version, "revision", 0, "get the named release with revision")
return cmd
}
// getManifest implements 'helm get manifest'
func (g *getManifestCmd) run() error {
res, err := g.client.ReleaseContent(g.release, g.version)
func (o *getManifestOptions) run(out io.Writer) error {
res, err := o.client.ReleaseContent(o.release, o.version)
if err != nil {
return err
}
fmt.Fprintln(g.out, res.Manifest)
fmt.Fprintln(out, res.Manifest)
return nil
}

@ -30,19 +30,18 @@ var getValuesHelp = `
This command downloads a values file for a given release.
`
type getValuesCmd struct {
release string
allValues bool
out io.Writer
client helm.Interface
version int
type getValuesOptions struct {
allValues bool // --all
version int // --revision
release string
client helm.Interface
}
func newGetValuesCmd(client helm.Interface, out io.Writer) *cobra.Command {
get := &getValuesCmd{
out: out,
client: client,
}
o := &getValuesOptions{client: client}
cmd := &cobra.Command{
Use: "values [flags] RELEASE_NAME",
Short: "download the values file for a named release",
@ -51,26 +50,26 @@ func newGetValuesCmd(client helm.Interface, out io.Writer) *cobra.Command {
if len(args) == 0 {
return errReleaseRequired
}
get.release = args[0]
get.client = ensureHelmClient(get.client, false)
return get.run()
o.release = args[0]
o.client = ensureHelmClient(o.client, false)
return o.run(out)
},
}
cmd.Flags().IntVar(&get.version, "revision", 0, "get the named release with revision")
cmd.Flags().BoolVarP(&get.allValues, "all", "a", false, "dump all (computed) values")
cmd.Flags().BoolVarP(&o.allValues, "all", "a", false, "dump all (computed) values")
cmd.Flags().IntVar(&o.version, "revision", 0, "get the named release with revision")
return cmd
}
// getValues implements 'helm get values'
func (g *getValuesCmd) run() error {
res, err := g.client.ReleaseContent(g.release, g.version)
func (o *getValuesOptions) run(out io.Writer) error {
res, err := o.client.ReleaseContent(o.release, o.version)
if err != nil {
return err
}
// If the user wants all values, compute the values and return.
if g.allValues {
if o.allValues {
cfg, err := chartutil.CoalesceValues(res.Chart, res.Config)
if err != nil {
return err
@ -79,10 +78,10 @@ func (g *getValuesCmd) run() error {
if err != nil {
return err
}
fmt.Fprintln(g.out, cfgStr)
fmt.Fprintln(out, cfgStr)
return nil
}
fmt.Fprintln(g.out, string(res.Config))
fmt.Fprintln(out, string(res.Config))
return nil
}

@ -30,13 +30,13 @@ import (
"k8s.io/client-go/tools/clientcmd"
"k8s.io/helm/pkg/helm"
helm_env "k8s.io/helm/pkg/helm/environment"
"k8s.io/helm/pkg/helm/environment"
"k8s.io/helm/pkg/kube"
"k8s.io/helm/pkg/storage/driver"
)
var (
settings helm_env.EnvSettings
settings environment.EnvSettings
config clientcmd.ClientConfig
configOnce sync.Once
)

@ -56,17 +56,18 @@ The historical release set is printed as a formatted table, e.g:
4 Mon Oct 3 10:15:13 2016 deployed alpine-0.1.0 Upgraded successfully
`
type historyCmd struct {
max int
rls string
out io.Writer
helmc helm.Interface
colWidth uint
outputFormat string
type historyOptions struct {
colWidth uint // --col-width
max int // --max
outputFormat string // --output
release string
client helm.Interface
}
func newHistoryCmd(c helm.Interface, w io.Writer) *cobra.Command {
his := &historyCmd{out: w, helmc: c}
func newHistoryCmd(c helm.Interface, out io.Writer) *cobra.Command {
o := &historyOptions{client: c}
cmd := &cobra.Command{
Use: "history [flags] RELEASE_NAME",
@ -77,22 +78,22 @@ func newHistoryCmd(c helm.Interface, w io.Writer) *cobra.Command {
if len(args) == 0 {
return errReleaseRequired
}
his.helmc = ensureHelmClient(his.helmc, false)
his.rls = args[0]
return his.run()
o.client = ensureHelmClient(o.client, false)
o.release = args[0]
return o.run(out)
},
}
f := cmd.Flags()
f.IntVar(&his.max, "max", 256, "maximum number of revision to include in history")
f.UintVar(&his.colWidth, "col-width", 60, "specifies the max column width of output")
f.StringVarP(&his.outputFormat, "output", "o", "table", "prints the output in the specified format (json|table|yaml)")
f.IntVar(&o.max, "max", 256, "maximum number of revision to include in history")
f.UintVar(&o.colWidth, "col-width", 60, "specifies the max column width of output")
f.StringVarP(&o.outputFormat, "output", "o", "table", "prints the output in the specified format (json|table|yaml)")
return cmd
}
func (cmd *historyCmd) run() error {
rels, err := cmd.helmc.ReleaseHistory(cmd.rls, cmd.max)
func (o *historyOptions) run(out io.Writer) error {
rels, err := o.client.ReleaseHistory(o.release, o.max)
if err != nil {
return err
}
@ -105,22 +106,22 @@ func (cmd *historyCmd) run() error {
var history []byte
var formattingError error
switch cmd.outputFormat {
switch o.outputFormat {
case "yaml":
history, formattingError = yaml.Marshal(releaseHistory)
case "json":
history, formattingError = json.Marshal(releaseHistory)
case "table":
history = formatAsTable(releaseHistory, cmd.colWidth)
history = formatAsTable(releaseHistory, o.colWidth)
default:
return fmt.Errorf("unknown output format %q", cmd.outputFormat)
return fmt.Errorf("unknown output format %q", o.outputFormat)
}
if formattingError != nil {
return formattingError
}
fmt.Fprintln(cmd.out, string(history))
fmt.Fprintln(out, string(history))
return nil
}

@ -33,18 +33,20 @@ const initDesc = `
This command sets up local configuration in $HELM_HOME (default ~/.helm/).
`
const stableRepository = "stable"
const (
stableRepository = "stable"
defaultStableRepositoryURL = "https://kubernetes-charts.storage.googleapis.com"
)
var stableRepositoryURL = "https://kubernetes-charts.storage.googleapis.com"
type initOptions struct {
skipRefresh bool // --skip-refresh
stableRepositoryURL string // --stable-repo-url
type initCmd struct {
skipRefresh bool
out io.Writer
home helmpath.Home
home helmpath.Home
}
func newInitCmd(out io.Writer) *cobra.Command {
i := &initCmd{out: out}
o := &initOptions{}
cmd := &cobra.Command{
Use: "init",
@ -54,31 +56,31 @@ func newInitCmd(out io.Writer) *cobra.Command {
if len(args) != 0 {
return errors.New("This command does not accept arguments")
}
i.home = settings.Home
return i.run()
o.home = settings.Home
return o.run(out)
},
}
f := cmd.Flags()
f.BoolVar(&i.skipRefresh, "skip-refresh", false, "do not refresh (download) the local repository cache")
f.StringVar(&stableRepositoryURL, "stable-repo-url", stableRepositoryURL, "URL for stable repository")
f.BoolVar(&o.skipRefresh, "skip-refresh", false, "do not refresh (download) the local repository cache")
f.StringVar(&o.stableRepositoryURL, "stable-repo-url", defaultStableRepositoryURL, "URL for stable repository")
return cmd
}
// run initializes local config and installs Tiller to Kubernetes cluster.
func (i *initCmd) run() error {
if err := ensureDirectories(i.home, i.out); err != nil {
// run initializes local config.
func (o *initOptions) run(out io.Writer) error {
if err := ensureDirectories(o.home, out); err != nil {
return err
}
if err := ensureDefaultRepos(i.home, i.out, i.skipRefresh); err != nil {
if err := ensureDefaultRepos(o.home, out, o.skipRefresh, o.stableRepositoryURL); err != nil {
return err
}
if err := ensureRepoFileFormat(i.home.RepositoryFile(), i.out); err != nil {
if err := ensureRepoFileFormat(o.home.RepositoryFile(), out); err != nil {
return err
}
fmt.Fprintf(i.out, "$HELM_HOME has been configured at %s.\n", settings.Home)
fmt.Fprintln(i.out, "Happy Helming!")
fmt.Fprintf(out, "$HELM_HOME has been configured at %s.\n", settings.Home)
fmt.Fprintln(out, "Happy Helming!")
return nil
}
@ -108,12 +110,12 @@ func ensureDirectories(home helmpath.Home, out io.Writer) error {
return nil
}
func ensureDefaultRepos(home helmpath.Home, out io.Writer, skipRefresh bool) error {
func ensureDefaultRepos(home helmpath.Home, out io.Writer, skipRefresh bool, url string) error {
repoFile := home.RepositoryFile()
if fi, err := os.Stat(repoFile); err != nil {
fmt.Fprintf(out, "Creating %s \n", repoFile)
f := repo.NewRepoFile()
sr, err := initStableRepo(home.CacheIndex(stableRepository), out, skipRefresh, home)
sr, err := initRepo(url, home.CacheIndex(stableRepository), out, skipRefresh, home)
if err != nil {
return err
}
@ -127,11 +129,11 @@ func ensureDefaultRepos(home helmpath.Home, out io.Writer, skipRefresh bool) err
return nil
}
func initStableRepo(cacheFile string, out io.Writer, skipRefresh bool, home helmpath.Home) (*repo.Entry, error) {
fmt.Fprintf(out, "Adding %s repo with URL: %s \n", stableRepository, stableRepositoryURL)
func initRepo(url, cacheFile string, out io.Writer, skipRefresh bool, home helmpath.Home) (*repo.Entry, error) {
fmt.Fprintf(out, "Adding %s repo with URL: %s \n", stableRepository, url)
c := repo.Entry{
Name: stableRepository,
URL: stableRepositoryURL,
URL: url,
Cache: cacheFile,
}
r, err := repo.NewChartRepository(&c, getter.All(settings))
@ -146,7 +148,7 @@ func initStableRepo(cacheFile string, out io.Writer, skipRefresh bool, home helm
// In this case, the cacheFile is always absolute. So passing empty string
// is safe.
if err := r.DownloadIndexFile(""); err != nil {
return nil, fmt.Errorf("Looks like %q is not a valid chart repository or cannot be reached: %s", stableRepositoryURL, err.Error())
return nil, fmt.Errorf("Looks like %q is not a valid chart repository or cannot be reached: %s", url, err.Error())
}
return &c, nil

@ -38,10 +38,10 @@ func TestEnsureHome(t *testing.T) {
if err := ensureDirectories(hh, b); err != nil {
t.Error(err)
}
if err := ensureDefaultRepos(hh, b, false); err != nil {
if err := ensureDefaultRepos(hh, b, false, defaultStableRepositoryURL); err != nil {
t.Error(err)
}
if err := ensureDefaultRepos(hh, b, true); err != nil {
if err := ensureDefaultRepos(hh, b, true, defaultStableRepositoryURL); err != nil {
t.Error(err)
}
if err := ensureRepoFileFormat(hh.RepositoryFile(), b); err != nil {

@ -50,20 +50,18 @@ This command inspects a chart (directory, file, or URL) and displays the content
of the README file
`
type inspectCmd struct {
type inspectOptions struct {
chartpath string
output string
verify bool
keyring string
out io.Writer
version string
repoURL string
username string
password string
certFile string
keyFile string
caFile string
certFile string
keyFile string
caFile string
}
const (
@ -76,10 +74,7 @@ const (
var readmeFileNames = []string{"readme.md", "readme.txt", "readme"}
func newInspectCmd(out io.Writer) *cobra.Command {
insp := &inspectCmd{
out: out,
output: all,
}
o := &inspectOptions{output: all}
inspectCommand := &cobra.Command{
Use: "inspect [CHART]",
@ -89,13 +84,13 @@ func newInspectCmd(out io.Writer) *cobra.Command {
if err := checkArgsLength(len(args), "chart name"); err != nil {
return err
}
cp, err := locateChartPath(insp.repoURL, insp.username, insp.password, args[0], insp.version, insp.verify, insp.keyring,
insp.certFile, insp.keyFile, insp.caFile)
cp, err := locateChartPath(o.repoURL, o.username, o.password, args[0], o.version, o.verify, o.keyring,
o.certFile, o.keyFile, o.caFile)
if err != nil {
return err
}
insp.chartpath = cp
return insp.run()
o.chartpath = cp
return o.run(out)
},
}
@ -104,17 +99,17 @@ func newInspectCmd(out io.Writer) *cobra.Command {
Short: "shows inspect values",
Long: inspectValuesDesc,
RunE: func(cmd *cobra.Command, args []string) error {
insp.output = valuesOnly
o.output = valuesOnly
if err := checkArgsLength(len(args), "chart name"); err != nil {
return err
}
cp, err := locateChartPath(insp.repoURL, insp.username, insp.password, args[0], insp.version, insp.verify, insp.keyring,
insp.certFile, insp.keyFile, insp.caFile)
cp, err := locateChartPath(o.repoURL, o.username, o.password, args[0], o.version, o.verify, o.keyring,
o.certFile, o.keyFile, o.caFile)
if err != nil {
return err
}
insp.chartpath = cp
return insp.run()
o.chartpath = cp
return o.run(out)
},
}
@ -123,17 +118,17 @@ func newInspectCmd(out io.Writer) *cobra.Command {
Short: "shows inspect chart",
Long: inspectChartDesc,
RunE: func(cmd *cobra.Command, args []string) error {
insp.output = chartOnly
o.output = chartOnly
if err := checkArgsLength(len(args), "chart name"); err != nil {
return err
}
cp, err := locateChartPath(insp.repoURL, insp.username, insp.password, args[0], insp.version, insp.verify, insp.keyring,
insp.certFile, insp.keyFile, insp.caFile)
cp, err := locateChartPath(o.repoURL, o.username, o.password, args[0], o.version, o.verify, o.keyring,
o.certFile, o.keyFile, o.caFile)
if err != nil {
return err
}
insp.chartpath = cp
return insp.run()
o.chartpath = cp
return o.run(out)
},
}
@ -142,17 +137,17 @@ func newInspectCmd(out io.Writer) *cobra.Command {
Short: "shows inspect readme",
Long: readmeChartDesc,
RunE: func(cmd *cobra.Command, args []string) error {
insp.output = readmeOnly
o.output = readmeOnly
if err := checkArgsLength(len(args), "chart name"); err != nil {
return err
}
cp, err := locateChartPath(insp.repoURL, insp.username, insp.password, args[0], insp.version, insp.verify, insp.keyring,
insp.certFile, insp.keyFile, insp.caFile)
cp, err := locateChartPath(o.repoURL, o.username, o.password, args[0], o.version, o.verify, o.keyring,
o.certFile, o.keyFile, o.caFile)
if err != nil {
return err
}
insp.chartpath = cp
return insp.run()
o.chartpath = cp
return o.run(out)
},
}
@ -160,56 +155,56 @@ func newInspectCmd(out io.Writer) *cobra.Command {
vflag := "verify"
vdesc := "verify the provenance data for this chart"
for _, subCmd := range cmds {
subCmd.Flags().BoolVar(&insp.verify, vflag, false, vdesc)
subCmd.Flags().BoolVar(&o.verify, vflag, false, vdesc)
}
kflag := "keyring"
kdesc := "path to the keyring containing public verification keys"
kdefault := defaultKeyring()
for _, subCmd := range cmds {
subCmd.Flags().StringVar(&insp.keyring, kflag, kdefault, kdesc)
subCmd.Flags().StringVar(&o.keyring, kflag, kdefault, kdesc)
}
verflag := "version"
verdesc := "version of the chart. By default, the newest chart is shown"
for _, subCmd := range cmds {
subCmd.Flags().StringVar(&insp.version, verflag, "", verdesc)
subCmd.Flags().StringVar(&o.version, verflag, "", verdesc)
}
repoURL := "repo"
repoURLdesc := "chart repository url where to locate the requested chart"
for _, subCmd := range cmds {
subCmd.Flags().StringVar(&insp.repoURL, repoURL, "", repoURLdesc)
subCmd.Flags().StringVar(&o.repoURL, repoURL, "", repoURLdesc)
}
username := "username"
usernamedesc := "chart repository username where to locate the requested chart"
inspectCommand.Flags().StringVar(&insp.username, username, "", usernamedesc)
valuesSubCmd.Flags().StringVar(&insp.username, username, "", usernamedesc)
chartSubCmd.Flags().StringVar(&insp.username, username, "", usernamedesc)
inspectCommand.Flags().StringVar(&o.username, username, "", usernamedesc)
valuesSubCmd.Flags().StringVar(&o.username, username, "", usernamedesc)
chartSubCmd.Flags().StringVar(&o.username, username, "", usernamedesc)
password := "password"
passworddesc := "chart repository password where to locate the requested chart"
inspectCommand.Flags().StringVar(&insp.password, password, "", passworddesc)
valuesSubCmd.Flags().StringVar(&insp.password, password, "", passworddesc)
chartSubCmd.Flags().StringVar(&insp.password, password, "", passworddesc)
inspectCommand.Flags().StringVar(&o.password, password, "", passworddesc)
valuesSubCmd.Flags().StringVar(&o.password, password, "", passworddesc)
chartSubCmd.Flags().StringVar(&o.password, password, "", passworddesc)
certFile := "cert-file"
certFiledesc := "verify certificates of HTTPS-enabled servers using this CA bundle"
for _, subCmd := range cmds {
subCmd.Flags().StringVar(&insp.certFile, certFile, "", certFiledesc)
subCmd.Flags().StringVar(&o.certFile, certFile, "", certFiledesc)
}
keyFile := "key-file"
keyFiledesc := "identify HTTPS client using this SSL key file"
for _, subCmd := range cmds {
subCmd.Flags().StringVar(&insp.keyFile, keyFile, "", keyFiledesc)
subCmd.Flags().StringVar(&o.keyFile, keyFile, "", keyFiledesc)
}
caFile := "ca-file"
caFiledesc := "chart repository url where to locate the requested chart"
for _, subCmd := range cmds {
subCmd.Flags().StringVar(&insp.caFile, caFile, "", caFiledesc)
subCmd.Flags().StringVar(&o.caFile, caFile, "", caFiledesc)
}
for _, subCmd := range cmds[1:] {
@ -219,7 +214,7 @@ func newInspectCmd(out io.Writer) *cobra.Command {
return inspectCommand
}
func (i *inspectCmd) run() error {
func (i *inspectOptions) run(out io.Writer) error {
chrt, err := chartutil.Load(i.chartpath)
if err != nil {
return err
@ -230,25 +225,25 @@ func (i *inspectCmd) run() error {
}
if i.output == chartOnly || i.output == all {
fmt.Fprintln(i.out, string(cf))
fmt.Fprintln(out, string(cf))
}
if (i.output == valuesOnly || i.output == all) && chrt.Values != nil {
if i.output == all {
fmt.Fprintln(i.out, "---")
fmt.Fprintln(out, "---")
}
fmt.Fprintln(i.out, string(chrt.Values))
fmt.Fprintln(out, string(chrt.Values))
}
if i.output == readmeOnly || i.output == all {
if i.output == all {
fmt.Fprintln(i.out, "---")
fmt.Fprintln(out, "---")
}
readme := findReadme(chrt.Files)
if readme == nil {
return nil
}
fmt.Fprintln(i.out, string(readme.Data))
fmt.Fprintln(out, string(readme.Data))
}
return nil
}

@ -26,12 +26,11 @@ import (
func TestInspect(t *testing.T) {
b := bytes.NewBuffer(nil)
insp := &inspectCmd{
o := &inspectOptions{
chartpath: "testdata/testcharts/alpine",
output: all,
out: b,
}
insp.run()
o.run(b)
// Load the data from the textfixture directly.
cdata, err := ioutil.ReadFile("testdata/testcharts/alpine/Chart.yaml")
@ -68,12 +67,11 @@ func TestInspect(t *testing.T) {
// Regression tests for missing values. See issue #1024.
b.Reset()
insp = &inspectCmd{
o = &inspectOptions{
chartpath: "testdata/testcharts/novals",
output: "values",
out: b,
}
insp.run()
o.run(b)
if b.Len() != 0 {
t.Errorf("expected empty values buffer, got %q", b.String())
}

@ -104,7 +104,7 @@ To see the list of chart repositories, use 'helm repo list'. To search for
charts in a repository, use 'helm search'.
`
type installCmd struct {
type installOptions struct {
name string // --name
valueFiles valueFiles // --values
dryRun bool // --dry-run
@ -128,7 +128,6 @@ type installCmd struct {
caFile string // --ca-file
chartPath string // arg
out io.Writer
client helm.Interface
}
@ -150,10 +149,7 @@ func (v *valueFiles) Set(value string) error {
}
func newInstallCmd(c helm.Interface, out io.Writer) *cobra.Command {
inst := &installCmd{
out: out,
client: c,
}
o := &installOptions{client: c}
cmd := &cobra.Command{
Use: "install [CHART]",
@ -164,69 +160,69 @@ func newInstallCmd(c helm.Interface, out io.Writer) *cobra.Command {
return err
}
debug("Original chart version: %q", inst.version)
if inst.version == "" && inst.devel {
debug("Original chart version: %q", o.version)
if o.version == "" && o.devel {
debug("setting version to >0.0.0-0")
inst.version = ">0.0.0-0"
o.version = ">0.0.0-0"
}
cp, err := locateChartPath(inst.repoURL, inst.username, inst.password, args[0], inst.version, inst.verify, inst.keyring,
inst.certFile, inst.keyFile, inst.caFile)
cp, err := locateChartPath(o.repoURL, o.username, o.password, args[0], o.version, o.verify, o.keyring,
o.certFile, o.keyFile, o.caFile)
if err != nil {
return err
}
inst.chartPath = cp
inst.client = ensureHelmClient(inst.client, false)
return inst.run()
o.chartPath = cp
o.client = ensureHelmClient(o.client, false)
return o.run(out)
},
}
f := cmd.Flags()
f.VarP(&inst.valueFiles, "values", "f", "specify values in a YAML file or a URL(can specify multiple)")
f.StringVarP(&inst.name, "name", "", "", "release name. If unspecified, it will autogenerate one for you")
f.BoolVar(&inst.dryRun, "dry-run", false, "simulate an install")
f.BoolVar(&inst.disableHooks, "no-hooks", false, "prevent hooks from running during install")
f.BoolVar(&inst.replace, "replace", false, "re-use the given name, even if that name is already used. This is unsafe in production")
f.StringArrayVar(&inst.values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
f.StringArrayVar(&inst.stringValues, "set-string", []string{}, "set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
f.StringVar(&inst.nameTemplate, "name-template", "", "specify template used to name the release")
f.BoolVar(&inst.verify, "verify", false, "verify the package before installing it")
f.StringVar(&inst.keyring, "keyring", defaultKeyring(), "location of public keys used for verification")
f.StringVar(&inst.version, "version", "", "specify the exact chart version to install. If this is not specified, the latest version is installed")
f.Int64Var(&inst.timeout, "timeout", 300, "time in seconds to wait for any individual Kubernetes operation (like Jobs for hooks)")
f.BoolVar(&inst.wait, "wait", false, "if set, will wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment are in a ready state before marking the release as successful. It will wait for as long as --timeout")
f.StringVar(&inst.repoURL, "repo", "", "chart repository url where to locate the requested chart")
f.StringVar(&inst.username, "username", "", "chart repository username where to locate the requested chart")
f.StringVar(&inst.password, "password", "", "chart repository password where to locate the requested chart")
f.StringVar(&inst.certFile, "cert-file", "", "identify HTTPS client using this SSL certificate file")
f.StringVar(&inst.keyFile, "key-file", "", "identify HTTPS client using this SSL key file")
f.StringVar(&inst.caFile, "ca-file", "", "verify certificates of HTTPS-enabled servers using this CA bundle")
f.BoolVar(&inst.devel, "devel", false, "use development versions, too. Equivalent to version '>0.0.0-0'. If --version is set, this is ignored.")
f.BoolVar(&inst.depUp, "dep-up", false, "run helm dependency update before installing the chart")
f.VarP(&o.valueFiles, "values", "f", "specify values in a YAML file or a URL(can specify multiple)")
f.StringVarP(&o.name, "name", "", "", "release name. If unspecified, it will autogenerate one for you")
f.BoolVar(&o.dryRun, "dry-run", false, "simulate an install")
f.BoolVar(&o.disableHooks, "no-hooks", false, "prevent hooks from running during install")
f.BoolVar(&o.replace, "replace", false, "re-use the given name, even if that name is already used. This is unsafe in production")
f.StringArrayVar(&o.values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
f.StringArrayVar(&o.stringValues, "set-string", []string{}, "set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
f.StringVar(&o.nameTemplate, "name-template", "", "specify template used to name the release")
f.BoolVar(&o.verify, "verify", false, "verify the package before installing it")
f.StringVar(&o.keyring, "keyring", defaultKeyring(), "location of public keys used for verification")
f.StringVar(&o.version, "version", "", "specify the exact chart version to install. If this is not specified, the latest version is installed")
f.Int64Var(&o.timeout, "timeout", 300, "time in seconds to wait for any individual Kubernetes operation (like Jobs for hooks)")
f.BoolVar(&o.wait, "wait", false, "if set, will wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment are in a ready state before marking the release as successful. It will wait for as long as --timeout")
f.StringVar(&o.repoURL, "repo", "", "chart repository url where to locate the requested chart")
f.StringVar(&o.username, "username", "", "chart repository username where to locate the requested chart")
f.StringVar(&o.password, "password", "", "chart repository password where to locate the requested chart")
f.StringVar(&o.certFile, "cert-file", "", "identify HTTPS client using this SSL certificate file")
f.StringVar(&o.keyFile, "key-file", "", "identify HTTPS client using this SSL key file")
f.StringVar(&o.caFile, "ca-file", "", "verify certificates of HTTPS-enabled servers using this CA bundle")
f.BoolVar(&o.devel, "devel", false, "use development versions, too. Equivalent to version '>0.0.0-0'. If --version is set, this is ignored.")
f.BoolVar(&o.depUp, "dep-up", false, "run helm dependency update before installing the chart")
return cmd
}
func (i *installCmd) run() error {
debug("CHART PATH: %s\n", i.chartPath)
func (o *installOptions) run(out io.Writer) error {
debug("CHART PATH: %s\n", o.chartPath)
rawVals, err := vals(i.valueFiles, i.values, i.stringValues)
rawVals, err := vals(o.valueFiles, o.values, o.stringValues)
if err != nil {
return err
}
// If template is specified, try to run the template.
if i.nameTemplate != "" {
i.name, err = generateName(i.nameTemplate)
if o.nameTemplate != "" {
o.name, err = generateName(o.nameTemplate)
if err != nil {
return err
}
// Print the final name so the user knows what the final name of the release is.
fmt.Printf("FINAL NAME: %s\n", i.name)
fmt.Printf("FINAL NAME: %s\n", o.name)
}
// Check chart requirements to make sure all dependencies are present in /charts
chartRequested, err := chartutil.Load(i.chartPath)
chartRequested, err := chartutil.Load(o.chartPath)
if err != nil {
return err
}
@ -236,10 +232,10 @@ func (i *installCmd) run() error {
// As of Helm 2.4.0, this is treated as a stopping condition:
// https://github.com/kubernetes/helm/issues/2209
if err := checkDependencies(chartRequested, req); err != nil {
if i.depUp {
if o.depUp {
man := &downloader.Manager{
Out: i.out,
ChartPath: i.chartPath,
Out: out,
ChartPath: o.chartPath,
HelmHome: settings.Home,
Keyring: defaultKeyring(),
SkipUpdate: false,
@ -257,16 +253,16 @@ func (i *installCmd) run() error {
return fmt.Errorf("cannot load requirements: %v", err)
}
rel, err := i.client.InstallReleaseFromChart(
rel, err := o.client.InstallReleaseFromChart(
chartRequested,
getNamespace(),
helm.ValueOverrides(rawVals),
helm.ReleaseName(i.name),
helm.InstallDryRun(i.dryRun),
helm.InstallReuseName(i.replace),
helm.InstallDisableHooks(i.disableHooks),
helm.InstallTimeout(i.timeout),
helm.InstallWait(i.wait))
helm.ReleaseName(o.name),
helm.InstallDryRun(o.dryRun),
helm.InstallReuseName(o.replace),
helm.InstallDisableHooks(o.disableHooks),
helm.InstallTimeout(o.timeout),
helm.InstallWait(o.wait))
if err != nil {
return err
}
@ -274,19 +270,19 @@ func (i *installCmd) run() error {
if rel == nil {
return nil
}
i.printRelease(rel)
o.printRelease(out, rel)
// If this is a dry run, we can't display status.
if i.dryRun {
if o.dryRun {
return nil
}
// Print the status like status command does
status, err := i.client.ReleaseStatus(rel.Name, 0)
status, err := o.client.ReleaseStatus(rel.Name, 0)
if err != nil {
return err
}
PrintStatus(i.out, status)
PrintStatus(out, status)
return nil
}
@ -363,14 +359,14 @@ func vals(valueFiles valueFiles, values []string, stringValues []string) ([]byte
}
// printRelease prints info about a release if the Debug is true.
func (i *installCmd) printRelease(rel *release.Release) {
func (o *installOptions) printRelease(out io.Writer, rel *release.Release) {
if rel == nil {
return
}
// TODO: Switch to text/template like everything else.
fmt.Fprintf(i.out, "NAME: %s\n", rel.Name)
fmt.Fprintf(out, "NAME: %s\n", rel.Name)
if settings.Debug {
printRelease(i.out, rel)
printRelease(out, rel)
}
}

@ -43,60 +43,57 @@ it will emit [ERROR] messages. If it encounters issues that break with conventio
or recommendation, it will emit [WARNING] messages.
`
type lintCmd struct {
type lintOptions struct {
valueFiles valueFiles
values []string
sValues []string
strict bool
paths []string
out io.Writer
}
func newLintCmd(out io.Writer) *cobra.Command {
l := &lintCmd{
paths: []string{"."},
out: out,
}
o := &lintOptions{paths: []string{"."}}
cmd := &cobra.Command{
Use: "lint [flags] PATH",
Short: "examines a chart for possible issues",
Long: longLintHelp,
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) > 0 {
l.paths = args
o.paths = args
}
return l.run()
return o.run(out)
},
}
cmd.Flags().VarP(&l.valueFiles, "values", "f", "specify values in a YAML file (can specify multiple)")
cmd.Flags().StringArrayVar(&l.values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
cmd.Flags().StringArrayVar(&l.sValues, "set-string", []string{}, "set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
cmd.Flags().BoolVar(&l.strict, "strict", false, "fail on lint warnings")
cmd.Flags().VarP(&o.valueFiles, "values", "f", "specify values in a YAML file (can specify multiple)")
cmd.Flags().StringArrayVar(&o.values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
cmd.Flags().StringArrayVar(&o.sValues, "set-string", []string{}, "set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
cmd.Flags().BoolVar(&o.strict, "strict", false, "fail on lint warnings")
return cmd
}
var errLintNoChart = errors.New("No chart found for linting (missing Chart.yaml)")
func (l *lintCmd) run() error {
func (o *lintOptions) run(out io.Writer) error {
var lowestTolerance int
if l.strict {
if o.strict {
lowestTolerance = support.WarningSev
} else {
lowestTolerance = support.ErrorSev
}
// Get the raw values
rvals, err := l.vals()
rvals, err := o.vals()
if err != nil {
return err
}
var total int
var failures int
for _, path := range l.paths {
if linter, err := lintChart(path, rvals, getNamespace(), l.strict); err != nil {
for _, path := range o.paths {
if linter, err := lintChart(path, rvals, getNamespace(), o.strict); err != nil {
fmt.Println("==> Skipping", path)
fmt.Println(err)
if err == errLintNoChart {
@ -126,7 +123,7 @@ func (l *lintCmd) run() error {
return fmt.Errorf("%s, %d chart(s) failed", msg, failures)
}
fmt.Fprintf(l.out, "%s, no failures\n", msg)
fmt.Fprintf(out, "%s, no failures\n", msg)
return nil
}
@ -170,11 +167,11 @@ func lintChart(path string, vals []byte, namespace string, strict bool) (support
return lint.All(chartPath, vals, namespace, strict), nil
}
func (l *lintCmd) vals() ([]byte, error) {
func (o *lintOptions) vals() ([]byte, error) {
base := map[string]interface{}{}
// User specified a values files via -f/--values
for _, filePath := range l.valueFiles {
for _, filePath := range o.valueFiles {
currentMap := map[string]interface{}{}
bytes, err := ioutil.ReadFile(filePath)
if err != nil {
@ -189,14 +186,14 @@ func (l *lintCmd) vals() ([]byte, error) {
}
// User specified a value via --set
for _, value := range l.values {
for _, value := range o.values {
if err := strvals.ParseInto(value, base); err != nil {
return []byte{}, fmt.Errorf("failed parsing --set data: %s", err)
}
}
// User specified a value via --set-string
for _, value := range l.sValues {
for _, value := range o.sValues {
if err := strvals.ParseIntoString(value, base); err != nil {
return []byte{}, fmt.Errorf("failed parsing --set-string data: %s", err)
}

@ -56,31 +56,31 @@ server's default, which may be much higher than 256. Pairing the '--max'
flag with the '--offset' flag allows you to page through results.
`
type listCmd struct {
filter string
short bool
limit int
offset string
byDate bool
sortDesc bool
out io.Writer
all bool
deleted bool
deleting bool
deployed bool
failed bool
superseded bool
pending bool
client helm.Interface
colWidth uint
allNamespaces bool
type listOptions struct {
// flags
all bool // --all
allNamespaces bool // --all-namespaces
byDate bool // --date
colWidth uint // --col-width
deleted bool // --deleted
deleting bool // --deleting
deployed bool // --deployed
failed bool // --failed
limit int // --max
offset string // --offset
pending bool // --pending
short bool // --short
sortDesc bool // --reverse
superseded bool // --superseded
// args
filter string
client helm.Interface
}
func newListCmd(client helm.Interface, out io.Writer) *cobra.Command {
list := &listCmd{
out: out,
client: client,
}
o := &listOptions{client: client}
cmd := &cobra.Command{
Use: "list [flags] [FILTER]",
@ -89,48 +89,49 @@ func newListCmd(client helm.Interface, out io.Writer) *cobra.Command {
Aliases: []string{"ls"},
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) > 0 {
list.filter = strings.Join(args, " ")
o.filter = strings.Join(args, " ")
}
list.client = ensureHelmClient(list.client, list.allNamespaces)
return list.run()
o.client = ensureHelmClient(o.client, o.allNamespaces)
return o.run(out)
},
}
f := cmd.Flags()
f.BoolVarP(&list.short, "short", "q", false, "output short (quiet) listing format")
f.BoolVarP(&list.byDate, "date", "d", false, "sort by release date")
f.BoolVarP(&list.sortDesc, "reverse", "r", false, "reverse the sort order")
f.IntVarP(&list.limit, "max", "m", 256, "maximum number of releases to fetch")
f.StringVarP(&list.offset, "offset", "o", "", "next release name in the list, used to offset from start value")
f.BoolVarP(&list.all, "all", "a", false, "show all releases, not just the ones marked deployed")
f.BoolVar(&list.deleted, "deleted", false, "show deleted releases")
f.BoolVar(&list.deleting, "deleting", false, "show releases that are currently being deleted")
f.BoolVar(&list.deployed, "deployed", false, "show deployed releases. If no other is specified, this will be automatically enabled")
f.BoolVar(&list.failed, "failed", false, "show failed releases")
f.BoolVar(&list.pending, "pending", false, "show pending releases")
f.UintVar(&list.colWidth, "col-width", 60, "specifies the max column width of output")
f.BoolVar(&list.allNamespaces, "all-namespaces", false, "list releases across all namespaces")
f.BoolVarP(&o.short, "short", "q", false, "output short (quiet) listing format")
f.BoolVarP(&o.byDate, "date", "d", false, "sort by release date")
f.BoolVarP(&o.sortDesc, "reverse", "r", false, "reverse the sort order")
f.IntVarP(&o.limit, "max", "m", 256, "maximum number of releases to fetch")
f.StringVarP(&o.offset, "offset", "o", "", "next release name in the list, used to offset from start value")
f.BoolVarP(&o.all, "all", "a", false, "show all releases, not just the ones marked deployed")
f.BoolVar(&o.deleted, "deleted", false, "show deleted releases")
f.BoolVar(&o.superseded, "superseded", false, "show superseded releases")
f.BoolVar(&o.deleting, "deleting", false, "show releases that are currently being deleted")
f.BoolVar(&o.deployed, "deployed", false, "show deployed releases. If no other is specified, this will be automatically enabled")
f.BoolVar(&o.failed, "failed", false, "show failed releases")
f.BoolVar(&o.pending, "pending", false, "show pending releases")
f.UintVar(&o.colWidth, "col-width", 60, "specifies the max column width of output")
f.BoolVar(&o.allNamespaces, "all-namespaces", false, "list releases across all namespaces")
return cmd
}
func (l *listCmd) run() error {
func (o *listOptions) run(out io.Writer) error {
sortBy := hapi.SortByName
if l.byDate {
if o.byDate {
sortBy = hapi.SortByLastReleased
}
sortOrder := hapi.SortAsc
if l.sortDesc {
if o.sortDesc {
sortOrder = hapi.SortDesc
}
stats := l.statusCodes()
stats := o.statusCodes()
res, err := l.client.ListReleases(
helm.ReleaseListLimit(l.limit),
helm.ReleaseListOffset(l.offset),
helm.ReleaseListFilter(l.filter),
res, err := o.client.ListReleases(
helm.ReleaseListLimit(o.limit),
helm.ReleaseListOffset(o.offset),
helm.ReleaseListFilter(o.filter),
helm.ReleaseListSort(sortBy),
helm.ReleaseListOrder(sortOrder),
helm.ReleaseListStatuses(stats),
@ -146,13 +147,13 @@ func (l *listCmd) run() error {
rels := filterList(res)
if l.short {
if o.short {
for _, r := range rels {
fmt.Fprintln(l.out, r.Name)
fmt.Fprintln(out, r.Name)
}
return nil
}
fmt.Fprintln(l.out, formatList(rels, l.colWidth))
fmt.Fprintln(out, formatList(rels, o.colWidth))
return nil
}
@ -181,8 +182,8 @@ func filterList(rels []*release.Release) []*release.Release {
}
// statusCodes gets the list of status codes that are to be included in the results.
func (l *listCmd) statusCodes() []release.ReleaseStatus {
if l.all {
func (o *listOptions) statusCodes() []release.ReleaseStatus {
if o.all {
return []release.ReleaseStatus{
release.StatusUnknown,
release.StatusDeployed,
@ -195,22 +196,22 @@ func (l *listCmd) statusCodes() []release.ReleaseStatus {
}
}
status := []release.ReleaseStatus{}
if l.deployed {
if o.deployed {
status = append(status, release.StatusDeployed)
}
if l.deleted {
if o.deleted {
status = append(status, release.StatusDeleted)
}
if l.deleting {
if o.deleting {
status = append(status, release.StatusDeleting)
}
if l.failed {
if o.failed {
status = append(status, release.StatusFailed)
}
if l.superseded {
if o.superseded {
status = append(status, release.StatusSuperseded)
}
if l.pending {
if o.pending {
status = append(status, release.StatusPendingInstall, release.StatusPendingUpgrade, release.StatusPendingRollback)
}

@ -49,46 +49,47 @@ Chart.yaml file, and (if found) build the current directory into a chart.
Versioned chart archives are used by Helm package repositories.
`
type packageCmd struct {
sign bool
path string
valueFiles valueFiles
values []string
stringValues []string
key string
keyring string
version string
appVersion string
destination string
dependencyUpdate bool
out io.Writer
type packageOptions struct {
appVersion string // --app-version
dependencyUpdate bool // --dependency-update
destination string // --destination
key string // --key
keyring string // --keyring
sign bool // --sign
stringValues []string // --set-string
valueFiles valueFiles // --values
values []string // --set
version string // --version
// args
path string
home helmpath.Home
}
func newPackageCmd(out io.Writer) *cobra.Command {
pkg := &packageCmd{out: out}
o := &packageOptions{}
cmd := &cobra.Command{
Use: "package [flags] [CHART_PATH] [...]",
Short: "package a chart directory into a chart archive",
Long: packageDesc,
RunE: func(cmd *cobra.Command, args []string) error {
pkg.home = settings.Home
o.home = settings.Home
if len(args) == 0 {
return fmt.Errorf("need at least one argument, the path to the chart")
}
if pkg.sign {
if pkg.key == "" {
if o.sign {
if o.key == "" {
return errors.New("--key is required for signing a package")
}
if pkg.keyring == "" {
if o.keyring == "" {
return errors.New("--keyring is required for signing a package")
}
}
for i := 0; i < len(args); i++ {
pkg.path = args[i]
if err := pkg.run(); err != nil {
o.path = args[i]
if err := o.run(out); err != nil {
return err
}
}
@ -97,32 +98,32 @@ func newPackageCmd(out io.Writer) *cobra.Command {
}
f := cmd.Flags()
f.VarP(&pkg.valueFiles, "values", "f", "specify values in a YAML file or a URL(can specify multiple)")
f.StringArrayVar(&pkg.values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
f.StringArrayVar(&pkg.stringValues, "set-string", []string{}, "set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
f.BoolVar(&pkg.sign, "sign", false, "use a PGP private key to sign this package")
f.StringVar(&pkg.key, "key", "", "name of the key to use when signing. Used if --sign is true")
f.StringVar(&pkg.keyring, "keyring", defaultKeyring(), "location of a public keyring")
f.StringVar(&pkg.version, "version", "", "set the version on the chart to this semver version")
f.StringVar(&pkg.appVersion, "app-version", "", "set the appVersion on the chart to this version")
f.StringVarP(&pkg.destination, "destination", "d", ".", "location to write the chart.")
f.BoolVarP(&pkg.dependencyUpdate, "dependency-update", "u", false, `update dependencies from "requirements.yaml" to dir "charts/" before packaging`)
f.VarP(&o.valueFiles, "values", "f", "specify values in a YAML file or a URL(can specify multiple)")
f.StringArrayVar(&o.values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
f.StringArrayVar(&o.stringValues, "set-string", []string{}, "set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
f.BoolVar(&o.sign, "sign", false, "use a PGP private key to sign this package")
f.StringVar(&o.key, "key", "", "name of the key to use when signing. Used if --sign is true")
f.StringVar(&o.keyring, "keyring", defaultKeyring(), "location of a public keyring")
f.StringVar(&o.version, "version", "", "set the version on the chart to this semver version")
f.StringVar(&o.appVersion, "app-version", "", "set the appVersion on the chart to this version")
f.StringVarP(&o.destination, "destination", "d", ".", "location to write the chart.")
f.BoolVarP(&o.dependencyUpdate, "dependency-update", "u", false, `update dependencies from "requirements.yaml" to dir "charts/" before packaging`)
return cmd
}
func (p *packageCmd) run() error {
path, err := filepath.Abs(p.path)
func (o *packageOptions) run(out io.Writer) error {
path, err := filepath.Abs(o.path)
if err != nil {
return err
}
if p.dependencyUpdate {
if o.dependencyUpdate {
downloadManager := &downloader.Manager{
Out: p.out,
Out: out,
ChartPath: path,
HelmHome: settings.Home,
Keyring: p.keyring,
Keyring: o.keyring,
Getters: getter.All(settings),
Debug: settings.Debug,
}
@ -137,7 +138,7 @@ func (p *packageCmd) run() error {
return err
}
overrideVals, err := vals(p.valueFiles, p.values, p.stringValues)
overrideVals, err := vals(o.valueFiles, o.values, o.stringValues)
if err != nil {
return err
}
@ -152,16 +153,16 @@ func (p *packageCmd) run() error {
ch.Values = newVals
// If version is set, modify the version.
if len(p.version) != 0 {
if err := setVersion(ch, p.version); err != nil {
if len(o.version) != 0 {
if err := setVersion(ch, o.version); err != nil {
return err
}
debug("Setting version to %s", p.version)
debug("Setting version to %s", o.version)
}
if p.appVersion != "" {
ch.Metadata.AppVersion = p.appVersion
debug("Setting appVersion to %s", p.appVersion)
if o.appVersion != "" {
ch.Metadata.AppVersion = o.appVersion
debug("Setting appVersion to %s", o.appVersion)
}
if filepath.Base(path) != ch.Metadata.Name {
@ -179,7 +180,7 @@ func (p *packageCmd) run() error {
}
var dest string
if p.destination == "." {
if o.destination == "." {
// Save to the current working directory.
dest, err = os.Getwd()
if err != nil {
@ -187,18 +188,18 @@ func (p *packageCmd) run() error {
}
} else {
// Otherwise save to set destination
dest = p.destination
dest = o.destination
}
name, err := chartutil.Save(ch, dest)
if err == nil {
fmt.Fprintf(p.out, "Successfully packaged chart and saved it to: %s\n", name)
fmt.Fprintf(out, "Successfully packaged chart and saved it to: %s\n", name)
} else {
return fmt.Errorf("Failed to save: %s", err)
}
if p.sign {
err = p.clearsign(name)
if o.sign {
err = o.clearsign(name)
}
return err
@ -215,9 +216,9 @@ func setVersion(ch *chart.Chart, ver string) error {
return nil
}
func (p *packageCmd) clearsign(filename string) error {
func (o *packageOptions) clearsign(filename string) error {
// Load keyring
signer, err := provenance.NewFromKeyring(p.keyring, p.key)
signer, err := provenance.NewFromKeyring(o.keyring, o.key)
if err != nil {
return err
}

@ -26,11 +26,10 @@ import (
"github.com/spf13/cobra"
)
type pluginInstallCmd struct {
type pluginInstallOptions struct {
source string
version string
home helmpath.Home
out io.Writer
}
const pluginInstallDesc = `
@ -41,35 +40,35 @@ Example usage:
`
func newPluginInstallCmd(out io.Writer) *cobra.Command {
pcmd := &pluginInstallCmd{out: out}
o := &pluginInstallOptions{}
cmd := &cobra.Command{
Use: "install [options] <path|url>...",
Short: "install one or more Helm plugins",
Long: pluginInstallDesc,
PreRunE: func(cmd *cobra.Command, args []string) error {
return pcmd.complete(args)
return o.complete(args)
},
RunE: func(cmd *cobra.Command, args []string) error {
return pcmd.run()
return o.run(out)
},
}
cmd.Flags().StringVar(&pcmd.version, "version", "", "specify a version constraint. If this is not specified, the latest version is installed")
cmd.Flags().StringVar(&o.version, "version", "", "specify a version constraint. If this is not specified, the latest version is installed")
return cmd
}
func (pcmd *pluginInstallCmd) complete(args []string) error {
func (o *pluginInstallOptions) complete(args []string) error {
if err := checkArgsLength(len(args), "plugin"); err != nil {
return err
}
pcmd.source = args[0]
pcmd.home = settings.Home
o.source = args[0]
o.home = settings.Home
return nil
}
func (pcmd *pluginInstallCmd) run() error {
func (o *pluginInstallOptions) run(out io.Writer) error {
installer.Debug = settings.Debug
i, err := installer.NewForSource(pcmd.source, pcmd.version, pcmd.home)
i, err := installer.NewForSource(o.source, o.version, o.home)
if err != nil {
return err
}
@ -87,6 +86,6 @@ func (pcmd *pluginInstallCmd) run() error {
return err
}
fmt.Fprintf(pcmd.out, "Installed plugin: %s\n", p.Metadata.Name)
fmt.Fprintf(out, "Installed plugin: %s\n", p.Metadata.Name)
return nil
}

@ -25,25 +25,24 @@ import (
"github.com/spf13/cobra"
)
type pluginListCmd struct {
type pluginListOptions struct {
home helmpath.Home
out io.Writer
}
func newPluginListCmd(out io.Writer) *cobra.Command {
pcmd := &pluginListCmd{out: out}
o := &pluginListOptions{}
cmd := &cobra.Command{
Use: "list",
Short: "list installed Helm plugins",
RunE: func(cmd *cobra.Command, args []string) error {
pcmd.home = settings.Home
return pcmd.run()
o.home = settings.Home
return o.run(out)
},
}
return cmd
}
func (pcmd *pluginListCmd) run() error {
func (o *pluginListOptions) run(out io.Writer) error {
debug("pluginDirs: %s", settings.PluginDirs())
plugins, err := findPlugins(settings.PluginDirs())
if err != nil {
@ -55,6 +54,6 @@ func (pcmd *pluginListCmd) run() error {
for _, p := range plugins {
table.AddRow(p.Metadata.Name, p.Metadata.Version, p.Metadata.Description)
}
fmt.Fprintln(pcmd.out, table)
fmt.Fprintln(out, table)
return nil
}

@ -28,49 +28,48 @@ import (
"github.com/spf13/cobra"
)
type pluginRemoveCmd struct {
type pluginRemoveOptions struct {
names []string
home helmpath.Home
out io.Writer
}
func newPluginRemoveCmd(out io.Writer) *cobra.Command {
pcmd := &pluginRemoveCmd{out: out}
o := &pluginRemoveOptions{}
cmd := &cobra.Command{
Use: "remove <plugin>...",
Short: "remove one or more Helm plugins",
PreRunE: func(cmd *cobra.Command, args []string) error {
return pcmd.complete(args)
return o.complete(args)
},
RunE: func(cmd *cobra.Command, args []string) error {
return pcmd.run()
return o.run(out)
},
}
return cmd
}
func (pcmd *pluginRemoveCmd) complete(args []string) error {
func (o *pluginRemoveOptions) complete(args []string) error {
if len(args) == 0 {
return errors.New("please provide plugin name to remove")
}
pcmd.names = args
pcmd.home = settings.Home
o.names = args
o.home = settings.Home
return nil
}
func (pcmd *pluginRemoveCmd) run() error {
func (o *pluginRemoveOptions) run(out io.Writer) error {
debug("loading installed plugins from %s", settings.PluginDirs())
plugins, err := findPlugins(settings.PluginDirs())
if err != nil {
return err
}
var errorPlugins []string
for _, name := range pcmd.names {
for _, name := range o.names {
if found := findPlugin(plugins, name); found != nil {
if err := removePlugin(found); err != nil {
errorPlugins = append(errorPlugins, fmt.Sprintf("Failed to remove plugin %s, got error (%v)", name, err))
} else {
fmt.Fprintf(pcmd.out, "Removed plugin: %s\n", name)
fmt.Fprintf(out, "Removed plugin: %s\n", name)
}
} else {
errorPlugins = append(errorPlugins, fmt.Sprintf("Plugin: %s not found", name))

@ -29,37 +29,36 @@ import (
"github.com/spf13/cobra"
)
type pluginUpdateCmd struct {
type pluginUpdateOptions struct {
names []string
home helmpath.Home
out io.Writer
}
func newPluginUpdateCmd(out io.Writer) *cobra.Command {
pcmd := &pluginUpdateCmd{out: out}
o := &pluginUpdateOptions{}
cmd := &cobra.Command{
Use: "update <plugin>...",
Short: "update one or more Helm plugins",
PreRunE: func(cmd *cobra.Command, args []string) error {
return pcmd.complete(args)
return o.complete(args)
},
RunE: func(cmd *cobra.Command, args []string) error {
return pcmd.run()
return o.run(out)
},
}
return cmd
}
func (pcmd *pluginUpdateCmd) complete(args []string) error {
func (o *pluginUpdateOptions) complete(args []string) error {
if len(args) == 0 {
return errors.New("please provide plugin name to update")
}
pcmd.names = args
pcmd.home = settings.Home
o.names = args
o.home = settings.Home
return nil
}
func (pcmd *pluginUpdateCmd) run() error {
func (o *pluginUpdateOptions) run(out io.Writer) error {
installer.Debug = settings.Debug
debug("loading installed plugins from %s", settings.PluginDirs())
plugins, err := findPlugins(settings.PluginDirs())
@ -68,12 +67,12 @@ func (pcmd *pluginUpdateCmd) run() error {
}
var errorPlugins []string
for _, name := range pcmd.names {
for _, name := range o.names {
if found := findPlugin(plugins, name); found != nil {
if err := updatePlugin(found, pcmd.home); err != nil {
if err := updatePlugin(found, o.home); err != nil {
errorPlugins = append(errorPlugins, fmt.Sprintf("Failed to update plugin %s, got error (%v)", name, err))
} else {
fmt.Fprintf(pcmd.out, "Updated plugin: %s\n", name)
fmt.Fprintf(out, "Updated plugin: %s\n", name)
}
} else {
errorPlugins = append(errorPlugins, fmt.Sprintf("Plugin: %s not found", name))

@ -33,19 +33,15 @@ The argument this command takes is the name of a deployed release.
The tests to be run are defined in the chart that was installed.
`
type releaseTestCmd struct {
type releaseTestOptions struct {
name string
out io.Writer
client helm.Interface
timeout int64
cleanup bool
}
func newReleaseTestCmd(c helm.Interface, out io.Writer) *cobra.Command {
rlsTest := &releaseTestCmd{
out: out,
client: c,
}
o := &releaseTestOptions{client: c}
cmd := &cobra.Command{
Use: "test [RELEASE]",
@ -56,24 +52,24 @@ func newReleaseTestCmd(c helm.Interface, out io.Writer) *cobra.Command {
return err
}
rlsTest.name = args[0]
rlsTest.client = ensureHelmClient(rlsTest.client, false)
return rlsTest.run()
o.name = args[0]
o.client = ensureHelmClient(o.client, false)
return o.run(out)
},
}
f := cmd.Flags()
f.Int64Var(&rlsTest.timeout, "timeout", 300, "time in seconds to wait for any individual Kubernetes operation (like Jobs for hooks)")
f.BoolVar(&rlsTest.cleanup, "cleanup", false, "delete test pods upon completion")
f.Int64Var(&o.timeout, "timeout", 300, "time in seconds to wait for any individual Kubernetes operation (like Jobs for hooks)")
f.BoolVar(&o.cleanup, "cleanup", false, "delete test pods upon completion")
return cmd
}
func (t *releaseTestCmd) run() (err error) {
c, errc := t.client.RunReleaseTest(
t.name,
helm.ReleaseTestTimeout(t.timeout),
helm.ReleaseTestCleanup(t.cleanup),
func (o *releaseTestOptions) run(out io.Writer) (err error) {
c, errc := o.client.RunReleaseTest(
o.name,
helm.ReleaseTestTimeout(o.timeout),
helm.ReleaseTestCleanup(o.cleanup),
)
testErr := &testErr{}
@ -92,12 +88,9 @@ func (t *releaseTestCmd) run() (err error) {
if res.Status == release.TestRunFailure {
testErr.failed++
}
fmt.Fprintf(t.out, res.Msg+"\n")
fmt.Fprintf(out, res.Msg+"\n")
}
}
}
type testErr struct {

@ -27,7 +27,7 @@ import (
"k8s.io/helm/pkg/repo"
)
type repoAddCmd struct {
type repoAddOptions struct {
name string
url string
username string
@ -38,12 +38,10 @@ type repoAddCmd struct {
certFile string
keyFile string
caFile string
out io.Writer
}
func newRepoAddCmd(out io.Writer) *cobra.Command {
add := &repoAddCmd{out: out}
o := &repoAddOptions{}
cmd := &cobra.Command{
Use: "add [flags] [NAME] [URL]",
@ -53,30 +51,30 @@ func newRepoAddCmd(out io.Writer) *cobra.Command {
return err
}
add.name = args[0]
add.url = args[1]
add.home = settings.Home
o.name = args[0]
o.url = args[1]
o.home = settings.Home
return add.run()
return o.run(out)
},
}
f := cmd.Flags()
f.StringVar(&add.username, "username", "", "chart repository username")
f.StringVar(&add.password, "password", "", "chart repository password")
f.BoolVar(&add.noupdate, "no-update", false, "raise error if repo is already registered")
f.StringVar(&add.certFile, "cert-file", "", "identify HTTPS client using this SSL certificate file")
f.StringVar(&add.keyFile, "key-file", "", "identify HTTPS client using this SSL key file")
f.StringVar(&add.caFile, "ca-file", "", "verify certificates of HTTPS-enabled servers using this CA bundle")
f.StringVar(&o.username, "username", "", "chart repository username")
f.StringVar(&o.password, "password", "", "chart repository password")
f.BoolVar(&o.noupdate, "no-update", false, "raise error if repo is already registered")
f.StringVar(&o.certFile, "cert-file", "", "identify HTTPS client using this SSL certificate file")
f.StringVar(&o.keyFile, "key-file", "", "identify HTTPS client using this SSL key file")
f.StringVar(&o.caFile, "ca-file", "", "verify certificates of HTTPS-enabled servers using this CA bundle")
return cmd
}
func (a *repoAddCmd) run() error {
if err := addRepository(a.name, a.url, a.username, a.password, a.home, a.certFile, a.keyFile, a.caFile, a.noupdate); err != nil {
func (o *repoAddOptions) run(out io.Writer) error {
if err := addRepository(o.name, o.url, o.username, o.password, o.home, o.certFile, o.keyFile, o.caFile, o.noupdate); err != nil {
return err
}
fmt.Fprintf(a.out, "%q has been added to your repositories\n", a.name)
fmt.Fprintf(out, "%q has been added to your repositories\n", o.name)
return nil
}

@ -38,15 +38,14 @@ flag. In this case, the charts found in the current directory will be merged
into the existing index, with local charts taking priority over existing charts.
`
type repoIndexCmd struct {
type repoIndexOptions struct {
dir string
url string
out io.Writer
merge string
}
func newRepoIndexCmd(out io.Writer) *cobra.Command {
index := &repoIndexCmd{out: out}
o := &repoIndexOptions{}
cmd := &cobra.Command{
Use: "index [flags] [DIR]",
@ -57,20 +56,20 @@ func newRepoIndexCmd(out io.Writer) *cobra.Command {
return err
}
index.dir = args[0]
o.dir = args[0]
return index.run()
return o.run(out)
},
}
f := cmd.Flags()
f.StringVar(&index.url, "url", "", "url of chart repository")
f.StringVar(&index.merge, "merge", "", "merge the generated index into the given index")
f.StringVar(&o.url, "url", "", "url of chart repository")
f.StringVar(&o.merge, "merge", "", "merge the generated index into the given index")
return cmd
}
func (i *repoIndexCmd) run() error {
func (i *repoIndexOptions) run(out io.Writer) error {
path, err := filepath.Abs(i.dir)
if err != nil {
return err

@ -28,28 +28,27 @@ import (
"k8s.io/helm/pkg/repo"
)
type repoListCmd struct {
out io.Writer
type repoListOptions struct {
home helmpath.Home
}
func newRepoListCmd(out io.Writer) *cobra.Command {
list := &repoListCmd{out: out}
o := &repoListOptions{}
cmd := &cobra.Command{
Use: "list [flags]",
Short: "list chart repositories",
RunE: func(cmd *cobra.Command, args []string) error {
list.home = settings.Home
return list.run()
o.home = settings.Home
return o.run(out)
},
}
return cmd
}
func (a *repoListCmd) run() error {
f, err := repo.LoadRepositoriesFile(a.home.RepositoryFile())
func (o *repoListOptions) run(out io.Writer) error {
f, err := repo.LoadRepositoriesFile(o.home.RepositoryFile())
if err != nil {
return err
}
@ -61,6 +60,6 @@ func (a *repoListCmd) run() error {
for _, re := range f.Repositories {
table.AddRow(re.Name, re.URL)
}
fmt.Fprintln(a.out, table)
fmt.Fprintln(out, table)
return nil
}

@ -27,14 +27,13 @@ import (
"k8s.io/helm/pkg/repo"
)
type repoRemoveCmd struct {
out io.Writer
type repoRemoveOptions struct {
name string
home helmpath.Home
}
func newRepoRemoveCmd(out io.Writer) *cobra.Command {
remove := &repoRemoveCmd{out: out}
o := &repoRemoveOptions{}
cmd := &cobra.Command{
Use: "remove [flags] [NAME]",
@ -44,18 +43,18 @@ func newRepoRemoveCmd(out io.Writer) *cobra.Command {
if err := checkArgsLength(len(args), "name of chart repository"); err != nil {
return err
}
remove.name = args[0]
remove.home = settings.Home
o.name = args[0]
o.home = settings.Home
return remove.run()
return o.run(out)
},
}
return cmd
}
func (r *repoRemoveCmd) run() error {
return removeRepoLine(r.out, r.name, r.home)
func (r *repoRemoveOptions) run(out io.Writer) error {
return removeRepoLine(out, r.name, r.home)
}
func removeRepoLine(out io.Writer, name string, home helmpath.Home) error {

@ -39,32 +39,29 @@ future releases.
var errNoRepositories = errors.New("no repositories found. You must add one before updating")
type repoUpdateCmd struct {
type repoUpdateOptions struct {
update func([]*repo.ChartRepository, io.Writer, helmpath.Home)
home helmpath.Home
out io.Writer
}
func newRepoUpdateCmd(out io.Writer) *cobra.Command {
u := &repoUpdateCmd{
out: out,
update: updateCharts,
}
o := &repoUpdateOptions{update: updateCharts}
cmd := &cobra.Command{
Use: "update",
Aliases: []string{"up"},
Short: "update information of available charts locally from chart repositories",
Long: updateDesc,
RunE: func(cmd *cobra.Command, args []string) error {
u.home = settings.Home
return u.run()
o.home = settings.Home
return o.run(out)
},
}
return cmd
}
func (u *repoUpdateCmd) run() error {
f, err := repo.LoadRepositoriesFile(u.home.RepositoryFile())
func (o *repoUpdateOptions) run(out io.Writer) error {
f, err := repo.LoadRepositoriesFile(o.home.RepositoryFile())
if err != nil {
return err
}
@ -81,7 +78,7 @@ func (u *repoUpdateCmd) run() error {
repos = append(repos, r)
}
u.update(repos, u.out, u.home)
o.update(repos, out, o.home)
return nil
}

@ -51,12 +51,11 @@ func TestUpdateCmd(t *testing.T) {
fmt.Fprintln(out, re.Config.Name)
}
}
uc := &repoUpdateCmd{
o := &repoUpdateOptions{
update: updater,
home: helmpath.Home(thome),
out: out,
}
if err := uc.run(); err != nil {
if err := o.run(out); err != nil {
t.Fatal(err)
}

@ -34,24 +34,20 @@ second is a revision (version) number. To see revision numbers, run
'helm history RELEASE'.
`
type rollbackCmd struct {
type rollbackOptions struct {
name string
revision int
dryRun bool
recreate bool
force bool
disableHooks bool
out io.Writer
client helm.Interface
timeout int64
wait bool
}
func newRollbackCmd(c helm.Interface, out io.Writer) *cobra.Command {
rollback := &rollbackCmd{
out: out,
client: c,
}
o := &rollbackOptions{client: c}
cmd := &cobra.Command{
Use: "rollback [flags] [RELEASE] [REVISION]",
@ -62,45 +58,45 @@ func newRollbackCmd(c helm.Interface, out io.Writer) *cobra.Command {
return err
}
rollback.name = args[0]
o.name = args[0]
v64, err := strconv.ParseInt(args[1], 10, 32)
if err != nil {
return fmt.Errorf("invalid revision number '%q': %s", args[1], err)
}
rollback.revision = int(v64)
rollback.client = ensureHelmClient(rollback.client, false)
return rollback.run()
o.revision = int(v64)
o.client = ensureHelmClient(o.client, false)
return o.run(out)
},
}
f := cmd.Flags()
f.BoolVar(&rollback.dryRun, "dry-run", false, "simulate a rollback")
f.BoolVar(&rollback.recreate, "recreate-pods", false, "performs pods restart for the resource if applicable")
f.BoolVar(&rollback.force, "force", false, "force resource update through delete/recreate if needed")
f.BoolVar(&rollback.disableHooks, "no-hooks", false, "prevent hooks from running during rollback")
f.Int64Var(&rollback.timeout, "timeout", 300, "time in seconds to wait for any individual Kubernetes operation (like Jobs for hooks)")
f.BoolVar(&rollback.wait, "wait", false, "if set, will wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment are in a ready state before marking the release as successful. It will wait for as long as --timeout")
f.BoolVar(&o.dryRun, "dry-run", false, "simulate a rollback")
f.BoolVar(&o.recreate, "recreate-pods", false, "performs pods restart for the resource if applicable")
f.BoolVar(&o.force, "force", false, "force resource update through delete/recreate if needed")
f.BoolVar(&o.disableHooks, "no-hooks", false, "prevent hooks from running during rollback")
f.Int64Var(&o.timeout, "timeout", 300, "time in seconds to wait for any individual Kubernetes operation (like Jobs for hooks)")
f.BoolVar(&o.wait, "wait", false, "if set, will wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment are in a ready state before marking the release as successful. It will wait for as long as --timeout")
return cmd
}
func (r *rollbackCmd) run() error {
_, err := r.client.RollbackRelease(
r.name,
helm.RollbackDryRun(r.dryRun),
helm.RollbackRecreate(r.recreate),
helm.RollbackForce(r.force),
helm.RollbackDisableHooks(r.disableHooks),
helm.RollbackVersion(r.revision),
helm.RollbackTimeout(r.timeout),
helm.RollbackWait(r.wait))
func (o *rollbackOptions) run(out io.Writer) error {
_, err := o.client.RollbackRelease(
o.name,
helm.RollbackDryRun(o.dryRun),
helm.RollbackRecreate(o.recreate),
helm.RollbackForce(o.force),
helm.RollbackDisableHooks(o.disableHooks),
helm.RollbackVersion(o.revision),
helm.RollbackTimeout(o.timeout),
helm.RollbackWait(o.wait))
if err != nil {
return err
}
fmt.Fprintf(r.out, "Rollback was a success! Happy Helming!\n")
fmt.Fprintf(out, "Rollback was a success! Happy Helming!\n")
return nil
}

@ -40,8 +40,7 @@ Repositories are managed with 'helm repo' commands.
// searchMaxScore suggests that any score higher than this is not considered a match.
const searchMaxScore = 25
type searchCmd struct {
out io.Writer
type searchOptions struct {
helmhome helmpath.Home
versions bool
@ -50,28 +49,28 @@ type searchCmd struct {
}
func newSearchCmd(out io.Writer) *cobra.Command {
sc := &searchCmd{out: out}
o := &searchOptions{}
cmd := &cobra.Command{
Use: "search [keyword]",
Short: "search for a keyword in charts",
Long: searchDesc,
RunE: func(cmd *cobra.Command, args []string) error {
sc.helmhome = settings.Home
return sc.run(args)
o.helmhome = settings.Home
return o.run(out, args)
},
}
f := cmd.Flags()
f.BoolVarP(&sc.regexp, "regexp", "r", false, "use regular expressions for searching")
f.BoolVarP(&sc.versions, "versions", "l", false, "show the long listing, with each version of each chart on its own line")
f.StringVarP(&sc.version, "version", "v", "", "search using semantic versioning constraints")
f.BoolVarP(&o.regexp, "regexp", "r", false, "use regular expressions for searching")
f.BoolVarP(&o.versions, "versions", "l", false, "show the long listing, with each version of each chart on its own line")
f.StringVarP(&o.version, "version", "v", "", "search using semantic versioning constraints")
return cmd
}
func (s *searchCmd) run(args []string) error {
index, err := s.buildIndex()
func (o *searchOptions) run(out io.Writer, args []string) error {
index, err := o.buildIndex(out)
if err != nil {
return err
}
@ -81,29 +80,29 @@ func (s *searchCmd) run(args []string) error {
res = index.All()
} else {
q := strings.Join(args, " ")
res, err = index.Search(q, searchMaxScore, s.regexp)
res, err = index.Search(q, searchMaxScore, o.regexp)
if err != nil {
return err
}
}
search.SortScore(res)
data, err := s.applyConstraint(res)
data, err := o.applyConstraint(res)
if err != nil {
return err
}
fmt.Fprintln(s.out, s.formatSearchResults(data))
fmt.Fprintln(out, o.formatSearchResults(data))
return nil
}
func (s *searchCmd) applyConstraint(res []*search.Result) ([]*search.Result, error) {
if len(s.version) == 0 {
func (o *searchOptions) applyConstraint(res []*search.Result) ([]*search.Result, error) {
if len(o.version) == 0 {
return res, nil
}
constraint, err := semver.NewConstraint(s.version)
constraint, err := semver.NewConstraint(o.version)
if err != nil {
return res, fmt.Errorf("an invalid version/constraint format: %s", err)
}
@ -117,7 +116,7 @@ func (s *searchCmd) applyConstraint(res []*search.Result) ([]*search.Result, err
v, err := semver.NewVersion(r.Chart.Version)
if err != nil || constraint.Check(v) {
data = append(data, r)
if !s.versions {
if !o.versions {
foundNames[r.Name] = true // If user hasn't requested all versions, only show the latest that matches
}
}
@ -126,7 +125,7 @@ func (s *searchCmd) applyConstraint(res []*search.Result) ([]*search.Result, err
return data, nil
}
func (s *searchCmd) formatSearchResults(res []*search.Result) string {
func (o *searchOptions) formatSearchResults(res []*search.Result) string {
if len(res) == 0 {
return "No results found"
}
@ -139,9 +138,9 @@ func (s *searchCmd) formatSearchResults(res []*search.Result) string {
return table.String()
}
func (s *searchCmd) buildIndex() (*search.Index, error) {
func (o *searchOptions) buildIndex(out io.Writer) (*search.Index, error) {
// Load the repositories.yaml
rf, err := repo.LoadRepositoriesFile(s.helmhome.RepositoryFile())
rf, err := repo.LoadRepositoriesFile(o.helmhome.RepositoryFile())
if err != nil {
return nil, err
}
@ -149,14 +148,15 @@ func (s *searchCmd) buildIndex() (*search.Index, error) {
i := search.NewIndex()
for _, re := range rf.Repositories {
n := re.Name
f := s.helmhome.CacheIndex(n)
f := o.helmhome.CacheIndex(n)
ind, err := repo.LoadIndexFile(f)
if err != nil {
fmt.Fprintf(s.out, "WARNING: Repo %q is corrupt or missing. Try 'helm repo update'.", n)
// TODO should print to stderr
fmt.Fprintf(out, "WARNING: Repo %q is corrupt or missing. Try 'helm repo update'.", n)
continue
}
i.AddRepo(n, ind, s.versions || len(s.version) > 0)
i.AddRepo(n, ind, o.versions || len(o.version) > 0)
}
return i, nil
}

@ -44,19 +44,15 @@ The status consists of:
- additional notes provided by the chart
`
type statusCmd struct {
type statusOptions struct {
release string
out io.Writer
client helm.Interface
version int
outfmt string
}
func newStatusCmd(client helm.Interface, out io.Writer) *cobra.Command {
status := &statusCmd{
out: out,
client: client,
}
o := &statusOptions{client: client}
cmd := &cobra.Command{
Use: "status [flags] RELEASE_NAME",
@ -66,45 +62,45 @@ func newStatusCmd(client helm.Interface, out io.Writer) *cobra.Command {
if len(args) == 0 {
return errReleaseRequired
}
status.release = args[0]
status.client = ensureHelmClient(status.client, false)
return status.run()
o.release = args[0]
o.client = ensureHelmClient(o.client, false)
return o.run(out)
},
}
cmd.PersistentFlags().IntVar(&status.version, "revision", 0, "if set, display the status of the named release with revision")
cmd.PersistentFlags().StringVarP(&status.outfmt, "output", "o", "", "output the status in the specified format (json or yaml)")
cmd.PersistentFlags().IntVar(&o.version, "revision", 0, "if set, display the status of the named release with revision")
cmd.PersistentFlags().StringVarP(&o.outfmt, "output", "o", "", "output the status in the specified format (json or yaml)")
return cmd
}
func (s *statusCmd) run() error {
res, err := s.client.ReleaseStatus(s.release, s.version)
func (o *statusOptions) run(out io.Writer) error {
res, err := o.client.ReleaseStatus(o.release, o.version)
if err != nil {
return err
}
switch s.outfmt {
switch o.outfmt {
case "":
PrintStatus(s.out, res)
PrintStatus(out, res)
return nil
case "json":
data, err := json.Marshal(res)
if err != nil {
return fmt.Errorf("Failed to Marshal JSON output: %s", err)
}
s.out.Write(data)
out.Write(data)
return nil
case "yaml":
data, err := yaml.Marshal(res)
if err != nil {
return fmt.Errorf("Failed to Marshal YAML output: %s", err)
}
s.out.Write(data)
out.Write(data)
return nil
}
return fmt.Errorf("Unknown output format %q", s.outfmt)
return fmt.Errorf("Unknown output format %q", o.outfmt)
}
// PrintStatus prints out the status of a release. Shared because also used by

@ -60,10 +60,9 @@ To render just one template in a chart, use '-x':
$ helm template mychart -x templates/deployment.yaml
`
type templateCmd struct {
type templateOptions struct {
valueFiles valueFiles
chartPath string
out io.Writer
values []string
stringValues []string
nameTemplate string
@ -75,52 +74,51 @@ type templateCmd struct {
}
func newTemplateCmd(out io.Writer) *cobra.Command {
t := &templateCmd{
out: out,
}
o := &templateOptions{}
cmd := &cobra.Command{
Use: "template [flags] CHART",
Short: fmt.Sprintf("locally render templates"),
Long: templateDesc,
RunE: t.run,
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return errors.New("chart is required")
}
// verify chart path exists
if _, err := os.Stat(args[0]); err == nil {
if o.chartPath, err = filepath.Abs(args[0]); err != nil {
return err
}
} else {
return err
}
return o.run(out)
},
}
f := cmd.Flags()
f.BoolVar(&t.showNotes, "notes", false, "show the computed NOTES.txt file as well")
f.StringVarP(&t.releaseName, "name", "", "RELEASE-NAME", "release name")
f.StringArrayVarP(&t.renderFiles, "execute", "x", []string{}, "only execute the given templates")
f.VarP(&t.valueFiles, "values", "f", "specify values in a YAML file (can specify multiple)")
f.StringArrayVar(&t.values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
f.StringArrayVar(&t.stringValues, "set-string", []string{}, "set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
f.StringVar(&t.nameTemplate, "name-template", "", "specify template used to name the release")
f.StringVar(&t.kubeVersion, "kube-version", defaultKubeVersion, "kubernetes version used as Capabilities.KubeVersion.Major/Minor")
f.StringVar(&t.outputDir, "output-dir", "", "writes the executed templates to files in output-dir instead of stdout")
f.BoolVar(&o.showNotes, "notes", false, "show the computed NOTES.txt file as well")
f.StringVarP(&o.releaseName, "name", "", "RELEASE-NAME", "release name")
f.StringArrayVarP(&o.renderFiles, "execute", "x", []string{}, "only execute the given templates")
f.VarP(&o.valueFiles, "values", "f", "specify values in a YAML file (can specify multiple)")
f.StringArrayVar(&o.values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
f.StringArrayVar(&o.stringValues, "set-string", []string{}, "set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
f.StringVar(&o.nameTemplate, "name-template", "", "specify template used to name the release")
f.StringVar(&o.kubeVersion, "kube-version", defaultKubeVersion, "kubernetes version used as Capabilities.KubeVersion.Major/Minor")
f.StringVar(&o.outputDir, "output-dir", "", "writes the executed templates to files in output-dir instead of stdout")
return cmd
}
func (t *templateCmd) run(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return errors.New("chart is required")
}
// verify chart path exists
if _, err := os.Stat(args[0]); err == nil {
if t.chartPath, err = filepath.Abs(args[0]); err != nil {
return err
}
} else {
return err
}
func (o *templateOptions) run(out io.Writer) error {
// verify specified templates exist relative to chart
rf := []string{}
var af string
var err error
if len(t.renderFiles) > 0 {
for _, f := range t.renderFiles {
if len(o.renderFiles) > 0 {
for _, f := range o.renderFiles {
if !filepath.IsAbs(f) {
af, err = filepath.Abs(filepath.Join(t.chartPath, f))
af, err = filepath.Abs(filepath.Join(o.chartPath, f))
if err != nil {
return fmt.Errorf("could not resolve template path: %s", err)
}
@ -136,29 +134,29 @@ func (t *templateCmd) run(cmd *cobra.Command, args []string) error {
}
// verify that output-dir exists if provided
if t.outputDir != "" {
_, err = os.Stat(t.outputDir)
if o.outputDir != "" {
_, err = os.Stat(o.outputDir)
if os.IsNotExist(err) {
return fmt.Errorf("output-dir '%s' does not exist", t.outputDir)
return fmt.Errorf("output-dir '%s' does not exist", o.outputDir)
}
}
// get combined values and create config
config, err := vals(t.valueFiles, t.values, t.stringValues)
config, err := vals(o.valueFiles, o.values, o.stringValues)
if err != nil {
return err
}
// If template is specified, try to run the template.
if t.nameTemplate != "" {
t.releaseName, err = generateName(t.nameTemplate)
if o.nameTemplate != "" {
o.releaseName, err = generateName(o.nameTemplate)
if err != nil {
return err
}
}
// Check chart requirements to make sure all dependencies are present in /charts
c, err := chartutil.Load(t.chartPath)
c, err := chartutil.Load(o.chartPath)
if err != nil {
return err
}
@ -171,7 +169,7 @@ func (t *templateCmd) run(cmd *cobra.Command, args []string) error {
return fmt.Errorf("cannot load requirements: %v", err)
}
options := chartutil.ReleaseOptions{
Name: t.releaseName,
Name: o.releaseName,
Time: time.Now(),
Namespace: getNamespace(),
}
@ -195,7 +193,7 @@ func (t *templateCmd) run(cmd *cobra.Command, args []string) error {
}
// kubernetes version
kv, err := semver.NewVersion(t.kubeVersion)
kv, err := semver.NewVersion(o.kubeVersion)
if err != nil {
return fmt.Errorf("could not parse a kubernetes version: %v", err)
}
@ -208,14 +206,14 @@ func (t *templateCmd) run(cmd *cobra.Command, args []string) error {
return err
}
out, err := renderer.Render(c, vals)
rendered, err := renderer.Render(c, vals)
listManifests := []tiller.Manifest{}
if err != nil {
return err
}
// extract kind and name
re := regexp.MustCompile("kind:(.*)\n")
for k, v := range out {
for k, v := range rendered {
match := re.FindStringSubmatch(v)
h := "Unknown"
if len(match) == 2 {
@ -228,7 +226,7 @@ func (t *templateCmd) run(cmd *cobra.Command, args []string) error {
// make needle path absolute
d := strings.Split(needle, string(os.PathSeparator))
dd := d[1:]
an := filepath.Join(t.chartPath, strings.Join(dd, string(os.PathSeparator)))
an := filepath.Join(o.chartPath, strings.Join(dd, string(os.PathSeparator)))
for _, h := range haystack {
if h == an {
@ -239,34 +237,34 @@ func (t *templateCmd) run(cmd *cobra.Command, args []string) error {
}
if settings.Debug {
rel := &release.Release{
Name: t.releaseName,
Name: o.releaseName,
Chart: c,
Config: config,
Version: 1,
Info: &release.Info{LastDeployed: time.Now()},
}
printRelease(os.Stdout, rel)
printRelease(out, rel)
}
for _, m := range tiller.SortByKind(listManifests) {
if len(t.renderFiles) > 0 && !in(m.Name, rf) {
if len(o.renderFiles) > 0 && !in(m.Name, rf) {
continue
}
data := m.Content
b := filepath.Base(m.Name)
if !t.showNotes && b == "NOTES.txt" {
if !o.showNotes && b == "NOTES.txt" {
continue
}
if strings.HasPrefix(b, "_") {
continue
}
if t.outputDir != "" {
if o.outputDir != "" {
// blank template after execution
if whitespaceRegex.MatchString(data) {
continue
}
err = writeToFile(t.outputDir, m.Name, data)
err = writeToFile(o.outputDir, m.Name, data)
if err != nil {
return err
}

@ -53,10 +53,9 @@ set for a key called 'foo', the 'newbar' value would take precedence:
$ helm upgrade --set foo=bar --set foo=newbar redis ./redis
`
type upgradeCmd struct {
type upgradeOptions struct {
release string
chart string
out io.Writer
client helm.Interface
dryRun bool
recreate bool
@ -84,11 +83,7 @@ type upgradeCmd struct {
}
func newUpgradeCmd(client helm.Interface, out io.Writer) *cobra.Command {
upgrade := &upgradeCmd{
out: out,
client: client,
}
o := &upgradeOptions{client: client}
cmd := &cobra.Command{
Use: "upgrade [RELEASE] [CHART]",
@ -99,82 +94,81 @@ func newUpgradeCmd(client helm.Interface, out io.Writer) *cobra.Command {
return err
}
if upgrade.version == "" && upgrade.devel {
if o.version == "" && o.devel {
debug("setting version to >0.0.0-0")
upgrade.version = ">0.0.0-0"
o.version = ">0.0.0-0"
}
upgrade.release = args[0]
upgrade.chart = args[1]
upgrade.client = ensureHelmClient(upgrade.client, false)
o.release = args[0]
o.chart = args[1]
o.client = ensureHelmClient(o.client, false)
return upgrade.run()
return o.run(out)
},
}
f := cmd.Flags()
f.VarP(&upgrade.valueFiles, "values", "f", "specify values in a YAML file or a URL(can specify multiple)")
f.BoolVar(&upgrade.dryRun, "dry-run", false, "simulate an upgrade")
f.BoolVar(&upgrade.recreate, "recreate-pods", false, "performs pods restart for the resource if applicable")
f.BoolVar(&upgrade.force, "force", false, "force resource update through delete/recreate if needed")
f.StringArrayVar(&upgrade.values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
f.StringArrayVar(&upgrade.stringValues, "set-string", []string{}, "set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
f.BoolVar(&upgrade.disableHooks, "disable-hooks", false, "disable pre/post upgrade hooks. DEPRECATED. Use no-hooks")
f.BoolVar(&upgrade.disableHooks, "no-hooks", false, "disable pre/post upgrade hooks")
f.BoolVar(&upgrade.verify, "verify", false, "verify the provenance of the chart before upgrading")
f.StringVar(&upgrade.keyring, "keyring", defaultKeyring(), "path to the keyring that contains public signing keys")
f.BoolVarP(&upgrade.install, "install", "i", false, "if a release by this name doesn't already exist, run an install")
f.StringVar(&upgrade.version, "version", "", "specify the exact chart version to use. If this is not specified, the latest version is used")
f.Int64Var(&upgrade.timeout, "timeout", 300, "time in seconds to wait for any individual Kubernetes operation (like Jobs for hooks)")
f.BoolVar(&upgrade.resetValues, "reset-values", false, "when upgrading, reset the values to the ones built into the chart")
f.BoolVar(&upgrade.reuseValues, "reuse-values", false, "when upgrading, reuse the last release's values and merge in any overrides from the command line via --set and -f. If '--reset-values' is specified, this is ignored.")
f.BoolVar(&upgrade.wait, "wait", false, "if set, will wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment are in a ready state before marking the release as successful. It will wait for as long as --timeout")
f.StringVar(&upgrade.repoURL, "repo", "", "chart repository url where to locate the requested chart")
f.StringVar(&upgrade.username, "username", "", "chart repository username where to locate the requested chart")
f.StringVar(&upgrade.password, "password", "", "chart repository password where to locate the requested chart")
f.StringVar(&upgrade.certFile, "cert-file", "", "identify HTTPS client using this SSL certificate file")
f.StringVar(&upgrade.keyFile, "key-file", "", "identify HTTPS client using this SSL key file")
f.StringVar(&upgrade.caFile, "ca-file", "", "verify certificates of HTTPS-enabled servers using this CA bundle")
f.BoolVar(&upgrade.devel, "devel", false, "use development versions, too. Equivalent to version '>0.0.0-0'. If --version is set, this is ignored.")
f.VarP(&o.valueFiles, "values", "f", "specify values in a YAML file or a URL(can specify multiple)")
f.BoolVar(&o.dryRun, "dry-run", false, "simulate an upgrade")
f.BoolVar(&o.recreate, "recreate-pods", false, "performs pods restart for the resource if applicable")
f.BoolVar(&o.force, "force", false, "force resource update through delete/recreate if needed")
f.StringArrayVar(&o.values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
f.StringArrayVar(&o.stringValues, "set-string", []string{}, "set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
f.BoolVar(&o.disableHooks, "disable-hooks", false, "disable pre/post upgrade hooks. DEPRECATED. Use no-hooks")
f.BoolVar(&o.disableHooks, "no-hooks", false, "disable pre/post upgrade hooks")
f.BoolVar(&o.verify, "verify", false, "verify the provenance of the chart before upgrading")
f.StringVar(&o.keyring, "keyring", defaultKeyring(), "path to the keyring that contains public signing keys")
f.BoolVarP(&o.install, "install", "i", false, "if a release by this name doesn't already exist, run an install")
f.StringVar(&o.version, "version", "", "specify the exact chart version to use. If this is not specified, the latest version is used")
f.Int64Var(&o.timeout, "timeout", 300, "time in seconds to wait for any individual Kubernetes operation (like Jobs for hooks)")
f.BoolVar(&o.resetValues, "reset-values", false, "when upgrading, reset the values to the ones built into the chart")
f.BoolVar(&o.reuseValues, "reuse-values", false, "when upgrading, reuse the last release's values and merge in any overrides from the command line via --set and -f. If '--reset-values' is specified, this is ignored.")
f.BoolVar(&o.wait, "wait", false, "if set, will wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment are in a ready state before marking the release as successful. It will wait for as long as --timeout")
f.StringVar(&o.repoURL, "repo", "", "chart repository url where to locate the requested chart")
f.StringVar(&o.username, "username", "", "chart repository username where to locate the requested chart")
f.StringVar(&o.password, "password", "", "chart repository password where to locate the requested chart")
f.StringVar(&o.certFile, "cert-file", "", "identify HTTPS client using this SSL certificate file")
f.StringVar(&o.keyFile, "key-file", "", "identify HTTPS client using this SSL key file")
f.StringVar(&o.caFile, "ca-file", "", "verify certificates of HTTPS-enabled servers using this CA bundle")
f.BoolVar(&o.devel, "devel", false, "use development versions, too. Equivalent to version '>0.0.0-0'. If --version is set, this is ignored.")
f.MarkDeprecated("disable-hooks", "use --no-hooks instead")
return cmd
}
func (u *upgradeCmd) run() error {
chartPath, err := locateChartPath(u.repoURL, u.username, u.password, u.chart, u.version, u.verify, u.keyring, u.certFile, u.keyFile, u.caFile)
func (o *upgradeOptions) run(out io.Writer) error {
chartPath, err := locateChartPath(o.repoURL, o.username, o.password, o.chart, o.version, o.verify, o.keyring, o.certFile, o.keyFile, o.caFile)
if err != nil {
return err
}
if u.install {
if o.install {
// If a release does not exist, install it. If another error occurs during
// the check, ignore the error and continue with the upgrade.
_, err := u.client.ReleaseHistory(u.release, 1)
_, err := o.client.ReleaseHistory(o.release, 1)
if err != nil && strings.Contains(err.Error(), driver.ErrReleaseNotFound(u.release).Error()) {
fmt.Fprintf(u.out, "Release %q does not exist. Installing it now.\n", u.release)
ic := &installCmd{
if err != nil && strings.Contains(err.Error(), driver.ErrReleaseNotFound(o.release).Error()) {
fmt.Fprintf(out, "Release %q does not exist. Installing it now.\n", o.release)
io := &installOptions{
chartPath: chartPath,
client: u.client,
out: u.out,
name: u.release,
valueFiles: u.valueFiles,
dryRun: u.dryRun,
verify: u.verify,
disableHooks: u.disableHooks,
keyring: u.keyring,
values: u.values,
stringValues: u.stringValues,
timeout: u.timeout,
wait: u.wait,
client: o.client,
name: o.release,
valueFiles: o.valueFiles,
dryRun: o.dryRun,
verify: o.verify,
disableHooks: o.disableHooks,
keyring: o.keyring,
values: o.values,
stringValues: o.stringValues,
timeout: o.timeout,
wait: o.wait,
}
return ic.run()
return io.run(out)
}
}
rawVals, err := vals(u.valueFiles, u.values, u.stringValues)
rawVals, err := vals(o.valueFiles, o.values, o.stringValues)
if err != nil {
return err
}
@ -192,34 +186,34 @@ func (u *upgradeCmd) run() error {
return err
}
resp, err := u.client.UpdateRelease(
u.release,
resp, err := o.client.UpdateRelease(
o.release,
chartPath,
helm.UpdateValueOverrides(rawVals),
helm.UpgradeDryRun(u.dryRun),
helm.UpgradeRecreate(u.recreate),
helm.UpgradeForce(u.force),
helm.UpgradeDisableHooks(u.disableHooks),
helm.UpgradeTimeout(u.timeout),
helm.ResetValues(u.resetValues),
helm.ReuseValues(u.reuseValues),
helm.UpgradeWait(u.wait))
helm.UpgradeDryRun(o.dryRun),
helm.UpgradeRecreate(o.recreate),
helm.UpgradeForce(o.force),
helm.UpgradeDisableHooks(o.disableHooks),
helm.UpgradeTimeout(o.timeout),
helm.ResetValues(o.resetValues),
helm.ReuseValues(o.reuseValues),
helm.UpgradeWait(o.wait))
if err != nil {
return fmt.Errorf("UPGRADE FAILED: %v", err)
}
if settings.Debug {
printRelease(u.out, resp)
printRelease(out, resp)
}
fmt.Fprintf(u.out, "Release %q has been upgraded. Happy Helming!\n", u.release)
fmt.Fprintf(out, "Release %q has been upgraded. Happy Helming!\n", o.release)
// Print the status like status command does
status, err := u.client.ReleaseStatus(u.release, 0)
status, err := o.client.ReleaseStatus(o.release, 0)
if err != nil {
return err
}
PrintStatus(u.out, status)
PrintStatus(out, status)
return nil
}

@ -35,15 +35,13 @@ This command can be used to verify a local chart. Several other commands provide
the 'helm package --sign' command.
`
type verifyCmd struct {
type verifyOptions struct {
keyring string
chartfile string
out io.Writer
}
func newVerifyCmd(out io.Writer) *cobra.Command {
vc := &verifyCmd{out: out}
o := &verifyOptions{}
cmd := &cobra.Command{
Use: "verify [flags] PATH",
@ -53,18 +51,18 @@ func newVerifyCmd(out io.Writer) *cobra.Command {
if len(args) == 0 {
return errors.New("a path to a package file is required")
}
vc.chartfile = args[0]
return vc.run()
o.chartfile = args[0]
return o.run(out)
},
}
f := cmd.Flags()
f.StringVar(&vc.keyring, "keyring", defaultKeyring(), "keyring containing public keys")
f.StringVar(&o.keyring, "keyring", defaultKeyring(), "keyring containing public keys")
return cmd
}
func (v *verifyCmd) run() error {
_, err := downloader.VerifyChart(v.chartfile, v.keyring)
func (o *verifyOptions) run(out io.Writer) error {
_, err := downloader.VerifyChart(o.chartfile, o.keyring)
return err
}

@ -40,39 +40,38 @@ version.BuildInfo{Version:"v2.0.0", GitCommit:"ff52399e51bb880526e9cd0ed8386f643
built, and "dirty" if the binary was built from locally modified code.
`
type versionCmd struct {
out io.Writer
type versionOptions struct {
short bool
template string
}
func newVersionCmd(out io.Writer) *cobra.Command {
version := &versionCmd{out: out}
o := &versionOptions{}
cmd := &cobra.Command{
Use: "version",
Short: "print the client version information",
Long: versionDesc,
RunE: func(cmd *cobra.Command, args []string) error {
return version.run()
return o.run(out)
},
}
f := cmd.Flags()
f.BoolVar(&version.short, "short", false, "print the version number")
f.StringVar(&version.template, "template", "", "template for version string format")
f.BoolVar(&o.short, "short", false, "print the version number")
f.StringVar(&o.template, "template", "", "template for version string format")
return cmd
}
func (v *versionCmd) run() error {
if v.template != "" {
tt, err := template.New("_").Parse(v.template)
func (o *versionOptions) run(out io.Writer) error {
if o.template != "" {
tt, err := template.New("_").Parse(o.template)
if err != nil {
return err
}
return tt.Execute(v.out, version.GetBuildInfo())
return tt.Execute(out, version.GetBuildInfo())
}
fmt.Fprintln(v.out, formatVersion(v.short))
fmt.Fprintln(out, formatVersion(o.short))
return nil
}

Loading…
Cancel
Save