@@ -356,11 +356,11 @@ func (c *copier) copyMultipleImages(ctx context.Context, policyContext *signatur
356356 if err != nil {
357357 return nil , "" , errors .Wrapf (err , "Error reading manifest list" )
358358 }
359- list , err := manifest .ListFromBlob (manifestList , manifestType )
359+ originalList , err := manifest .ListFromBlob (manifestList , manifestType )
360360 if err != nil {
361361 return nil , "" , errors .Wrapf (err , "Error parsing manifest list %q" , string (manifestList ))
362362 }
363- originalList := list .Clone ()
363+ updatedList := originalList .Clone ()
364364
365365 // Read and/or clear the set of signatures for this list.
366366 var sigs [][]byte
@@ -390,18 +390,18 @@ func (c *copier) copyMultipleImages(ctx context.Context, policyContext *signatur
390390 case imgspecv1 .MediaTypeImageManifest :
391391 forceListMIMEType = imgspecv1 .MediaTypeImageIndex
392392 }
393- selectedListType , err := c .determineListConversion (manifestType , c .dest .SupportedManifestMIMETypes (), forceListMIMEType )
393+ selectedListType , otherManifestMIMETypeCandidates , err := c .determineListConversion (manifestType , c .dest .SupportedManifestMIMETypes (), forceListMIMEType )
394394 if err != nil {
395395 return nil , "" , errors .Wrapf (err , "Error determining manifest list type to write to destination" )
396396 }
397- if selectedListType != list .MIMEType () {
397+ if selectedListType != originalList .MIMEType () {
398398 if ! canModifyManifestList {
399399 return nil , "" , errors .Errorf ("Error: manifest list must be converted to type %q to be written to destination, but that would invalidate signatures" , selectedListType )
400400 }
401401 }
402402
403403 // Copy each image, or just the ones we want to copy, in turn.
404- instanceDigests := list .Instances ()
404+ instanceDigests := updatedList .Instances ()
405405 imagesToCopy := len (instanceDigests )
406406 if options .ImageListSelection == CopySpecificImages {
407407 imagesToCopy = len (options .Instances )
@@ -419,7 +419,7 @@ func (c *copier) copyMultipleImages(ctx context.Context, policyContext *signatur
419419 }
420420 }
421421 if skip {
422- update , err := list .Instance (instanceDigest )
422+ update , err := updatedList .Instance (instanceDigest )
423423 if err != nil {
424424 return nil , "" , err
425425 }
@@ -447,42 +447,58 @@ func (c *copier) copyMultipleImages(ctx context.Context, policyContext *signatur
447447 }
448448
449449 // Now reset the digest/size/types of the manifests in the list to account for any conversions that we made.
450- if err = list .UpdateInstances (updates ); err != nil {
450+ if err = updatedList .UpdateInstances (updates ); err != nil {
451451 return nil , "" , errors .Wrapf (err , "Error updating manifest list" )
452452 }
453453
454- // Perform the list conversion.
455- if selectedListType != list .MIMEType () {
456- list , err = list .ConvertToMIMEType (selectedListType )
454+ // Iterate through supported list types, preferred format first.
455+ c .Printf ("Writing manifest list to image destination\n " )
456+ var errs []string
457+ for _ , thisListType := range append ([]string {selectedListType }, otherManifestMIMETypeCandidates ... ) {
458+ attemptedList := updatedList
459+
460+ logrus .Debugf ("Trying to use manifest list type %s…" , thisListType )
461+
462+ // Perform the list conversion, if we need one.
463+ if thisListType != updatedList .MIMEType () {
464+ attemptedList , err = updatedList .ConvertToMIMEType (thisListType )
465+ if err != nil {
466+ return nil , "" , errors .Wrapf (err , "Error converting manifest list to list with MIME type %q" , thisListType )
467+ }
468+ }
469+
470+ // Check if the updates or a type conversion meaningfully changed the list of images
471+ // by serializing them both so that we can compare them.
472+ attemptedManifestList , err := attemptedList .Serialize ()
457473 if err != nil {
458- return nil , "" , errors .Wrapf (err , "Error converting manifest list to list with MIME type %q" , selectedListType )
474+ return nil , "" , errors .Wrapf (err , "Error encoding updated manifest list (%q: %#v)" , updatedList .MIMEType (), updatedList .Instances ())
475+ }
476+ originalManifestList , err := originalList .Serialize ()
477+ if err != nil {
478+ return nil , "" , errors .Wrapf (err , "Error encoding original manifest list for comparison (%q: %#v)" , originalList .MIMEType (), originalList .Instances ())
459479 }
460- }
461480
462- // Check if the updates or a type conversion meaningfully changed the list of images
463- // by serializing them both so that we can compare them.
464- updatedManifestList , err := list .Serialize ()
465- if err != nil {
466- return nil , "" , errors .Wrapf (err , "Error encoding updated manifest list (%q: %#v)" , list .MIMEType (), list .Instances ())
467- }
468- originalManifestList , err := originalList .Serialize ()
469- if err != nil {
470- return nil , "" , errors .Wrapf (err , "Error encoding original manifest list for comparison (%q: %#v)" , originalList .MIMEType (), originalList .Instances ())
471- }
481+ // If we can't just use the original value, but we have to change it, flag an error.
482+ if ! bytes .Equal (attemptedManifestList , originalManifestList ) {
483+ if ! canModifyManifestList {
484+ return nil , "" , errors .Errorf ("Error: manifest list must be converted to type %q to be written to destination, but that would invalidate signatures" , thisListType )
485+ }
486+ logrus .Debugf ("Manifest list has been updated" )
487+ }
472488
473- // If we can't just use the original value, but we have to change it, flag an error.
474- if ! bytes .Equal (updatedManifestList , originalManifestList ) {
475- if ! canModifyManifestList {
476- return nil , "" , errors .Errorf ("Error: manifest list must be converted to type %q to be written to destination, but that would invalidate signatures" , selectedListType )
489+ // Save the manifest list.
490+ err = c .dest .PutManifest (ctx , attemptedManifestList , nil )
491+ if err != nil {
492+ logrus .Debugf ("Upload of manifest list type %s failed: %v" , thisListType , err )
493+ errs = append (errs , fmt .Sprintf ("%s(%v)" , thisListType , err ))
494+ continue
477495 }
478- manifestList = updatedManifestList
479- logrus .Debugf ("Manifest list has been updated" )
496+ errs = nil
497+ manifestList = attemptedManifestList
498+ break
480499 }
481-
482- // Save the manifest list.
483- c .Printf ("Writing manifest list to image destination\n " )
484- if err = c .dest .PutManifest (ctx , manifestList , nil ); err != nil {
485- return nil , "" , errors .Wrapf (err , "Error writing manifest list %q" , string (manifestList ))
500+ if errs != nil {
501+ return nil , "" , fmt .Errorf ("Uploading manifest list failed, attempted the following formats: %s" , strings .Join (errs , ", " ))
486502 }
487503
488504 // Sign the manifest list.
0 commit comments