@@ -244,8 +244,6 @@ func (client *registryClient) TagMetadata(manifest distribution.Manifest, opts *
244
244
245
245
case * manifestlist.DeserializedManifestList :
246
246
var list manifestlist.DeserializedManifestList = * deserialized
247
- var ml []distribution.Descriptor
248
- platforms := []string {}
249
247
250
248
// List must contain at least one image manifest
251
249
if len (list .Manifests ) == 0 {
@@ -262,63 +260,27 @@ func (client *registryClient) TagMetadata(manifest distribution.Manifest, opts *
262
260
263
261
logCtx .Tracef ("SHA256 of manifest parent is %v" , ti .EncodedDigest ())
264
262
265
- for _ , ref := range list .References () {
266
- platforms = append (platforms , ref .Platform .OS + "/" + ref .Platform .Architecture )
267
- logCtx .Tracef ("Found %s" , options .PlatformKey (ref .Platform .OS , ref .Platform .Architecture , ref .Platform .Variant ))
268
- if ! opts .WantsPlatform (ref .Platform .OS , ref .Platform .Architecture , ref .Platform .Variant ) {
269
- logCtx .Tracef ("Ignoring referenced manifest %v because platform %s does not match any of: %s" ,
270
- ref .Digest ,
271
- options .PlatformKey (ref .Platform .OS , ref .Platform .Architecture , ref .Platform .Variant ),
272
- strings .Join (opts .Platforms (), "," ))
273
- continue
274
- }
275
- ml = append (ml , ref )
276
- }
263
+ return TagInfoFromReferences (client , opts , logCtx , ti , list .References ())
277
264
278
- // We need at least one reference that matches requested plaforms
279
- if len (ml ) == 0 {
280
- logCtx .Debugf ("Manifest list did not contain any usable reference. Platforms requested: (%s), platforms included: (%s)" ,
281
- strings .Join (opts .Platforms (), "," ), strings .Join (platforms , "," ))
282
- return nil , nil
283
- }
265
+ case * ocischema.DeserializedImageIndex :
266
+ var index ocischema.DeserializedImageIndex = * deserialized
284
267
285
- // For some strategies, we do not need to fetch metadata for further
286
- // processing.
287
- if ! opts .WantsMetadata () {
288
- return ti , nil
268
+ // Index must contain at least one image manifest
269
+ if len (index .Manifests ) == 0 {
270
+ return nil , fmt .Errorf ("empty index not supported" )
289
271
}
290
272
291
- // Loop through all referenced manifests to get their metadata. We only
292
- // consider manifests for platforms we are interested in.
293
- for _ , ref := range ml {
294
- logCtx .Tracef ("Inspecting metadata of reference: %v" , ref .Digest )
295
-
296
- man , err := client .ManifestForDigest (ref .Digest )
297
- if err != nil {
298
- return nil , fmt .Errorf ("could not fetch manifest %v: %v" , ref .Digest , err )
299
- }
300
-
301
- cti , err := client .TagMetadata (man , opts )
302
- if err != nil {
303
- return nil , fmt .Errorf ("could not fetch metadata for manifest %v: %v" , ref .Digest , err )
304
- }
305
-
306
- // We save the timestamp of the most recent pushed manifest for any
307
- // given reference, if the metadata for the tag was correctly
308
- // retrieved. This is important for the latest update strategy to
309
- // be able to handle multi-arch images. The latest strategy will
310
- // consider the most recent reference from a manifest list.
311
- if cti != nil {
312
- if cti .CreatedAt .After (ti .CreatedAt ) {
313
- ti .CreatedAt = cti .CreatedAt
314
- }
315
- } else {
316
- logCtx .Warnf ("returned metadata for manifest %v is nil, this should not happen." , ref .Digest )
317
- continue
318
- }
273
+ // We use the SHA from the manifest index to let the container engine
274
+ // decide which image to pull, in case of multi-arch clusters.
275
+ _ , mBytes , err := index .Payload ()
276
+ if err != nil {
277
+ return nil , fmt .Errorf ("could not retrieve index payload: %v" , err )
319
278
}
279
+ ti .Digest = sha256 .Sum256 (mBytes )
320
280
321
- return ti , nil
281
+ logCtx .Tracef ("SHA256 of manifest parent is %v" , ti .EncodedDigest ())
282
+
283
+ return TagInfoFromReferences (client , opts , logCtx , ti , index .References ())
322
284
323
285
case * schema2.DeserializedManifest :
324
286
var man schema2.Manifest = deserialized .Manifest
@@ -387,8 +349,74 @@ func (client *registryClient) TagMetadata(manifest distribution.Manifest, opts *
387
349
388
350
return ti , nil
389
351
default :
390
- return nil , fmt .Errorf ("invalid manifest type" )
352
+ return nil , fmt .Errorf ("invalid manifest type %T" , manifest )
353
+ }
354
+ }
355
+
356
+ // TagInfoFromReferences is a helper method to retrieve metadata for a given
357
+ // list of references. It will return the most recent pushed manifest from the
358
+ // list of references.
359
+ func TagInfoFromReferences (client * registryClient , opts * options.ManifestOptions , logCtx * log.LogContext , ti * tag.TagInfo , references []distribution.Descriptor ) (* tag.TagInfo , error ) {
360
+ var ml []distribution.Descriptor
361
+ platforms := []string {}
362
+
363
+ for _ , ref := range references {
364
+ platforms = append (platforms , ref .Platform .OS + "/" + ref .Platform .Architecture )
365
+ logCtx .Tracef ("Found %s" , options .PlatformKey (ref .Platform .OS , ref .Platform .Architecture , ref .Platform .Variant ))
366
+ if ! opts .WantsPlatform (ref .Platform .OS , ref .Platform .Architecture , ref .Platform .Variant ) {
367
+ logCtx .Tracef ("Ignoring referenced manifest %v because platform %s does not match any of: %s" ,
368
+ ref .Digest ,
369
+ options .PlatformKey (ref .Platform .OS , ref .Platform .Architecture , ref .Platform .Variant ),
370
+ strings .Join (opts .Platforms (), "," ))
371
+ continue
372
+ }
373
+ ml = append (ml , ref )
374
+ }
375
+
376
+ // We need at least one reference that matches requested plaforms
377
+ if len (ml ) == 0 {
378
+ logCtx .Debugf ("Manifest list did not contain any usable reference. Platforms requested: (%s), platforms included: (%s)" ,
379
+ strings .Join (opts .Platforms (), "," ), strings .Join (platforms , "," ))
380
+ return nil , nil
381
+ }
382
+
383
+ // For some strategies, we do not need to fetch metadata for further
384
+ // processing.
385
+ if ! opts .WantsMetadata () {
386
+ return ti , nil
391
387
}
388
+
389
+ // Loop through all referenced manifests to get their metadata. We only
390
+ // consider manifests for platforms we are interested in.
391
+ for _ , ref := range ml {
392
+ logCtx .Tracef ("Inspecting metadata of reference: %v" , ref .Digest )
393
+
394
+ man , err := client .ManifestForDigest (ref .Digest )
395
+ if err != nil {
396
+ return nil , fmt .Errorf ("could not fetch manifest %v: %v" , ref .Digest , err )
397
+ }
398
+
399
+ cti , err := client .TagMetadata (man , opts )
400
+ if err != nil {
401
+ return nil , fmt .Errorf ("could not fetch metadata for manifest %v: %v" , ref .Digest , err )
402
+ }
403
+
404
+ // We save the timestamp of the most recent pushed manifest for any
405
+ // given reference, if the metadata for the tag was correctly
406
+ // retrieved. This is important for the latest update strategy to
407
+ // be able to handle multi-arch images. The latest strategy will
408
+ // consider the most recent reference from an image index.
409
+ if cti != nil {
410
+ if cti .CreatedAt .After (ti .CreatedAt ) {
411
+ ti .CreatedAt = cti .CreatedAt
412
+ }
413
+ } else {
414
+ logCtx .Warnf ("returned metadata for manifest %v is nil, this should not happen." , ref .Digest )
415
+ continue
416
+ }
417
+ }
418
+
419
+ return ti , nil
392
420
}
393
421
394
422
// Implementation of ping method to intialize the challenge list
0 commit comments