Repository: helm/helm
Pull request #8751 (2020-09-17 17:22:12)

fixed bug that caused helm create to not overwrite modified files
Signed-off-by: Matt Butcher <matt.butcher@microsoft.com>

<!--  Thanks for sending a pull request!  Here are some tips for you:
1. Make sure to read the Contributing Guide before submitting your PR: https://github.com/helm/helm/blob/master/CONTRIBUTING.md
2. If this PR closes another issue, add 'closes #<issue number>' somewhere in the PR summary. GitHub will automatically close that issue when this PR gets merged. Alternatively, adding 'refs #<issue number>' will not close the issue, but help provide the reviewer more context.-->

**What this PR does / why we need it**:

Fix the create logic to do what the documentation already says it does: Overwrite files if found.

**Special notes for your reviewer**:

**If applicable**:
- [ ] this PR contains documentation
- [x] this PR contains unit tests
- [x] this PR has been tested for backwards compatibility



Patch:
diff --git a/cmd/helm/create.go b/cmd/helm/create.go
index 21a7e026c..fe5cc540a 100644
--- a/cmd/helm/create.go
+++ b/cmd/helm/create.go
@@ -107,6 +107,7 @@ func (o *createOptions) run(out io.Writer) error {
 		return chartutil.CreateFrom(cfile, filepath.Dir(o.name), lstarter)
 	}
 
+	chartutil.Stderr = out
 	_, err := chartutil.Create(chartname, filepath.Dir(o.name))
 	return err
 }
diff --git a/pkg/chartutil/create.go b/pkg/chartutil/create.go
index d4b65e9b8..86681247e 100644
--- a/pkg/chartutil/create.go
+++ b/pkg/chartutil/create.go
@@ -18,6 +18,7 @@ package chartutil
 
 import (
 	"fmt"
+	"io"
 	"io/ioutil"
 	"os"
 	"path/filepath"
@@ -479,6 +480,12 @@ spec:
   restartPolicy: Never
 `
 
+// Stderr is an io.Writer to which error messages can be written
+//
+// In Helm 4, this will be replaced. It is needed in Helm 3 to preserve API backward
+// compatibility.
+var Stderr io.Writer = os.Stderr
+
 // CreateFrom creates a new chart, but scaffolds it from the src chart.
 func CreateFrom(chartfile *chart.Metadata, dest, src string) error {
 	schart, err := loader.Load(src)
@@ -618,8 +625,8 @@ func Create(name, dir string) (string, error) {
 
 	for _, file := range files {
 		if _, err := os.Stat(file.path); err == nil {
-			// File exists and is okay. Skip it.
-			continue
+			// There is no handle to a preferred output stream here.
+			fmt.Fprintf(Stderr, "WARNING: File %q already exists. Overwriting.\n", file.path)
 		}
 		if err := writeFile(file.path, file.content); err != nil {
 			return cdir, err


Test patch:
diff --git a/pkg/chartutil/create_test.go b/pkg/chartutil/create_test.go
index f68ebbd63..9a473fc59 100644
--- a/pkg/chartutil/create_test.go
+++ b/pkg/chartutil/create_test.go
@@ -118,6 +118,45 @@ func TestCreateFrom(t *testing.T) {
 	}
 }
 
+// TestCreate_Overwrite is a regression test for making sure that files are overwritten.
+func TestCreate_Overwrite(t *testing.T) {
+	tdir, err := ioutil.TempDir("", "helm-")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer os.RemoveAll(tdir)
+
+	var errlog bytes.Buffer
+
+	if _, err := Create("foo", tdir); err != nil {
+		t.Fatal(err)
+	}
+
+	dir := filepath.Join(tdir, "foo")
+
+	tplname := filepath.Join(dir, "templates/hpa.yaml")
+	writeFile(tplname, []byte("FOO"))
+
+	// Now re-run the create
+	Stderr = &errlog
+	if _, err := Create("foo", tdir); err != nil {
+		t.Fatal(err)
+	}
+
+	data, err := ioutil.ReadFile(tplname)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if string(data) == "FOO" {
+		t.Fatal("File that should have been modified was not.")
+	}
+
+	if errlog.Len() == 0 {
+		t.Errorf("Expected warnings about overwriting files.")
+	}
+}
+
 func TestValidateChartName(t *testing.T) {
 	for name, shouldPass := range map[string]bool{
 		"":                              false,