From 4aff7431feaa0ab94ed16d36f0ed940db0ec3948 Mon Sep 17 00:00:00 2001 From: Phil Estes Date: Tue, 25 Jan 2022 14:11:20 -0500 Subject: [PATCH] Fix possibly incorrect media type default on import As reported, running import twice without using the compress import option means that the content store will have existing layers during the second import and the existing code hardcodes existing layer media type to compressed. This fixes the issue by actually reading the header bytes from the store and setting the media type appropriately. Signed-off-by: Phil Estes --- images/archive/importer.go | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/images/archive/importer.go b/images/archive/importer.go index 8afdd68f23a0..c53104950841 100644 --- a/images/archive/importer.go +++ b/images/archive/importer.go @@ -269,9 +269,13 @@ func resolveLayers(ctx context.Context, store content.Store, layerFiles []string if ok { desc := descs[digest.Digest(dgst)] if desc != nil { - desc.MediaType = images.MediaTypeDockerSchema2LayerGzip desc.Digest = info.Digest desc.Size = info.Size + mediaType, err := detectLayerMediaType(ctx, store, *desc) + if err != nil { + return fmt.Errorf("failed to detect media type of layer: %w", err) + } + desc.MediaType = mediaType } } return nil @@ -381,3 +385,29 @@ func writeManifest(ctx context.Context, cs content.Ingester, manifest interface{ return desc, nil } + +func detectLayerMediaType(ctx context.Context, store content.Store, desc ocispec.Descriptor) (string, error) { + var mediaType string + // need to parse existing blob to use the proper media type + bytes := make([]byte, 10) + ra, err := store.ReaderAt(ctx, desc) + if err != nil { + return "", fmt.Errorf("failed to read content store to detect layer media type: %w", err) + } + defer ra.Close() + _, err = ra.ReadAt(bytes, 0) + if err != nil && err != io.EOF { + return "", fmt.Errorf("failed to read header bytes from layer to detect media type: %w", err) + } + if err == io.EOF { + // in the case of an empty layer then the media type should be uncompressed + return images.MediaTypeDockerSchema2Layer, nil + } + switch c := compression.DetectCompression(bytes); c { + case compression.Uncompressed: + mediaType = images.MediaTypeDockerSchema2Layer + default: + mediaType = images.MediaTypeDockerSchema2LayerGzip + } + return mediaType, nil +}