From 8b050bb9ea4838fbf834b4c3bc74a371a98ab7c9 Mon Sep 17 00:00:00 2001 From: quantumsheep Date: Wed, 23 Jun 2021 11:55:53 +0200 Subject: [PATCH] Add --directory/-d options to `helm create` Signed-off-by: quantumsheep --- cmd/helm/create.go | 11 +++++++-- cmd/helm/create_test.go | 14 ++++++------ pkg/chartutil/create.go | 44 ++++++++++++++++-------------------- pkg/chartutil/create_test.go | 29 +++++++++++------------- pkg/chartutil/save.go | 8 +++++++ pkg/lint/lint_test.go | 4 +++- 6 files changed, 60 insertions(+), 50 deletions(-) diff --git a/cmd/helm/create.go b/cmd/helm/create.go index fe5cc540a..f37a5d387 100644 --- a/cmd/helm/create.go +++ b/cmd/helm/create.go @@ -52,6 +52,7 @@ will be overwritten, but other files will be left alone. type createOptions struct { starter string // --starter + directory string // --directory name string starterDir string } @@ -81,6 +82,7 @@ func newCreateCmd(out io.Writer) *cobra.Command { } cmd.Flags().StringVarP(&o.starter, "starter", "p", "", "the name or absolute path to Helm starter scaffold") + cmd.Flags().StringVarP(&o.directory, "directory", "d", "", "the location of the created chart") return cmd } @@ -97,6 +99,11 @@ func (o *createOptions) run(out io.Writer) error { APIVersion: chart.APIVersionV2, } + destination := o.directory + if destination == "" { + destination = o.name + } + if o.starter != "" { // Create from the starter lstarter := filepath.Join(o.starterDir, o.starter) @@ -104,10 +111,10 @@ func (o *createOptions) run(out io.Writer) error { if filepath.IsAbs(o.starter) { lstarter = o.starter } - return chartutil.CreateFrom(cfile, filepath.Dir(o.name), lstarter) + return chartutil.CreateFrom(cfile, destination, lstarter) } chartutil.Stderr = out - _, err := chartutil.Create(chartname, filepath.Dir(o.name)) + _, err := chartutil.Create(chartname, destination) return err } diff --git a/cmd/helm/create_test.go b/cmd/helm/create_test.go index 1db6bed52..60a568d11 100644 --- a/cmd/helm/create_test.go +++ b/cmd/helm/create_test.go @@ -71,12 +71,13 @@ func TestCreateStarterCmd(t *testing.T) { // Create a starter. starterchart := helmpath.DataPath("starters") os.MkdirAll(starterchart, 0755) - if dest, err := chartutil.Create("starterchart", starterchart); err != nil { + destination := filepath.Join(starterchart, "starterchart") + if dest, err := chartutil.Create("starterchart", destination); err != nil { t.Fatalf("Could not create chart: %s", err) } else { t.Logf("Created %s", dest) } - tplpath := filepath.Join(starterchart, "starterchart", "templates", "foo.tpl") + tplpath := filepath.Join(destination, "templates", "foo.tpl") if err := ioutil.WriteFile(tplpath, []byte("test"), 0644); err != nil { t.Fatalf("Could not write template: %s", err) } @@ -134,12 +135,13 @@ func TestCreateStarterAbsoluteCmd(t *testing.T) { // Create a starter. starterchart := helmpath.DataPath("starters") os.MkdirAll(starterchart, 0755) - if dest, err := chartutil.Create("starterchart", starterchart); err != nil { + destination := filepath.Join(starterchart, "starterchart") + if dest, err := chartutil.Create("starterchart", destination); err != nil { t.Fatalf("Could not create chart: %s", err) } else { t.Logf("Created %s", dest) } - tplpath := filepath.Join(starterchart, "starterchart", "templates", "foo.tpl") + tplpath := filepath.Join(destination, "templates", "foo.tpl") if err := ioutil.WriteFile(tplpath, []byte("test"), 0644); err != nil { t.Fatalf("Could not write template: %s", err) } @@ -147,10 +149,8 @@ func TestCreateStarterAbsoluteCmd(t *testing.T) { os.MkdirAll(helmpath.CachePath(), 0755) defer testChdir(t, helmpath.CachePath())() - starterChartPath := filepath.Join(starterchart, "starterchart") - // Run a create - if _, _, err := executeActionCommand(fmt.Sprintf("create --starter=%s %s", starterChartPath, cname)); err != nil { + if _, _, err := executeActionCommand(fmt.Sprintf("create --starter=%s %s", destination, cname)); err != nil { t.Errorf("Failed to run create: %s", err) return } diff --git a/pkg/chartutil/create.go b/pkg/chartutil/create.go index ca79e7ab2..ad8a6ca07 100644 --- a/pkg/chartutil/create.go +++ b/pkg/chartutil/create.go @@ -547,7 +547,7 @@ func CreateFrom(chartfile *chart.Metadata, dest, src string) error { } } - return SaveDir(schart, dest) + return SaveDirCustom(schart, dest) } // Create creates a new chart in a directory. @@ -575,15 +575,11 @@ func Create(name, dir string) (string, error) { return path, err } - if fi, err := os.Stat(path); err != nil { - return path, err + parentPath := filepath.Dir(path) + if fi, err := os.Stat(parentPath); err != nil { + return parentPath, err } else if !fi.IsDir() { - return path, errors.Errorf("no such directory %s", path) - } - - cdir := filepath.Join(path, name) - if fi, err := os.Stat(cdir); err == nil && !fi.IsDir() { - return cdir, errors.Errorf("file %s already exists and is not a directory", cdir) + return parentPath, errors.Errorf("no such directory %s", parentPath) } files := []struct { @@ -592,57 +588,57 @@ func Create(name, dir string) (string, error) { }{ { // Chart.yaml - path: filepath.Join(cdir, ChartfileName), + path: filepath.Join(path, ChartfileName), content: []byte(fmt.Sprintf(defaultChartfile, name)), }, { // values.yaml - path: filepath.Join(cdir, ValuesfileName), + path: filepath.Join(path, ValuesfileName), content: []byte(fmt.Sprintf(defaultValues, name)), }, { // .helmignore - path: filepath.Join(cdir, IgnorefileName), + path: filepath.Join(path, IgnorefileName), content: []byte(defaultIgnore), }, { // ingress.yaml - path: filepath.Join(cdir, IngressFileName), + path: filepath.Join(path, IngressFileName), content: transform(defaultIngress, name), }, { // deployment.yaml - path: filepath.Join(cdir, DeploymentName), + path: filepath.Join(path, DeploymentName), content: transform(defaultDeployment, name), }, { // service.yaml - path: filepath.Join(cdir, ServiceName), + path: filepath.Join(path, ServiceName), content: transform(defaultService, name), }, { // serviceaccount.yaml - path: filepath.Join(cdir, ServiceAccountName), + path: filepath.Join(path, ServiceAccountName), content: transform(defaultServiceAccount, name), }, { // hpa.yaml - path: filepath.Join(cdir, HorizontalPodAutoscalerName), + path: filepath.Join(path, HorizontalPodAutoscalerName), content: transform(defaultHorizontalPodAutoscaler, name), }, { // NOTES.txt - path: filepath.Join(cdir, NotesName), + path: filepath.Join(path, NotesName), content: transform(defaultNotes, name), }, { // _helpers.tpl - path: filepath.Join(cdir, HelpersName), + path: filepath.Join(path, HelpersName), content: transform(defaultHelpers, name), }, { // test-connection.yaml - path: filepath.Join(cdir, TestConnectionName), + path: filepath.Join(path, TestConnectionName), content: transform(defaultTestConnection, name), }, } @@ -653,14 +649,14 @@ func Create(name, dir string) (string, error) { fmt.Fprintf(Stderr, "WARNING: File %q already exists. Overwriting.\n", file.path) } if err := writeFile(file.path, file.content); err != nil { - return cdir, err + return path, err } } // Need to add the ChartsDir explicitly as it does not contain any file OOTB - if err := os.MkdirAll(filepath.Join(cdir, ChartsDir), 0755); err != nil { - return cdir, err + if err := os.MkdirAll(filepath.Join(path, ChartsDir), 0755); err != nil { + return path, err } - return cdir, nil + return path, nil } // transform performs a string replacement of the specified source for diff --git a/pkg/chartutil/create_test.go b/pkg/chartutil/create_test.go index 9a473fc59..507babd3c 100644 --- a/pkg/chartutil/create_test.go +++ b/pkg/chartutil/create_test.go @@ -34,13 +34,12 @@ func TestCreate(t *testing.T) { } defer os.RemoveAll(tdir) - c, err := Create("foo", tdir) + destination := filepath.Join(tdir, "foo") + c, err := Create("foo", destination) if err != nil { t.Fatal(err) } - dir := filepath.Join(tdir, "foo") - mychart, err := loader.LoadDir(c) if err != nil { t.Fatalf("Failed to load newly created chart %q: %s", c, err) @@ -63,7 +62,7 @@ func TestCreate(t *testing.T) { TestConnectionName, ValuesfileName, } { - if _, err := os.Stat(filepath.Join(dir, f)); err != nil { + if _, err := os.Stat(filepath.Join(destination, f)); err != nil { t.Errorf("Expected %s file: %s", f, err) } } @@ -83,15 +82,14 @@ func TestCreateFrom(t *testing.T) { } srcdir := "./testdata/frobnitz/charts/mariner" - if err := CreateFrom(cf, tdir, srcdir); err != nil { + destination := filepath.Join(tdir, cf.Name) + if err := CreateFrom(cf, destination, srcdir); err != nil { t.Fatal(err) } - dir := filepath.Join(tdir, "foo") - c := filepath.Join(tdir, cf.Name) - mychart, err := loader.LoadDir(c) + mychart, err := loader.LoadDir(destination) if err != nil { - t.Fatalf("Failed to load newly created chart %q: %s", c, err) + t.Fatalf("Failed to load newly created chart %q: %s", destination, err) } if mychart.Name() != "foo" { @@ -103,12 +101,12 @@ func TestCreateFrom(t *testing.T) { ValuesfileName, filepath.Join(TemplatesDir, "placeholder.tpl"), } { - if _, err := os.Stat(filepath.Join(dir, f)); err != nil { + if _, err := os.Stat(filepath.Join(destination, f)); err != nil { t.Errorf("Expected %s file: %s", f, err) } // Check each file to make sure has been replaced - b, err := ioutil.ReadFile(filepath.Join(dir, f)) + b, err := ioutil.ReadFile(filepath.Join(destination, f)) if err != nil { t.Errorf("Unable to read file %s: %s", f, err) } @@ -128,18 +126,17 @@ func TestCreate_Overwrite(t *testing.T) { var errlog bytes.Buffer - if _, err := Create("foo", tdir); err != nil { + destination := filepath.Join(tdir, "foo") + if _, err := Create("foo", destination); err != nil { t.Fatal(err) } - dir := filepath.Join(tdir, "foo") - - tplname := filepath.Join(dir, "templates/hpa.yaml") + tplname := filepath.Join(destination, "templates/hpa.yaml") writeFile(tplname, []byte("FOO")) // Now re-run the create Stderr = &errlog - if _, err := Create("foo", tdir); err != nil { + if _, err := Create("foo", destination); err != nil { t.Fatal(err) } diff --git a/pkg/chartutil/save.go b/pkg/chartutil/save.go index 2ce4eddaf..aff0055ac 100644 --- a/pkg/chartutil/save.go +++ b/pkg/chartutil/save.go @@ -40,6 +40,14 @@ var headerBytes = []byte("+aHR0cHM6Ly95b3V0dS5iZS96OVV6MWljandyTQo=") func SaveDir(c *chart.Chart, dest string) error { // Create the chart directory outdir := filepath.Join(dest, c.Name()) + return SaveDirCustom(c, outdir) +} + +// SaveDirCustom saves a chart as files in a custom directory. +// +// This takes the chart name and the output directory, writing the chart's contents +// to that directory. +func SaveDirCustom(c *chart.Chart, outdir string) error { if fi, err := os.Stat(outdir); err == nil && !fi.IsDir() { return errors.Errorf("file %s already exists and is not a directory", outdir) } diff --git a/pkg/lint/lint_test.go b/pkg/lint/lint_test.go index 29ed67026..0a75b12c4 100644 --- a/pkg/lint/lint_test.go +++ b/pkg/lint/lint_test.go @@ -19,6 +19,7 @@ package lint import ( "io/ioutil" "os" + "path/filepath" "strings" "testing" @@ -125,7 +126,8 @@ func TestHelmCreateChart(t *testing.T) { } defer os.RemoveAll(dir) - createdChart, err := chartutil.Create("testhelmcreatepasseslint", dir) + destination := filepath.Join(dir, "testhelmcreatepasseslint") + createdChart, err := chartutil.Create("testhelmcreatepasseslint", destination) if err != nil { t.Error(err) // Fatal is bad because of the defer.