Merge pull request #5601 from adamreese/v3/capabilities

ref(pkg/chartutil): remove k8s version object dependency
pull/5708/head
Adam Reese 6 years ago committed by GitHub
commit b7a14de590
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -42,8 +42,8 @@ metadata:
helm.sh/chart: "subchart1-0.1.0" helm.sh/chart: "subchart1-0.1.0"
app.kubernetes.io/instance: "foobar-YWJj-baz" app.kubernetes.io/instance: "foobar-YWJj-baz"
kube-version/major: "1" kube-version/major: "1"
kube-version/minor: "9" kube-version/minor: "14"
kube-version/gitversion: "v1.9.0" kube-version/version: "v1.14.0"
spec: spec:
type: ClusterIP type: ClusterIP
ports: ports:

@ -42,8 +42,8 @@ metadata:
helm.sh/chart: "subchart1-0.1.0" helm.sh/chart: "subchart1-0.1.0"
app.kubernetes.io/instance: "RELEASE-NAME" app.kubernetes.io/instance: "RELEASE-NAME"
kube-version/major: "1" kube-version/major: "1"
kube-version/minor: "9" kube-version/minor: "14"
kube-version/gitversion: "v1.9.0" kube-version/version: "v1.14.0"
spec: spec:
type: ClusterIP type: ClusterIP
ports: ports:

@ -42,8 +42,8 @@ metadata:
helm.sh/chart: "subchart1-0.1.0" helm.sh/chart: "subchart1-0.1.0"
app.kubernetes.io/instance: "RELEASE-NAME" app.kubernetes.io/instance: "RELEASE-NAME"
kube-version/major: "1" kube-version/major: "1"
kube-version/minor: "9" kube-version/minor: "14"
kube-version/gitversion: "v1.9.0" kube-version/version: "v1.14.0"
spec: spec:
type: ClusterIP type: ClusterIP
ports: ports:

@ -42,8 +42,8 @@ metadata:
helm.sh/chart: "subchart1-0.1.0" helm.sh/chart: "subchart1-0.1.0"
app.kubernetes.io/instance: "RELEASE-NAME" app.kubernetes.io/instance: "RELEASE-NAME"
kube-version/major: "1" kube-version/major: "1"
kube-version/minor: "9" kube-version/minor: "14"
kube-version/gitversion: "v1.9.0" kube-version/version: "v1.14.0"
spec: spec:
type: ClusterIP type: ClusterIP
ports: ports:

@ -19,7 +19,10 @@ In the previous section, we use `{{.Release.Name}}` to insert the name of a rele
- `Capabilities`: This provides information about what capabilities the Kubernetes cluster supports. - `Capabilities`: This provides information about what capabilities the Kubernetes cluster supports.
- `Capabilities.APIVersions` is a set of versions. - `Capabilities.APIVersions` is a set of versions.
- `Capabilities.APIVersions.Has $version` indicates whether a version (`batch/v1`) is enabled on the cluster. - `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.Kube.Version` is the Kubernetes version.
- `Capabilities.Kube` is a short form for Kubernetes version.
- `Capabilities.Kube.Major` is the Kubernetes major version.
- `Capabilities.Kube.Minor` is the Kubernetes minor version.
- `Template`: Contains information about the current template that is being executed - `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`) - `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`). - `BasePath`: The namespaced path to the templates directory of the current chart (e.g. `mychart/templates`).

@ -25,6 +25,11 @@ In Helm 2, in order to purge the release ledger, the `--purge` flag had to be pr
functionality is now enabled by default. To retain the previous behaviour, use functionality is now enabled by default. To retain the previous behaviour, use
`helm uninstall --keep-history`. `helm uninstall --keep-history`.
### Capabilities
Capabilities built-in has been simplified.
[Built-in Objects](chart_template_guide/builtin_objects.md)
## Installing ## Installing

@ -86,7 +86,6 @@ func (c *Configuration) getCapabilities() (*chartutil.Capabilities, error) {
if c.Capabilities != nil { if c.Capabilities != nil {
return c.Capabilities, nil return c.Capabilities, nil
} }
dc, err := c.RESTClientGetter.ToDiscoveryClient() dc, err := c.RESTClientGetter.ToDiscoveryClient()
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not get Kubernetes discovery client") return nil, errors.Wrap(err, "could not get Kubernetes discovery client")
@ -95,15 +94,18 @@ func (c *Configuration) getCapabilities() (*chartutil.Capabilities, error) {
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not get server version from Kubernetes") return nil, errors.Wrap(err, "could not get server version from Kubernetes")
} }
apiVersions, err := GetVersionSet(dc) apiVersions, err := GetVersionSet(dc)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not get apiVersions from Kubernetes") return nil, errors.Wrap(err, "could not get apiVersions from Kubernetes")
} }
c.Capabilities = &chartutil.Capabilities{ c.Capabilities = &chartutil.Capabilities{
KubeVersion: kubeVersion,
APIVersions: apiVersions, APIVersions: apiVersions,
KubeVersion: chartutil.KubeVersion{
Version: kubeVersion.GitVersion,
Major: kubeVersion.Major,
Minor: kubeVersion.Minor,
},
} }
return c.Capabilities, nil return c.Capabilities, nil
} }
@ -144,7 +146,7 @@ func GetVersionSet(client discovery.ServerGroupsInterface) (chartutil.VersionSet
} }
versions := metav1.ExtractGroupVersions(groups) versions := metav1.ExtractGroupVersions(groups)
return chartutil.NewVersionSet(versions...), nil return chartutil.VersionSet(versions), nil
} }
// recordRelease with an update operation in case reuse has been set. // recordRelease with an update operation in case reuse has been set.

@ -304,10 +304,8 @@ func (c *Configuration) renderResources(ch *chart.Chart, values chartutil.Values
} }
if ch.Metadata.KubeVersion != "" { if ch.Metadata.KubeVersion != "" {
gitVersion := caps.KubeVersion.String() if !version.IsCompatibleRange(ch.Metadata.KubeVersion, caps.KubeVersion.String()) {
k8sVersion := strings.Split(gitVersion, "+")[0] return hs, b, "", errors.Errorf("chart requires kubernetesVersion: %s which is incompatible with Kubernetes %s", ch.Metadata.KubeVersion, caps.KubeVersion.String())
if !version.IsCompatibleRange(ch.Metadata.KubeVersion, k8sVersion) {
return hs, b, "", errors.Errorf("chart requires kubernetesVersion: %s which is incompatible with Kubernetes %s", ch.Metadata.KubeVersion, k8sVersion)
} }
} }

@ -16,13 +16,6 @@ limitations under the License.
package chartutil package chartutil
import ( import (
"encoding/json"
"fmt"
"runtime"
"sort"
"k8s.io/apimachinery/pkg/version"
"k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/kubernetes/scheme"
) )
@ -30,75 +23,60 @@ var (
// DefaultVersionSet is the default version set, which includes only Core V1 ("v1"). // DefaultVersionSet is the default version set, which includes only Core V1 ("v1").
DefaultVersionSet = allKnownVersions() DefaultVersionSet = allKnownVersions()
// DefaultKubeVersion is the default kubernetes version
DefaultKubeVersion = &version.Info{
Major: "1",
Minor: "9",
GitVersion: "v1.9.0",
GoVersion: runtime.Version(),
Compiler: runtime.Compiler,
Platform: fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH),
}
// DefaultCapabilities is the default set of capabilities. // DefaultCapabilities is the default set of capabilities.
DefaultCapabilities = &Capabilities{ DefaultCapabilities = &Capabilities{
KubeVersion: KubeVersion{
Version: "v1.14.0",
Major: "1",
Minor: "14",
},
APIVersions: DefaultVersionSet, APIVersions: DefaultVersionSet,
KubeVersion: DefaultKubeVersion,
} }
) )
// Capabilities describes the capabilities of the Kubernetes cluster that Tiller is attached to. // Capabilities describes the capabilities of the Kubernetes cluster.
type Capabilities struct { type Capabilities struct {
// List of all supported API versions // KubeVersion is the Kubernetes version.
KubeVersion KubeVersion
// APIversions are supported Kubernetes API versions.
APIVersions VersionSet APIVersions VersionSet
// KubeVerison is the Kubernetes version
KubeVersion *version.Info
} }
// VersionSet is a set of Kubernetes API versions. // KubeVersion is the Kubernetes version.
type VersionSet map[string]struct{} type KubeVersion struct {
Version string // Kubernetes version
// NewVersionSet creates a new version set from a list of strings. Major string // Kubernetes major version
func NewVersionSet(apiVersions ...string) VersionSet { Minor string // Kubernetes minor version
vs := make(VersionSet)
for _, v := range apiVersions {
vs[v] = struct{}{}
}
return vs
} }
// String implements fmt.Stringer
func (kv *KubeVersion) String() string { return kv.Version }
// GitVersion returns the Kubernetes version string.
//
// Deprecated: use KubeVersion.Version.
func (kv *KubeVersion) GitVersion() string { return kv.Version }
// VersionSet is a set of Kubernetes API versions.
type VersionSet []string
// Has returns true if the version string is in the set. // Has returns true if the version string is in the set.
// //
// vs.Has("apps/v1") // vs.Has("apps/v1")
func (v VersionSet) Has(apiVersion string) bool { func (v VersionSet) Has(apiVersion string) bool {
_, ok := v[apiVersion] for _, x := range v {
return ok if x == apiVersion {
return true
}
}
return false
} }
func allKnownVersions() VersionSet { func allKnownVersions() VersionSet {
vs := make(VersionSet) groups := scheme.Scheme.PrioritizedVersionsAllGroups()
for _, gv := range scheme.Scheme.PrioritizedVersionsAllGroups() { vs := make(VersionSet, 0, len(groups))
vs[gv.String()] = struct{}{} for _, gv := range groups {
vs = append(vs, gv.String())
} }
return vs return vs
} }
// MarshalJSON implements the encoding/json.Marshaler interface.
func (v VersionSet) MarshalJSON() ([]byte, error) {
out := make([]string, 0, len(v))
for i := range v {
out = append(out, i)
}
sort.Strings(out)
return json.Marshal(out)
}
// UnmarshalJSON implements the encoding/json.Unmarshaler interface.
func (v *VersionSet) UnmarshalJSON(data []byte) error {
var vs []string
if err := json.Unmarshal(data, &vs); err != nil {
return err
}
*v = NewVersionSet(vs...)
return nil
}

@ -16,12 +16,11 @@ limitations under the License.
package chartutil package chartutil
import ( import (
"encoding/json"
"testing" "testing"
) )
func TestVersionSet(t *testing.T) { func TestVersionSet(t *testing.T) {
vs := NewVersionSet("v1", "apps/v1") vs := VersionSet{"v1", "apps/v1"}
if d := len(vs); d != 2 { if d := len(vs); d != 2 {
t.Errorf("Expected 2 versions, got %d", d) t.Errorf("Expected 2 versions, got %d", d)
} }
@ -41,38 +40,21 @@ func TestDefaultVersionSet(t *testing.T) {
} }
} }
func TestCapabilities(t *testing.T) { func TestDefaultCapabilities(t *testing.T) {
cap := Capabilities{ kv := DefaultCapabilities.KubeVersion
APIVersions: DefaultVersionSet, if kv.String() != "v1.14.0" {
t.Errorf("Expected default KubeVersion.String() to be v1.14.0, got %q", kv.String())
} }
if kv.Version != "v1.14.0" {
if !cap.APIVersions.Has("v1") { t.Errorf("Expected default KubeVersion.Version to be v1.14.0, got %q", kv.Version)
t.Error("APIVersions should have v1")
} }
} if kv.GitVersion() != "v1.14.0" {
t.Errorf("Expected default KubeVersion.GitVersion() to be v1.14.0, got %q", kv.Version)
func TestCapabilitiesJSONMarshal(t *testing.T) {
vs := NewVersionSet("v1", "apps/v1")
b, err := json.Marshal(vs)
if err != nil {
t.Fatal(err)
} }
if kv.Major != "1" {
expect := `["apps/v1","v1"]` t.Errorf("Expected default KubeVersion.Major to be 1, got %q", kv.Major)
if string(b) != expect {
t.Fatalf("JSON marshaled semantic version not equal: expected %q, got %q", expect, string(b))
} }
} if kv.Minor != "14" {
t.Errorf("Expected default KubeVersion.Minor to be 14, got %q", kv.Minor)
func TestCapabilitiesJSONUnmarshal(t *testing.T) {
in := `["apps/v1","v1"]`
var vs VersionSet
if err := json.Unmarshal([]byte(in), &vs); err != nil {
t.Fatal(err)
}
if len(vs) != 2 {
t.Fatalf("JSON unmarshaled semantic version not equal: expected 2, got %d", len(vs))
} }
} }

@ -7,7 +7,7 @@ metadata:
app.kubernetes.io/instance: "{{ .Release.Name }}" app.kubernetes.io/instance: "{{ .Release.Name }}"
kube-version/major: "{{ .Capabilities.KubeVersion.Major }}" kube-version/major: "{{ .Capabilities.KubeVersion.Major }}"
kube-version/minor: "{{ .Capabilities.KubeVersion.Minor }}" kube-version/minor: "{{ .Capabilities.KubeVersion.Minor }}"
kube-version/gitversion: "v{{ .Capabilities.KubeVersion.Major }}.{{ .Capabilities.KubeVersion.Minor }}.0" kube-version/version: "v{{ .Capabilities.KubeVersion.Major }}.{{ .Capabilities.KubeVersion.Minor }}.0"
spec: spec:
type: {{ .Values.service.type }} type: {{ .Values.service.type }}
ports: ports:

@ -375,6 +375,9 @@ type ReleaseOptions struct {
// //
// This takes both ReleaseOptions and Capabilities to merge into the render values. // This takes both ReleaseOptions and Capabilities to merge into the render values.
func ToRenderValues(chrt *chart.Chart, chrtVals map[string]interface{}, options ReleaseOptions, caps *Capabilities) (Values, error) { func ToRenderValues(chrt *chart.Chart, chrtVals map[string]interface{}, options ReleaseOptions, caps *Capabilities) (Values, error) {
if caps == nil {
caps = DefaultCapabilities
}
top := map[string]interface{}{ top := map[string]interface{}{
"Chart": chrt.Metadata, "Chart": chrt.Metadata,
"Capabilities": caps, "Capabilities": caps,

@ -24,8 +24,6 @@ import (
"testing" "testing"
"text/template" "text/template"
kversion "k8s.io/apimachinery/pkg/version"
"helm.sh/helm/pkg/chart" "helm.sh/helm/pkg/chart"
) )
@ -105,12 +103,7 @@ func TestToRenderValues(t *testing.T) {
IsInstall: true, IsInstall: true,
} }
caps := &Capabilities{ res, err := ToRenderValues(c, overideValues, o, nil)
APIVersions: DefaultVersionSet,
KubeVersion: &kversion.Info{Major: "1"},
}
res, err := ToRenderValues(c, overideValues, o, caps)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

@ -56,8 +56,7 @@ func Templates(linter *support.Linter, values map[string]interface{}, namespace
if err != nil { if err != nil {
return return
} }
caps := chartutil.DefaultCapabilities valuesToRender, err := chartutil.ToRenderValues(chart, cvals, options, nil)
valuesToRender, err := chartutil.ToRenderValues(chart, cvals, options, caps)
if err != nil { if err != nil {
// FIXME: This seems to generate a duplicate, but I can't find where the first // FIXME: This seems to generate a duplicate, but I can't find where the first
// error is coming from. // error is coming from.

@ -139,7 +139,7 @@ metadata:
manifests[o.path] = o.manifest manifests[o.path] = o.manifest
} }
hs, generic, err := SortManifests(manifests, chartutil.NewVersionSet("v1", "v1beta1"), InstallOrder) hs, generic, err := SortManifests(manifests, chartutil.VersionSet{"v1", "v1beta1"}, InstallOrder)
if err != nil { if err != nil {
t.Fatalf("Unexpected error: %s", err) t.Fatalf("Unexpected error: %s", err)
} }

Loading…
Cancel
Save