image export: Use correct media type when creating new layer blobs. #1541
Conversation
tonistiigi
left a comment
There was a problem hiding this comment.
As we discussed in slack this should also use conversion between equivalent docker and oci layer types when manifest is created so the manifest always contains the correct information. Did you plan that as a separate PR? Tbh when we have that fix I don't think it would be very bad if differ always created oci types. The information about the mediatype that was used when blob was first created is kind of meaningless apart from the compression.
The fix in GetMediaTypeForLayers LGTM
| @@ -102,21 +102,30 @@ func detectCompressionType(cr io.Reader) (CompressionType, error) { | |||
|
|
|||
| // GetMediaTypeForLayers retrieves media type for layer from ref information. | |||
| func GetMediaTypeForLayers(diffPairs []DiffPair, ref cache.ImmutableRef) []string { | |||
There was a problem hiding this comment.
Add a comment that on error, slice with full length and partial data would be returned. This confused me in the beginning.
Ah okay, I think I slightly misunderstood originally. I thought I had addressed this already by including these lines but now that you mention it those lines won't handle the case where there is already a blob associated with a layer but the media type stored in cache metadata is different from what the exporter wants. I'll update to do the mediatype conversion on a higher level in the exporter rather than |
You can add a public helper function that takes an array of descriptors and makes sure they are either docker or oci. Then if someone calls |
| }); !ok { | ||
| cdAddress := sb.ContainerdAddress() | ||
| if cdAddress == "" { | ||
| return |
There was a problem hiding this comment.
could you mind to add some log for skip check? It will be nice to debug!
There was a problem hiding this comment.
Yeah good call, updated with that
There is a bug in the way images are pushed that results in oci types being used for layers even when docker types should be used, but only in single-layer images. Signed-off-by: Erik Sipsma <erik@sipsma.dev>
Makes sense, but when I went to actually make the updates for this PR I remembered that as it currently stands the exporter uses a slice of diffpairs and slice of mediatype strings rather than a slice of descriptors, so for now I updated this PR to have a public helper func |
| converted = toDockerLayerType[mediaType] | ||
| } | ||
| if converted == "" { | ||
| return "", fmt.Errorf("unhandled layer media type %q", mediaType) |
There was a problem hiding this comment.
I think ignoring error (and maybe printing the warning would be more appropriate). Especially because the conversion doesn't currently handle the alternative compressions (zstd etc).
| parent := tref.Parent() | ||
| tref.Release(context.TODO()) | ||
| tref = parent | ||
| } |
There was a problem hiding this comment.
in an odd case where parent chain length does not match the length of diffPairs (shouldn't happen) we should make sure we don't leave the tref referenced after returning.
|
Updated from all the comments, think travis just needs a retry due to |
| } | ||
|
|
||
| func (ic *ImageWriter) exportLayers(ctx context.Context, compression blobs.CompressionType, refs ...cache.ImmutableRef) ([][]blobs.DiffPair, error) { | ||
| func (ic *ImageWriter) exportLayers(ctx context.Context, compression blobs.CompressionType, oci bool, refs ...cache.ImmutableRef) ([][]blobs.DiffPair, error) { |
There are a few bugs in the image export related code being fixed here. GetMediaTypeForLayers was iterating over diffPairs in the wrong order, resulting in it always returning nil for images with more than one layer. This actually worked most of the time because it accidentally triggered a separate codepath meant to handle v0.6 migrations where mediatypes left empty get filled in. However, fixing that bug revealed another existing bug where the "oci" parameter in the image exporter was not being honored except when the v0.6 codepath got followed, resulting in images to always have oci layer media types even when docker types are used for the rest of the image descriptors. Due to the interaction between these various bugs, the only practical end effect previously was that single-layer images could use the wrong layer media type. An existing test has been expanded to cover that case in a previous commit. Signed-off-by: Erik Sipsma <erik@sipsma.dev>
Signed-off-by: Erik Sipsma <erik@sipsma.dev>
There are a few bugs in the image export related code being fixed here. GetMediaTypeForLayers was iterating over diffPairs in the wrong order, resulting in it always returning nil for images with more than one layer. This actually worked most of the time because it accidentally triggered a separate codepath meant to handle v0.6 migrations where mediatypes left empty get filled in. However, fixing that bug revealed another existing bug where the "oci" parameter in the image exporter was never passed to GetDiffPairs, resulting in newly created images to always have oci layer media types even when docker types are used for the rest of the image descriptors (manifests, config, etc.).
Due to the interaction between these various bugs, the only practical end effect previously was that single-layer images could incorrectly use oci layer media types when docker types were supposed to be used. An existing test has been expanded to cover that case in a previous commit.
Signed-off-by: Erik Sipsma erik@sipsma.dev
Note: This PR currently also includes the commits from #1538 so that tests can run in full. I'll rebase once #1538 is merged.