Unverified Commit 1bfe85eb authored by Matt Farina's avatar Matt Farina Committed by GitHub

Merge pull request #5069 from adshmh/5044-add-app-version-to-history

add AppVersion column to the history command
parents 126ab055 a55af70e
...@@ -36,6 +36,7 @@ type releaseInfo struct { ...@@ -36,6 +36,7 @@ type releaseInfo struct {
Updated string `json:"updated"` Updated string `json:"updated"`
Status string `json:"status"` Status string `json:"status"`
Chart string `json:"chart"` Chart string `json:"chart"`
AppVersion string `json:"appVersion"`
Description string `json:"description"` Description string `json:"description"`
} }
...@@ -50,11 +51,11 @@ configures the maximum length of the revision list returned. ...@@ -50,11 +51,11 @@ configures the maximum length of the revision list returned.
The historical release set is printed as a formatted table, e.g: The historical release set is printed as a formatted table, e.g:
$ helm history angry-bird --max=4 $ helm history angry-bird --max=4
REVISION UPDATED STATUS CHART DESCRIPTION REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION
1 Mon Oct 3 10:15:13 2016 SUPERSEDED alpine-0.1.0 Initial install 1 Mon Oct 3 10:15:13 2016 SUPERSEDED alpine-0.1.0 1.1 Initial install
2 Mon Oct 3 10:15:13 2016 SUPERSEDED alpine-0.1.0 Upgraded successfully 2 Mon Oct 3 10:15:13 2016 SUPERSEDED alpine-0.1.0 1.2 Upgraded successfully
3 Mon Oct 3 10:15:13 2016 SUPERSEDED alpine-0.1.0 Rolled back to 2 3 Mon Oct 3 10:15:13 2016 SUPERSEDED alpine-0.1.0 1.1 Rolled back to 2
4 Mon Oct 3 10:15:13 2016 DEPLOYED alpine-0.1.0 Upgraded successfully 4 Mon Oct 3 10:15:13 2016 DEPLOYED alpine-0.1.0 1.3 Upgraded successfully
` `
type historyCmd struct { type historyCmd struct {
...@@ -136,16 +137,17 @@ func getReleaseHistory(rls []*release.Release) (history releaseHistory) { ...@@ -136,16 +137,17 @@ func getReleaseHistory(rls []*release.Release) (history releaseHistory) {
for i := len(rls) - 1; i >= 0; i-- { for i := len(rls) - 1; i >= 0; i-- {
r := rls[i] r := rls[i]
c := formatChartname(r.Chart) c := formatChartname(r.Chart)
a := appVersionFromChart(r.Chart)
t := timeconv.String(r.Info.LastDeployed) t := timeconv.String(r.Info.LastDeployed)
s := r.Info.Status.Code.String() s := r.Info.Status.Code.String()
v := r.Version v := r.Version
d := r.Info.Description d := r.Info.Description
rInfo := releaseInfo{ rInfo := releaseInfo{
Revision: v, Revision: v,
Updated: t, Updated: t,
Status: s, Status: s,
Chart: c, Chart: c,
AppVersion: a,
Description: d, Description: d,
} }
history = append(history, rInfo) history = append(history, rInfo)
...@@ -158,10 +160,10 @@ func formatAsTable(releases releaseHistory, colWidth uint) []byte { ...@@ -158,10 +160,10 @@ func formatAsTable(releases releaseHistory, colWidth uint) []byte {
tbl := uitable.New() tbl := uitable.New()
tbl.MaxColWidth = colWidth tbl.MaxColWidth = colWidth
tbl.AddRow("REVISION", "UPDATED", "STATUS", "CHART", "DESCRIPTION") tbl.AddRow("REVISION", "UPDATED", "STATUS", "CHART", "APP VERSION", "DESCRIPTION")
for i := 0; i <= len(releases)-1; i++ { for i := 0; i <= len(releases)-1; i++ {
r := releases[i] r := releases[i]
tbl.AddRow(r.Revision, r.Updated, r.Status, r.Chart, r.Description) tbl.AddRow(r.Revision, r.Updated, r.Status, r.Chart, r.AppVersion, r.Description)
} }
return tbl.Bytes() return tbl.Bytes()
} }
...@@ -174,3 +176,10 @@ func formatChartname(c *chart.Chart) string { ...@@ -174,3 +176,10 @@ func formatChartname(c *chart.Chart) string {
} }
return fmt.Sprintf("%s-%s", c.Metadata.Name, c.Metadata.Version) return fmt.Sprintf("%s-%s", c.Metadata.Name, c.Metadata.Version)
} }
func appVersionFromChart(c *chart.Chart) string {
if c == nil || c.Metadata == nil {
return "MISSING"
}
return c.Metadata.AppVersion
}
...@@ -23,59 +23,62 @@ import ( ...@@ -23,59 +23,62 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/helm/pkg/helm" "k8s.io/helm/pkg/helm"
"k8s.io/helm/pkg/proto/hapi/chart"
rpb "k8s.io/helm/pkg/proto/hapi/release" rpb "k8s.io/helm/pkg/proto/hapi/release"
) )
func TestHistoryCmd(t *testing.T) { func TestHistoryCmd(t *testing.T) {
mk := func(name string, vers int32, code rpb.Status_Code) *rpb.Release { mk := func(name string, vers int32, code rpb.Status_Code, appVersion string) *rpb.Release {
ch := &chart.Chart{
Metadata: &chart.Metadata{
Name: "foo",
Version: "0.1.0-beta.1",
AppVersion: appVersion,
},
}
return helm.ReleaseMock(&helm.MockReleaseOptions{ return helm.ReleaseMock(&helm.MockReleaseOptions{
Name: name, Name: name,
Chart: ch,
Version: vers, Version: vers,
StatusCode: code, StatusCode: code,
}) })
} }
releases := []*rpb.Release{
mk("angry-bird", 4, rpb.Status_DEPLOYED, "1.4"),
mk("angry-bird", 3, rpb.Status_SUPERSEDED, "1.3"),
mk("angry-bird", 2, rpb.Status_SUPERSEDED, "1.2"),
mk("angry-bird", 1, rpb.Status_SUPERSEDED, "1.1"),
}
tests := []releaseCase{ tests := []releaseCase{
{ {
name: "get history for release", name: "get history for release",
args: []string{"angry-bird"}, args: []string{"angry-bird"},
rels: []*rpb.Release{ rels: releases,
mk("angry-bird", 4, rpb.Status_DEPLOYED), expected: "REVISION\tUPDATED \tSTATUS \tCHART \tAPP VERSION\tDESCRIPTION \n1 \t(.*)\tSUPERSEDED\tfoo-0.1.0-beta.1\t1.1 \tRelease mock\n2 \t(.*)\tSUPERSEDED\tfoo-0.1.0-beta.1\t1.2 \tRelease mock\n3 \t(.*)\tSUPERSEDED\tfoo-0.1.0-beta.1\t1.3 \tRelease mock\n4 \t(.*)\tDEPLOYED \tfoo-0.1.0-beta.1\t1.4 \tRelease mock\n",
mk("angry-bird", 3, rpb.Status_SUPERSEDED),
mk("angry-bird", 2, rpb.Status_SUPERSEDED),
mk("angry-bird", 1, rpb.Status_SUPERSEDED),
},
expected: "REVISION\tUPDATED \tSTATUS \tCHART \tDESCRIPTION \n1 \t(.*)\tSUPERSEDED\tfoo-0.1.0-beta.1\tRelease mock\n2 \t(.*)\tSUPERSEDED\tfoo-0.1.0-beta.1\tRelease mock\n3 \t(.*)\tSUPERSEDED\tfoo-0.1.0-beta.1\tRelease mock\n4 \t(.*)\tDEPLOYED \tfoo-0.1.0-beta.1\tRelease mock\n",
}, },
{ {
name: "get history with max limit set", name: "get history with max limit set",
args: []string{"angry-bird"}, args: []string{"angry-bird"},
flags: []string{"--max", "2"}, flags: []string{"--max", "2"},
rels: []*rpb.Release{ rels: releases,
mk("angry-bird", 4, rpb.Status_DEPLOYED), expected: "REVISION\tUPDATED \tSTATUS \tCHART \tAPP VERSION\tDESCRIPTION \n3 \t(.*)\tSUPERSEDED\tfoo-0.1.0-beta.1\t1.3 \tRelease mock\n4 \t(.*)\tDEPLOYED \tfoo-0.1.0-beta.1\t1.4 \tRelease mock\n",
mk("angry-bird", 3, rpb.Status_SUPERSEDED),
},
expected: "REVISION\tUPDATED \tSTATUS \tCHART \tDESCRIPTION \n3 \t(.*)\tSUPERSEDED\tfoo-0.1.0-beta.1\tRelease mock\n4 \t(.*)\tDEPLOYED \tfoo-0.1.0-beta.1\tRelease mock\n",
}, },
{ {
name: "get history with yaml output format", name: "get history with yaml output format",
args: []string{"angry-bird"}, args: []string{"angry-bird"},
flags: []string{"--output", "yaml"}, flags: []string{"--output", "yaml"},
rels: []*rpb.Release{ rels: releases[:2],
mk("angry-bird", 4, rpb.Status_DEPLOYED), expected: "- appVersion: \"1.3\"\n chart: foo-0.1.0-beta.1\n description: Release mock\n revision: 3\n status: SUPERSEDED\n updated: (.*)\n- appVersion: \"1.4\"\n chart: foo-0.1.0-beta.1\n description: Release mock\n revision: 4\n status: DEPLOYED\n updated: (.*)\n\n",
mk("angry-bird", 3, rpb.Status_SUPERSEDED),
},
expected: "- chart: foo-0.1.0-beta.1\n description: Release mock\n revision: 3\n status: SUPERSEDED\n updated: (.*)\n- chart: foo-0.1.0-beta.1\n description: Release mock\n revision: 4\n status: DEPLOYED\n updated: (.*)\n\n",
}, },
{ {
name: "get history with json output format", name: "get history with json output format",
args: []string{"angry-bird"}, args: []string{"angry-bird"},
flags: []string{"--output", "json"}, flags: []string{"--output", "json"},
rels: []*rpb.Release{ rels: releases[:2],
mk("angry-bird", 4, rpb.Status_DEPLOYED), expected: `[{"revision":3,"updated":".*","status":"SUPERSEDED","chart":"foo\-0.1.0-beta.1","appVersion":"1.3","description":"Release mock"},{"revision":4,"updated":".*","status":"DEPLOYED","chart":"foo\-0.1.0-beta.1","appVersion":"1.4","description":"Release mock"}]\n`,
mk("angry-bird", 3, rpb.Status_SUPERSEDED),
},
expected: `[{"revision":3,"updated":".*","status":"SUPERSEDED","chart":"foo\-0.1.0-beta.1","description":"Release mock"},{"revision":4,"updated":".*","status":"DEPLOYED","chart":"foo\-0.1.0-beta.1","description":"Release mock"}]\n`,
}, },
} }
......
...@@ -13,11 +13,11 @@ configures the maximum length of the revision list returned. ...@@ -13,11 +13,11 @@ configures the maximum length of the revision list returned.
The historical release set is printed as a formatted table, e.g: The historical release set is printed as a formatted table, e.g:
$ helm history angry-bird --max=4 $ helm history angry-bird --max=4
REVISION UPDATED STATUS CHART DESCRIPTION REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION
1 Mon Oct 3 10:15:13 2016 SUPERSEDED alpine-0.1.0 Initial install 1 Mon Oct 3 10:15:13 2016 SUPERSEDED alpine-0.1.0 1.1 Initial install
2 Mon Oct 3 10:15:13 2016 SUPERSEDED alpine-0.1.0 Upgraded successfully 2 Mon Oct 3 10:15:13 2016 SUPERSEDED alpine-0.1.0 1.2 Upgraded successfully
3 Mon Oct 3 10:15:13 2016 SUPERSEDED alpine-0.1.0 Rolled back to 2 3 Mon Oct 3 10:15:13 2016 SUPERSEDED alpine-0.1.0 1.1 Rolled back to 2
4 Mon Oct 3 10:15:13 2016 DEPLOYED alpine-0.1.0 Upgraded successfully 4 Mon Oct 3 10:15:13 2016 DEPLOYED alpine-0.1.0 1.3 Upgraded successfully
``` ```
......
...@@ -229,7 +229,22 @@ func (c *FakeClient) ReleaseContent(rlsName string, opts ...ContentOption) (resp ...@@ -229,7 +229,22 @@ func (c *FakeClient) ReleaseContent(rlsName string, opts ...ContentOption) (resp
// ReleaseHistory returns a release's revision history. // ReleaseHistory returns a release's revision history.
func (c *FakeClient) ReleaseHistory(rlsName string, opts ...HistoryOption) (*rls.GetHistoryResponse, error) { func (c *FakeClient) ReleaseHistory(rlsName string, opts ...HistoryOption) (*rls.GetHistoryResponse, error) {
return &rls.GetHistoryResponse{Releases: c.Rels}, nil reqOpts := c.Opts
for _, opt := range opts {
opt(&reqOpts)
}
maxLen := int(reqOpts.histReq.Max)
var resp rls.GetHistoryResponse
for _, rel := range c.Rels {
if maxLen > 0 && len(resp.Releases) >= maxLen {
return &resp, nil
}
if rel.Name == rlsName {
resp.Releases = append(resp.Releases, rel)
}
}
return &resp, nil
} }
// RunReleaseTest executes a pre-defined tests on a release // RunReleaseTest executes a pre-defined tests on a release
......
...@@ -448,3 +448,75 @@ func TestFakeClient_UpdateReleaseFromChart(t *testing.T) { ...@@ -448,3 +448,75 @@ func TestFakeClient_UpdateReleaseFromChart(t *testing.T) {
}) })
} }
} }
func TestFakeClient_ReleaseHistory(t *testing.T) {
relName := "angry-dolphin"
rels := []*release.Release{
ReleaseMock(&MockReleaseOptions{Name: relName, Version: 1}),
ReleaseMock(&MockReleaseOptions{Name: relName, Version: 2}),
ReleaseMock(&MockReleaseOptions{Name: relName, Version: 3}),
ReleaseMock(&MockReleaseOptions{Name: relName, Version: 4}),
}
type fields struct {
Rels []*release.Release
}
type args struct {
rlsName string
opts []HistoryOption
}
tests := []struct {
name string
fields fields
args args
want *rls.GetHistoryResponse
wantErr bool
}{
{
name: "Get all revisions of a release",
fields: fields{
Rels: rels,
},
args: args{
rlsName: relName,
opts: nil,
},
want: &rls.GetHistoryResponse{
Releases: rels,
},
wantErr: false,
},
{
name: "Get only 2 revisions of a release",
fields: fields{
Rels: rels,
},
args: args{
rlsName: relName,
opts: []HistoryOption{
WithMaxHistory(2),
},
},
want: &rls.GetHistoryResponse{
Releases: rels[:2],
},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := &FakeClient{
Rels: tt.fields.Rels,
}
got, err := c.ReleaseHistory(tt.args.rlsName, tt.args.opts...)
if (err != nil) != tt.wantErr {
t.Errorf("FakeClient.ReleaseHistory() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("FakeClient.ReleaseHistory() = %v, want %v", got, tt.want)
}
})
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment