From 1ca20165636b8b844b8cc7f2f9fb4227aedebf74 Mon Sep 17 00:00:00 2001 From: Nalin Dahyabhai Date: Wed, 8 Oct 2025 15:18:00 -0400 Subject: [PATCH] `manifest add`: prefer lists when looking up for `--all` When looking up the image to add, if we were passed `--all`, set the flag that we pass to libimage to indicate that we prefer a list if there is one, so that it doesn't just hand us back one image from a list. Signed-off-by: Nalin Dahyabhai --- cmd/buildah/manifest.go | 12 ++++++------ internal/util/util.go | 20 ++++++++++++++------ internal/volumes/volumes.go | 4 ++-- tests/lists.bats | 8 ++++++++ util/util.go | 12 ++---------- 5 files changed, 32 insertions(+), 24 deletions(-) diff --git a/cmd/buildah/manifest.go b/cmd/buildah/manifest.go index da53913cd67..5ecb54090a3 100644 --- a/cmd/buildah/manifest.go +++ b/cmd/buildah/manifest.go @@ -10,6 +10,7 @@ import ( "strings" "time" + iutil "github.com/containers/buildah/internal/util" "github.com/containers/buildah/pkg/cli" "github.com/containers/buildah/pkg/parse" "github.com/containers/buildah/util" @@ -400,15 +401,14 @@ func manifestCreateCmd(c *cobra.Command, args []string, opts manifestCreateOpts) if err != nil { if ref, err = alltransports.ParseImageName(util.DefaultTransport + imageSpec); err != nil { // check if the local image exists - if ref, _, err = util.FindImage(store, "", systemContext, imageSpec); err != nil { + if _, ref, err = iutil.LookupImage(systemContext, store, imageSpec, opts.all); err != nil { return err } } } - refLocal, _, err := util.FindImage(store, "", systemContext, imageSpec) - if err == nil { + if _, storageRef, err := iutil.LookupImage(systemContext, store, imageSpec, opts.all); err == nil { // Found local image so use that. - ref = refLocal + ref = storageRef } if _, err = list.Add(getContext(), systemContext, ref, opts.all); err != nil { return err @@ -553,7 +553,7 @@ func manifestAddCmd(c *cobra.Command, args []string, opts manifestAddOpts) error var ref types.ImageReference if ref, err = alltransports.ParseImageName(imageSpec); err != nil { if ref, err = alltransports.ParseImageName(util.DefaultTransport + imageSpec); err != nil { - if ref, _, err = util.FindImage(store, "", systemContext, imageSpec); err != nil { + if _, ref, err = iutil.LookupImage(systemContext, store, imageSpec, opts.all); err != nil { return err } } @@ -564,7 +564,7 @@ func manifestAddCmd(c *cobra.Command, args []string, opts manifestAddOpts) error var storeErr error // Retry without a custom system context. A user may want to add // a custom platform (see #3511). - if ref, _, storeErr = util.FindImage(store, "", nil, imageSpec); storeErr != nil { + if _, ref, storeErr = iutil.LookupImage(nil, store, imageSpec, opts.all); storeErr != nil { logrus.Errorf("Error while trying to find image on local storage: %v", storeErr) return err } diff --git a/internal/util/util.go b/internal/util/util.go index b230d0e3055..c6eafc95dee 100644 --- a/internal/util/util.go +++ b/internal/util/util.go @@ -17,21 +17,29 @@ import ( "go.podman.io/storage/pkg/unshare" ) -// LookupImage returns *Image to corresponding imagename or id -func LookupImage(ctx *types.SystemContext, store storage.Store, image string) (*libimage.Image, error) { +// LookupImage returns the *libimage.Image and an ImageReference for a local image record with the +// corresponding image name or ID. Wraps libimage.Runtime.LookupImage() to do most of the work. +func LookupImage(ctx *types.SystemContext, store storage.Store, image string, preferList bool) (*libimage.Image, types.ImageReference, error) { systemContext := ctx if systemContext == nil { systemContext = &types.SystemContext{} } runtime, err := libimage.RuntimeFromStore(store, &libimage.RuntimeOptions{SystemContext: systemContext}) if err != nil { - return nil, err + return nil, nil, err } - localImage, _, err := runtime.LookupImage(image, nil) + options := &libimage.LookupImageOptions{ + ManifestList: preferList, + } + localImage, _, err := runtime.LookupImage(image, options) + if err != nil { + return nil, nil, err + } + storageRef, err := localImage.StorageReference() if err != nil { - return nil, err + return nil, nil, err } - return localImage, nil + return localImage, storageRef, nil } // NormalizePlatform validates and translate the platform to the canonical value. diff --git a/internal/volumes/volumes.go b/internal/volumes/volumes.go index 8b4b30cd79e..8751548d9b1 100644 --- a/internal/volumes/volumes.go +++ b/internal/volumes/volumes.go @@ -253,7 +253,7 @@ func GetBindMount(sys *types.SystemContext, args []string, contextDir string, st // if mountPoint of image was not found in additionalMap // or additionalMap was nil, try mounting image if mountPoint == "" { - image, err := internalUtil.LookupImage(sys, store, fromWhere) + image, _, err := internalUtil.LookupImage(sys, store, fromWhere, false) if err != nil { return newMount, "", "", "", err } @@ -515,7 +515,7 @@ func GetCacheMount(sys *types.SystemContext, args []string, store storage.Store, // it's not an additional build context, stage, or // already-mounted image, but it might still be an image if mountPoint == "" { - image, err := internalUtil.LookupImage(sys, store, fromWhere) + image, _, err := internalUtil.LookupImage(sys, store, fromWhere, false) if err != nil { return newMount, "", "", "", nil, err } diff --git a/tests/lists.bats b/tests/lists.bats index c21851124e7..7b5a2dc4264 100644 --- a/tests/lists.bats +++ b/tests/lists.bats @@ -112,6 +112,14 @@ IMAGE_LIST_S390X_INSTANCE_DIGEST=sha256:882a20ee0df7399a445285361d38b711c299ca09 expect_output --substring ${IMAGE_LIST_ARM64_INSTANCE_DIGEST} expect_output --substring ${IMAGE_LIST_PPC64LE_INSTANCE_DIGEST} expect_output --substring ${IMAGE_LIST_S390X_INSTANCE_DIGEST} + run_buildah manifest create foo2 + run_buildah manifest add --all foo2 foo + run_buildah manifest inspect foo2 + expect_output --substring ${IMAGE_LIST_AMD64_INSTANCE_DIGEST} + expect_output --substring ${IMAGE_LIST_ARM_INSTANCE_DIGEST} + expect_output --substring ${IMAGE_LIST_ARM64_INSTANCE_DIGEST} + expect_output --substring ${IMAGE_LIST_PPC64LE_INSTANCE_DIGEST} + expect_output --substring ${IMAGE_LIST_S390X_INSTANCE_DIGEST} } @test "manifest-annotate global annotation" { diff --git a/util/util.go b/util/util.go index 0b2339e16d0..5ecec98414f 100644 --- a/util/util.go +++ b/util/util.go @@ -13,6 +13,7 @@ import ( "syscall" "github.com/containers/buildah/define" + "github.com/containers/buildah/internal/util" "github.com/docker/distribution/registry/api/errcode" "github.com/opencontainers/go-digest" specs "github.com/opencontainers/runtime-spec/specs-go" @@ -140,16 +141,7 @@ func ExpandNames(names []string, systemContext *types.SystemContext, store stora // name. Please note that the second argument has been deprecated and has no // effect anymore. func FindImage(store storage.Store, _ string, systemContext *types.SystemContext, image string) (types.ImageReference, *storage.Image, error) { - runtime, err := libimage.RuntimeFromStore(store, &libimage.RuntimeOptions{SystemContext: systemContext}) - if err != nil { - return nil, nil, err - } - - localImage, _, err := runtime.LookupImage(image, nil) - if err != nil { - return nil, nil, err - } - ref, err := localImage.StorageReference() + localImage, ref, err := util.LookupImage(systemContext, store, image, false) if err != nil { return nil, nil, err }