Skip to content

Commit 7893989

Browse files
authored
Merge pull request #814 from bashSunny101/fix/helm-uncompressed-tar-error
files: improve error for uncompressed Helm .tar archives
2 parents 7d68732 + 81b3982 commit 7893989

File tree

3 files changed

+78
-3
lines changed

3 files changed

+78
-3
lines changed

files/error.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ var (
3838
ErrInvalidHelmChartCode = "meshkit-11292"
3939
ErrInvalidDockerComposeCode = "meshkit-11293"
4040
ErrInvalidKustomizationCode = "meshkit-11294"
41+
ErrUncompressedTarCode = "meshkit-11305"
4142
ErrFileTypeNotSupportedForDesignConversionCode = "meshkit-11300"
4243
)
4344

@@ -260,6 +261,22 @@ func ErrInvalidHelmChart(fileName string, err error) error {
260261
return errors.New(ErrInvalidHelmChartCode, errors.Critical, sdescription, ldescription, probableCause, remedy)
261262
}
262263

264+
// ErrUncompressedTar returns an error explaining that Helm requires
265+
// compressed tarballs (tgz / tar.gz) and that an uncompressed .tar was provided.
266+
func ErrUncompressedTar(fileName string, err error) error {
267+
return errors.New(
268+
ErrUncompressedTarCode,
269+
errors.Critical,
270+
[]string{fmt.Sprintf("The file '%s' appears to be an uncompressed TAR archive.", fileName)},
271+
[]string{fmt.Sprintf("Expected archives to be compressed (e.g., .tgz or .tar.gz). Error details: %s", err.Error())},
272+
[]string{"The archive was created as an uncompressed .tar, but archives required to be compressed."},
273+
[]string{
274+
"Compress the .tar file to .tgz or .tar.gz and try again.",
275+
"If it is a Helm chart archive, create using 'helm package' or gzip the archive before uploading.",
276+
},
277+
)
278+
}
279+
263280
func ErrInvalidDockerCompose(fileName string, err error) error {
264281
sdescription := []string{
265282
fmt.Sprintf("The file '%s' is not a valid Docker Compose file.", fileName),

files/identification.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ package files
33
import (
44
"bytes"
55
"encoding/json"
6+
"errors"
67
"fmt"
78
"io"
89
"os"
910
"path/filepath"
1011
"strings"
12+
"compress/gzip"
1113

1214
"github.com/meshery/meshkit/encoding"
1315
"github.com/meshery/meshkit/models/oci"
@@ -298,11 +300,16 @@ func ParseFileAsHelmChart(file SanitizedFile) (*chart.Chart, error) {
298300
return nil, fmt.Errorf("Invalid file extension %s", file.FileExt)
299301
}
300302

301-
// Use Helm's loader.LoadDir to load the chart
302-
// This function automatically handles nested directories and locates Chart.yaml
303+
// Use Helm's loader.LoadArchive to load the chart
304+
// This function expects a gzipped tar archive for charts (tgz / tar.gz)
303305
chart, err := loader.LoadArchive(bytes.NewReader(file.RawData))
304306
if err != nil {
305-
return nil, fmt.Errorf("failed to load Helm chart %v", err)
307+
// If the file extension was an uncompressed .tar and the loader failed
308+
// due to gzip/invalid header, provide a human friendly hint.
309+
if file.FileExt == ".tar" && errors.Is(err, gzip.ErrHeader) {
310+
return nil, ErrUncompressedTar(file.FileName, err)
311+
}
312+
return nil, ErrInvalidHelmChart(file.FileName, err)
306313
}
307314

308315
// Validate the chart (optional but recommended)

files/tests/sanitization_test.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
package files_test
22

33
import (
4+
"archive/tar"
5+
"bytes"
46
"os"
57
"path/filepath"
68
"testing"
79

810
"github.com/meshery/meshkit/errors"
911
"github.com/meshery/meshkit/files"
12+
"github.com/stretchr/testify/assert"
1013
coreV1 "github.com/meshery/schemas/models/v1alpha1/core"
1114
)
1215

@@ -192,3 +195,51 @@ func TestSanitizeFile(t *testing.T) {
192195
})
193196
}
194197
}
198+
199+
// Test that providing an uncompressed .tar containing a Helm chart yields the
200+
// helpful ErrUncompressedTar (which uses ErrInvalidHelmChartCode).
201+
func TestUncompressedHelmTarError(t *testing.T) {
202+
// Build an in-memory uncompressed tar with a Chart.yaml
203+
var buf bytes.Buffer
204+
tw := tar.NewWriter(&buf)
205+
chartYAML := []byte("apiVersion: v2\nname: test-chart\nversion: 0.1.0\n")
206+
hdr := &tar.Header{
207+
Name: "Chart.yaml",
208+
Mode: 0600,
209+
Size: int64(len(chartYAML)),
210+
}
211+
if err := tw.WriteHeader(hdr); err != nil {
212+
t.Fatalf("failed to write tar header: %v", err)
213+
}
214+
if _, err := tw.Write(chartYAML); err != nil {
215+
t.Fatalf("failed to write chart content: %v", err)
216+
}
217+
if err := tw.Close(); err != nil {
218+
t.Fatalf("failed to close tar writer: %v", err)
219+
}
220+
221+
tempDir, err := os.MkdirTemp("", "temp-tests")
222+
if err != nil {
223+
t.Fatalf("failed to create temp directory: %v", err)
224+
}
225+
defer os.RemoveAll(tempDir)
226+
227+
validExts := map[string]bool{
228+
".json": true,
229+
".yml": true,
230+
".yaml": true,
231+
".tar": true,
232+
".tgz": true,
233+
".gz": true,
234+
".zip": true,
235+
}
236+
237+
sanitized, err := files.SanitizeFile(buf.Bytes(), "uncompressed-helm.tar", tempDir, validExts)
238+
if err != nil {
239+
t.Fatalf("unexpected sanitize error: %v", err)
240+
}
241+
242+
_, err = files.ParseFileAsHelmChart(sanitized)
243+
assert.NotNil(t, err)
244+
assert.Equal(t, files.ErrUncompressedTarCode, errors.GetCode(err))
245+
}

0 commit comments

Comments
 (0)