diff --git a/pkg/crane/append.go b/pkg/crane/append.go index f1c2ef69a..0997322df 100644 --- a/pkg/crane/append.go +++ b/pkg/crane/append.go @@ -18,7 +18,9 @@ import ( "fmt" "os" + comp "github.com/google/go-containerregistry/internal/compression" "github.com/google/go-containerregistry/internal/windows" + "github.com/google/go-containerregistry/pkg/compression" v1 "github.com/google/go-containerregistry/pkg/v1" "github.com/google/go-containerregistry/pkg/v1/mutate" "github.com/google/go-containerregistry/pkg/v1/stream" @@ -50,13 +52,11 @@ func Append(base v1.Image, paths ...string) (v1.Image, error) { } baseMediaType, err := base.MediaType() - if err != nil { return nil, fmt.Errorf("getting base image media type: %w", err) } layerType := types.DockerLayer - if baseMediaType == types.OCIManifestSchema1 { layerType = types.OCILayer } @@ -90,6 +90,21 @@ func getLayer(path string, layerType types.MediaType) (v1.Layer, error) { return stream.NewLayer(f, stream.WithMediaType(layerType)), nil } + // This is dumb but the tarball package assumes things about mediaTypes that aren't true + // and doesn't have enough context to know what the right default is. + f, err = os.Open(path) + if err != nil { + return nil, err + } + defer f.Close() + z, _, err := comp.PeekCompression(f) + if err != nil { + return nil, err + } + if z == compression.ZStd { + layerType = types.OCILayerZStd + } + return tarball.LayerFromFile(path, tarball.WithMediaType(layerType)) } diff --git a/pkg/crane/append_test.go b/pkg/crane/append_test.go index d894a9dac..9312953e8 100644 --- a/pkg/crane/append_test.go +++ b/pkg/crane/append_test.go @@ -71,3 +71,28 @@ func TestAppendWithDockerBaseImage(t *testing.T) { t.Errorf("MediaType(): want %q, got %q", want, got) } } + +func TestAppendWithZstd(t *testing.T) { + base := mutate.MediaType(empty.Image, types.OCIManifestSchema1) + img, err := crane.Append(base, "testdata/content.tar.zst") + + if err != nil { + t.Fatalf("crane.Append(): %v", err) + } + + layers, err := img.Layers() + + if err != nil { + t.Fatalf("img.Layers(): %v", err) + } + + mediaType, err := layers[0].MediaType() + + if err != nil { + t.Fatalf("layers[0].MediaType(): %v", err) + } + + if got, want := mediaType, types.OCILayerZStd; got != want { + t.Errorf("MediaType(): want %q, got %q", want, got) + } +} diff --git a/pkg/crane/testdata/content.tar.zst b/pkg/crane/testdata/content.tar.zst new file mode 100644 index 000000000..6da62798d Binary files /dev/null and b/pkg/crane/testdata/content.tar.zst differ