ref(pkg/chart): add validation method to chart

Consolidate validation of Chart.yaml.

Signed-off-by: Adam Reese <adam@reese.io>
pull/5560/head
Adam Reese 6 years ago
parent d4323c1da8
commit e458a67f0c
No known key found for this signature in database
GPG Key ID: 06F35E60A7A18DD6

@ -81,7 +81,7 @@ func (o *createOptions) run(out io.Writer) error {
Type: "application",
Version: "0.1.0",
AppVersion: "1.0",
APIVersion: chart.APIVersionv1,
APIVersion: chart.APIVersionV1,
}
if o.starter != "" {

@ -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,11 @@ 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(&chart.Metadata{
APIVersion: chart.APIVersionV1,
Name: "starterchart",
Version: "0.1.0",
}, starterchart); err != nil {
t.Fatalf("Could not create chart: %s", err)
} else {
t.Logf("Created %s", dest)
@ -106,7 +110,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)
}

@ -205,8 +205,9 @@ func TestDependencyUpdateCmd_DontDeleteOldChartsOnError(t *testing.T) {
// The baseURL can be used to point to a particular repository server.
func createTestingMetadata(name, baseURL string) *chart.Metadata {
return &chart.Metadata{
Name: name,
Version: "1.2.3",
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},

@ -113,7 +113,7 @@ func TestInstall(t *testing.T) {
},
// Install, chart with bad dependencies in Chart.yaml in /charts
{
name: "install chart with bad dependencies in Chart.yaml",
name: "install chart with bad dependencies in Chart.yaml",
cmd: "install badreq testdata/testcharts/chart-bad-requirements",
wantError: true,
},

@ -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

@ -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

@ -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

@ -29,6 +29,7 @@ import (
func TestUpgradeCmd(t *testing.T) {
tmpChart := testTempDir(t)
cfile := &chart.Metadata{
APIVersion: chart.APIVersionV1,
Name: "testUpgradeChart",
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: 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,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).
@ -96,3 +96,7 @@ func (ch *Chart) ChartFullPath() string {
}
return ch.Name()
}
func (ch *Chart) Validate() error {
return ch.Metadata.Validate()
}

@ -106,12 +106,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 {

@ -109,7 +109,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 {

@ -34,7 +34,11 @@ func TestCreate(t *testing.T) {
}
defer os.RemoveAll(tdir)
cf := &chart.Metadata{Name: "foo"}
cf := &chart.Metadata{
APIVersion: chart.APIVersionV1,
Name: "foo",
Version: "0.1.0",
}
c, err := Create(cf, tdir)
if err != nil {
@ -85,7 +89,11 @@ func TestCreateFrom(t *testing.T) {
}
defer os.RemoveAll(tdir)
cf := &chart.Metadata{Name: "foo"}
cf := &chart.Metadata{
APIVersion: chart.APIVersionV1,
Name: "foo",
Version: "0.1.0",
}
srcdir := "./testdata/mariner"
if err := CreateFrom(cf, tdir, srcdir); err != nil {

@ -27,6 +27,7 @@ import (
)
func loadChart(t *testing.T, path string) *chart.Chart {
t.Helper()
c, err := loader.Load(path)
if err != nil {
t.Fatalf("failed to load testdata: %s", err)

@ -109,18 +109,11 @@ func Save(c *chart.Chart, outDir string) (string, error) {
return "", errors.Errorf("location %s is not a directory", outDir)
}
if c.Metadata == nil {
return "", errors.New("no Chart.yaml data")
if err := c.Validate(); err != nil {
return "", errors.Wrap(err, "chart validation")
}
cfile := c.Metadata
if cfile.Name == "" {
return "", errors.New("no chart name specified (Chart.yaml)")
} else if cfile.Version == "" {
return "", errors.New("no chart version specified (Chart.yaml)")
}
filename := fmt.Sprintf("%s-%s.tgz", cfile.Name, cfile.Version)
filename := fmt.Sprintf("%s-%s.tgz", c.Name(), c.Metadata.Version)
filename = filepath.Join(outDir, filename)
if stat, err := os.Stat(filepath.Dir(filename)); os.IsNotExist(err) {
if err := os.MkdirAll(filepath.Dir(filename), 0755); !os.IsExist(err) {

@ -35,8 +35,9 @@ func TestSave(t *testing.T) {
c := &chart.Chart{
Metadata: &chart.Metadata{
Name: "ahab",
Version: "1.2.3.4",
APIVersion: chart.APIVersionV1,
Name: "ahab",
Version: "1.2.3",
},
Files: []*chart.File{
{Name: "scheherazade/shahryar.txt", Data: []byte("1,001 Nights")},
@ -80,8 +81,9 @@ func TestSaveDir(t *testing.T) {
c := &chart.Chart{
Metadata: &chart.Metadata{
Name: "ahab",
Version: "1.2.3.4",
APIVersion: chart.APIVersionV1,
Name: "ahab",
Version: "1.2.3",
},
Files: []*chart.File{
{Name: "scheherazade/shahryar.txt", Data: []byte("1,001 Nights")},

@ -1,3 +1,4 @@
apiVersion: v1
name: albatross
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

@ -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

@ -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

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

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

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

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

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

@ -282,11 +282,12 @@ func (c *ChartDownloader) getRepoCredentials(r *repo.ChartRepository) (username,
// name is the archive file name plus the ".prov" extension.
func VerifyChart(path, keyring string) (*provenance.Verification, error) {
// For now, error out if it's not a tar file.
if fi, err := os.Stat(path); err != nil {
switch fi, err := os.Stat(path); {
case err != nil:
return nil, err
} else if fi.IsDir() {
case fi.IsDir():
return nil, errors.New("unpacked charts cannot be verified")
} else if !isTar(path) {
case !isTar(path):
return nil, errors.New("chart must be a tgz file")
}
@ -307,7 +308,7 @@ func VerifyChart(path, keyring string) (*provenance.Verification, error) {
// Currently, this simply checks extension, since a subsequent function will
// untar the file and validate its binary format.
func isTar(filename string) bool {
return strings.ToLower(filepath.Ext(filename)) == ".tgz"
return strings.EqualFold(filepath.Ext(filename), ".tgz")
}
func pickChartRepositoryConfigByName(name string, cfgs []*repo.Entry) (*repo.Entry, error) {

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

@ -1,3 +1,4 @@
apiVersion: v1
name: albatross
description: testing chart
version: 199.44.12345-Alpha.1+cafe009

@ -1,3 +1,4 @@
apiVersion: v1
description: A Helm chart for Kubernetes
version: 0.0.0
home: ""

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

@ -1,3 +1,4 @@
apiVersion: v1
name: goodone
description: good testing chart
version: 199.44.12345-Alpha.1+cafe009

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

Loading…
Cancel
Save