Browse code

Use docker media type for plugin layers

This was changed as part of a refactor to use containerd dist code. The
problem is the OCI media types are not compatible with older versions of
Docker.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
(cherry picked from commit a876ede24f4c6e13717f56897fb34f6c73914602)
Signed-off-by: Brian Goff <cpuguy83@gmail.com>

Brian Goff authored on 2021/03/27 07:07:41
Showing 2 changed files
... ...
@@ -15,12 +15,17 @@ import (
15 15
 	"strings"
16 16
 	"testing"
17 17
 
18
+	"github.com/containerd/containerd/images"
19
+	"github.com/containerd/containerd/remotes/docker"
18 20
 	"github.com/docker/docker/api/types"
21
+	"github.com/docker/docker/pkg/jsonmessage"
19 22
 	"github.com/docker/docker/testutil/daemon"
20 23
 	"github.com/docker/docker/testutil/fixtures/plugin"
21 24
 	"github.com/docker/docker/testutil/registry"
22 25
 	"github.com/docker/docker/testutil/request"
26
+	v1 "github.com/opencontainers/image-spec/specs-go/v1"
23 27
 	"gotest.tools/v3/assert"
28
+	"gotest.tools/v3/assert/cmp"
24 29
 	is "gotest.tools/v3/assert/cmp"
25 30
 	"gotest.tools/v3/skip"
26 31
 )
... ...
@@ -223,3 +228,61 @@ func TestPluginsWithRuntimes(t *testing.T) {
223 223
 		assert.NilError(t, err)
224 224
 	})
225 225
 }
226
+
227
+func TestPluginBackCompatMediaTypes(t *testing.T) {
228
+	skip.If(t, testEnv.IsRemoteDaemon, "cannot run daemon when remote daemon")
229
+	skip.If(t, testEnv.OSType == "windows")
230
+	skip.If(t, testEnv.IsRootless, "Rootless has a different view of localhost (needed for test registry access)")
231
+
232
+	defer setupTest(t)()
233
+
234
+	reg := registry.NewV2(t)
235
+	defer reg.Close()
236
+	reg.WaitReady(t)
237
+
238
+	repo := path.Join(registry.DefaultURL, strings.ToLower(t.Name())+":latest")
239
+
240
+	client := testEnv.APIClient()
241
+
242
+	ctx := context.Background()
243
+	assert.NilError(t, plugin.Create(ctx, client, repo))
244
+
245
+	rdr, err := client.PluginPush(ctx, repo, "")
246
+	assert.NilError(t, err)
247
+	defer rdr.Close()
248
+
249
+	buf := &strings.Builder{}
250
+	assert.NilError(t, jsonmessage.DisplayJSONMessagesStream(rdr, buf, 0, false, nil), buf)
251
+
252
+	// Use custom header here because older versions of the registry do not
253
+	// parse the accept header correctly and does not like the accept header
254
+	// that the default resolver code uses. "Older registries" here would be
255
+	// like the one currently included in the test suite.
256
+	headers := http.Header{}
257
+	headers.Add("Accept", images.MediaTypeDockerSchema2Manifest)
258
+
259
+	resolver := docker.NewResolver(docker.ResolverOptions{
260
+		Headers: headers,
261
+	})
262
+	assert.NilError(t, err)
263
+
264
+	n, desc, err := resolver.Resolve(ctx, repo)
265
+	assert.NilError(t, err, repo)
266
+
267
+	fetcher, err := resolver.Fetcher(ctx, n)
268
+	assert.NilError(t, err)
269
+
270
+	rdr, err = fetcher.Fetch(ctx, desc)
271
+	assert.NilError(t, err)
272
+	defer rdr.Close()
273
+
274
+	type manifest struct {
275
+		MediaType string
276
+		v1.Manifest
277
+	}
278
+	var m manifest
279
+	assert.NilError(t, json.NewDecoder(rdr).Decode(&m))
280
+	assert.Check(t, cmp.Equal(m.MediaType, images.MediaTypeDockerSchema2Manifest))
281
+	assert.Check(t, cmp.Len(m.Layers, 1))
282
+	assert.Check(t, cmp.Equal(m.Layers[0].MediaType, images.MediaTypeDockerSchema2LayerGzip))
283
+}
... ...
@@ -492,7 +492,7 @@ func buildManifest(ctx context.Context, s content.Manager, config digest.Digest,
492 492
 			return m, errors.Wrapf(err, "error fetching info for content digest %s", l)
493 493
 		}
494 494
 		m.Layers = append(m.Layers, specs.Descriptor{
495
-			MediaType: specs.MediaTypeImageLayerGzip, // TODO: This is assuming everything is a gzip compressed layer, but that may not be true.
495
+			MediaType: images.MediaTypeDockerSchema2LayerGzip, // TODO: This is assuming everything is a gzip compressed layer, but that may not be true.
496 496
 			Digest:    l,
497 497
 			Size:      info.Size,
498 498
 		})