@@ -304,11 +304,35 @@ func (b *Builder) addManifest(ctx context.Context, manifestName string, imageSpe
304304 return imageID , err
305305}
306306
307+ // CommitResults is a structure returned when CommitResults() succeeds.
308+ type CommitResults struct {
309+ ImageID string // a local image ID, or part of the digest of the image's config blob
310+ Canonical reference.Canonical // set if destination included a DockerReference
311+ MediaType string // always returned
312+ ImageManifest []byte // always returned
313+ Digest digest.Digest // always returned
314+ }
315+
307316// Commit writes the contents of the container, along with its updated
308317// configuration, to a new image in the specified location, and if we know how,
309318// add any additional tags that were specified. Returns the ID of the new image
310- // if commit was successful and the image destination was local.
319+ // if commit was successful and the image destination was local, a canonical
320+ // reference if the destination ImageReference include a DockerReference, and
321+ // the digest of the written image's manifest.
322+ // Commit() is implemented as a wrapper around CommitResults().
311323func (b * Builder ) Commit (ctx context.Context , dest types.ImageReference , options CommitOptions ) (string , reference.Canonical , digest.Digest , error ) {
324+ results , err := b .CommitResults (ctx , dest , options )
325+ if err != nil {
326+ return "" , nil , "" , err
327+ }
328+ return results .ImageID , results .Canonical , results .Digest , nil
329+ }
330+
331+ // CommitResults writes the contents of the container, along with its updated
332+ // configuration, to a new image in the specified location, and if we know how,
333+ // add any additional tags that were specified. Returns a CommitResults
334+ // structure.
335+ func (b * Builder ) CommitResults (ctx context.Context , dest types.ImageReference , options CommitOptions ) (* CommitResults , error ) {
312336 var (
313337 imgID string
314338 src types.ImageReference
@@ -325,7 +349,7 @@ func (b *Builder) Commit(ctx context.Context, dest types.ImageReference, options
325349 // work twice.
326350 if options .OmitTimestamp {
327351 if options .HistoryTimestamp != nil {
328- return imgID , nil , "" , fmt .Errorf ("OmitTimestamp and HistoryTimestamp can not be used together" )
352+ return nil , fmt .Errorf ("OmitTimestamp and HistoryTimestamp can not be used together" )
329353 }
330354 timestamp := time .Unix (0 , 0 ).UTC ()
331355 options .HistoryTimestamp = & timestamp
@@ -339,7 +363,7 @@ func (b *Builder) Commit(ctx context.Context, dest types.ImageReference, options
339363 nameToRemove = stringid .GenerateRandomID () + "-tmp"
340364 dest2 , err := is .Transport .ParseStoreReference (b .store , nameToRemove )
341365 if err != nil {
342- return imgID , nil , "" , fmt .Errorf ("creating temporary destination reference for image: %w" , err )
366+ return nil , fmt .Errorf ("creating temporary destination reference for image: %w" , err )
343367 }
344368 dest = dest2
345369 }
@@ -348,23 +372,23 @@ func (b *Builder) Commit(ctx context.Context, dest types.ImageReference, options
348372
349373 blocked , err := isReferenceBlocked (dest , systemContext )
350374 if err != nil {
351- return "" , nil , "" , fmt .Errorf ("checking if committing to registry for %q is blocked: %w" , transports .ImageName (dest ), err )
375+ return nil , fmt .Errorf ("checking if committing to registry for %q is blocked: %w" , transports .ImageName (dest ), err )
352376 }
353377 if blocked {
354- return "" , nil , "" , fmt .Errorf ("commit access to registry for %q is blocked by configuration" , transports .ImageName (dest ))
378+ return nil , fmt .Errorf ("commit access to registry for %q is blocked by configuration" , transports .ImageName (dest ))
355379 }
356380
357381 // Load the system signing policy.
358382 commitPolicy , err := signature .DefaultPolicy (systemContext )
359383 if err != nil {
360- return "" , nil , "" , fmt .Errorf ("obtaining default signature policy: %w" , err )
384+ return nil , fmt .Errorf ("obtaining default signature policy: %w" , err )
361385 }
362386 // Override the settings for local storage to make sure that we can always read the source "image".
363387 commitPolicy .Transports [is .Transport .Name ()] = storageAllowedPolicyScopes
364388
365389 policyContext , err := signature .NewPolicyContext (commitPolicy )
366390 if err != nil {
367- return imgID , nil , "" , fmt .Errorf ("creating new signature policy context: %w" , err )
391+ return nil , fmt .Errorf ("creating new signature policy context: %w" , err )
368392 }
369393 defer func () {
370394 if err2 := policyContext .Destroy (); err2 != nil {
@@ -375,11 +399,11 @@ func (b *Builder) Commit(ctx context.Context, dest types.ImageReference, options
375399 // Check if the commit is blocked by $BUILDER_REGISTRY_SOURCES.
376400 insecure , err := checkRegistrySourcesAllows ("commit to" , dest )
377401 if err != nil {
378- return imgID , nil , "" , err
402+ return nil , err
379403 }
380404 if insecure {
381405 if systemContext .DockerInsecureSkipTLSVerify == types .OptionalBoolFalse {
382- return imgID , nil , "" , fmt .Errorf ("can't require tls verification on an insecured registry" )
406+ return nil , fmt .Errorf ("can't require tls verification on an insecured registry" )
383407 }
384408 systemContext .DockerInsecureSkipTLSVerify = types .OptionalBoolTrue
385409 systemContext .OCIInsecureSkipTLSVerify = true
@@ -393,7 +417,7 @@ func (b *Builder) Commit(ctx context.Context, dest types.ImageReference, options
393417 if len (options .SBOMScanOptions ) != 0 {
394418 var scansDirectory string
395419 if extraImageContent , extraLocalContent , scansDirectory , err = b .sbomScan (ctx , options ); err != nil {
396- return imgID , nil , "" , fmt .Errorf ("scanning rootfs to generate SBOM for container %q: %w" , b .ContainerID , err )
420+ return nil , fmt .Errorf ("scanning rootfs to generate SBOM for container %q: %w" , b .ContainerID , err )
397421 }
398422 if scansDirectory != "" {
399423 defer func () {
@@ -418,7 +442,7 @@ func (b *Builder) Commit(ctx context.Context, dest types.ImageReference, options
418442 // Build an image reference from which we can copy the finished image.
419443 src , err = b .makeContainerImageRef (options )
420444 if err != nil {
421- return imgID , nil , "" , fmt .Errorf ("computing layer digests and building metadata for container %q: %w" , b .ContainerID , err )
445+ return nil , fmt .Errorf ("computing layer digests and building metadata for container %q: %w" , b .ContainerID , err )
422446 }
423447 // In case we're using caching, decide how to handle compression for a cache.
424448 // If we're using blob caching, set it up for the source.
@@ -431,12 +455,12 @@ func (b *Builder) Commit(ctx context.Context, dest types.ImageReference, options
431455 }
432456 cache , err := blobcache .NewBlobCache (src , options .BlobDirectory , compress )
433457 if err != nil {
434- return imgID , nil , "" , fmt .Errorf ("wrapping image reference %q in blob cache at %q: %w" , transports .ImageName (src ), options .BlobDirectory , err )
458+ return nil , fmt .Errorf ("wrapping image reference %q in blob cache at %q: %w" , transports .ImageName (src ), options .BlobDirectory , err )
435459 }
436460 maybeCachedSrc = cache
437461 cache , err = blobcache .NewBlobCache (dest , options .BlobDirectory , compress )
438462 if err != nil {
439- return imgID , nil , "" , fmt .Errorf ("wrapping image reference %q in blob cache at %q: %w" , transports .ImageName (dest ), options .BlobDirectory , err )
463+ return nil , fmt .Errorf ("wrapping image reference %q in blob cache at %q: %w" , transports .ImageName (dest ), options .BlobDirectory , err )
440464 }
441465 maybeCachedDest = cache
442466 }
@@ -457,7 +481,7 @@ func (b *Builder) Commit(ctx context.Context, dest types.ImageReference, options
457481
458482 var manifestBytes []byte
459483 if manifestBytes , err = retryCopyImage (ctx , policyContext , maybeCachedDest , maybeCachedSrc , dest , getCopyOptions (b .store , options .ReportWriter , nil , systemContext , "" , false , options .SignBy , options .OciEncryptLayers , options .OciEncryptConfig , nil , destinationTimestamp ), options .MaxRetries , options .RetryDelay ); err != nil {
460- return imgID , nil , "" , fmt .Errorf ("copying layers and metadata for container %q: %w" , b .ContainerID , err )
484+ return nil , fmt .Errorf ("copying layers and metadata for container %q: %w" , b .ContainerID , err )
461485 }
462486 // If we've got more names to attach, and we know how to do that for
463487 // the transport that we're writing the new image to, add them now.
@@ -466,10 +490,10 @@ func (b *Builder) Commit(ctx context.Context, dest types.ImageReference, options
466490 case is .Transport .Name ():
467491 _ , img , err := is .ResolveReference (dest )
468492 if err != nil {
469- return imgID , nil , "" , fmt .Errorf ("locating just-written image %q: %w" , transports .ImageName (dest ), err )
493+ return nil , fmt .Errorf ("locating just-written image %q: %w" , transports .ImageName (dest ), err )
470494 }
471495 if err = util .AddImageNames (b .store , "" , systemContext , img , options .AdditionalTags ); err != nil {
472- return imgID , nil , "" , fmt .Errorf ("setting image names to %v: %w" , append (img .Names , options .AdditionalTags ... ), err )
496+ return nil , fmt .Errorf ("setting image names to %v: %w" , append (img .Names , options .AdditionalTags ... ), err )
473497 }
474498 logrus .Debugf ("assigned names %v to image %q" , img .Names , img .ID )
475499 default :
@@ -480,7 +504,7 @@ func (b *Builder) Commit(ctx context.Context, dest types.ImageReference, options
480504 if dest .Transport ().Name () == is .Transport .Name () {
481505 dest2 , img , err := is .ResolveReference (dest )
482506 if err != nil {
483- return imgID , nil , "" , fmt .Errorf ("locating image %q in local storage: %w" , transports .ImageName (dest ), err )
507+ return nil , fmt .Errorf ("locating image %q in local storage: %w" , transports .ImageName (dest ), err )
484508 }
485509 dest = dest2
486510 imgID = img .ID
@@ -492,13 +516,13 @@ func (b *Builder) Commit(ctx context.Context, dest types.ImageReference, options
492516 }
493517 if len (toPruneNames ) > 0 {
494518 if err = b .store .RemoveNames (imgID , toPruneNames ); err != nil {
495- return imgID , nil , "" , fmt .Errorf ("failed to remove temporary name from image %q: %w" , imgID , err )
519+ return nil , fmt .Errorf ("failed to remove temporary name from image %q: %w" , imgID , err )
496520 }
497521 logrus .Debugf ("removing %v from assigned names to image %q" , nameToRemove , img .ID )
498522 }
499523 if options .IIDFile != "" {
500524 if err = os .WriteFile (options .IIDFile , []byte ("sha256:" + img .ID ), 0o644 ); err != nil {
501- return imgID , nil , "" , err
525+ return nil , err
502526 }
503527 }
504528 }
@@ -521,20 +545,20 @@ func (b *Builder) Commit(ctx context.Context, dest types.ImageReference, options
521545 return nil
522546 }()
523547 if err != nil {
524- return imgID , nil , "" , err
548+ return nil , err
525549 }
526550 }
527551
528552 // Calculate the as-written digest of the image's manifest and build the digested
529553 // reference for the image.
530554 manifestDigest , err := manifest .Digest (manifestBytes )
531555 if err != nil {
532- return imgID , nil , "" , fmt .Errorf ("computing digest of manifest of new image %q: %w" , transports .ImageName (dest ), err )
556+ return nil , fmt .Errorf ("computing digest of manifest of new image %q: %w" , transports .ImageName (dest ), err )
533557 }
534558 if imgID == "" {
535559 parsedManifest , err := manifest .FromBlob (manifestBytes , manifest .GuessMIMEType (manifestBytes ))
536560 if err != nil {
537- return imgID , nil , "" , fmt .Errorf ("parsing written manifest to determine the image's ID: %w" , err )
561+ return nil , fmt .Errorf ("parsing written manifest to determine the image's ID: %w" , err )
538562 }
539563 configInfo := parsedManifest .ConfigInfo ()
540564 if configInfo .Size > 2 && configInfo .Digest .Validate () == nil { // don't be returning a digest of "" or "{}"
@@ -553,9 +577,17 @@ func (b *Builder) Commit(ctx context.Context, dest types.ImageReference, options
553577 if options .Manifest != "" {
554578 manifestID , err := b .addManifest (ctx , options .Manifest , imgID )
555579 if err != nil {
556- return imgID , nil , "" , err
580+ return nil , err
557581 }
558582 logrus .Debugf ("added imgID %s to manifestID %s" , imgID , manifestID )
559583 }
560- return imgID , ref , manifestDigest , nil
584+
585+ results := CommitResults {
586+ ImageID : imgID ,
587+ Canonical : ref ,
588+ MediaType : manifest .GuessMIMEType (manifestBytes ),
589+ ImageManifest : manifestBytes ,
590+ Digest : manifestDigest ,
591+ }
592+ return & results , nil
561593}
0 commit comments