diff --git a/cmd/helm/testdata/output/version-template.txt b/cmd/helm/testdata/output/version-template.txt index c12e29c2d..51a8bc93a 100644 --- a/cmd/helm/testdata/output/version-template.txt +++ b/cmd/helm/testdata/output/version-template.txt @@ -1 +1 @@ -Version: v3.0+unreleased \ No newline at end of file +Version: v3.0+unreleased diff --git a/cmd/helm/version.go b/cmd/helm/version.go index 4b895bf06..52ec1c35b 100644 --- a/cmd/helm/version.go +++ b/cmd/helm/version.go @@ -19,12 +19,11 @@ package main import ( "fmt" "io" - "text/template" "github.com/spf13/cobra" "k8s.io/helm/cmd/helm/require" - "k8s.io/helm/pkg/version" + "k8s.io/helm/pkg/action" ) const versionDesc = ` @@ -66,21 +65,19 @@ func newVersionCmd(out io.Writer) *cobra.Command { } func (o *versionOptions) run(out io.Writer) error { + + ver := &action.Version{} + if o.short { + ver.Formatter = action.ShortVersion() + } if o.template != "" { - tt, err := template.New("_").Parse(o.template) - if err != nil { - return err - } - return tt.Execute(out, version.GetBuildInfo()) + ver.Formatter = action.TemplateVersion(o.template) } - fmt.Fprintln(out, formatVersion(o.short)) - return nil -} -func formatVersion(short bool) string { - v := version.GetBuildInfo() - if short { - return fmt.Sprintf("%s+g%s", v.Version, v.GitCommit[:7]) + result, err := ver.Run() + if err != nil { + return err } - return fmt.Sprintf("%#v", v) + fmt.Fprintln(out, result) + return nil } diff --git a/pkg/action/version.go b/pkg/action/version.go new file mode 100644 index 000000000..3891507a6 --- /dev/null +++ b/pkg/action/version.go @@ -0,0 +1,73 @@ +/* +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 ( + "bytes" + "fmt" + "text/template" + + "k8s.io/helm/pkg/version" +) + +// Version represents a Helm version action. +type Version struct { + Formatter VersionFormatter +} + +// VersionFormatter takes a version.BuildInfo and returns a printable string. +type VersionFormatter func(info version.BuildInfo) (string, error) + +// Run retrieves the Helm version. +func (v *Version) Run() (string, error) { + bi := version.GetBuildInfo() + if v.Formatter == nil { + v.Formatter = DefaultVersion() + } + return v.Formatter(bi) +} + +// ShortVersion returns a VersionFormatter capable of generating a SemVer representation of the Helm version +func ShortVersion() VersionFormatter { + return func(v version.BuildInfo) (string, error) { + commit := v.GitCommit + if len(commit) >= 7 { + commit = commit[:7] + } + return fmt.Sprintf("%s+g%s", v.Version, commit), nil + } +} + +// TemplateVersion returns a VersionFormatter that uses a template to render the version +func TemplateVersion(tpl string) VersionFormatter { + return func(v version.BuildInfo) (string, error) { + renderer, err := template.New("_").Parse(tpl) + if err != nil { + return "", err + } + var buf bytes.Buffer + err = renderer.Execute(&buf, v) + return buf.String(), err + } +} + +// DefaultVersion returns a version formatted like kubectl formats its version. +func DefaultVersion() VersionFormatter { + return func(v version.BuildInfo) (string, error) { + return fmt.Sprintf("%#v", v), nil + } +} diff --git a/pkg/action/version_test.go b/pkg/action/version_test.go new file mode 100644 index 000000000..2055be8ba --- /dev/null +++ b/pkg/action/version_test.go @@ -0,0 +1,98 @@ +/* +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" + "testing" + + "github.com/stretchr/testify/assert" + "k8s.io/helm/pkg/version" +) + +func TestVersionFormatter(t *testing.T) { + var _ VersionFormatter = DefaultVersion() + var _ VersionFormatter = ShortVersion() + var _ VersionFormatter = TemplateVersion("") +} + +func TestDefaultVersion(t *testing.T) { + golden := version.GetBuildInfo() + is := assert.New(t) + expect := fmt.Sprintf("%#v", golden) + result, err := DefaultVersion()(golden) + is.NoError(err) + is.Equal(expect, result) +} + +func TestShortVersion(t *testing.T) { + v := version.GetBuildInfo() + v.GitCommit = "aaaaaaaaaaaaaaaa" + expect := fmt.Sprintf("%s+g%s", v.Version, v.GitCommit[:7]) + is := assert.New(t) + + got, err := ShortVersion()(v) + is.NoError(err) + is.Equal(expect, got) + + // Make sure it handles the case where it can't get commit info + v.GitCommit = "test" + expect = fmt.Sprintf("%s+g%s", v.Version, v.GitCommit) + got, err = ShortVersion()(v) + is.NoError(err) + is.Equal(expect, got) +} + +func TestTemplateVersion(t *testing.T) { + v := version.GetBuildInfo() + is := assert.New(t) + expect := fmt.Sprintf("foo-%s", v.GitCommit) + + got, err := TemplateVersion("foo-{{.GitCommit}}")(v) + is.NoError(err) + is.Equal(expect, got) + + // Test a broken template, too + _, err = TemplateVersion("foo-{{.GitCommit")(v) + is.Error(err) +} + +func TestVersion(t *testing.T) { + // This test ensures that the default formatter works when none is specified + golden := version.GetBuildInfo() + is := assert.New(t) + expect := fmt.Sprintf("%#v", golden) + + ver := new(Version) + got, err := ver.Run() + is.NoError(err) + is.Equal(expect, got) +} + +func TestVersion_TemplateVersion(t *testing.T) { + // The purpose of this test is to ensure that we can override the formatter + v := version.GetBuildInfo() + is := assert.New(t) + expect := fmt.Sprintf("foo-%s", v.GitCommit) + + ver := &Version{ + Formatter: TemplateVersion("foo-{{.GitCommit}}"), + } + got, err := ver.Run() + is.NoError(err) + is.Equal(expect, got) +}