From 0f589254f192389d2160743dc08a30be3d5ea975 Mon Sep 17 00:00:00 2001 From: frenchben Date: Thu, 23 Sep 2021 17:58:57 -0700 Subject: [PATCH] Add signing of package without tgz Signed-off-by: frenchben --- cmd/helm/package.go | 2 +- pkg/action/package.go | 78 ++++++++++++++++++++++++-------------- pkg/action/package_test.go | 45 ++++++++++++++++++++++ 3 files changed, 95 insertions(+), 30 deletions(-) diff --git a/cmd/helm/package.go b/cmd/helm/package.go index 7134a8784..a118ecde7 100644 --- a/cmd/helm/package.go +++ b/cmd/helm/package.go @@ -112,7 +112,7 @@ func newPackageCmd(out io.Writer) *cobra.Command { f := cmd.Flags() f.BoolVar(&client.Sign, "sign", false, "use a PGP private key to sign this package") - f.StringVar(&client.Key, "key", "", "name of the key to use when signing. Used if --sign is true") + f.StringVar(&client.Key, "key", "", "name of the key to use when signing. Used if --sign, or --sign-tgz, is true") f.StringVar(&client.Keyring, "keyring", defaultKeyring(), "location of a public keyring") f.StringVar(&client.PassphraseFile, "passphrase-file", "", `location of a file which contains the passphrase for the signing key. Use "-" in order to read from stdin.`) f.StringVar(&client.Version, "version", "", "set the version on the chart to this semver version") diff --git a/pkg/action/package.go b/pkg/action/package.go index 52920956f..01533dbaf 100644 --- a/pkg/action/package.go +++ b/pkg/action/package.go @@ -21,6 +21,8 @@ import ( "fmt" "io/ioutil" "os" + "path/filepath" + "strings" "syscall" "github.com/Masterminds/semver/v3" @@ -56,45 +58,51 @@ func NewPackage() *Package { // Run executes 'helm package' against the given chart and returns the path to the packaged chart. func (p *Package) Run(path string, vals map[string]interface{}) (string, error) { - ch, err := loader.LoadDir(path) + err := validatePackage(path) + var name string if err != nil { - return "", err - } + ch, err := loader.LoadDir(path) + if err != nil { + return "", err + } - // If version is set, modify the version. - if p.Version != "" { - ch.Metadata.Version = p.Version - } + // If version is set, modify the version. + if p.Version != "" { + ch.Metadata.Version = p.Version + } - if err := validateVersion(ch.Metadata.Version); err != nil { - return "", err - } + if err := validateVersion(ch.Metadata.Version); err != nil { + return "", err + } - if p.AppVersion != "" { - ch.Metadata.AppVersion = p.AppVersion - } + if p.AppVersion != "" { + ch.Metadata.AppVersion = p.AppVersion + } - if reqs := ch.Metadata.Dependencies; reqs != nil { - if err := CheckDependencies(ch, reqs); err != nil { - return "", err + if reqs := ch.Metadata.Dependencies; reqs != nil { + if err := CheckDependencies(ch, reqs); err != nil { + return "", err + } + } + + var dest string + if p.Destination == "." { + // Save to the current working directory. + dest, err = os.Getwd() + if err != nil { + return "", err + } + } else { + // Otherwise save to set destination + dest = p.Destination } - } - var dest string - if p.Destination == "." { - // Save to the current working directory. - dest, err = os.Getwd() + name, err = chartutil.Save(ch, dest) if err != nil { - return "", err + return "", errors.Wrap(err, "failed to save") } } else { - // Otherwise save to set destination - dest = p.Destination - } - - name, err := chartutil.Save(ch, dest) - if err != nil { - return "", errors.Wrap(err, "failed to save") + name = path } if p.Sign { @@ -104,6 +112,18 @@ func (p *Package) Run(path string, vals map[string]interface{}) (string, error) return name, err } +func validatePackage(filename string) error { + switch fi, err := os.Stat(filename); { + case err != nil: + return err + case fi.IsDir(): + return errors.New("filename is a folder") + case strings.EqualFold(filepath.Ext(filename), ".tgz"): + return nil + } + return errors.New("chart must be a tgz file") +} + // validateVersion Verify that version is a Version, and error out if it is not. func validateVersion(ver string) error { if _, err := semver.NewVersion(ver); err != nil { diff --git a/pkg/action/package_test.go b/pkg/action/package_test.go index 5c5fed571..4d18a9dfc 100644 --- a/pkg/action/package_test.go +++ b/pkg/action/package_test.go @@ -22,6 +22,8 @@ import ( "path" "testing" + "github.com/pkg/errors" + "github.com/Masterminds/semver/v3" "helm.sh/helm/v3/internal/test/ensure" @@ -123,3 +125,46 @@ func TestValidateVersion(t *testing.T) { }) } } + +func TestValidatePackage(t *testing.T) { + tests := []struct { + name string + path string + wantErr error + }{ + { + "normal package", + "testdata/charts/compressedchart-0.1.0.tgz", + nil, + }, + { + "invalid archived path", + "testdata/charts/invalidcompressedchart0.1.0.tgz", + errors.New("stat testdata/charts/invalidcompressedchart0.1.0.tgz: no such file or directory"), + }, + { + "non-helm created package", + "testdata/charts/compressedchart-0.1.0.tar.gz", + errors.New("chart must be a tgz file"), + }, + { + "path is a folder", + "testdata/charts/", + errors.New("chart must be a tgz file"), + }, + { + "path is a file", + "testdata/charts/decompressedchart/Chart.yaml", + errors.New("chart must be a tgz file"), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := validatePackage(tt.path); err != nil { + if err != tt.wantErr { + t.Errorf("Expected {%v}, got {%v}", tt.wantErr, err) + } + } + }) + } +}