pull/32264/merge
Kartik Suryavanshi 3 months ago committed by GitHub
commit 048eeb93a1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -77,6 +77,10 @@ func LoadDir(dir string) (*chart.Chart, error) {
n = filepath.ToSlash(n) n = filepath.ToSlash(n)
if err != nil { if err != nil {
// For broken symlinks, respect .helmignore before erroring.
if os.IsNotExist(err) && fi != nil && rules.Ignore(n, fi) {
return nil
}
return err return err
} }
if fi.IsDir() { if fi.IsDir() {

@ -93,6 +93,96 @@ func TestLoadDirWithSymlink(t *testing.T) {
verifyDependenciesLock(t, c) verifyDependenciesLock(t, c)
} }
func TestLoadDirWithBrokenSymlinkNotInHelmignore(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("symlink tests require unix")
}
tmpDir := t.TempDir()
chartYAML := `apiVersion: v2
name: test
version: 0.1.0
`
valuesYAML := `{}
`
if err := os.WriteFile(filepath.Join(tmpDir, "Chart.yaml"), []byte(chartYAML), 0644); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(tmpDir, "values.yaml"), []byte(valuesYAML), 0644); err != nil {
t.Fatal(err)
}
// Create a broken symlink NOT listed in .helmignore
brokenLink := filepath.Join(tmpDir, "broken")
if err := os.Symlink("nonexistent", brokenLink); err != nil {
t.Fatal(err)
}
// Empty .helmignore — broken symlink is not ignored
if err := os.WriteFile(filepath.Join(tmpDir, ".helmignore"), []byte(""), 0644); err != nil {
t.Fatal(err)
}
l, err := Loader(tmpDir)
if err != nil {
t.Fatal(err)
}
if _, err := l.Load(); err == nil || !os.IsNotExist(err) {
t.Fatalf("expected broken symlink error (os.IsNotExist), got: %v", err)
}
}
func TestLoadDirWithBrokenSymlinkInHelmignore(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("symlink tests require unix")
}
tmpDir := t.TempDir()
// Create minimal chart structure
chartYAML := `apiVersion: v2
name: test
version: 0.1.0
`
valuesYAML := `{}
`
tpl := `config: {}
`
if err := os.WriteFile(filepath.Join(tmpDir, "Chart.yaml"), []byte(chartYAML), 0644); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(tmpDir, "values.yaml"), []byte(valuesYAML), 0644); err != nil {
t.Fatal(err)
}
if err := os.MkdirAll(filepath.Join(tmpDir, "templates"), 0755); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(tmpDir, "templates", "config.yaml"), []byte(tpl), 0644); err != nil {
t.Fatal(err)
}
// Create a broken symlink in templates/
brokenLink := filepath.Join(tmpDir, "templates", "broken")
if err := os.Symlink("nonexistent", brokenLink); err != nil {
t.Fatal(err)
}
// Add the broken symlink to .helmignore
if err := os.WriteFile(filepath.Join(tmpDir, ".helmignore"), []byte("templates/broken\n"), 0644); err != nil {
t.Fatal(err)
}
// Loading should succeed despite the broken symlink
l, err := Loader(tmpDir)
if err != nil {
t.Fatal(err)
}
if _, err := l.Load(); err != nil {
t.Fatalf("loading chart with broken symlink in .helmignore should not fail: %s", err)
}
}
func TestBomTestData(t *testing.T) { func TestBomTestData(t *testing.T) {
testFiles := []string{"frobnitz_with_bom/.helmignore", "frobnitz_with_bom/templates/template.tpl", "frobnitz_with_bom/Chart.yaml"} testFiles := []string{"frobnitz_with_bom/.helmignore", "frobnitz_with_bom/templates/template.tpl", "frobnitz_with_bom/Chart.yaml"}
for _, file := range testFiles { for _, file := range testFiles {

@ -21,7 +21,6 @@ limitations under the License.
package sympath package sympath
import ( import (
"fmt"
"log/slog" "log/slog"
"os" "os"
"path/filepath" "path/filepath"
@ -68,12 +67,17 @@ func symwalk(path string, info os.FileInfo, walkFn filepath.WalkFunc) error {
if IsSymlink(info) { if IsSymlink(info) {
resolved, err := filepath.EvalSymlinks(path) resolved, err := filepath.EvalSymlinks(path)
if err != nil { if err != nil {
return fmt.Errorf("error evaluating symlink %s: %w", path, err) // Pass the error to walkFn so callers (e.g. chart loaders)
// can decide whether to skip it based on .helmignore rules.
return walkFn(path, info, err)
} }
// This log message is to highlight a symlink that is being used within a chart, symlinks can be used for nefarious reasons. // This log message is to highlight a symlink that is being used within a chart, symlinks can be used for nefarious reasons.
slog.Info("found symbolic link in path. Contents of linked file included and used", "path", path, "resolved", resolved) slog.Info("found symbolic link in path. Contents of linked file included and used", "path", path, "resolved", resolved)
originalInfo := info
if info, err = os.Lstat(resolved); err != nil { if info, err = os.Lstat(resolved); err != nil {
return err // Route through walkFn with the original symlink info so callers
// can decide whether to skip it based on .helmignore rules.
return walkFn(path, originalInfo, err)
} }
if err := symwalk(path, info, walkFn); err != nil && err != filepath.SkipDir { if err := symwalk(path, info, walkFn); err != nil && err != filepath.SkipDir {
return err return err

@ -77,6 +77,10 @@ func LoadDir(dir string) (*chart.Chart, error) {
n = filepath.ToSlash(n) n = filepath.ToSlash(n)
if err != nil { if err != nil {
// For broken symlinks, respect .helmignore before erroring.
if os.IsNotExist(err) && fi != nil && rules.Ignore(n, fi) {
return nil
}
return err return err
} }
if fi.IsDir() { if fi.IsDir() {

@ -92,6 +92,96 @@ func TestLoadDirWithSymlink(t *testing.T) {
verifyDependenciesLock(t, c) verifyDependenciesLock(t, c)
} }
func TestLoadDirWithBrokenSymlinkNotInHelmignore(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("symlink tests require unix")
}
tmpDir := t.TempDir()
chartYAML := `apiVersion: v2
name: test
version: 0.1.0
`
valuesYAML := `{}
`
if err := os.WriteFile(filepath.Join(tmpDir, "Chart.yaml"), []byte(chartYAML), 0644); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(tmpDir, "values.yaml"), []byte(valuesYAML), 0644); err != nil {
t.Fatal(err)
}
// Create a broken symlink NOT listed in .helmignore
brokenLink := filepath.Join(tmpDir, "broken")
if err := os.Symlink("nonexistent", brokenLink); err != nil {
t.Fatal(err)
}
// Empty .helmignore — broken symlink is not ignored
if err := os.WriteFile(filepath.Join(tmpDir, ".helmignore"), []byte(""), 0644); err != nil {
t.Fatal(err)
}
l, err := Loader(tmpDir)
if err != nil {
t.Fatal(err)
}
if _, err := l.Load(); err == nil || !os.IsNotExist(err) {
t.Fatalf("expected broken symlink error (os.IsNotExist), got: %v", err)
}
}
func TestLoadDirWithBrokenSymlinkInHelmignore(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("symlink tests require unix")
}
tmpDir := t.TempDir()
// Create minimal chart structure
chartYAML := `apiVersion: v2
name: test
version: 0.1.0
`
valuesYAML := `{}
`
tpl := `config: {}
`
if err := os.WriteFile(filepath.Join(tmpDir, "Chart.yaml"), []byte(chartYAML), 0644); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(tmpDir, "values.yaml"), []byte(valuesYAML), 0644); err != nil {
t.Fatal(err)
}
if err := os.MkdirAll(filepath.Join(tmpDir, "templates"), 0755); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(tmpDir, "templates", "config.yaml"), []byte(tpl), 0644); err != nil {
t.Fatal(err)
}
// Create a broken symlink in templates/
brokenLink := filepath.Join(tmpDir, "templates", "broken")
if err := os.Symlink("nonexistent", brokenLink); err != nil {
t.Fatal(err)
}
// Add the broken symlink to .helmignore
if err := os.WriteFile(filepath.Join(tmpDir, ".helmignore"), []byte("templates/broken\n"), 0644); err != nil {
t.Fatal(err)
}
// Loading should succeed despite the broken symlink
l, err := Loader(tmpDir)
if err != nil {
t.Fatal(err)
}
if _, err := l.Load(); err != nil {
t.Fatalf("loading chart with broken symlink in .helmignore should not fail: %s", err)
}
}
func TestBomTestData(t *testing.T) { func TestBomTestData(t *testing.T) {
testFiles := []string{"frobnitz_with_bom/.helmignore", "frobnitz_with_bom/templates/template.tpl", "frobnitz_with_bom/Chart.yaml"} testFiles := []string{"frobnitz_with_bom/.helmignore", "frobnitz_with_bom/templates/template.tpl", "frobnitz_with_bom/Chart.yaml"}
for _, file := range testFiles { for _, file := range testFiles {

Loading…
Cancel
Save