fix(helm): chart install error when files or dirs of same name as chart present in CWD.

Signed-off-by: Alex Somesan <alex.somesan@gmail.com>
pull/13009/head
Alex Somesan 2 months ago
parent 1df00645e0
commit d5a77ac493

@ -737,7 +737,7 @@ func (c *ChartPathOptions) LocateChart(name string, settings *cli.EnvSettings) (
name = strings.TrimSpace(name)
version := strings.TrimSpace(c.Version)
if _, err := os.Stat(name); err == nil {
if chartAtPath(name) {
abs, err := filepath.Abs(name)
if err != nil {
return abs, err

@ -17,7 +17,13 @@ limitations under the License.
package action
import (
"archive/tar"
"compress/gzip"
"fmt"
"io"
"os"
"path/filepath"
"strings"
"github.com/pkg/errors"
apierrors "k8s.io/apimachinery/pkg/api/errors"
@ -182,3 +188,49 @@ func mergeStrStrMaps(current, desired map[string]string) map[string]string {
}
return result
}
func chartAtPath(path string) bool {
fi, err := os.Stat(path)
if err != nil {
// give up, can't do any of the other checks
return false
}
if fi.IsDir() {
// if path is a directory, check for Chart.yaml inside
cy, err := os.Stat(filepath.Join(path, "Chart.yaml"))
if err != nil {
// directory without a Chart.yaml is not a valid chart
return false
}
return cy.Mode().IsRegular()
}
if !fi.Mode().IsRegular() {
// if path isn't a regular file, it cannot be a valid chart
return false
}
// if path is a file, try to peek inside as an archive and look for Chart.yaml
buf, err := os.Open(path)
if err != nil {
return false
}
defer buf.Close()
gz, err := gzip.NewReader(buf)
if err != nil {
return false
}
tr := tar.NewReader(gz)
for {
hdr, err := tr.Next()
if err == io.EOF {
break // End of archive
}
if err != nil {
return false
}
_, f := filepath.Split(hdr.Name)
if strings.Compare(f, "Chart.yaml") == 0 {
return true
}
}
return false
}

@ -17,6 +17,11 @@ limitations under the License.
package action
import (
"archive/tar"
"compress/gzip"
"io"
"os"
"path/filepath"
"testing"
"helm.sh/helm/v3/pkg/kube"
@ -121,3 +126,97 @@ func TestSetMetadataVisitor(t *testing.T) {
assert.Error(t, err)
assert.Contains(t, err.Error(), `Deployment "baz" in namespace "" cannot be owned`)
}
func TestChartAtPath(t *testing.T) {
is := assert.New(t)
cases := map[string]struct{
path func() string
result bool
}{
"empty-dir": {
result: false,
path: func() string {
return t.TempDir()
},
},
"empty-file": {
result: false,
path: func() string {
fp := filepath.Join(t.TempDir(), "notachart")
f, err := os.Create(fp)
if err!= nil {
t.Skip()
}
f.Close()
return fp
},
},
"dir-with-chart-yaml": {
result: true,
path: func() string {
d := t.TempDir()
fp := filepath.Join(d, "Chart.yaml")
f, err := os.Create(fp)
if err!= nil {
t.Skip()
}
f.Close()
return d
},
},
"chart-archive": {
result: true,
path: func() string {
d1 := t.TempDir()
fp := filepath.Join(d1, "Chart.yaml")
f, err := os.Create(fp)
if err!= nil {
t.Skip()
}
f.Close()
d2 := t.TempDir()
ap := filepath.Join(d2, "chart.tar.gz")
ar, err := os.Create(ap)
if err!= nil {
t.Skip(err)
}
defer ar.Close()
gz := gzip.NewWriter(ar)
defer gz.Close()
tr := tar.NewWriter(gz)
defer tr.Close()
ch, err := os.Open(fp)
if err != nil {
t.Skip(err)
}
defer ch.Close()
fi, err := ch.Stat()
if err != nil {
t.Skip(err)
}
h := &tar.Header{
Name: fp,
Size: fi.Size(),
Mode: int64(fi.Mode()),
ModTime: fi.ModTime(),
}
err = tr.WriteHeader(h)
if err != nil {
t.Skip(err)
}
_, err = io.Copy(tr, ch)
if err != nil {
t.Skip(err)
}
return ap
},
},
}
for k, v := range cases {
t.Run(k, func(t *testing.T) {
is.Equal(chartAtPath(v.path()), v.result, k)
})
}
}
Loading…
Cancel
Save