Merge branch 'dev-v3' of github.com:helm/helm into HEAD

pull/5597/head
Josh Dolitsky 7 years ago
commit a138699686

25
Gopkg.lock generated

@ -929,6 +929,30 @@
revision = "ffdc059bfe9ce6a4e144ba849dbedead332c6053"
version = "v1.3.0"
[[projects]]
branch = "master"
digest = "1:f4e5276a3b356f4692107047fd2890f2fe534f4feeb6b1fd2f6dfbd87f1ccf54"
name = "github.com/xeipuuv/gojsonpointer"
packages = ["."]
pruneopts = "UT"
revision = "4e3ac2762d5f479393488629ee9370b50873b3a6"
[[projects]]
branch = "master"
digest = "1:dc6a6c28ca45d38cfce9f7cb61681ee38c5b99ec1425339bfc1e1a7ba769c807"
name = "github.com/xeipuuv/gojsonreference"
packages = ["."]
pruneopts = "UT"
revision = "bd5ef7bd5415a7ac448318e64f11a24cd21e594b"
[[projects]]
digest = "1:1c898ea6c30c16e8d55fdb6fe44c4bee5f9b7d68aa260cfdfc3024491dcc7bea"
name = "github.com/xeipuuv/gojsonschema"
packages = ["."]
pruneopts = "UT"
revision = "f971f3cd73b2899de6923801c147f075263e0c50"
version = "v1.1.0"
[[projects]]
digest = "1:340553b2fdaab7d53e63fd40f8ed82203bdd3274253055bdb80a46828482ef81"
name = "github.com/xenolf/lego"
@ -1777,6 +1801,7 @@
"github.com/spf13/pflag",
"github.com/stretchr/testify/assert",
"github.com/stretchr/testify/suite",
"github.com/xeipuuv/gojsonschema",
"golang.org/x/crypto/bcrypt",
"golang.org/x/crypto/openpgp",
"golang.org/x/crypto/openpgp/clearsign",

@ -102,3 +102,6 @@
go-tests = true
unused-packages = true
[[constraint]]
name = "github.com/xeipuuv/gojsonschema"
version = "1.1.0"

@ -80,8 +80,8 @@ func (o *createOptions) run(out io.Writer) error {
Description: "A Helm chart for Kubernetes",
Type: "application",
Version: "0.1.0",
AppVersion: "1.0",
APIVersion: chart.APIVersionv1,
AppVersion: "0.1.0",
APIVersion: chart.APIVersionV1,
}
if o.starter != "" {
@ -90,6 +90,6 @@ func (o *createOptions) run(out io.Writer) error {
return chartutil.CreateFrom(cfile, filepath.Dir(o.name), lstarter)
}
_, err := chartutil.Create(cfile, filepath.Dir(o.name))
_, err := chartutil.Create(chartname, filepath.Dir(o.name))
return err
}

@ -55,7 +55,7 @@ func TestCreateCmd(t *testing.T) {
if c.Name() != cname {
t.Errorf("Expected %q name, got %q", cname, c.Name())
}
if c.Metadata.APIVersion != chart.APIVersionv1 {
if c.Metadata.APIVersion != chart.APIVersionV1 {
t.Errorf("Wrong API version: %q", c.Metadata.APIVersion)
}
}
@ -73,7 +73,7 @@ func TestCreateStarterCmd(t *testing.T) {
// Create a starter.
starterchart := hh.Starters()
os.Mkdir(starterchart, 0755)
if dest, err := chartutil.Create(&chart.Metadata{Name: "starterchart"}, starterchart); err != nil {
if dest, err := chartutil.Create("starterchart", starterchart); err != nil {
t.Fatalf("Could not create chart: %s", err)
} else {
t.Logf("Created %s", dest)
@ -106,7 +106,7 @@ func TestCreateStarterCmd(t *testing.T) {
if c.Name() != cname {
t.Errorf("Expected %q name, got %q", cname, c.Name())
}
if c.Metadata.APIVersion != chart.APIVersionv1 {
if c.Metadata.APIVersion != chart.APIVersionV1 {
t.Errorf("Wrong API version: %q", c.Metadata.APIVersion)
}

@ -46,8 +46,9 @@ func TestDependencyUpdateCmd(t *testing.T) {
t.Logf("Listening on directory %s", srv.Root())
chartname := "depup"
md := createTestingMetadata(chartname, srv.URL())
if _, err := chartutil.Create(md, hh.String()); err != nil {
ch := createTestingMetadata(chartname, srv.URL())
md := ch.Metadata
if err := chartutil.SaveDir(ch, hh.String()); err != nil {
t.Fatal(err)
}
@ -203,14 +204,17 @@ func TestDependencyUpdateCmd_DontDeleteOldChartsOnError(t *testing.T) {
// createTestingMetadata creates a basic chart that depends on reqtest-0.1.0
//
// The baseURL can be used to point to a particular repository server.
func createTestingMetadata(name, baseURL string) *chart.Metadata {
return &chart.Metadata{
func createTestingMetadata(name, baseURL string) *chart.Chart {
return &chart.Chart{
Metadata: &chart.Metadata{
APIVersion: chart.APIVersionV1,
Name: name,
Version: "1.2.3",
Dependencies: []*chart.Dependency{
{Name: "reqtest", Version: "0.1.0", Repository: baseURL},
{Name: "compressedchart", Version: "0.1.0", Repository: baseURL},
},
},
}
}
@ -219,6 +223,5 @@ func createTestingMetadata(name, baseURL string) *chart.Metadata {
// The baseURL can be used to point to a particular repository server.
func createTestingChart(dest, name, baseURL string) error {
cfile := createTestingMetadata(name, baseURL)
_, err := chartutil.Create(cfile, dest)
return err
return chartutil.SaveDir(cfile, dest)
}

@ -35,11 +35,11 @@ configures the maximum length of the revision list returned.
The historical release set is printed as a formatted table, e.g:
$ helm history angry-bird --max=4
REVISION UPDATED STATUS CHART DESCRIPTION
1 Mon Oct 3 10:15:13 2016 superseded alpine-0.1.0 Initial install
2 Mon Oct 3 10:15:13 2016 superseded alpine-0.1.0 Upgraded successfully
3 Mon Oct 3 10:15:13 2016 superseded alpine-0.1.0 Rolled back to 2
4 Mon Oct 3 10:15:13 2016 deployed alpine-0.1.0 Upgraded successfully
REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION
1 Mon Oct 3 10:15:13 2016 superseded alpine-0.1.0 1.0 Initial install
2 Mon Oct 3 10:15:13 2016 superseded alpine-0.1.0 1.0 Upgraded successfully
3 Mon Oct 3 10:15:13 2016 superseded alpine-0.1.0 1.0 Rolled back to 2
4 Mon Oct 3 10:15:13 2016 deployed alpine-0.1.0 1.0 Upgraded successfully
`
func newHistoryCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {

@ -136,6 +136,53 @@ func TestInstall(t *testing.T) {
wantError: true,
golden: "output/install-chart-bad-type.txt",
},
// Install, values from yaml, schematized
{
name: "install with schema file",
cmd: "install schema testdata/testcharts/chart-with-schema",
golden: "output/schema.txt",
},
// Install, values from yaml, schematized with errors
{
name: "install with schema file, with errors",
cmd: "install schema testdata/testcharts/chart-with-schema-negative",
wantError: true,
golden: "output/schema-negative.txt",
},
// Install, values from yaml, extra values from yaml, schematized with errors
{
name: "install with schema file, extra values from yaml, with errors",
cmd: "install schema testdata/testcharts/chart-with-schema -f testdata/testcharts/chart-with-schema/extra-values.yaml",
wantError: true,
golden: "output/schema-negative.txt",
},
// Install, values from yaml, extra values from cli, schematized with errors
{
name: "install with schema file, extra values from cli, with errors",
cmd: "install schema testdata/testcharts/chart-with-schema --set age=-5",
wantError: true,
golden: "output/schema-negative-cli.txt",
},
// Install with subchart, values from yaml, schematized with errors
{
name: "install with schema file and schematized subchart, with errors",
cmd: "install schema testdata/testcharts/chart-with-schema-and-subchart",
wantError: true,
golden: "output/subchart-schema-negative.txt",
},
// Install with subchart, values from yaml, extra values from cli, schematized with errors
{
name: "install with schema file and schematized subchart, extra values from cli",
cmd: "install schema testdata/testcharts/chart-with-schema-and-subchart --set lastname=doe --set subchart-with-schema.age=25",
golden: "output/subchart-schema-cli.txt",
},
// Install with subchart, values from yaml, extra values from cli, schematized with errors
{
name: "install with schema file and schematized subchart, extra values from cli, with errors",
cmd: "install schema testdata/testcharts/chart-with-schema-and-subchart --set lastname=doe --set subchart-with-schema.age=-25",
wantError: true,
golden: "output/subchart-schema-cli-negative.txt",
},
}
runTestActionCmd(t, tests)

@ -17,68 +17,29 @@ limitations under the License.
package main
import (
"fmt"
"io"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"helm.sh/helm/cmd/helm/require"
"helm.sh/helm/pkg/action"
"helm.sh/helm/pkg/release"
)
const releaseTestDesc = `
The test command runs the tests for a release.
const releaseTestHelp = `
The test command consists of multiple subcommands around running tests on a release.
Example usage:
$ helm test run [RELEASE]
The argument this command takes is the name of a deployed release.
The tests to be run are defined in the chart that was installed.
`
func newReleaseTestCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
client := action.NewReleaseTesting(cfg)
cmd := &cobra.Command{
Use: "test [RELEASE]",
Short: "test a release",
Long: releaseTestDesc,
Args: require.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
c, errc := client.Run(args[0])
testErr := &testErr{}
for {
select {
case err := <-errc:
if err == nil && testErr.failed > 0 {
return testErr.Error()
}
return err
case res, ok := <-c:
if !ok {
break
}
if res.Status == release.TestRunFailure {
testErr.failed++
}
fmt.Fprintf(out, res.Msg+"\n")
}
Use: "test",
Short: "test a release or cleanup test artifacts",
Long: releaseTestHelp,
}
},
}
f := cmd.Flags()
f.Int64Var(&client.Timeout, "timeout", 300, "time in seconds to wait for any individual Kubernetes operation (like Jobs for hooks)")
f.BoolVar(&client.Cleanup, "cleanup", false, "delete test pods upon completion")
cmd.AddCommand(
newReleaseTestRunCmd(cfg, out),
)
return cmd
}
type testErr struct {
failed int
}
func (err *testErr) Error() error {
return errors.Errorf("%v test(s) failed", err.failed)
}

@ -0,0 +1,83 @@
/*
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 main
import (
"fmt"
"io"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"helm.sh/helm/cmd/helm/require"
"helm.sh/helm/pkg/action"
"helm.sh/helm/pkg/release"
)
const releaseTestRunHelp = `
The test command runs the tests for a release.
The argument this command takes is the name of a deployed release.
The tests to be run are defined in the chart that was installed.
`
func newReleaseTestRunCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
client := action.NewReleaseTesting(cfg)
cmd := &cobra.Command{
Use: "run [RELEASE]",
Short: "run tests for a release",
Long: releaseTestRunHelp,
Args: require.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
c, errc := client.Run(args[0])
testErr := &testErr{}
for {
select {
case err := <-errc:
if err != nil && testErr.failed > 0 {
return testErr.Error()
}
return err
case res, ok := <-c:
if !ok {
break
}
if res.Status == release.TestRunFailure {
testErr.failed++
}
fmt.Fprintf(out, res.Msg+"\n")
}
}
},
}
f := cmd.Flags()
f.Int64Var(&client.Timeout, "timeout", 300, "time in seconds to wait for any individual Kubernetes operation (like Jobs for hooks)")
f.BoolVar(&client.Cleanup, "cleanup", false, "delete test pods upon completion")
return cmd
}
type testErr struct {
failed int
}
func (err *testErr) Error() error {
return errors.Errorf("%v test(s) failed", err.failed)
}

@ -1,96 +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 main
import (
"testing"
"time"
"helm.sh/helm/pkg/release"
)
func TestReleaseTesting(t *testing.T) {
timestamp := time.Unix(1452902400, 0).UTC()
tests := []cmdTestCase{{
name: "successful test",
cmd: "status test-success",
rels: []*release.Release{release.Mock(&release.MockReleaseOptions{
Name: "test-success",
TestSuiteResults: []*release.TestRun{
{
Name: "test-success",
Status: release.TestRunSuccess,
StartedAt: timestamp,
CompletedAt: timestamp,
},
},
})},
golden: "output/test-success.txt",
}, {
name: "test failure",
cmd: "status test-failure",
rels: []*release.Release{release.Mock(&release.MockReleaseOptions{
Name: "test-failure",
TestSuiteResults: []*release.TestRun{
{
Name: "test-failure",
Status: release.TestRunFailure,
StartedAt: timestamp,
CompletedAt: timestamp,
},
},
})},
golden: "output/test-failure.txt",
}, {
name: "test unknown",
cmd: "status test-unknown",
rels: []*release.Release{release.Mock(&release.MockReleaseOptions{
Name: "test-unknown",
TestSuiteResults: []*release.TestRun{
{
Name: "test-unknown",
Status: release.TestRunUnknown,
StartedAt: timestamp,
CompletedAt: timestamp,
},
},
})},
golden: "output/test-unknown.txt",
}, {
name: "test running",
cmd: "status test-running",
rels: []*release.Release{release.Mock(&release.MockReleaseOptions{
Name: "test-running",
TestSuiteResults: []*release.TestRun{
{
Name: "test-running",
Status: release.TestRunRunning,
StartedAt: timestamp,
CompletedAt: timestamp,
},
},
})},
golden: "output/test-running.txt",
}, {
name: "test with no tests",
cmd: "test no-tests",
rels: []*release.Release{release.Mock(&release.MockReleaseOptions{Name: "no-tests"})},
golden: "output/test-no-tests.txt",
}}
runTestCmd(t, tests)
}

@ -1,3 +1,3 @@
REVISION UPDATED STATUS CHART DESCRIPTION
3 1977-09-02 22:04:05 +0000 UTC superseded foo-0.1.0-beta.1 Release mock
4 1977-09-02 22:04:05 +0000 UTC deployed foo-0.1.0-beta.1 Release mock
REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION
3 1977-09-02 22:04:05 +0000 UTC superseded foo-0.1.0-beta.1 1.0 Release mock
4 1977-09-02 22:04:05 +0000 UTC deployed foo-0.1.0-beta.1 1.0 Release mock

@ -1 +1 @@
[{"revision":3,"updated":"1977-09-02 22:04:05 +0000 UTC","status":"superseded","chart":"foo-0.1.0-beta.1","description":"Release mock"},{"revision":4,"updated":"1977-09-02 22:04:05 +0000 UTC","status":"deployed","chart":"foo-0.1.0-beta.1","description":"Release mock"}]
[{"revision":3,"updated":"1977-09-02 22:04:05 +0000 UTC","status":"superseded","chart":"foo-0.1.0-beta.1","app_version":"1.0","description":"Release mock"},{"revision":4,"updated":"1977-09-02 22:04:05 +0000 UTC","status":"deployed","chart":"foo-0.1.0-beta.1","app_version":"1.0","description":"Release mock"}]

@ -1,5 +1,5 @@
REVISION UPDATED STATUS CHART DESCRIPTION
1 1977-09-02 22:04:05 +0000 UTC superseded foo-0.1.0-beta.1 Release mock
2 1977-09-02 22:04:05 +0000 UTC superseded foo-0.1.0-beta.1 Release mock
3 1977-09-02 22:04:05 +0000 UTC superseded foo-0.1.0-beta.1 Release mock
4 1977-09-02 22:04:05 +0000 UTC deployed foo-0.1.0-beta.1 Release mock
REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION
1 1977-09-02 22:04:05 +0000 UTC superseded foo-0.1.0-beta.1 1.0 Release mock
2 1977-09-02 22:04:05 +0000 UTC superseded foo-0.1.0-beta.1 1.0 Release mock
3 1977-09-02 22:04:05 +0000 UTC superseded foo-0.1.0-beta.1 1.0 Release mock
4 1977-09-02 22:04:05 +0000 UTC deployed foo-0.1.0-beta.1 1.0 Release mock

@ -1,9 +1,11 @@
- chart: foo-0.1.0-beta.1
- app_version: "1.0"
chart: foo-0.1.0-beta.1
description: Release mock
revision: 3
status: superseded
updated: 1977-09-02 22:04:05 +0000 UTC
- chart: foo-0.1.0-beta.1
- app_version: "1.0"
chart: foo-0.1.0-beta.1
description: Release mock
revision: 4
status: deployed

@ -0,0 +1,4 @@
Error: values don't meet the specifications of the schema(s) in the following chart(s):
empty:
- age: Must be greater than or equal to 0/1

@ -0,0 +1,5 @@
Error: values don't meet the specifications of the schema(s) in the following chart(s):
empty:
- (root): employmentInfo is required
- age: Must be greater than or equal to 0/1

@ -0,0 +1,5 @@
NAME: schema
LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC
NAMESPACE: default
STATUS: deployed

@ -0,0 +1,4 @@
Error: values don't meet the specifications of the schema(s) in the following chart(s):
subchart-with-schema:
- age: Must be greater than or equal to 0/1

@ -0,0 +1,5 @@
NAME: schema
LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC
NAMESPACE: default
STATUS: deployed

@ -0,0 +1,6 @@
Error: values don't meet the specifications of the schema(s) in the following chart(s):
chart-without-schema:
- (root): lastname is required
subchart-with-schema:
- (root): age is required

@ -0,0 +1,2 @@
release "aeneas" uninstalled
release "aeneas2" uninstalled

@ -1 +1 @@
Error: cannot load Chart.yaml: error converting YAML to JSON: yaml: line 5: did not find expected '-' indicator
Error: cannot load Chart.yaml: error converting YAML to JSON: yaml: line 6: did not find expected '-' indicator

@ -4,8 +4,3 @@ LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC
NAMESPACE: default
STATUS: deployed
NOTES:
1. Get the application URL by running these commands:
export POD_NAME=$(kubectl get pods -l "app=testUpgradeChart,release=crazy-bunny" -o jsonpath="{.items[0].metadata.name}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl port-forward $POD_NAME 8080:80

@ -4,8 +4,3 @@ LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC
NAMESPACE: default
STATUS: deployed
NOTES:
1. Get the application URL by running these commands:
export POD_NAME=$(kubectl get pods -l "app=testUpgradeChart,release=zany-bunny" -o jsonpath="{.items[0].metadata.name}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl port-forward $POD_NAME 8080:80

@ -4,8 +4,3 @@ LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC
NAMESPACE: default
STATUS: deployed
NOTES:
1. Get the application URL by running these commands:
export POD_NAME=$(kubectl get pods -l "app=testUpgradeChart,release=funny-bunny" -o jsonpath="{.items[0].metadata.name}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl port-forward $POD_NAME 8080:80

@ -4,8 +4,3 @@ LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC
NAMESPACE: default
STATUS: deployed
NOTES:
1. Get the application URL by running these commands:
export POD_NAME=$(kubectl get pods -l "app=testUpgradeChart,release=funny-bunny" -o jsonpath="{.items[0].metadata.name}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl port-forward $POD_NAME 8080:80

@ -4,8 +4,3 @@ LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC
NAMESPACE: default
STATUS: deployed
NOTES:
1. Get the application URL by running these commands:
export POD_NAME=$(kubectl get pods -l "app=testUpgradeChart,release=funny-bunny" -o jsonpath="{.items[0].metadata.name}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl port-forward $POD_NAME 8080:80

@ -4,8 +4,3 @@ LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC
NAMESPACE: default
STATUS: deployed
NOTES:
1. Get the application URL by running these commands:
export POD_NAME=$(kubectl get pods -l "app=testUpgradeChart,release=crazy-bunny" -o jsonpath="{.items[0].metadata.name}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl port-forward $POD_NAME 8080:80

@ -4,8 +4,3 @@ LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC
NAMESPACE: default
STATUS: deployed
NOTES:
1. Get the application URL by running these commands:
export POD_NAME=$(kubectl get pods -l "app=testUpgradeChart,release=funny-bunny" -o jsonpath="{.items[0].metadata.name}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl port-forward $POD_NAME 8080:80

@ -1,3 +1,4 @@
apiVersion: v1
description: Deploy a basic Alpine Linux pod
home: https://helm.sh/helm
name: alpine

@ -1,3 +1,4 @@
apiVersion: v1
description: A Helm chart for Kubernetes
name: chart-missing-deps
version: 0.1.0

@ -1,3 +1,4 @@
apiVersion: v1
description: A Helm chart for Kubernetes
name: reqsubchart
version: 0.1.0

@ -1,7 +1,8 @@
apiVersion: v1
description: Deploy a basic Alpine Linux pod
home: https://helm.sh/helm
name: chart-bad-type
sources:
- https://github.com/helm/helm
- https://github.com/helm/helm
version: 0.1.0
type: foobar

@ -1,3 +1,4 @@
apiVersion: v1
description: A Helm chart for Kubernetes
name: chart-missing-deps
version: 0.1.0

@ -1,3 +1,4 @@
apiVersion: v1
description: A Helm chart for Kubernetes
name: reqsubchart
version: 0.1.0

@ -0,0 +1,6 @@
apiVersion: v1
name: chart-without-schema
description: A Helm chart for Kubernetes
type: application
version: 0.1.0
appVersion: 0.1.0

@ -0,0 +1,6 @@
apiVersion: v1
name: subchart-with-schema
description: A Helm chart for Kubernetes
type: application
version: 0.1.0
appVersion: 0.1.0

@ -0,0 +1,15 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Values",
"type": "object",
"properties": {
"age": {
"description": "Age",
"minimum": 0,
"type": "integer"
}
},
"required": [
"age"
]
}

@ -0,0 +1,18 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Values",
"type": "object",
"properties": {
"firstname": {
"description": "First name",
"type": "string"
},
"lastname": {
"type": "string"
}
},
"required": [
"firstname",
"lastname"
]
}

@ -0,0 +1,7 @@
apiVersion: v1
description: Empty testing chart
home: https://k8s.io/helm
name: empty
sources:
- https://github.com/kubernetes/helm
version: 0.1.0

@ -0,0 +1,67 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"addresses": {
"description": "List of addresses",
"items": {
"properties": {
"city": {
"type": "string"
},
"number": {
"type": "number"
},
"street": {
"type": "string"
}
},
"type": "object"
},
"type": "array"
},
"age": {
"description": "Age",
"minimum": 0,
"type": "integer"
},
"employmentInfo": {
"properties": {
"salary": {
"minimum": 0,
"type": "number"
},
"title": {
"type": "string"
}
},
"required": [
"salary"
],
"type": "object"
},
"firstname": {
"description": "First name",
"type": "string"
},
"lastname": {
"type": "string"
},
"likesCoffee": {
"type": "boolean"
},
"phoneNumbers": {
"items": {
"type": "string"
},
"type": "array"
}
},
"required": [
"firstname",
"lastname",
"addresses",
"employmentInfo"
],
"title": "Values",
"type": "object"
}

@ -0,0 +1,14 @@
firstname: John
lastname: Doe
age: -5
likesCoffee: true
addresses:
- city: Springfield
street: Main
number: 12345
- city: New York
street: Broadway
number: 67890
phoneNumbers:
- "(888) 888-8888"
- "(555) 555-5555"

@ -0,0 +1,7 @@
apiVersion: v1
description: Empty testing chart
home: https://k8s.io/helm
name: empty
sources:
- https://github.com/kubernetes/helm
version: 0.1.0

@ -0,0 +1,2 @@
age: -5
employmentInfo: null

@ -0,0 +1 @@
# This file is intentionally blank

@ -0,0 +1,67 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"addresses": {
"description": "List of addresses",
"items": {
"properties": {
"city": {
"type": "string"
},
"number": {
"type": "number"
},
"street": {
"type": "string"
}
},
"type": "object"
},
"type": "array"
},
"age": {
"description": "Age",
"minimum": 0,
"type": "integer"
},
"employmentInfo": {
"properties": {
"salary": {
"minimum": 0,
"type": "number"
},
"title": {
"type": "string"
}
},
"required": [
"salary"
],
"type": "object"
},
"firstname": {
"description": "First name",
"type": "string"
},
"lastname": {
"type": "string"
},
"likesCoffee": {
"type": "boolean"
},
"phoneNumbers": {
"items": {
"type": "string"
},
"type": "array"
}
},
"required": [
"firstname",
"lastname",
"addresses",
"employmentInfo"
],
"title": "Values",
"type": "object"
}

@ -0,0 +1,17 @@
firstname: John
lastname: Doe
age: 25
likesCoffee: true
employmentInfo:
title: Software Developer
salary: 100000
addresses:
- city: Springfield
street: Main
number: 12345
- city: New York
street: Broadway
number: 67890
phoneNumbers:
- "(888) 888-8888"
- "(555) 555-5555"

@ -1,3 +1,4 @@
apiVersion: v1
description: A Helm chart for Kubernetes
name: decompressedchart
version: 0.1.0

@ -1,6 +1,7 @@
apiVersion: v1
description: Empty testing chart
home: https://helm.sh/helm
name: empty
sources:
- https://github.com/helm/helm
- https://github.com/helm/helm
version: 0.1.0

@ -1,6 +1,7 @@
apiVersion: v1
description: Deploy a basic Alpine Linux pod
home: https://helm.sh/helm
name: alpine
sources:
- https://github.com/helm/helm
- https://github.com/helm/helm
version: 0.1.0

@ -1,6 +1,7 @@
apiVersion: v1
description: Deploy a basic Alpine Linux pod
home: https://helm.sh/helm
name: novals
sources:
- https://github.com/helm/helm
- https://github.com/helm/helm
version: 0.2.0

Binary file not shown.

@ -1,3 +1,4 @@
apiVersion: v1
description: A Helm chart for Kubernetes
name: reqtest
version: 0.1.0

@ -1,3 +1,4 @@
apiVersion: v1
description: A Helm chart for Kubernetes
name: reqsubchart
version: 0.1.0

@ -1,3 +1,4 @@
apiVersion: v1
description: A Helm chart for Kubernetes
name: reqsubchart2
version: 0.2.0

Binary file not shown.

@ -1,20 +1,21 @@
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
apiVersion: v1
description: A Helm chart for Kubernetes
name: signtest
version: 0.1.0
...
files:
signtest-0.1.0.tgz: sha256:dee72947753628425b82814516bdaa37aef49f25e8820dd2a6e15a33a007823b
signtest-0.1.0.tgz: sha256:e5ef611620fb97704d8751c16bab17fedb68883bfb0edc76f78a70e9173f9b55
-----BEGIN PGP SIGNATURE-----
wsBcBAEBCgAQBQJXomNHCRCEO7+YH8GHYgAALywIAG1Me852Fpn1GYu8Q1GCcw4g
l2k7vOFchdDwDhdSVbkh4YyvTaIO3iE2Jtk1rxw+RIJiUr0eLO/rnIJuxZS8WKki
DR1LI9J1VD4dxN3uDETtWDWq7ScoPsRY5mJvYZXC8whrWEt/H2kfqmoA9LloRPWp
flOE0iktA4UciZOblTj6nAk3iDyjh/4HYL4a6tT0LjjKI7OTw4YyHfjHad1ywVCz
9dMUc1rPgTnl+fnRiSPSrlZIWKOt1mcQ4fVrU3nwtRUwTId2k8FtygL0G6M+Y6t0
S6yaU7qfk9uTxkdkUF7Bf1X3ukxfe+cNBC32vf4m8LY4NkcYfSqK2fGtQsnVr6s=
=NyOM
wsBcBAEBCgAQBQJcoosfCRCEO7+YH8GHYgAA220IALAs8T8NPgkcLvHu+5109cAN
BOCNPSZDNsqLZW/2Dc9cKoBG7Jen4Qad+i5l9351kqn3D9Gm6eRfAWcjfggRobV/
9daZ19h0nl4O1muQNAkjvdgZt8MOP3+PB3I3/Tu2QCYjI579SLUmuXlcZR5BCFPR
PJy+e3QpV2PcdeU2KZLG4tjtlrq+3QC9ZHHEJLs+BVN9d46Dwo6CxJdHJrrrAkTw
M8MhA92vbiTTPRSCZI9x5qDAwJYhoq0oxLflpuL2tIlo3qVoCsaTSURwMESEHO32
XwYG7BaVDMELWhAorBAGBGBwWFbJ1677qQ2gd9CN0COiVhekWlFRcnn60800r84=
=k9Y9
-----END PGP SIGNATURE-----

@ -1,3 +1,4 @@
apiVersion: v1
description: A Helm chart for Kubernetes
name: signtest
version: 0.1.0

@ -1,3 +1,4 @@
apiVersion: v1
description: Deploy a basic Alpine Linux pod
home: https://helm.sh/helm
name: alpine

@ -27,8 +27,10 @@ import (
)
const uninstallDesc = `
This command takes a release name, and then uninstalls the release from Kubernetes.
It removes all of the resources associated with the last release of the chart.
This command takes a release name and uninstalls the release.
It removes all of the resources associated with the last release of the chart
as well as the release history, freeing it up for future use.
Use the '--dry-run' flag to see which releases will be uninstalled without actually
uninstalling them.
@ -41,13 +43,13 @@ func newUninstallCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
Use: "uninstall RELEASE_NAME [...]",
Aliases: []string{"del", "delete", "un"},
SuggestFor: []string{"remove", "rm"},
Short: "given a release name, uninstall the release from Kubernetes",
Short: "uninstall a release",
Long: uninstallDesc,
Args: require.MinimumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
for i := 0; i < len(args); i++ {
res, err := client.Run(args[0])
res, err := client.Run(args[i])
if err != nil {
return err
}
@ -64,7 +66,7 @@ func newUninstallCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
f := cmd.Flags()
f.BoolVar(&client.DryRun, "dry-run", false, "simulate a uninstall")
f.BoolVar(&client.DisableHooks, "no-hooks", false, "prevent hooks from running during uninstallation")
f.BoolVar(&client.Purge, "purge", false, "remove the release from the store and make its name free for later use")
f.BoolVar(&client.KeepHistory, "keep-history", false, "remove all associated resources and mark the release as deleted, but retain the release history")
f.Int64Var(&client.Timeout, "timeout", 300, "time in seconds to wait for any individual Kubernetes operation (like Jobs for hooks)")
return cmd

@ -30,6 +30,15 @@ func TestUninstall(t *testing.T) {
golden: "output/uninstall.txt",
rels: []*release.Release{release.Mock(&release.MockReleaseOptions{Name: "aeneas"})},
},
{
name: "multiple uninstall",
cmd: "uninstall aeneas aeneas2",
golden: "output/uninstall-multiple.txt",
rels: []*release.Release{
release.Mock(&release.MockReleaseOptions{Name: "aeneas"}),
release.Mock(&release.MockReleaseOptions{Name: "aeneas2"}),
},
},
{
name: "uninstall with timeout",
cmd: "uninstall aeneas --timeout 120",
@ -43,9 +52,9 @@ func TestUninstall(t *testing.T) {
rels: []*release.Release{release.Mock(&release.MockReleaseOptions{Name: "aeneas"})},
},
{
name: "purge",
cmd: "uninstall aeneas --purge",
golden: "output/uninstall-purge.txt",
name: "keep history",
cmd: "uninstall aeneas --keep-history",
golden: "output/uninstall-keep-history.txt",
rels: []*release.Release{release.Mock(&release.MockReleaseOptions{Name: "aeneas"})},
},
{

@ -18,6 +18,7 @@ package main
import (
"fmt"
"path/filepath"
"testing"
"helm.sh/helm/pkg/chart"
@ -28,13 +29,16 @@ import (
func TestUpgradeCmd(t *testing.T) {
tmpChart := testTempDir(t)
cfile := &chart.Metadata{
cfile := &chart.Chart{
Metadata: &chart.Metadata{
APIVersion: chart.APIVersionV1,
Name: "testUpgradeChart",
Description: "A Helm chart for Kubernetes",
Version: "0.1.0",
},
}
chartPath, err := chartutil.Create(cfile, tmpChart)
if err != nil {
chartPath := filepath.Join(tmpChart, cfile.Metadata.Name)
if err := chartutil.SaveDir(cfile, tmpChart); err != nil {
t.Fatalf("Error creating chart for upgrade: %v", err)
}
ch, err := loader.Load(chartPath)
@ -47,14 +51,9 @@ func TestUpgradeCmd(t *testing.T) {
})
// update chart version
cfile = &chart.Metadata{
Name: "testUpgradeChart",
Description: "A Helm chart for Kubernetes",
Version: "0.1.2",
}
cfile.Metadata.Version = "0.1.2"
chartPath, err = chartutil.Create(cfile, tmpChart)
if err != nil {
if err := chartutil.SaveDir(cfile, tmpChart); err != nil {
t.Fatalf("Error creating chart: %v", err)
}
ch, err = loader.Load(chartPath)
@ -63,14 +62,9 @@ func TestUpgradeCmd(t *testing.T) {
}
// update chart version again
cfile = &chart.Metadata{
Name: "testUpgradeChart",
Description: "A Helm chart for Kubernetes",
Version: "0.1.3",
}
cfile.Metadata.Version = "0.1.3"
chartPath, err = chartutil.Create(cfile, tmpChart)
if err != nil {
if err := chartutil.SaveDir(cfile, tmpChart); err != nil {
t.Fatalf("Error creating chart: %v", err)
}
var ch2 *chart.Chart

@ -26,6 +26,7 @@ wordpress/
LICENSE # OPTIONAL: A plain text file containing the license for the chart
README.md # OPTIONAL: A human-readable README file
values.yaml # The default configuration values for this chart
values.schema.json # OPTIONAL: A JSON Schema for imposing a structure on the values.yaml file
charts/ # A directory containing any charts upon which this chart depends.
templates/ # A directory of templates that, when combined with values,
# will generate valid Kubernetes manifest files.
@ -763,14 +764,98 @@ parent chart.
Also, global variables of parent charts take precedence over the global variables from subcharts.
### Schema Files
Sometimes, a chart maintainer might want to define a structure on their values.
This can be done by defining a schema in the `values.schema.json` file. A
schema is represented as a [JSON Schema](https://json-schema.org/).
It might look something like this:
```json
{
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"image": {
"description": "Container Image",
"properties": {
"repo": {
"type": "string"
},
"tag": {
"type": "string"
}
},
"type": "object"
},
"name": {
"description": "Service name",
"type": "string"
},
"port": {
"description": "Port",
"minimum": 0,
"type": "integer"
},
"protocol": {
"type": "string"
}
},
"required": [
"protocol",
"port"
],
"title": "Values",
"type": "object"
}
```
This schema will be applied to the values to validate it. Validation occurs
when any of the following commands are invoked:
* `helm install`
* `helm upgrade`
* `helm lint`
* `helm template`
An example of a
`values.yaml` file that meets the requirements of this schema might look
something like this:
```yaml
name: frontend
protocol: https
port: 443
```
Note that the schema is applied to the final `.Values` object, and not just to
the `values.yaml` file. This means that the following `yaml` file is valid,
given that the chart is installed with the appropriate `--set` option shown
below.
```yaml
name: frontend
protocol: https
```
````
helm install --set port=443
````
Furthermore, the final `.Values` object is checked against *all* subchart
schemas. This means that restrictions on a subchart can't be circumvented by a
parent chart. This also works backwards - if a subchart has a requirement that
is not met in the subchart's `values.yaml` file, the parent chart *must*
satisfy those restrictions in order to be valid.
### References
When it comes to writing templates and values files, there are several
When it comes to writing templates, values, and schema files, there are several
standard references that will help you out.
- [Go templates](https://godoc.org/text/template)
- [Extra template functions](https://godoc.org/github.com/Masterminds/sprig)
- [The YAML format](http://yaml.org/spec/)
- [JSON Schema](https://json-schema.org/)
## Using Helm to Manage Charts

@ -19,7 +19,7 @@ $ make bootstrap build
```
NOTE: This will fail if not running from the path `$GOPATH/src/helm.sh/helm`. The
directory `k8s.io` should not be a symlink or `build` will not find the relevant
directory `helm.sh` should not be a symlink or `build` will not find the relevant
packages.
This will build both Helm and the Helm library. `make bootstrap` will attempt to
@ -94,7 +94,7 @@ home of the current development candidate. Releases are tagged.
We accept changes to the code via GitHub Pull Requests (PRs). One
workflow for doing this is as follows:
1. Go to your `$GOPATH/src/k8s.io` directory and `git clone` the
1. Go to your `$GOPATH/src` directory, then `mkdir helm.sh; cd helm.sh` and `git clone` the
`github.com/helm/helm` repository.
2. Fork that repository into your GitHub account
3. Add your repository as a remote for `$GOPATH/src/helm.sh/helm`

@ -1,3 +1,4 @@
apiVersion: v1
name: alpine
description: Deploy a basic Alpine Linux pod
version: 0.1.0

@ -1,3 +1,4 @@
apiVersion: v1
name: nginx
description: A basic NGINX HTTP server
version: 0.1.0

@ -1,3 +1,4 @@
apiVersion: v1
name: alpine
description: Deploy a basic Alpine Linux pod
version: 0.1.0

@ -15,6 +15,16 @@ Here's an exhaustive list of all the major changes introduced in Helm 3.
In Helm 3, Helm switched the Go import path over from `k8s.io/helm` to `helm.sh/helm`. If you intend
to upgrade to the Helm 3 Go client libraries, make sure to change your import paths.
### Helm delete
In order to better align the verbiage from other package managers, `helm delete` was re-named to
`helm uninstall`. `helm delete` is still retained as an alias to `helm uninstall`, so either form
can be used.
In Helm 2, in order to purge the release ledger, the `--purge` flag had to be provided. This
functionality is now enabled by default. To retain the previous behaviour, use
`helm uninstall --keep-history`.
## Installing

@ -34,6 +34,7 @@ type releaseInfo struct {
Updated string `json:"updated"`
Status string `json:"status"`
Chart string `json:"chart"`
AppVersion string `json:"app_version"`
Description string `json:"description"`
}
@ -142,11 +143,13 @@ func getReleaseHistory(rls []*release.Release) (history releaseHistory) {
s := r.Info.Status.String()
v := r.Version
d := r.Info.Description
a := formatAppVersion(r.Chart)
rInfo := releaseInfo{
Revision: v,
Status: s,
Chart: c,
AppVersion: a,
Description: d,
}
if !r.Info.LastDeployed.IsZero() {
@ -162,10 +165,10 @@ func getReleaseHistory(rls []*release.Release) (history releaseHistory) {
func formatAsTable(releases releaseHistory) []byte {
tbl := uitable.New()
tbl.AddRow("REVISION", "UPDATED", "STATUS", "CHART", "DESCRIPTION")
tbl.AddRow("REVISION", "UPDATED", "STATUS", "CHART", "APP VERSION", "DESCRIPTION")
for i := 0; i <= len(releases)-1; 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()
}
@ -178,3 +181,12 @@ func formatChartname(c *chart.Chart) string {
}
return fmt.Sprintf("%s-%s", c.Name(), c.Metadata.Version)
}
func formatAppVersion(c *chart.Chart) string {
if c == nil || c.Metadata == nil {
// This is an edge case that has happened in prod, though we don't
// know how: https://github.com/helm/helm/issues/1347
return "MISSING"
}
return c.AppVersion()
}

@ -29,6 +29,8 @@ var (
invalidArchivedChartPath = "../../cmd/helm/testdata/testcharts/invalidcompressedchart0.1.0.tgz"
chartDirPath = "../../cmd/helm/testdata/testcharts/decompressedchart/"
chartMissingManifest = "../../cmd/helm/testdata/testcharts/chart-missing-manifest"
chartSchema = "../../cmd/helm/testdata/testcharts/chart-with-schema"
chartSchemaNegative = "../../cmd/helm/testdata/testcharts/chart-with-schema-negative"
)
func TestLintChart(t *testing.T) {
@ -47,4 +49,10 @@ func TestLintChart(t *testing.T) {
if _, err := lintChart(chartMissingManifest, values, namespace, strict); err == nil {
t.Error("Expected a chart parsing error")
}
if _, err := lintChart(chartSchema, values, namespace, strict); err != nil {
t.Error(err)
}
if _, err := lintChart(chartSchemaNegative, values, namespace, strict); err != nil {
t.Error(err)
}
}

@ -38,7 +38,7 @@ type Uninstall struct {
DisableHooks bool
DryRun bool
Purge bool
KeepHistory bool
Timeout int64
}
@ -78,7 +78,7 @@ func (u *Uninstall) Run(name string) (*release.UninstallReleaseResponse, error)
// TODO: Are there any cases where we want to force a delete even if it's
// already marked deleted?
if rel.Info.Status == release.StatusUninstalled {
if u.Purge {
if !u.KeepHistory {
if err := u.purgeReleases(rels...); err != nil {
return nil, errors.Wrap(err, "uninstall: Failed to purge the release")
}
@ -119,7 +119,7 @@ func (u *Uninstall) Run(name string) (*release.UninstallReleaseResponse, error)
rel.Info.Status = release.StatusUninstalled
rel.Info.Description = "Uninstallation complete"
if u.Purge {
if !u.KeepHistory {
u.cfg.Log("purge requested for %s", name)
err := u.purgeReleases(rels...)
return res, errors.Wrap(err, "uninstall: Failed to purge the release")

@ -15,8 +15,8 @@ limitations under the License.
package chart
// APIVersionv1 is the API version number for version 1.
const APIVersionv1 = "v1"
// APIVersionV1 is the API version number for version 1.
const APIVersionV1 = "v1"
// Chart is a helm package that contains metadata, a default config, zero or more
// optionally parameterizable templates, and zero or more charts (dependencies).
@ -31,6 +31,8 @@ type Chart struct {
RawValues []byte
// Values are default config for this template.
Values map[string]interface{}
// Schema is an optional JSON schema for imposing structure on Values
Schema []byte
// Files are miscellaneous files in a chart archive,
// e.g. README, LICENSE, etc.
Files []*File
@ -96,3 +98,15 @@ func (ch *Chart) ChartFullPath() string {
}
return ch.Name()
}
func (ch *Chart) Validate() error {
return ch.Metadata.Validate()
}
// AppVersion returns the appversion of the chart.
func (ch *Chart) AppVersion() string {
if ch.Metadata == nil {
return ""
}
return ch.Metadata.AppVersion
}

@ -90,6 +90,8 @@ func LoadFiles(files []*BufferedFile) (*chart.Chart, error) {
return c, errors.Wrap(err, "cannot load values.yaml")
}
c.RawValues = f.Data
case f.Name == "values.schema.json":
c.Schema = f.Data
case strings.HasPrefix(f.Name, "templates/"):
c.Templates = append(c.Templates, &chart.File{Name: f.Name, Data: f.Data})
case strings.HasPrefix(f.Name, "charts/"):
@ -106,12 +108,8 @@ func LoadFiles(files []*BufferedFile) (*chart.Chart, error) {
}
}
// Ensure that we got a Chart.yaml file
if c.Metadata == nil {
return c, errors.New("chart metadata (Chart.yaml) missing")
}
if c.Name() == "" {
return c, errors.New("invalid chart (Chart.yaml): name must not be empty")
if err := c.Validate(); err != nil {
return c, err
}
for n, files := range subcharts {

@ -17,6 +17,7 @@ limitations under the License.
package loader
import (
"bytes"
"testing"
"helm.sh/helm/pkg/chart"
@ -78,6 +79,10 @@ icon: https://example.com/64x64.png
Name: "values.yaml",
Data: []byte("var: some values"),
},
{
Name: "values.schema.json",
Data: []byte("type: Values"),
},
{
Name: "templates/deployment.yaml",
Data: []byte("some deployment"),
@ -101,6 +106,10 @@ icon: https://example.com/64x64.png
t.Error("Expected chart values to be populated with default values")
}
if !bytes.Equal(c.Schema, []byte("type: Values")) {
t.Error("Expected chart schema to be populated with default values")
}
if len(c.Templates) != 2 {
t.Errorf("Expected number of templates == 2, got %d", len(c.Templates))
}
@ -109,7 +118,7 @@ icon: https://example.com/64x64.png
if err == nil {
t.Fatal("Expected err to be non-nil")
}
if err.Error() != "chart metadata (Chart.yaml) missing" {
if err.Error() != "metadata is required" {
t.Errorf("Expected chart metadata missing error, got '%s'", err.Error())
}
}

@ -1,3 +1,4 @@
apiVersion: v1
name: albatross
description: A Helm chart for Kubernetes
version: 0.1.0

Binary file not shown.

@ -1,3 +1,4 @@
apiVersion: v1
name: alpine
description: Deploy a basic Alpine Linux pod
version: 0.1.0

@ -1,3 +1,4 @@
apiVersion: v1
name: mast1
description: A Helm chart for Kubernetes
version: 0.1.0

@ -1,3 +1,4 @@
apiVersion: v1
name: alpine
description: Deploy a basic Alpine Linux pod
version: 0.1.0

@ -1,3 +1,4 @@
apiVersion: v1
name: mast1
description: A Helm chart for Kubernetes
version: 0.1.0

@ -6,7 +6,9 @@ tar -zcvf mariner/charts/albatross-0.1.0.tgz albatross
echo "Packing mariner into frobnitz"
tar -zcvf frobnitz/charts/mariner-4.3.2.tgz mariner
tar -zcvf frobnitz_backslash/charts/mariner-4.3.2.tgz mariner
# Pack the frobnitz chart.
echo "Packing frobnitz"
tar --exclude=ignore/* -zcvf frobnitz-1.2.3.tgz frobnitz
tar --exclude=ignore/* -zcvf frobnitz_backslash-1.2.3.tgz frobnitz_backslash

@ -1,3 +1,4 @@
apiVersion: v1
name: mariner
description: A Helm chart for Kubernetes
version: 4.3.2

@ -15,6 +15,8 @@ limitations under the License.
package chart
import "errors"
// Maintainer describes a Chart maintainer.
type Maintainer struct {
// Name is a user name or organization name
@ -65,3 +67,20 @@ type Metadata struct {
// Specifies the chart type: application or library
Type string `json:"type,omitempty"`
}
func (md *Metadata) Validate() error {
if md == nil {
return errors.New("metadata is required")
}
if md.APIVersion == "" {
return errors.New("metadata apiVersion is required")
}
if md.Name == "" {
return errors.New("metadata name is required")
}
if md.Version == "" {
return errors.New("metadata version is required")
}
// TODO validate valid semver here?
return nil
}

@ -40,8 +40,8 @@ func verifyChartfile(t *testing.T, f *chart.Metadata, name string) {
}
// Api instead of API because it was generated via protobuf.
if f.APIVersion != chart.APIVersionv1 {
t.Errorf("Expected API Version %q, got %q", chart.APIVersionv1, f.APIVersion)
if f.APIVersion != chart.APIVersionV1 {
t.Errorf("Expected API Version %q, got %q", chart.APIVersionV1, f.APIVersion)
}
if f.Name != name {

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save