Merge pull request #5142 from adamreese/v3/version

ref(*): remove helmVersion chart constraint
pull/5188/head
Adam Reese 6 years ago committed by GitHub
commit 1b51da9aa4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -31,15 +31,15 @@ BINARY_VERSION ?= ${GIT_TAG}
# Only set Version if building a tag or VERSION is set
ifneq ($(BINARY_VERSION),)
LDFLAGS += -X k8s.io/helm/pkg/version.version=${BINARY_VERSION}
LDFLAGS += -X k8s.io/helm/internal/version.version=${BINARY_VERSION}
endif
# Clear the "unreleased" string in BuildMetadata
ifneq ($(GIT_TAG),)
LDFLAGS += -X k8s.io/helm/pkg/version.metadata=
LDFLAGS += -X k8s.io/helm/internal/version.metadata=
endif
LDFLAGS += -X k8s.io/helm/pkg/version.gitCommit=${GIT_COMMIT}
LDFLAGS += -X k8s.io/helm/pkg/version.gitTreeState=${GIT_DIRTY}
LDFLAGS += -X k8s.io/helm/internal/version.gitCommit=${GIT_COMMIT}
LDFLAGS += -X k8s.io/helm/internal/version.gitTreeState=${GIT_DIRTY}
.PHONY: all
all: build

@ -24,7 +24,7 @@ import (
"github.com/spf13/cobra"
"k8s.io/helm/cmd/helm/require"
"k8s.io/helm/pkg/version"
"k8s.io/helm/internal/version"
)
const versionDesc = `
@ -71,14 +71,14 @@ func (o *versionOptions) run(out io.Writer) error {
if err != nil {
return err
}
return tt.Execute(out, version.GetBuildInfo())
return tt.Execute(out, version.Get())
}
fmt.Fprintln(out, formatVersion(o.short))
return nil
}
func formatVersion(short bool) string {
v := version.GetBuildInfo()
v := version.Get()
if short {
return fmt.Sprintf("%s+g%s", v.Version, v.GitCommit[:7])
}

@ -37,21 +37,3 @@ There are a few small conventions followed for using the words Helm and helm.
- The term 'chart' does not need to be capitalized, as it is not a proper noun.
When in doubt, use _Helm_ (with an uppercase 'H').
## Restricting Helm by Version
A `Chart.yaml` file can specify a `helmVersion` SemVer constraint:
```yaml
name: mychart
version: 0.2.0
helmVersion: ">=2.4.0"
```
This constraint should be set when templates use a new feature that was not
supported in older versions of Helm. While this parameter will accept sophisticated
SemVer rules, the best practice is to default to the form `>=2.4.0`, where `2.4.0`
is the version that introduced the new feature used in the chart.
This feature was introduced in Helm 2.4.0, so any version of Helm older than
2.4.0 will simply ignore this field.

@ -20,7 +20,6 @@ In the previous section, we use `{{.Release.Name}}` to insert the name of a rele
- `Capabilities.APIVersions` is a set of versions.
- `Capabilities.APIVersions.Has $version` indicates whether a version (`batch/v1`) is enabled on the cluster.
- `Capabilities.KubeVersion` provides a way to look up the Kubernetes version. It has the following values: `Major`, `Minor`, `GitVersion`, `GitCommit`, `GitTreeState`, `BuildDate`, `GoVersion`, `Compiler`, and `Platform`.
- `Capabilities.HelmVersion` provides a way to look up the Helm version. It has the following values: `SemVer`, `GitCommit`, and `GitTreeState`.
- `Template`: Contains information about the current template that is being executed
- `Name`: A namespaced filepath to the current template (e.g. `mychart/templates/mytemplate.yaml`)
- `BasePath`: The namespaced path to the templates directory of the current chart (e.g. `mychart/templates`).

@ -587,8 +587,7 @@ sensitive_.
`{{.Files.GetString name}}` functions. You can also access the contents of the file
as `[]byte` using `{{.Files.GetBytes}}`
- `Capabilities`: A map-like object that contains information about the versions
of Kubernetes (`{{.Capabilities.KubeVersion}}`, Helm
(`{{.Capabilities.HelmVersion}}`, and the supported Kubernetes
of Kubernetes (`{{.Capabilities.KubeVersion}}` and the supported Kubernetes
API versions (`{{.Capabilities.APIVersions.Has "batch/v1"`)
**NOTE:** Any unknown Chart.yaml fields will be dropped. They will not

@ -0,0 +1,56 @@
/*
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 version // import "k8s.io/helm/internal/version"
import (
hversion "k8s.io/helm/pkg/version"
)
var (
// version is the current version of the Helm.
// Update this whenever making a new release.
// The version is of the format Major.Minor.Patch[-Prerelease][+BuildMetadata]
//
// Increment major number for new feature additions and behavioral changes.
// Increment minor number for bug fixes and performance enhancements.
// Increment patch number for critical fixes to existing releases.
version = "v3.0"
// metadata is extra build time data
metadata = "unreleased"
// gitCommit is the git sha1
gitCommit = ""
// gitTreeState is the state of the git tree
gitTreeState = ""
)
// GetVersion returns the semver string of the version
func GetVersion() string {
if metadata == "" {
return version
}
return version + "+" + metadata
}
// GetBuildInfo returns build info
func Get() hversion.BuildInfo {
return hversion.BuildInfo{
Version: GetVersion(),
GitCommit: gitCommit,
GitTreeState: gitTreeState,
}
}

@ -19,14 +19,12 @@ package action
import (
"time"
"github.com/pkg/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/discovery"
"k8s.io/helm/pkg/chartutil"
"k8s.io/helm/pkg/storage"
"k8s.io/helm/pkg/tiller/environment"
"k8s.io/helm/pkg/version"
)
// Timestamper is a function capable of producing a timestamp.Timestamper.
@ -45,24 +43,17 @@ type Configuration struct {
// KubeClient is a Kubernetes API client.
KubeClient environment.KubeClient
Capabilities *chartutil.Capabilities
Log func(string, ...interface{})
}
// capabilities builds a Capabilities from discovery information.
func (c *Configuration) capabilities() (*chartutil.Capabilities, error) {
sv, err := c.Discovery.ServerVersion()
if err != nil {
return nil, err
}
vs, err := GetVersionSet(c.Discovery)
if err != nil {
return nil, errors.Wrap(err, "could not get apiVersions from Kubernetes")
func (c *Configuration) capabilities() *chartutil.Capabilities {
if c.Capabilities == nil {
return chartutil.DefaultCapabilities
}
return &chartutil.Capabilities{
APIVersions: vs,
KubeVersion: sv,
HelmVersion: version.GetBuildInfo(),
}, nil
return c.Capabilities
}
// Now generates a timestamp

@ -26,6 +26,7 @@ import (
"time"
"github.com/pkg/errors"
"k8s.io/helm/pkg/chart"
"k8s.io/helm/pkg/chartutil"
"k8s.io/helm/pkg/engine"
@ -78,10 +79,7 @@ func (i *Install) Run(chrt *chart.Chart, rawValues map[string]interface{}) (*rel
return nil, err
}
caps, err := i.cfg.capabilities()
if err != nil {
return nil, err
}
caps := i.cfg.capabilities()
options := chartutil.ReleaseOptions{
Name: i.ReleaseName,
@ -260,12 +258,6 @@ func (i *Install) replaceRelease(rel *release.Release) error {
func (i *Install) renderResources(ch *chart.Chart, values chartutil.Values, vs chartutil.VersionSet) ([]*release.Hook, *bytes.Buffer, string, error) {
hooks := []*release.Hook{}
buf := bytes.NewBuffer(nil)
// Guard to make sure Helm is at the right version to handle this chart.
sver := version.GetVersion()
if ch.Metadata.HelmVersion != "" &&
!version.IsCompatibleRange(ch.Metadata.HelmVersion, sver) {
return hooks, buf, "", errors.Errorf("chart incompatible with Helm %s", sver)
}
if ch.Metadata.KubeVersion != "" {
cap, _ := values["Capabilities"].(*chartutil.Capabilities)

@ -57,9 +57,6 @@ type Metadata struct {
AppVersion string `json:"appVersion,omitempty"`
// Whether or not this chart is deprecated
Deprecated bool `json:"deprecated,omitempty"`
// HelmVersion is a SemVer constraints on what version of Helm is required.
// See SemVer ranges here: https://github.com/Masterminds/semver#basic-comparisons
HelmVersion string `json:"helmVersion,omitempty"`
// Annotations are additional mappings uninterpreted by Helm,
// made available for inspection by other applications.
Annotations map[string]string `json:"annotations,omitempty"`

@ -21,8 +21,6 @@ import (
"k8s.io/apimachinery/pkg/version"
"k8s.io/client-go/kubernetes/scheme"
tversion "k8s.io/helm/pkg/version"
)
var (
@ -52,10 +50,6 @@ type Capabilities struct {
APIVersions VersionSet
// KubeVerison is the Kubernetes version
KubeVersion *version.Info
// HelmVersion is the Helm version
//
// This always comes from pkg/version.BuildInfo().
HelmVersion tversion.BuildInfo
}
// VersionSet is a set of Kubernetes API versions.

@ -26,7 +26,6 @@ import (
kversion "k8s.io/apimachinery/pkg/version"
"k8s.io/helm/pkg/chart"
"k8s.io/helm/pkg/version"
)
func TestReadValues(t *testing.T) {
@ -107,7 +106,6 @@ func TestToRenderValues(t *testing.T) {
caps := &Capabilities{
APIVersions: DefaultVersionSet,
HelmVersion: version.GetBuildInfo(),
KubeVersion: &kversion.Info{Major: "1"},
}
@ -136,9 +134,6 @@ func TestToRenderValues(t *testing.T) {
if !res["Capabilities"].(*Capabilities).APIVersions.Has("v1") {
t.Error("Expected Capabilities to have v1 as an API")
}
if res["Capabilities"].(*Capabilities).HelmVersion.Version == "" {
t.Error("Expected Capabilities to have a Helm version")
}
if res["Capabilities"].(*Capabilities).KubeVersion.Major != "1" {
t.Error("Expected Capabilities to have a Kube version")
}

@ -153,7 +153,7 @@ func (c *ChartDownloader) ResolveChartVersion(ref, version string) (*url.URL, ge
}
// ResolveChartVersionAndGetRepo is the same as the ResolveChartVersion method, but returns the chart repositoryy.
func (c *ChartDownloader) ResolveChartVersionAndGetRepo(ref, version string) (*url.URL, *repo.ChartRepository, *getter.HttpGetter, error) {
func (c *ChartDownloader) ResolveChartVersionAndGetRepo(ref, version string) (*url.URL, *repo.ChartRepository, *getter.HTTPGetter, error) {
u, err := url.Parse(ref)
if err != nil {
return nil, nil, nil, errors.Errorf("invalid chart URL format: %s", ref)
@ -164,6 +164,7 @@ func (c *ChartDownloader) ResolveChartVersionAndGetRepo(ref, version string) (*u
return u, nil, nil, err
}
// TODO add user-agent
g, err := getter.NewHTTPGetter(ref, "", "", "")
if err != nil {
return u, nil, nil, err
@ -246,6 +247,7 @@ func (c *ChartDownloader) ResolveChartVersionAndGetRepo(ref, version string) (*u
repoURL.Path = strings.TrimSuffix(repoURL.Path, "/") + "/"
u = repoURL.ResolveReference(u)
u.RawQuery = q.Encode()
// TODO add user-agent
g, err := getter.NewHTTPGetter(rc.URL, "", "", "")
if err != nil {
return repoURL, r, nil, err

@ -19,35 +19,38 @@ import (
"bytes"
"io"
"net/http"
"strings"
"github.com/pkg/errors"
"k8s.io/helm/pkg/tlsutil"
"k8s.io/helm/pkg/urlutil"
"k8s.io/helm/pkg/version"
)
//HttpGetter is the efault HTTP(/S) backend handler
// TODO: change the name to HTTPGetter in Helm 3
type HttpGetter struct { //nolint
client *http.Client
username string
password string
// HTTPGetter is the efault HTTP(/S) backend handler
type HTTPGetter struct {
client *http.Client
username string
password string
userAgent string
}
//SetCredentials sets the credentials for the getter
func (g *HttpGetter) SetCredentials(username, password string) {
// SetCredentials sets the credentials for the getter
func (g *HTTPGetter) SetCredentials(username, password string) {
g.username = username
g.password = password
}
// SetUserAgent sets the HTTP User-Agent for the getter
func (g *HTTPGetter) SetUserAgent(userAgent string) {
g.userAgent = userAgent
}
//Get performs a Get from repo.Getter and returns the body.
func (g *HttpGetter) Get(href string) (*bytes.Buffer, error) {
func (g *HTTPGetter) Get(href string) (*bytes.Buffer, error) {
return g.get(href)
}
func (g *HttpGetter) get(href string) (*bytes.Buffer, error) {
func (g *HTTPGetter) get(href string) (*bytes.Buffer, error) {
buf := bytes.NewBuffer(nil)
// Set a helm specific user agent so that a repo server and metrics can
@ -56,7 +59,10 @@ func (g *HttpGetter) get(href string) (*bytes.Buffer, error) {
if err != nil {
return buf, err
}
req.Header.Set("User-Agent", "Helm/"+strings.TrimPrefix(version.GetVersion(), "v"))
// req.Header.Set("User-Agent", "Helm/"+strings.TrimPrefix(version.GetVersion(), "v"))
if g.userAgent != "" {
req.Header.Set("User-Agent", g.userAgent)
}
if g.username != "" && g.password != "" {
req.SetBasicAuth(g.username, g.password)
@ -80,9 +86,9 @@ func newHTTPGetter(URL, CertFile, KeyFile, CAFile string) (Getter, error) {
return NewHTTPGetter(URL, CertFile, KeyFile, CAFile)
}
// NewHTTPGetter constructs a valid http/https client as HttpGetter
func NewHTTPGetter(URL, CertFile, KeyFile, CAFile string) (*HttpGetter, error) {
var client HttpGetter
// NewHTTPGetter constructs a valid http/https client as HTTPGetter
func NewHTTPGetter(URL, CertFile, KeyFile, CAFile string) (*HTTPGetter, error) {
var client HTTPGetter
if CertFile != "" && KeyFile != "" {
tlsConf, err := tlsutil.NewClientTLS(CertFile, KeyFile, CAFile)
if err != nil {

@ -27,7 +27,7 @@ func TestHTTPGetter(t *testing.T) {
t.Fatal(err)
}
if hg, ok := g.(*HttpGetter); !ok {
if hg, ok := g.(*HTTPGetter); !ok {
t.Fatal("Expected newHTTPGetter to produce an httpGetter")
} else if hg.client != http.DefaultClient {
t.Fatal("Expected newHTTPGetter to return a default HTTP client.")
@ -42,7 +42,7 @@ func TestHTTPGetter(t *testing.T) {
t.Fatal(err)
}
if _, ok := g.(*HttpGetter); !ok {
if _, ok := g.(*HTTPGetter); !ok {
t.Fatal("Expected newHTTPGetter to produce an httpGetter")
}
}

@ -9,7 +9,6 @@ metadata:
release: {{ .Release.Name | quote }}
chart: "{{.Chart.Name}}-{{.Chart.Version}}"
kubeVersion: {{ .Capabilities.KubeVersion.Major }}
helmVersion: {{ .Capabilities.HelmVersion }}
spec:
ports:
- port: {{default 80 .Values.httpPort | quote}}

@ -120,6 +120,7 @@ func (r *ChartRepository) DownloadIndexFile(cachePath string) error {
parsedURL.Path = strings.TrimSuffix(parsedURL.Path, "/") + "/index.yaml"
indexURL = parsedURL.String()
// TODO add user-agent
g, err := getter.NewHTTPGetter(indexURL, r.Config.CertFile, r.Config.KeyFile, r.Config.CAFile)
if err != nil {
return err

@ -68,7 +68,7 @@ func (s *ReleaseServer) prepareRelease(req *hapi.InstallReleaseRequest) (*releas
return nil, err
}
caps, err := capabilities(s.discovery)
caps, err := newCapabilities(s.discovery)
if err != nil {
return nil, err
}

@ -165,53 +165,9 @@ func (s *ReleaseServer) uniqName(start string, reuse bool) (string, error) {
}
return "", errors.Errorf("a release named %s already exists.\nRun: helm ls --all %s; to check the status of the release\nOr run: helm del --purge %s; to delete it", start, start, start)
}
// capabilities builds a Capabilities from discovery information.
func capabilities(disc discovery.DiscoveryInterface) (*chartutil.Capabilities, error) {
sv, err := disc.ServerVersion()
if err != nil {
return nil, err
}
vs, err := GetVersionSet(disc)
if err != nil {
return nil, errors.Wrap(err, "could not get apiVersions from Kubernetes")
}
return &chartutil.Capabilities{
APIVersions: vs,
KubeVersion: sv,
HelmVersion: version.GetBuildInfo(),
}, nil
}
// GetVersionSet retrieves a set of available k8s API versions
func GetVersionSet(client discovery.ServerGroupsInterface) (chartutil.VersionSet, error) {
groups, err := client.ServerGroups()
if err != nil {
return chartutil.DefaultVersionSet, err
}
// FIXME: The Kubernetes test fixture for cli appears to always return nil
// for calls to Discovery().ServerGroups(). So in this case, we return
// the default API list. This is also a safe value to return in any other
// odd-ball case.
if groups.Size() == 0 {
return chartutil.DefaultVersionSet, nil
}
versions := metav1.ExtractGroupVersions(groups)
return chartutil.NewVersionSet(versions...), nil
}
func (s *ReleaseServer) renderResources(ch *chart.Chart, values chartutil.Values, vs chartutil.VersionSet) ([]*release.Hook, *bytes.Buffer, string, error) {
// Guard to make sure Helm is at the right version to handle this chart.
sver := version.GetVersion()
if ch.Metadata.HelmVersion != "" &&
!version.IsCompatibleRange(ch.Metadata.HelmVersion, sver) {
return nil, nil, "", errors.Errorf("chart incompatible with Helm %s", sver)
}
if ch.Metadata.KubeVersion != "" {
cap, _ := values["Capabilities"].(*chartutil.Capabilities)
gitVersion := cap.KubeVersion.String()
@ -383,3 +339,31 @@ func hookHasDeletePolicy(h *release.Hook, policy string) bool {
}
return false
}
func newCapabilities(dc discovery.DiscoveryInterface) (*chartutil.Capabilities, error) {
kubeVersion, err := dc.ServerVersion()
if err != nil {
return nil, err
}
apiVersions, err := GetVersionSet(dc)
if err != nil {
return nil, errors.Wrap(err, "could not get apiVersions from Kubernetes")
}
return &chartutil.Capabilities{
KubeVersion: kubeVersion,
APIVersions: apiVersions,
}, nil
}
// GetVersionSet retrieves a set of available k8s API versions
func GetVersionSet(dc discovery.ServerGroupsInterface) (chartutil.VersionSet, error) {
groups, err := dc.ServerGroups()
if groups.Size() > 0 {
versions := metav1.ExtractGroupVersions(groups)
return chartutil.NewVersionSet(versions...), err
}
return chartutil.DefaultVersionSet, err
}

@ -28,7 +28,7 @@ import (
"github.com/ghodss/yaml"
"github.com/pkg/errors"
"k8s.io/api/core/v1"
v1 "k8s.io/api/core/v1"
"k8s.io/cli-runtime/pkg/genericclioptions/resource"
"k8s.io/client-go/kubernetes/fake"
@ -303,20 +303,6 @@ func TestValidName(t *testing.T) {
}
}
func TestGetVersionSet(t *testing.T) {
rs := rsFixture(t)
vs, err := GetVersionSet(rs.discovery)
if err != nil {
t.Error(err)
}
if !vs.Has("v1") {
t.Errorf("Expected supported versions to at least include v1.")
}
if vs.Has("nosuchversion/v1") {
t.Error("Non-existent version is reported found.")
}
}
func TestUniqName(t *testing.T) {
rs := rsFixture(t)

@ -126,13 +126,13 @@ func (s *ReleaseServer) purgeReleases(rels ...*release.Release) error {
// deleteRelease deletes the release and returns manifests that were kept in the deletion process
func (s *ReleaseServer) deleteRelease(rel *release.Release) (kept string, errs []error) {
vs, err := GetVersionSet(s.discovery)
caps, err := newCapabilities(s.discovery)
if err != nil {
return rel.Manifest, []error{errors.Wrap(err, "could not get apiVersions from Kubernetes")}
}
manifests := relutil.SplitManifests(rel.Manifest)
_, files, err := SortManifests(manifests, vs, UninstallOrder)
_, files, err := SortManifests(manifests, caps.APIVersions, UninstallOrder)
if err != nil {
// We could instead just delete everything in no particular order.
// FIXME: One way to delete at this point would be to try a label-based

@ -103,7 +103,7 @@ func (s *ReleaseServer) prepareUpdate(req *hapi.UpdateReleaseRequest) (*release.
IsUpgrade: true,
}
caps, err := capabilities(s.discovery)
caps, err := newCapabilities(s.discovery)
if err != nil {
return nil, nil, err
}

@ -16,32 +16,6 @@ limitations under the License.
package version // import "k8s.io/helm/pkg/version"
var (
// version is the current version of the Helm.
// Update this whenever making a new release.
// The version is of the format Major.Minor.Patch[-Prerelease][+BuildMetadata]
//
// Increment major number for new feature additions and behavioral changes.
// Increment minor number for bug fixes and performance enhancements.
// Increment patch number for critical fixes to existing releases.
version = "v3.0"
// metadata is extra build time data
metadata = "unreleased"
// gitCommit is the git sha1
gitCommit = ""
// gitTreeState is the state of the git tree
gitTreeState = ""
)
// GetVersion returns the semver string of the version
func GetVersion() string {
if metadata == "" {
return version
}
return version + "+" + metadata
}
// BuildInfo describes the compile time information.
type BuildInfo struct {
// Version is the current semver.
@ -51,12 +25,3 @@ type BuildInfo struct {
// GitTreeState is the state of the git tree
GitTreeState string `json:"git_tree_state,omitempty"`
}
// GetBuildInfo returns build info
func GetBuildInfo() BuildInfo {
return BuildInfo{
Version: GetVersion(),
GitCommit: gitCommit,
GitTreeState: gitTreeState,
}
}

@ -1,45 +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 version represents the current version of the project.
package version // import "k8s.io/helm/pkg/version"
import "testing"
func TestBuildInfo(t *testing.T) {
tests := []struct {
version string
buildMetadata string
gitCommit string
gitTreeState string
expected BuildInfo
}{
{"", "", "", "", BuildInfo{Version: "", GitCommit: "", GitTreeState: ""}},
{"v1.0.0", "", "", "", BuildInfo{Version: "v1.0.0", GitCommit: "", GitTreeState: ""}},
{"v1.0.0", "79d5c5f7", "", "", BuildInfo{Version: "v1.0.0+79d5c5f7", GitCommit: "", GitTreeState: ""}},
{"v1.0.0", "79d5c5f7", "0d399baec2acda578a217d1aec8d7d707c71e44d", "", BuildInfo{Version: "v1.0.0+79d5c5f7", GitCommit: "0d399baec2acda578a217d1aec8d7d707c71e44d", GitTreeState: ""}},
{"v1.0.0", "79d5c5f7", "0d399baec2acda578a217d1aec8d7d707c71e44d", "clean", BuildInfo{Version: "v1.0.0+79d5c5f7", GitCommit: "0d399baec2acda578a217d1aec8d7d707c71e44d", GitTreeState: "clean"}},
}
for _, tt := range tests {
version = tt.version
metadata = tt.buildMetadata
gitCommit = tt.gitCommit
gitTreeState = tt.gitTreeState
if GetBuildInfo() != tt.expected {
t.Errorf("expected Version(%s), GitCommit(%s) and GitTreeState(%s) to be %v", tt.expected, tt.gitCommit, tt.gitTreeState, GetBuildInfo())
}
}
}
Loading…
Cancel
Save