Merge pull request #6550 from thomastaylor312/fix/missing_debug

fix(cmd): Fix all the outputs
pull/6596/head
Taylor Thomas 6 years ago committed by GitHub
commit 0210d43a66
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -23,6 +23,7 @@ import (
"github.com/spf13/pflag" "github.com/spf13/pflag"
"helm.sh/helm/v3/pkg/action" "helm.sh/helm/v3/pkg/action"
"helm.sh/helm/v3/pkg/cli/output"
"helm.sh/helm/v3/pkg/cli/values" "helm.sh/helm/v3/pkg/cli/values"
) )
@ -48,10 +49,34 @@ func addChartPathOptionsFlags(f *pflag.FlagSet, c *action.ChartPathOptions) {
} }
// bindOutputFlag will add the output flag to the given command and bind the // bindOutputFlag will add the output flag to the given command and bind the
// value to the given string pointer // value to the given format pointer
func bindOutputFlag(cmd *cobra.Command, varRef *string) { func bindOutputFlag(cmd *cobra.Command, varRef *output.Format) {
// NOTE(taylor): A possible refactor here is that we can implement all the cmd.Flags().VarP(newOutputValue(output.Table, varRef), outputFlag, "o", fmt.Sprintf("prints the output in the specified format. Allowed values: %s, %s, %s", output.Table, output.JSON, output.YAML))
// validation for the OutputFormat type here so we don't have to do the }
// parsing and checking in the command
cmd.Flags().StringVarP(varRef, outputFlag, "o", string(action.Table), fmt.Sprintf("prints the output in the specified format. Allowed values: %s, %s, %s", action.Table, action.JSON, action.YAML)) type outputValue output.Format
func newOutputValue(defaultValue output.Format, p *output.Format) *outputValue {
*p = defaultValue
return (*outputValue)(p)
}
func (o *outputValue) String() string {
// It is much cleaner looking (and technically less allocations) to just
// convert to a string rather than type asserting to the underlying
// output.Format
return string(*o)
}
func (o *outputValue) Type() string {
return "format"
}
func (o *outputValue) Set(s string) error {
outfmt, err := output.ParseFormat(s)
if err != nil {
return err
}
*o = outputValue(outfmt)
return nil
} }

@ -23,6 +23,7 @@ import (
"helm.sh/helm/v3/cmd/helm/require" "helm.sh/helm/v3/cmd/helm/require"
"helm.sh/helm/v3/pkg/action" "helm.sh/helm/v3/pkg/action"
"helm.sh/helm/v3/pkg/cli/output"
) )
var getHelp = ` var getHelp = `
@ -58,7 +59,8 @@ func newGetCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
} }
return tpl(template, data, out) return tpl(template, data, out)
} }
return printRelease(out, res)
return output.Table.Write(out, &statusPrinter{res, true})
}, },
} }

@ -19,6 +19,7 @@ package main
import ( import (
"fmt" "fmt"
"io" "io"
"time"
"github.com/gosuri/uitable" "github.com/gosuri/uitable"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@ -26,6 +27,7 @@ import (
"helm.sh/helm/v3/cmd/helm/require" "helm.sh/helm/v3/cmd/helm/require"
"helm.sh/helm/v3/pkg/action" "helm.sh/helm/v3/pkg/action"
"helm.sh/helm/v3/pkg/chart" "helm.sh/helm/v3/pkg/chart"
"helm.sh/helm/v3/pkg/cli/output"
"helm.sh/helm/v3/pkg/release" "helm.sh/helm/v3/pkg/release"
"helm.sh/helm/v3/pkg/releaseutil" "helm.sh/helm/v3/pkg/releaseutil"
) )
@ -48,6 +50,7 @@ The historical release set is printed as a formatted table, e.g:
func newHistoryCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { func newHistoryCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
client := action.NewHistory(cfg) client := action.NewHistory(cfg)
var outfmt output.Format
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "history RELEASE_NAME", Use: "history RELEASE_NAME",
@ -56,32 +59,25 @@ func newHistoryCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
Aliases: []string{"hist"}, Aliases: []string{"hist"},
Args: require.ExactArgs(1), Args: require.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
// validate the output format first so we don't waste time running a
// request that we'll throw away
output, err := action.ParseOutputFormat(client.OutputFormat)
if err != nil {
return err
}
history, err := getHistory(client, args[0]) history, err := getHistory(client, args[0])
if err != nil { if err != nil {
return err return err
} }
return output.Write(out, history) return outfmt.Write(out, history)
}, },
} }
f := cmd.Flags() f := cmd.Flags()
f.IntVar(&client.Max, "max", 256, "maximum number of revision to include in history") f.IntVar(&client.Max, "max", 256, "maximum number of revision to include in history")
bindOutputFlag(cmd, &client.OutputFormat) bindOutputFlag(cmd, &outfmt)
return cmd return cmd
} }
type releaseInfo struct { type releaseInfo struct {
Revision int `json:"revision"` Revision int `json:"revision"`
Updated string `json:"updated"` Updated time.Time `json:"updated"`
Status string `json:"status"` Status string `json:"status"`
Chart string `json:"chart"` Chart string `json:"chart"`
AppVersion string `json:"app_version"` AppVersion string `json:"app_version"`
@ -91,20 +87,20 @@ type releaseInfo struct {
type releaseHistory []releaseInfo type releaseHistory []releaseInfo
func (r releaseHistory) WriteJSON(out io.Writer) error { func (r releaseHistory) WriteJSON(out io.Writer) error {
return action.EncodeJSON(out, r) return output.EncodeJSON(out, r)
} }
func (r releaseHistory) WriteYAML(out io.Writer) error { func (r releaseHistory) WriteYAML(out io.Writer) error {
return action.EncodeYAML(out, r) return output.EncodeYAML(out, r)
} }
func (r releaseHistory) WriteTable(out io.Writer) error { func (r releaseHistory) WriteTable(out io.Writer) error {
tbl := uitable.New() tbl := uitable.New()
tbl.AddRow("REVISION", "UPDATED", "STATUS", "CHART", "APP VERSION", "DESCRIPTION") tbl.AddRow("REVISION", "UPDATED", "STATUS", "CHART", "APP VERSION", "DESCRIPTION")
for _, item := range r { for _, item := range r {
tbl.AddRow(item.Revision, item.Updated, item.Status, item.Chart, item.AppVersion, item.Description) tbl.AddRow(item.Revision, item.Updated.Format(time.ANSIC), item.Status, item.Chart, item.AppVersion, item.Description)
} }
return action.EncodeTable(out, tbl) return output.EncodeTable(out, tbl)
} }
func getHistory(client *action.History, name string) (releaseHistory, error) { func getHistory(client *action.History, name string) (releaseHistory, error) {
@ -146,7 +142,7 @@ func getReleaseHistory(rls []*release.Release) (history releaseHistory) {
Description: d, Description: d,
} }
if !r.Info.LastDeployed.IsZero() { if !r.Info.LastDeployed.IsZero() {
rInfo.Updated = r.Info.LastDeployed.String() rInfo.Updated = r.Info.LastDeployed
} }
history = append(history, rInfo) history = append(history, rInfo)

@ -28,6 +28,7 @@ import (
"helm.sh/helm/v3/pkg/action" "helm.sh/helm/v3/pkg/action"
"helm.sh/helm/v3/pkg/chart" "helm.sh/helm/v3/pkg/chart"
"helm.sh/helm/v3/pkg/chart/loader" "helm.sh/helm/v3/pkg/chart/loader"
"helm.sh/helm/v3/pkg/cli/output"
"helm.sh/helm/v3/pkg/cli/values" "helm.sh/helm/v3/pkg/cli/values"
"helm.sh/helm/v3/pkg/downloader" "helm.sh/helm/v3/pkg/downloader"
"helm.sh/helm/v3/pkg/getter" "helm.sh/helm/v3/pkg/getter"
@ -104,6 +105,7 @@ charts in a repository, use 'helm search'.
func newInstallCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { func newInstallCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
client := action.NewInstall(cfg) client := action.NewInstall(cfg)
valueOpts := &values.Options{} valueOpts := &values.Options{}
var outfmt output.Format
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "install [NAME] [CHART]", Use: "install [NAME] [CHART]",
@ -111,24 +113,17 @@ func newInstallCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
Long: installDesc, Long: installDesc,
Args: require.MinimumNArgs(1), Args: require.MinimumNArgs(1),
RunE: func(_ *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {
// validate the output format first so we don't waste time running a
// request that we'll throw away
output, err := action.ParseOutputFormat(client.OutputFormat)
if err != nil {
return err
}
rel, err := runInstall(args, client, valueOpts, out) rel, err := runInstall(args, client, valueOpts, out)
if err != nil { if err != nil {
return err return err
} }
return output.Write(out, &statusPrinter{rel}) return outfmt.Write(out, &statusPrinter{rel, settings.Debug})
}, },
} }
addInstallFlags(cmd.Flags(), client, valueOpts) addInstallFlags(cmd.Flags(), client, valueOpts)
bindOutputFlag(cmd, &client.OutputFormat) bindOutputFlag(cmd, &outfmt)
return cmd return cmd
} }

@ -26,6 +26,7 @@ import (
"helm.sh/helm/v3/cmd/helm/require" "helm.sh/helm/v3/cmd/helm/require"
"helm.sh/helm/v3/pkg/action" "helm.sh/helm/v3/pkg/action"
"helm.sh/helm/v3/pkg/cli/output"
"helm.sh/helm/v3/pkg/release" "helm.sh/helm/v3/pkg/release"
) )
@ -58,6 +59,7 @@ flag with the '--offset' flag allows you to page through results.
func newListCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { func newListCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
client := action.NewList(cfg) client := action.NewList(cfg)
var outfmt output.Format
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "list", Use: "list",
@ -66,13 +68,6 @@ func newListCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
Aliases: []string{"ls"}, Aliases: []string{"ls"},
Args: require.NoArgs, Args: require.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
// validate the output format first so we don't waste time running a
// request that we'll throw away
output, err := action.ParseOutputFormat(client.OutputFormat)
if err != nil {
return err
}
if client.AllNamespaces { if client.AllNamespaces {
initActionConfig(cfg, true) initActionConfig(cfg, true)
} }
@ -87,7 +82,7 @@ func newListCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
return err return err
} }
return output.Write(out, newReleaseListWriter(results)) return outfmt.Write(out, newReleaseListWriter(results))
}, },
} }
@ -106,7 +101,7 @@ func newListCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
f.IntVarP(&client.Limit, "max", "m", 256, "maximum number of releases to fetch") f.IntVarP(&client.Limit, "max", "m", 256, "maximum number of releases to fetch")
f.IntVar(&client.Offset, "offset", 0, "next release name in the list, used to offset from start value") f.IntVar(&client.Offset, "offset", 0, "next release name in the list, used to offset from start value")
f.StringVarP(&client.Filter, "filter", "f", "", "a regular expression (Perl compatible). Any releases that match the expression will be included in the results") f.StringVarP(&client.Filter, "filter", "f", "", "a regular expression (Perl compatible). Any releases that match the expression will be included in the results")
bindOutputFlag(cmd, &client.OutputFormat) bindOutputFlag(cmd, &outfmt)
return cmd return cmd
} }
@ -153,13 +148,13 @@ func (r *releaseListWriter) WriteTable(out io.Writer) error {
for _, r := range r.releases { for _, r := range r.releases {
table.AddRow(r.Name, r.Namespace, r.Revision, r.Updated, r.Status, r.Chart, r.AppVersion) table.AddRow(r.Name, r.Namespace, r.Revision, r.Updated, r.Status, r.Chart, r.AppVersion)
} }
return action.EncodeTable(out, table) return output.EncodeTable(out, table)
} }
func (r *releaseListWriter) WriteJSON(out io.Writer) error { func (r *releaseListWriter) WriteJSON(out io.Writer) error {
return action.EncodeJSON(out, r.releases) return output.EncodeJSON(out, r.releases)
} }
func (r *releaseListWriter) WriteYAML(out io.Writer) error { func (r *releaseListWriter) WriteYAML(out io.Writer) error {
return action.EncodeYAML(out, r.releases) return output.EncodeYAML(out, r.releases)
} }

@ -19,59 +19,8 @@ package main
import ( import (
"io" "io"
"text/template" "text/template"
"time"
"sigs.k8s.io/yaml"
"helm.sh/helm/v3/pkg/chartutil"
"helm.sh/helm/v3/pkg/release"
) )
var printReleaseTemplate = `REVISION: {{.Release.Version}}
RELEASED: {{.ReleaseDate}}
CHART: {{.Release.Chart.Metadata.Name}}-{{.Release.Chart.Metadata.Version}}
USER-SUPPLIED VALUES:
{{.Config}}
COMPUTED VALUES:
{{.ComputedValues}}
HOOKS:
{{- range .Release.Hooks }}
---
# {{.Name}}
{{.Manifest}}
{{- end }}
MANIFEST:
{{.Release.Manifest}}
`
func printRelease(out io.Writer, rel *release.Release) error {
if rel == nil {
return nil
}
cfg, err := chartutil.CoalesceValues(rel.Chart, rel.Config)
if err != nil {
return err
}
computed, err := cfg.YAML()
if err != nil {
return err
}
config, err := yaml.Marshal(rel.Config)
if err != nil {
return err
}
data := map[string]interface{}{
"Release": rel,
"Config": string(config),
"ComputedValues": computed,
"ReleaseDate": rel.Info.LastDeployed.Format(time.ANSIC),
}
return tpl(printReleaseTemplate, data, out)
}
func tpl(t string, vals map[string]interface{}, out io.Writer) error { func tpl(t string, vals map[string]interface{}, out io.Writer) error {
tt, err := template.New("_").Parse(t) tt, err := template.New("_").Parse(t)
if err != nil { if err != nil {

@ -24,24 +24,18 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"helm.sh/helm/v3/cmd/helm/require" "helm.sh/helm/v3/cmd/helm/require"
"helm.sh/helm/v3/pkg/action" "helm.sh/helm/v3/pkg/cli/output"
"helm.sh/helm/v3/pkg/repo" "helm.sh/helm/v3/pkg/repo"
) )
func newRepoListCmd(out io.Writer) *cobra.Command { func newRepoListCmd(out io.Writer) *cobra.Command {
var output string var outfmt output.Format
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "list", Use: "list",
Aliases: []string{"ls"}, Aliases: []string{"ls"},
Short: "list chart repositories", Short: "list chart repositories",
Args: require.NoArgs, Args: require.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
// validate the output format first so we don't waste time running a
// request that we'll throw away
outfmt, err := action.ParseOutputFormat(output)
if err != nil {
return err
}
f, err := repo.LoadFile(settings.RepositoryConfig) f, err := repo.LoadFile(settings.RepositoryConfig)
if isNotExist(err) || len(f.Repositories) == 0 { if isNotExist(err) || len(f.Repositories) == 0 {
return errors.New("no repositories to show") return errors.New("no repositories to show")
@ -51,7 +45,7 @@ func newRepoListCmd(out io.Writer) *cobra.Command {
}, },
} }
bindOutputFlag(cmd, &output) bindOutputFlag(cmd, &outfmt)
return cmd return cmd
} }
@ -71,18 +65,18 @@ func (r *repoListWriter) WriteTable(out io.Writer) error {
for _, re := range r.repos { for _, re := range r.repos {
table.AddRow(re.Name, re.URL) table.AddRow(re.Name, re.URL)
} }
return action.EncodeTable(out, table) return output.EncodeTable(out, table)
} }
func (r *repoListWriter) WriteJSON(out io.Writer) error { func (r *repoListWriter) WriteJSON(out io.Writer) error {
return r.encodeByFormat(out, action.JSON) return r.encodeByFormat(out, output.JSON)
} }
func (r *repoListWriter) WriteYAML(out io.Writer) error { func (r *repoListWriter) WriteYAML(out io.Writer) error {
return r.encodeByFormat(out, action.YAML) return r.encodeByFormat(out, output.YAML)
} }
func (r *repoListWriter) encodeByFormat(out io.Writer, format action.OutputFormat) error { func (r *repoListWriter) encodeByFormat(out io.Writer, format output.Format) error {
// Initialize the array so no results returns an empty array instead of null // Initialize the array so no results returns an empty array instead of null
repolist := make([]repositoryElement, 0, len(r.repos)) repolist := make([]repositoryElement, 0, len(r.repos))
@ -91,10 +85,10 @@ func (r *repoListWriter) encodeByFormat(out io.Writer, format action.OutputForma
} }
switch format { switch format {
case action.JSON: case output.JSON:
return action.EncodeJSON(out, repolist) return output.EncodeJSON(out, repolist)
case action.YAML: case output.YAML:
return action.EncodeYAML(out, repolist) return output.EncodeYAML(out, repolist)
} }
// Because this is a non-exported function and only called internally by // Because this is a non-exported function and only called internally by

@ -26,7 +26,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"helm.sh/helm/v3/internal/monocular" "helm.sh/helm/v3/internal/monocular"
"helm.sh/helm/v3/pkg/action" "helm.sh/helm/v3/pkg/cli/output"
) )
const searchHubDesc = ` const searchHubDesc = `
@ -44,7 +44,7 @@ Helm Hub. You can find it at https://github.com/helm/monocular
type searchHubOptions struct { type searchHubOptions struct {
searchEndpoint string searchEndpoint string
maxColWidth uint maxColWidth uint
outputFormat string outputFormat output.Format
} }
func newSearchHubCmd(out io.Writer) *cobra.Command { func newSearchHubCmd(out io.Writer) *cobra.Command {
@ -68,13 +68,6 @@ func newSearchHubCmd(out io.Writer) *cobra.Command {
} }
func (o *searchHubOptions) run(out io.Writer, args []string) error { func (o *searchHubOptions) run(out io.Writer, args []string) error {
// validate the output format first so we don't waste time running a
// request that we'll throw away
outfmt, err := action.ParseOutputFormat(o.outputFormat)
if err != nil {
return err
}
c, err := monocular.New(o.searchEndpoint) c, err := monocular.New(o.searchEndpoint)
if err != nil { if err != nil {
return errors.Wrap(err, fmt.Sprintf("unable to create connection to %q", o.searchEndpoint)) return errors.Wrap(err, fmt.Sprintf("unable to create connection to %q", o.searchEndpoint))
@ -87,7 +80,7 @@ func (o *searchHubOptions) run(out io.Writer, args []string) error {
return fmt.Errorf("unable to perform search against %q", o.searchEndpoint) return fmt.Errorf("unable to perform search against %q", o.searchEndpoint)
} }
return outfmt.Write(out, newHubSearchWriter(results, o.searchEndpoint, o.maxColWidth)) return o.outputFormat.Write(out, newHubSearchWriter(results, o.searchEndpoint, o.maxColWidth))
} }
type hubChartElement struct { type hubChartElement struct {
@ -125,18 +118,18 @@ func (h *hubSearchWriter) WriteTable(out io.Writer) error {
for _, r := range h.elements { for _, r := range h.elements {
table.AddRow(r.URL, r.Version, r.AppVersion, r.Description) table.AddRow(r.URL, r.Version, r.AppVersion, r.Description)
} }
return action.EncodeTable(out, table) return output.EncodeTable(out, table)
} }
func (h *hubSearchWriter) WriteJSON(out io.Writer) error { func (h *hubSearchWriter) WriteJSON(out io.Writer) error {
return h.encodeByFormat(out, action.JSON) return h.encodeByFormat(out, output.JSON)
} }
func (h *hubSearchWriter) WriteYAML(out io.Writer) error { func (h *hubSearchWriter) WriteYAML(out io.Writer) error {
return h.encodeByFormat(out, action.YAML) return h.encodeByFormat(out, output.YAML)
} }
func (h *hubSearchWriter) encodeByFormat(out io.Writer, format action.OutputFormat) error { func (h *hubSearchWriter) encodeByFormat(out io.Writer, format output.Format) error {
// Initialize the array so no results returns an empty array instead of null // Initialize the array so no results returns an empty array instead of null
chartList := make([]hubChartElement, 0, len(h.elements)) chartList := make([]hubChartElement, 0, len(h.elements))
@ -145,10 +138,10 @@ func (h *hubSearchWriter) encodeByFormat(out io.Writer, format action.OutputForm
} }
switch format { switch format {
case action.JSON: case output.JSON:
return action.EncodeJSON(out, chartList) return output.EncodeJSON(out, chartList)
case action.YAML: case output.YAML:
return action.EncodeYAML(out, chartList) return output.EncodeYAML(out, chartList)
} }
// Because this is a non-exported function and only called internally by // Because this is a non-exported function and only called internally by

@ -28,7 +28,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"helm.sh/helm/v3/cmd/helm/search" "helm.sh/helm/v3/cmd/helm/search"
"helm.sh/helm/v3/pkg/action" "helm.sh/helm/v3/pkg/cli/output"
"helm.sh/helm/v3/pkg/helmpath" "helm.sh/helm/v3/pkg/helmpath"
"helm.sh/helm/v3/pkg/repo" "helm.sh/helm/v3/pkg/repo"
) )
@ -51,7 +51,7 @@ type searchRepoOptions struct {
maxColWidth uint maxColWidth uint
repoFile string repoFile string
repoCacheDir string repoCacheDir string
outputFormat string outputFormat output.Format
} }
func newSearchRepoCmd(out io.Writer) *cobra.Command { func newSearchRepoCmd(out io.Writer) *cobra.Command {
@ -79,13 +79,6 @@ func newSearchRepoCmd(out io.Writer) *cobra.Command {
} }
func (o *searchRepoOptions) run(out io.Writer, args []string) error { func (o *searchRepoOptions) run(out io.Writer, args []string) error {
// validate the output format first so we don't waste time running a
// request that we'll throw away
outfmt, err := action.ParseOutputFormat(o.outputFormat)
if err != nil {
return err
}
index, err := o.buildIndex(out) index, err := o.buildIndex(out)
if err != nil { if err != nil {
return err return err
@ -108,7 +101,7 @@ func (o *searchRepoOptions) run(out io.Writer, args []string) error {
return err return err
} }
return outfmt.Write(out, &repoSearchWriter{data, o.maxColWidth}) return o.outputFormat.Write(out, &repoSearchWriter{data, o.maxColWidth})
} }
func (o *searchRepoOptions) applyConstraint(res []*search.Result) ([]*search.Result, error) { func (o *searchRepoOptions) applyConstraint(res []*search.Result) ([]*search.Result, error) {
@ -188,18 +181,18 @@ func (r *repoSearchWriter) WriteTable(out io.Writer) error {
for _, r := range r.results { for _, r := range r.results {
table.AddRow(r.Name, r.Chart.Version, r.Chart.AppVersion, r.Chart.Description) table.AddRow(r.Name, r.Chart.Version, r.Chart.AppVersion, r.Chart.Description)
} }
return action.EncodeTable(out, table) return output.EncodeTable(out, table)
} }
func (r *repoSearchWriter) WriteJSON(out io.Writer) error { func (r *repoSearchWriter) WriteJSON(out io.Writer) error {
return r.encodeByFormat(out, action.JSON) return r.encodeByFormat(out, output.JSON)
} }
func (r *repoSearchWriter) WriteYAML(out io.Writer) error { func (r *repoSearchWriter) WriteYAML(out io.Writer) error {
return r.encodeByFormat(out, action.YAML) return r.encodeByFormat(out, output.YAML)
} }
func (r *repoSearchWriter) encodeByFormat(out io.Writer, format action.OutputFormat) error { func (r *repoSearchWriter) encodeByFormat(out io.Writer, format output.Format) error {
// Initialize the array so no results returns an empty array instead of null // Initialize the array so no results returns an empty array instead of null
chartList := make([]repoChartElement, 0, len(r.results)) chartList := make([]repoChartElement, 0, len(r.results))
@ -208,10 +201,10 @@ func (r *repoSearchWriter) encodeByFormat(out io.Writer, format action.OutputFor
} }
switch format { switch format {
case action.JSON: case output.JSON:
return action.EncodeJSON(out, chartList) return output.EncodeJSON(out, chartList)
case action.YAML: case output.YAML:
return action.EncodeYAML(out, chartList) return output.EncodeYAML(out, chartList)
} }
// Because this is a non-exported function and only called internally by // Because this is a non-exported function and only called internally by

@ -17,12 +17,17 @@ limitations under the License.
package main package main
import ( import (
"fmt"
"io" "io"
"strings"
"time"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"helm.sh/helm/v3/cmd/helm/require" "helm.sh/helm/v3/cmd/helm/require"
"helm.sh/helm/v3/pkg/action" "helm.sh/helm/v3/pkg/action"
"helm.sh/helm/v3/pkg/chartutil"
"helm.sh/helm/v3/pkg/cli/output"
"helm.sh/helm/v3/pkg/release" "helm.sh/helm/v3/pkg/release"
) )
@ -39,6 +44,7 @@ The status consists of:
func newStatusCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { func newStatusCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
client := action.NewStatus(cfg) client := action.NewStatus(cfg)
var outfmt output.Format
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "status RELEASE_NAME", Use: "status RELEASE_NAME",
@ -46,13 +52,6 @@ func newStatusCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
Long: statusHelp, Long: statusHelp,
Args: require.ExactArgs(1), Args: require.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
// validate the output format first so we don't waste time running a
// request that we'll throw away
outfmt, err := action.ParseOutputFormat(client.OutputFormat)
if err != nil {
return err
}
rel, err := client.Run(args[0]) rel, err := client.Run(args[0])
if err != nil { if err != nil {
return err return err
@ -61,30 +60,105 @@ func newStatusCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
// strip chart metadata from the output // strip chart metadata from the output
rel.Chart = nil rel.Chart = nil
return outfmt.Write(out, &statusPrinter{rel}) return outfmt.Write(out, &statusPrinter{rel, false})
}, },
} }
f := cmd.PersistentFlags() f := cmd.PersistentFlags()
f.IntVar(&client.Version, "revision", 0, "if set, display the status of the named release with revision") f.IntVar(&client.Version, "revision", 0, "if set, display the status of the named release with revision")
bindOutputFlag(cmd, &client.OutputFormat) bindOutputFlag(cmd, &outfmt)
return cmd return cmd
} }
type statusPrinter struct { type statusPrinter struct {
release *release.Release release *release.Release
debug bool
} }
func (s statusPrinter) WriteJSON(out io.Writer) error { func (s statusPrinter) WriteJSON(out io.Writer) error {
return action.EncodeJSON(out, s.release) return output.EncodeJSON(out, s.release)
} }
func (s statusPrinter) WriteYAML(out io.Writer) error { func (s statusPrinter) WriteYAML(out io.Writer) error {
return action.EncodeYAML(out, s.release) return output.EncodeYAML(out, s.release)
} }
func (s statusPrinter) WriteTable(out io.Writer) error { func (s statusPrinter) WriteTable(out io.Writer) error {
action.PrintRelease(out, s.release) if s.release == nil {
return nil
}
fmt.Fprintf(out, "NAME: %s\n", s.release.Name)
if !s.release.Info.LastDeployed.IsZero() {
fmt.Fprintf(out, "LAST DEPLOYED: %s\n", s.release.Info.LastDeployed.Format(time.ANSIC))
}
fmt.Fprintf(out, "NAMESPACE: %s\n", s.release.Namespace)
fmt.Fprintf(out, "STATUS: %s\n", s.release.Info.Status.String())
fmt.Fprintf(out, "REVISION: %d\n", s.release.Version)
executions := executionsByHookEvent(s.release)
if tests, ok := executions[release.HookTest]; ok {
for _, h := range tests {
// Don't print anything if hook has not been initiated
if h.LastRun.StartedAt.IsZero() {
continue
}
fmt.Fprintf(out, "TEST SUITE: %s\n%s\n%s\n%s\n\n",
h.Name,
fmt.Sprintf("Last Started: %s", h.LastRun.StartedAt.Format(time.ANSIC)),
fmt.Sprintf("Last Completed: %s", h.LastRun.CompletedAt.Format(time.ANSIC)),
fmt.Sprintf("Phase: %s", h.LastRun.Phase),
)
}
}
if s.debug {
fmt.Fprintln(out, "USER-SUPPLIED VALUES:")
err := output.EncodeYAML(out, s.release.Config)
if err != nil {
return err
}
// Print an extra newline
fmt.Fprintln(out)
cfg, err := chartutil.CoalesceValues(s.release.Chart, s.release.Config)
if err != nil {
return err
}
fmt.Fprintln(out, "COMPUTED VALUES:")
err = output.EncodeYAML(out, cfg.AsMap())
if err != nil {
return err
}
// Print an extra newline
fmt.Fprintln(out)
}
if strings.EqualFold(s.release.Info.Description, "Dry run complete") || s.debug {
fmt.Fprintln(out, "HOOKS:")
for _, h := range s.release.Hooks {
fmt.Fprintf(out, "---\n# Source: %s\n%s\n", h.Path, h.Manifest)
}
fmt.Fprintf(out, "MANIFEST:\n%s\n", s.release.Manifest)
}
if len(s.release.Info.Notes) > 0 {
fmt.Fprintf(out, "NOTES:\n%s\n", strings.TrimSpace(s.release.Info.Notes))
}
return nil return nil
} }
func executionsByHookEvent(rel *release.Release) map[release.HookEvent][]*release.Hook {
result := make(map[release.HookEvent][]*release.Hook)
for _, h := range rel.Hooks {
for _, e := range h.Events {
executions, ok := result[e]
if !ok {
executions = []*release.Hook{}
}
result[e] = append(executions, h)
}
}
return result
}

@ -1,6 +1,8 @@
NAME: thomas-guide
LAST DEPLOYED: Fri Sep 2 22:04:05 1977
NAMESPACE: default
STATUS: deployed
REVISION: 1 REVISION: 1
RELEASED: Fri Sep 2 22:04:05 1977
CHART: foo-0.1.0-beta.1
USER-SUPPLIED VALUES: USER-SUPPLIED VALUES:
name: value name: value
@ -9,7 +11,7 @@ name: value
HOOKS: HOOKS:
--- ---
# pre-install-hook # Source: pre-install-hook.yaml
apiVersion: v1 apiVersion: v1
kind: Job kind: Job
metadata: metadata:

@ -1,3 +1,3 @@
REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION
3 1977-09-02 22:04:05 +0000 UTC superseded foo-0.1.0-beta.1 1.0 Release mock 3 Fri Sep 2 22:04:05 1977 superseded foo-0.1.0-beta.1 1.0 Release mock
4 1977-09-02 22:04:05 +0000 UTC deployed foo-0.1.0-beta.1 1.0 Release mock 4 Fri Sep 2 22:04:05 1977 deployed foo-0.1.0-beta.1 1.0 Release mock

@ -1 +1 @@
[{"revision":3,"updated":"1977-09-02 22:04:05 +0000 UTC","status":"superseded","chart":"foo-0.1.0-beta.1","app_version":"1.0","description":"Release mock"},{"revision":4,"updated":"1977-09-02 22:04:05 +0000 UTC","status":"deployed","chart":"foo-0.1.0-beta.1","app_version":"1.0","description":"Release mock"}] [{"revision":3,"updated":"1977-09-02T22:04:05Z","status":"superseded","chart":"foo-0.1.0-beta.1","app_version":"1.0","description":"Release mock"},{"revision":4,"updated":"1977-09-02T22:04:05Z","status":"deployed","chart":"foo-0.1.0-beta.1","app_version":"1.0","description":"Release mock"}]

@ -1,5 +1,5 @@
REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION
1 1977-09-02 22:04:05 +0000 UTC superseded foo-0.1.0-beta.1 1.0 Release mock 1 Fri Sep 2 22:04:05 1977 superseded foo-0.1.0-beta.1 1.0 Release mock
2 1977-09-02 22:04:05 +0000 UTC superseded foo-0.1.0-beta.1 1.0 Release mock 2 Fri Sep 2 22:04:05 1977 superseded foo-0.1.0-beta.1 1.0 Release mock
3 1977-09-02 22:04:05 +0000 UTC superseded foo-0.1.0-beta.1 1.0 Release mock 3 Fri Sep 2 22:04:05 1977 superseded foo-0.1.0-beta.1 1.0 Release mock
4 1977-09-02 22:04:05 +0000 UTC deployed foo-0.1.0-beta.1 1.0 Release mock 4 Fri Sep 2 22:04:05 1977 deployed foo-0.1.0-beta.1 1.0 Release mock

@ -3,10 +3,10 @@
description: Release mock description: Release mock
revision: 3 revision: 3
status: superseded status: superseded
updated: 1977-09-02 22:04:05 +0000 UTC updated: "1977-09-02T22:04:05Z"
- app_version: "1.0" - app_version: "1.0"
chart: foo-0.1.0-beta.1 chart: foo-0.1.0-beta.1
description: Release mock description: Release mock
revision: 4 revision: 4
status: deployed status: deployed
updated: 1977-09-02 22:04:05 +0000 UTC updated: "1977-09-02T22:04:05Z"

@ -1,4 +1,5 @@
NAME: aeneas NAME: aeneas
LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC LAST DEPLOYED: Fri Sep 2 22:04:05 1977
NAMESPACE: default NAMESPACE: default
STATUS: deployed STATUS: deployed
REVISION: 1

@ -1,4 +1,5 @@
NAME: FOOBAR NAME: FOOBAR
LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC LAST DEPLOYED: Fri Sep 2 22:04:05 1977
NAMESPACE: default NAMESPACE: default
STATUS: deployed STATUS: deployed
REVISION: 1

@ -1,4 +1,5 @@
NAME: aeneas NAME: aeneas
LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC LAST DEPLOYED: Fri Sep 2 22:04:05 1977
NAMESPACE: default NAMESPACE: default
STATUS: deployed STATUS: deployed
REVISION: 1

@ -1,4 +1,5 @@
NAME: virgil NAME: virgil
LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC LAST DEPLOYED: Fri Sep 2 22:04:05 1977
NAMESPACE: default NAMESPACE: default
STATUS: deployed STATUS: deployed
REVISION: 1

@ -1,4 +1,5 @@
NAME: virgil NAME: virgil
LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC LAST DEPLOYED: Fri Sep 2 22:04:05 1977
NAMESPACE: default NAMESPACE: default
STATUS: deployed STATUS: deployed
REVISION: 1

@ -1,4 +1,5 @@
NAME: foobar NAME: foobar
LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC LAST DEPLOYED: Fri Sep 2 22:04:05 1977
NAMESPACE: default NAMESPACE: default
STATUS: deployed STATUS: deployed
REVISION: 1

@ -1,4 +1,5 @@
NAME: virgil NAME: virgil
LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC LAST DEPLOYED: Fri Sep 2 22:04:05 1977
NAMESPACE: default NAMESPACE: default
STATUS: deployed STATUS: deployed
REVISION: 1

@ -1,4 +1,5 @@
NAME: virgil NAME: virgil
LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC LAST DEPLOYED: Fri Sep 2 22:04:05 1977
NAMESPACE: default NAMESPACE: default
STATUS: deployed STATUS: deployed
REVISION: 1

@ -1,4 +1,5 @@
NAME: apollo NAME: apollo
LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC LAST DEPLOYED: Fri Sep 2 22:04:05 1977
NAMESPACE: default NAMESPACE: default
STATUS: deployed STATUS: deployed
REVISION: 1

@ -1,4 +1,5 @@
NAME: aeneas NAME: aeneas
LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC LAST DEPLOYED: Fri Sep 2 22:04:05 1977
NAMESPACE: default NAMESPACE: default
STATUS: deployed STATUS: deployed
REVISION: 1

@ -1,4 +1,5 @@
NAME: schema NAME: schema
LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC LAST DEPLOYED: Fri Sep 2 22:04:05 1977
NAMESPACE: default NAMESPACE: default
STATUS: deployed STATUS: deployed
REVISION: 1

@ -1,6 +1,7 @@
NAME: flummoxed-chickadee NAME: flummoxed-chickadee
LAST DEPLOYED: 2016-01-16 00:00:00 +0000 UTC LAST DEPLOYED: Sat Jan 16 00:00:00 2016
NAMESPACE: default NAMESPACE: default
STATUS: deployed STATUS: deployed
REVISION: 0
NOTES: NOTES:
release notes release notes

@ -1,14 +1,15 @@
NAME: flummoxed-chickadee NAME: flummoxed-chickadee
LAST DEPLOYED: 2016-01-16 00:00:00 +0000 UTC LAST DEPLOYED: Sat Jan 16 00:00:00 2016
NAMESPACE: default NAMESPACE: default
STATUS: deployed STATUS: deployed
REVISION: 0
TEST SUITE: passing-test TEST SUITE: passing-test
Last Started: 2006-01-02 15:04:05 +0000 UTC Last Started: Mon Jan 2 15:04:05 2006
Last Completed: 2006-01-02 15:04:07 +0000 UTC Last Completed: Mon Jan 2 15:04:07 2006
Phase: Succeeded Phase: Succeeded
TEST SUITE: failing-test TEST SUITE: failing-test
Last Started: 2006-01-02 15:10:05 +0000 UTC Last Started: Mon Jan 2 15:10:05 2006
Last Completed: 2006-01-02 15:10:07 +0000 UTC Last Completed: Mon Jan 2 15:10:07 2006
Phase: Failed Phase: Failed

@ -1,4 +1,5 @@
NAME: flummoxed-chickadee NAME: flummoxed-chickadee
LAST DEPLOYED: 2016-01-16 00:00:00 +0000 UTC LAST DEPLOYED: Sat Jan 16 00:00:00 2016
NAMESPACE: default NAMESPACE: default
STATUS: deployed STATUS: deployed
REVISION: 0

@ -1,4 +1,5 @@
NAME: schema NAME: schema
LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC LAST DEPLOYED: Fri Sep 2 22:04:05 1977
NAMESPACE: default NAMESPACE: default
STATUS: deployed STATUS: deployed
REVISION: 1

@ -1,5 +1,6 @@
Release "crazy-bunny" has been upgraded. Happy Helming! Release "crazy-bunny" has been upgraded. Happy Helming!
NAME: crazy-bunny NAME: crazy-bunny
LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC LAST DEPLOYED: Fri Sep 2 22:04:05 1977
NAMESPACE: default NAMESPACE: default
STATUS: deployed STATUS: deployed
REVISION: 2

@ -1,5 +1,6 @@
Release "zany-bunny" has been upgraded. Happy Helming! Release "zany-bunny" has been upgraded. Happy Helming!
NAME: zany-bunny NAME: zany-bunny
LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC LAST DEPLOYED: Fri Sep 2 22:04:05 1977
NAMESPACE: default NAMESPACE: default
STATUS: deployed STATUS: deployed
REVISION: 2

@ -1,5 +1,6 @@
Release "funny-bunny" has been upgraded. Happy Helming! Release "funny-bunny" has been upgraded. Happy Helming!
NAME: funny-bunny NAME: funny-bunny
LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC LAST DEPLOYED: Fri Sep 2 22:04:05 1977
NAMESPACE: default NAMESPACE: default
STATUS: deployed STATUS: deployed
REVISION: 5

@ -1,5 +1,6 @@
Release "funny-bunny" has been upgraded. Happy Helming! Release "funny-bunny" has been upgraded. Happy Helming!
NAME: funny-bunny NAME: funny-bunny
LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC LAST DEPLOYED: Fri Sep 2 22:04:05 1977
NAMESPACE: default NAMESPACE: default
STATUS: deployed STATUS: deployed
REVISION: 6

@ -1,5 +1,6 @@
Release "funny-bunny" has been upgraded. Happy Helming! Release "funny-bunny" has been upgraded. Happy Helming!
NAME: funny-bunny NAME: funny-bunny
LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC LAST DEPLOYED: Fri Sep 2 22:04:05 1977
NAMESPACE: default NAMESPACE: default
STATUS: deployed STATUS: deployed
REVISION: 4

@ -1,5 +1,6 @@
Release "crazy-bunny" has been upgraded. Happy Helming! Release "crazy-bunny" has been upgraded. Happy Helming!
NAME: crazy-bunny NAME: crazy-bunny
LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC LAST DEPLOYED: Fri Sep 2 22:04:05 1977
NAMESPACE: default NAMESPACE: default
STATUS: deployed STATUS: deployed
REVISION: 3

@ -1,5 +1,6 @@
Release "funny-bunny" has been upgraded. Happy Helming! Release "funny-bunny" has been upgraded. Happy Helming!
NAME: funny-bunny NAME: funny-bunny
LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC LAST DEPLOYED: Fri Sep 2 22:04:05 1977
NAMESPACE: default NAMESPACE: default
STATUS: deployed STATUS: deployed
REVISION: 3

@ -27,6 +27,7 @@ import (
"helm.sh/helm/v3/cmd/helm/require" "helm.sh/helm/v3/cmd/helm/require"
"helm.sh/helm/v3/pkg/action" "helm.sh/helm/v3/pkg/action"
"helm.sh/helm/v3/pkg/chart/loader" "helm.sh/helm/v3/pkg/chart/loader"
"helm.sh/helm/v3/pkg/cli/output"
"helm.sh/helm/v3/pkg/cli/values" "helm.sh/helm/v3/pkg/cli/values"
"helm.sh/helm/v3/pkg/getter" "helm.sh/helm/v3/pkg/getter"
"helm.sh/helm/v3/pkg/storage/driver" "helm.sh/helm/v3/pkg/storage/driver"
@ -62,6 +63,7 @@ set for a key called 'foo', the 'newbar' value would take precedence:
func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
client := action.NewUpgrade(cfg) client := action.NewUpgrade(cfg)
valueOpts := &values.Options{} valueOpts := &values.Options{}
var outfmt output.Format
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "upgrade [RELEASE] [CHART]", Use: "upgrade [RELEASE] [CHART]",
@ -69,13 +71,6 @@ func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
Long: upgradeDesc, Long: upgradeDesc,
Args: require.ExactArgs(2), Args: require.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
// validate the output format first so we don't waste time running a
// request that we'll throw away
output, err := action.ParseOutputFormat(client.OutputFormat)
if err != nil {
return err
}
client.Namespace = getNamespace() client.Namespace = getNamespace()
if client.Version == "" && client.Devel { if client.Version == "" && client.Devel {
@ -99,7 +94,10 @@ func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
histClient := action.NewHistory(cfg) histClient := action.NewHistory(cfg)
histClient.Max = 1 histClient.Max = 1
if _, err := histClient.Run(args[0]); err == driver.ErrReleaseNotFound { if _, err := histClient.Run(args[0]); err == driver.ErrReleaseNotFound {
// Only print this to stdout for table output
if outfmt == output.Table {
fmt.Fprintf(out, "Release %q does not exist. Installing it now.\n", args[0]) fmt.Fprintf(out, "Release %q does not exist. Installing it now.\n", args[0])
}
instClient := action.NewInstall(cfg) instClient := action.NewInstall(cfg)
instClient.ChartPathOptions = client.ChartPathOptions instClient.ChartPathOptions = client.ChartPathOptions
instClient.DryRun = client.DryRun instClient.DryRun = client.DryRun
@ -114,7 +112,7 @@ func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
if err != nil { if err != nil {
return err return err
} }
return output.Write(out, &statusPrinter{rel}) return outfmt.Write(out, &statusPrinter{rel, settings.Debug})
} }
} }
@ -129,27 +127,16 @@ func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
} }
} }
resp, err := client.Run(args[0], ch, vals) rel, err := client.Run(args[0], ch, vals)
if err != nil { if err != nil {
return errors.Wrap(err, "UPGRADE FAILED") return errors.Wrap(err, "UPGRADE FAILED")
} }
if settings.Debug { if outfmt == output.Table {
action.PrintRelease(out, resp)
}
if output == action.Table {
fmt.Fprintf(out, "Release %q has been upgraded. Happy Helming!\n", args[0]) fmt.Fprintf(out, "Release %q has been upgraded. Happy Helming!\n", args[0])
} }
// Print the status like status command does return outfmt.Write(out, &statusPrinter{rel, settings.Debug})
statusClient := action.NewStatus(cfg)
rel, err := statusClient.Run(args[0])
if err != nil {
return err
}
return output.Write(out, &statusPrinter{rel})
}, },
} }
@ -171,7 +158,7 @@ func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
f.BoolVar(&client.SubNotes, "render-subchart-notes", false, "if set, render subchart notes along with the parent") f.BoolVar(&client.SubNotes, "render-subchart-notes", false, "if set, render subchart notes along with the parent")
addChartPathOptionsFlags(f, &client.ChartPathOptions) addChartPathOptionsFlags(f, &client.ChartPathOptions)
addValueOptionsFlags(f, valueOpts) addValueOptionsFlags(f, valueOpts)
bindOutputFlag(cmd, &client.OutputFormat) bindOutputFlag(cmd, &outfmt)
return cmd return cmd
} }

@ -29,7 +29,7 @@ type History struct {
cfg *Configuration cfg *Configuration
Max int Max int
OutputFormat string Version int
} }
// NewHistory creates a new History object with the given configuration. // NewHistory creates a new History object with the given configuration.

@ -82,7 +82,6 @@ type Install struct {
OutputDir string OutputDir string
Atomic bool Atomic bool
SkipCRDs bool SkipCRDs bool
OutputFormat string
SubNotes bool SubNotes bool
} }

@ -125,7 +125,6 @@ type List struct {
Deployed bool Deployed bool
Failed bool Failed bool
Pending bool Pending bool
OutputFormat string
} }
// NewList constructs a new *List // NewList constructs a new *List

@ -1,76 +0,0 @@
/*
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package action
import (
"fmt"
"io"
"strings"
"helm.sh/helm/v3/pkg/release"
)
// PrintRelease prints info about a release
func PrintRelease(out io.Writer, rel *release.Release) {
if rel == nil {
return
}
fmt.Fprintf(out, "NAME: %s\n", rel.Name)
if !rel.Info.LastDeployed.IsZero() {
fmt.Fprintf(out, "LAST DEPLOYED: %s\n", rel.Info.LastDeployed)
}
fmt.Fprintf(out, "NAMESPACE: %s\n", rel.Namespace)
fmt.Fprintf(out, "STATUS: %s\n", rel.Info.Status.String())
executions := executionsByHookEvent(rel)
if tests, ok := executions[release.HookTest]; ok {
for _, h := range tests {
// Don't print anything if hook has not been initiated
if h.LastRun.StartedAt.IsZero() {
continue
}
fmt.Fprintf(out, "TEST SUITE: %s\n%s\n%s\n%s\n\n",
h.Name,
fmt.Sprintf("Last Started: %s", h.LastRun.StartedAt),
fmt.Sprintf("Last Completed: %s", h.LastRun.CompletedAt),
fmt.Sprintf("Phase: %s", h.LastRun.Phase),
)
}
}
if strings.EqualFold(rel.Info.Description, "Dry run complete") {
fmt.Fprintf(out, "MANIFEST:\n%s\n", rel.Manifest)
}
if len(rel.Info.Notes) > 0 {
fmt.Fprintf(out, "NOTES:\n%s\n", strings.TrimSpace(rel.Info.Notes))
}
}
func executionsByHookEvent(rel *release.Release) map[release.HookEvent][]*release.Hook {
result := make(map[release.HookEvent][]*release.Hook)
for _, h := range rel.Hooks {
for _, e := range h.Events {
executions, ok := result[e]
if !ok {
executions = []*release.Hook{}
}
result[e] = append(executions, h)
}
}
return result
}

@ -27,7 +27,6 @@ type Status struct {
cfg *Configuration cfg *Configuration
Version int Version int
OutputFormat string
} }
// NewStatus creates a new Status object with the given configuration. // NewStatus creates a new Status object with the given configuration.

@ -57,7 +57,6 @@ type Upgrade struct {
MaxHistory int MaxHistory int
Atomic bool Atomic bool
CleanupOnFail bool CleanupOnFail bool
OutputFormat string
SubNotes bool SubNotes bool
} }

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package action package output
import ( import (
"encoding/json" "encoding/json"
@ -26,26 +26,26 @@ import (
"sigs.k8s.io/yaml" "sigs.k8s.io/yaml"
) )
// OutputFormat is a type for capturing supported output formats // Format is a type for capturing supported output formats
type OutputFormat string type Format string
const ( const (
Table OutputFormat = "table" Table Format = "table"
JSON OutputFormat = "json" JSON Format = "json"
YAML OutputFormat = "yaml" YAML Format = "yaml"
) )
// ErrInvalidFormatType is returned when an unsupported format type is used // ErrInvalidFormatType is returned when an unsupported format type is used
var ErrInvalidFormatType = fmt.Errorf("invalid format type") var ErrInvalidFormatType = fmt.Errorf("invalid format type")
// String returns the string reprsentation of the OutputFormat // String returns the string reprsentation of the Format
func (o OutputFormat) String() string { func (o Format) String() string {
return string(o) return string(o)
} }
// Write the output in the given format to the io.Writer. Unsupported formats // Write the output in the given format to the io.Writer. Unsupported formats
// will return an error // will return an error
func (o OutputFormat) Write(out io.Writer, w Writer) error { func (o Format) Write(out io.Writer, w Writer) error {
switch o { switch o {
case Table: case Table:
return w.WriteTable(out) return w.WriteTable(out)
@ -57,9 +57,9 @@ func (o OutputFormat) Write(out io.Writer, w Writer) error {
return ErrInvalidFormatType return ErrInvalidFormatType
} }
// ParseOutputFormat takes a raw string and returns the matching OutputFormat. // ParseFormat takes a raw string and returns the matching Format.
// If the format does not exists, ErrInvalidFormatType is returned // If the format does not exists, ErrInvalidFormatType is returned
func ParseOutputFormat(s string) (out OutputFormat, err error) { func ParseFormat(s string) (out Format, err error) {
switch s { switch s {
case Table.String(): case Table.String():
out, err = Table, nil out, err = Table, nil
Loading…
Cancel
Save