diff --git a/cmd/helm/list.go b/cmd/helm/list.go index 08a26be04..5b9ba8769 100644 --- a/cmd/helm/list.go +++ b/cmd/helm/list.go @@ -29,6 +29,7 @@ import ( "helm.sh/helm/v3/pkg/action" "helm.sh/helm/v3/pkg/cli/output" "helm.sh/helm/v3/pkg/release" + helmtime "helm.sh/helm/v3/pkg/time" ) var listHelp = ` @@ -46,8 +47,8 @@ regular expressions (Perl compatible) that are applied to the list of releases. Only items that match the filter will be returned. $ helm list --filter 'ara[a-z]+' - NAME UPDATED CHART - maudlin-arachnid Mon May 9 16:07:08 2016 alpine-0.1.0 + NAME UPDATED CHART + maudlin-arachnid 1977-09-02 22:04:05 +0000 UTC alpine-0.1.0 If no results are found, 'helm list' will exit 0, but with no output (or in the case of no '-q' flag, only headers). @@ -104,16 +105,17 @@ func newListCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { } return nil default: - return outfmt.Write(out, newReleaseListWriter(results)) + return outfmt.Write(out, newReleaseListWriter(results, client.FormatTime)) } } - return outfmt.Write(out, newReleaseListWriter(results)) + return outfmt.Write(out, newReleaseListWriter(results, client.FormatTime)) }, } f := cmd.Flags() f.BoolVarP(&client.Short, "short", "q", false, "output short (quiet) listing format") + f.BoolVar(&client.FormatTime, "format-time", false, "format time") f.BoolVarP(&client.ByDate, "date", "d", false, "sort by release date") f.BoolVarP(&client.SortReverse, "reverse", "r", false, "reverse the sort order") f.BoolVarP(&client.All, "all", "a", false, "show all releases without any filter applied") @@ -147,28 +149,51 @@ type releaseListWriter struct { releases []releaseElement } -func newReleaseListWriter(releases []*release.Release) *releaseListWriter { +func newReleaseListWriter(releases []*release.Release, formatTime bool) *releaseListWriter { // Initialize the array so no results returns an empty array instead of null elements := make([]releaseElement, 0, len(releases)) for _, r := range releases { - element := releaseElement{ - Name: r.Name, - Namespace: r.Namespace, - Revision: strconv.Itoa(r.Version), - Status: r.Info.Status.String(), - Chart: fmt.Sprintf("%s-%s", r.Chart.Metadata.Name, r.Chart.Metadata.Version), - AppVersion: r.Chart.Metadata.AppVersion, - } - t := "-" - if tspb := r.Info.LastDeployed; !tspb.IsZero() { - t = tspb.String() + var element releaseElement + + if formatTime { + element = timeFormattedElement(r) + } else { + element = releaseElement{ + Name: r.Name, + Namespace: r.Namespace, + Revision: strconv.Itoa(r.Version), + Status: r.Info.Status.String(), + Chart: fmt.Sprintf("%s-%s", r.Chart.Metadata.Name, r.Chart.Metadata.Version), + AppVersion: r.Chart.Metadata.AppVersion, + } + t := "-" + if tspb := r.Info.LastDeployed; !tspb.IsZero() { + t = tspb.String() + } + element.Updated = t } - element.Updated = t + elements = append(elements, element) } return &releaseListWriter{elements} } +func timeFormattedElement(r *release.Release) releaseElement { + t := "-" + if tspb := r.Info.LastDeployed; !tspb.IsZero() { + t = helmtime.Format(tspb) + } + return releaseElement{ + Name: r.Name, + Namespace: r.Namespace, + Revision: strconv.Itoa(r.Version), + Updated: t, + Status: r.Info.Status.String(), + Chart: fmt.Sprintf("%s-%s", r.Chart.Metadata.Name, r.Chart.Metadata.Version), + AppVersion: r.Chart.Metadata.AppVersion, + } +} + func (r *releaseListWriter) WriteTable(out io.Writer) error { table := uitable.New() table.AddRow("NAME", "NAMESPACE", "REVISION", "UPDATED", "STATUS", "CHART", "APP VERSION") diff --git a/pkg/action/list.go b/pkg/action/list.go index 5ba0c4770..c4686f2c8 100644 --- a/pkg/action/list.go +++ b/pkg/action/list.go @@ -122,6 +122,7 @@ type List struct { // Filter is a filter that is applied to the results Filter string Short bool + FormatTime bool Uninstalled bool Superseded bool Uninstalling bool diff --git a/pkg/time/time.go b/pkg/time/time.go index 44f3fedfb..93ebc8520 100644 --- a/pkg/time/time.go +++ b/pkg/time/time.go @@ -89,3 +89,8 @@ func (t Time) Round(d time.Duration) Time { return Time{Time: t.Time.Round(d) func (t Time) Sub(u Time) time.Duration { return t.Time.Sub(u.Time) } func (t Time) Truncate(d time.Duration) Time { return Time{Time: t.Time.Truncate(d)} } func (t Time) UTC() Time { return Time{Time: t.Time.UTC()} } + +// Format formats time in custom output format +func Format(t Time) string { + return t.Format("2006-01-02 15:04:05 -0700 MST") +} diff --git a/pkg/time/time_test.go b/pkg/time/time_test.go index 20f0f8e29..c1eb4ba77 100644 --- a/pkg/time/time_test.go +++ b/pkg/time/time_test.go @@ -81,3 +81,12 @@ func TestZeroValueUnmarshal(t *testing.T) { t.Errorf("expected time to be equal to zero value, got %v", myTime) } } + +func TestFormat(t *testing.T) { + when := Date(2009, 11, 17, 20, 34, 58, 651387237, time.UTC) + expected := "2009-11-17 20:34:58 +0000 UTC" + got := Format(when) + if expected != got { + t.Errorf("expected %s, got %s", expected, got) + } +}