@@ -24,6 +24,7 @@ import (
24
24
"github.com/awslabs/soci-snapshotter/config"
25
25
"github.com/awslabs/soci-snapshotter/util/dockershell"
26
26
"github.com/awslabs/soci-snapshotter/util/testutil"
27
+ "github.com/containerd/containerd/reference"
27
28
"github.com/containerd/platforms"
28
29
)
29
30
@@ -252,3 +253,93 @@ func testV1IsNotUsedWhenDisabled(t *testing.T, imgName string) {
252
253
t .Fatalf ("expected no digest, got %s" , indexDigestUsed )
253
254
}
254
255
}
256
+
257
+ func TestDanglingV2Annotation (t * testing.T ) {
258
+ for _ , imgName := range pullModesImages {
259
+ t .Run (imgName , func (t * testing.T ) {
260
+ testDanglingV2Annotation (t , imgName )
261
+ })
262
+ }
263
+ }
264
+
265
+ func testDanglingV2Annotation (t * testing.T , imgName string ) {
266
+ regConfig := newRegistryConfig ()
267
+ sh , done := newShellWithRegistry (t , regConfig )
268
+ defer done ()
269
+
270
+ rebootContainerd (t , sh , "" , "" )
271
+
272
+ srcInfo := dockerhub (imgName )
273
+ dstInfo := regConfig .mirror (imgName )
274
+
275
+ sh .X ("nerdctl" , "pull" , "--all-platforms" , srcInfo .ref )
276
+ sh .X ("soci" , "convert" , "--min-layer-size" , "0" , srcInfo .ref , dstInfo .ref )
277
+
278
+ manifest , err := getManifestDigest (sh , dstInfo .ref , platforms .DefaultSpec ())
279
+ if err != nil {
280
+ t .Fatalf ("could not get manifest digest: %v" , err )
281
+ }
282
+
283
+ v2IndexDigest , err := sh .OLog ("soci" ,
284
+ "index" , "list" ,
285
+ "-q" , "--ref" , srcInfo .ref ,
286
+ "--platform" , platforms .Format (platforms .DefaultSpec ()),
287
+ )
288
+ if err != nil {
289
+ t .Fatal (err )
290
+ }
291
+
292
+ // Nither nerdctl nor ctr expose a way to "elevate" a platform-specific
293
+ // manifest to a top level image directly, so we do a little registry dance:
294
+ // push image:tag
295
+ // pull image@sha256:... (the specific manifest we want to elevate)
296
+ // tag image@sha256:... image/dangling:tag
297
+ // push image/dangling:tag
298
+ //
299
+ // After this, image/dangling:tag refers to a single manifest that is platform specific.
300
+ // We use this to separate an image manifest that contains a reference to a SOCI index
301
+ // from the SOCI index itself to verify that it correctly pulls the image without lazy loading.
302
+ platformManifestRef , err := reference .Parse (dstInfo .ref )
303
+ if err != nil {
304
+ t .Fatalf ("could not get parse destination ref: %v" , err )
305
+ }
306
+ danglingRef := platformManifestRef
307
+ danglingRef .Locator += "/dangling" // image/dangling:tag
308
+
309
+ platformManifestRef .Object = "@" + manifest // image@sha256...
310
+
311
+ sh .X ("nerdctl" , "login" , "--username" , regConfig .user , "--password" , regConfig .pass , platformManifestRef .String ())
312
+ sh .X ("nerdctl" , "push" , "--platform" , platforms .DefaultString (), dstInfo .ref )
313
+ sh .X ("nerdctl" , "pull" , platformManifestRef .String ())
314
+ sh .X ("nerdctl" , "image" , "tag" , platformManifestRef .String (), danglingRef .String ())
315
+ // Push a v1 index as well to verify that we do not fall back if we don't find the SOCI v2 index
316
+ sh .X ("nerdctl" , "push" , "--snapshotter" , "soci" , "--soci-min-layer-size" , "0" , danglingRef .String ())
317
+
318
+ m := rebootContainerd (t , sh , "" , getSnapshotterConfigToml (t , withPullModes (config .DefaultPullModes ())))
319
+
320
+ rsm , doneRsm := testutil .NewRemoteSnapshotMonitor (m )
321
+ defer doneRsm ()
322
+ var foundNoIndexMessage bool
323
+ var indexDigestUsed string
324
+ m .Add ("Look for digest" , func (s string ) {
325
+ if strings .Contains (s , "no valid SOCI index found" ) {
326
+ foundNoIndexMessage = true
327
+ }
328
+ structuredLog := make (map [string ]string )
329
+ err := json .Unmarshal ([]byte (s ), & structuredLog )
330
+ if err != nil {
331
+ return
332
+ }
333
+ if structuredLog ["msg" ] == "fetching SOCI artifacts using index descriptor" {
334
+ indexDigestUsed = structuredLog ["digest" ]
335
+ }
336
+ })
337
+ sh .X ("nerdctl" , "pull" , "--snapshotter" , "soci" , danglingRef .String ())
338
+ rsm .CheckAllLocalSnapshots (t )
339
+ if ! foundNoIndexMessage {
340
+ t .Fatalf ("did not find the message that no index was found" )
341
+ }
342
+ if strings .Trim (string (v2IndexDigest ), "\n " ) != indexDigestUsed {
343
+ t .Fatalf ("expected v2 index digest %s, got %s" , v2IndexDigest , indexDigestUsed )
344
+ }
345
+ }
0 commit comments