Skip to content

Commit

Permalink
Add os, arch, and ismanifest to libpod image list
Browse files Browse the repository at this point in the history
when listing images through the restful service, consumers want to know
if the image they are listing is a manifest or not because the libpod
endpoint returns both images and manifest lists.

in addition, we now add `arch` and `os` as fields in the libpod endpoint
for image listing as well.

Fixes: #22184
Fixes: #22185

Signed-off-by: Brent Baude <[email protected]>
  • Loading branch information
baude committed Apr 11, 2024
1 parent 0b03352 commit 08a4938
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 5 deletions.
2 changes: 1 addition & 1 deletion hack/xref-helpmsgs-manpages
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ my $Format_Exceptions = <<'END_EXCEPTIONS';
# Deep internal structs; pretty sure these are permanent exceptions
events .Details
history .ImageHistoryLayer
images .ImageSummary
images .Arch .ImageSummary .Os .IsManifestList
network-ls .Network
# FIXME: this one, maybe? But someone needs to write the text
Expand Down
2 changes: 1 addition & 1 deletion pkg/api/handlers/compat/images.go
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,7 @@ func GetImages(w http.ResponseWriter, r *http.Request) {

imageEngine := abi.ImageEngine{Libpod: runtime}

listOptions := entities.ImageListOptions{All: query.All, Filter: filterList}
listOptions := entities.ImageListOptions{All: query.All, Filter: filterList, ExtendedAttributes: utils.IsLibpodRequest(r)}
summaries, err := imageEngine.List(r.Context(), listOptions)
if err != nil {
utils.Error(w, http.StatusInternalServerError, err)
Expand Down
7 changes: 5 additions & 2 deletions pkg/domain/entities/images.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,8 +242,11 @@ type ImageSearchReport = entitiesTypes.ImageSearchReport

// Image List Options
type ImageListOptions struct {
All bool `json:"all" schema:"all"`
Filter []string `json:"Filter,omitempty"`
All bool
// ExtendedAttributes is used by the libpod endpoint only to deliver extra information
// that the compat endpoint does not
ExtendedAttributes bool
Filter []string
}

type ImagePruneOptions struct {
Expand Down
8 changes: 7 additions & 1 deletion pkg/domain/entities/types/images.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,15 @@ type ImageSummary struct {
Dangling bool `json:",omitempty"`

// Podman extensions
Names []string `json:",omitempty"`
Arch string `json:",omitempty"`
Digest string `json:",omitempty"`
History []string `json:",omitempty"`
// IsManifestList is a ptr so we can distinguish between a true
// json empty response and false. the docker compat side needs to return
// empty; where as the libpod side needs a value of true or false
IsManifestList *bool `json:",omitempty"`
Names []string `json:",omitempty"`
Os string `json:",omitempty"`
}

func (i *ImageSummary) Id() string { //nolint:revive,stylecheck
Expand Down
15 changes: 15 additions & 0 deletions pkg/domain/infra/abi/images_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,21 @@ func (ir *ImageEngine) List(ctx context.Context, opts entities.ImageListOptions)
RepoTags: img.Names(), // may include tags and digests
ParentId: parentID,
}
if opts.ExtendedAttributes {
iml, err := img.IsManifestList(ctx)
if err != nil {
return nil, err
}
s.IsManifestList = &iml
if !iml {
imgData, err := img.Inspect(ctx, nil)
if err != nil {
return nil, err
}
s.Arch = imgData.Architecture
s.Os = imgData.Os
}
}
s.Labels, err = img.Labels(ctx)
if err != nil {
return nil, fmt.Errorf("retrieving label for image %q: you may need to remove the image to resolve the error: %w", img.ID(), err)
Expand Down
38 changes: 38 additions & 0 deletions test/apiv2/12-imagesMore.at
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,41 @@ t DELETE libpod/images/$IMAGE 200 \
podman system connection rm $conn

stop_registry

# if an image is a manifest list, it should not have
# anything for arch or os
podman manifest create foobar
t GET libpod/images/json 200 \ .[0].IsManifestList=true \
.[0].Arch=null \
.[0].Os=null


# list images through the libpod endpoint should return
# IsManifestList (bool), Arch (string), and Os (string)
podman pull -q $IMAGE
t GET libpod/images/json 200 \ .[0].IsManifestList=true\
.[0].Arch=null \
.[0].Os=null \
'.[0].RepoDigests | length=1' \
.[1].IsManifestList=false \
.[1].Arch=amd64 \
.[1].Os=linux

# if a manifest list and an image are returned with libpod images
# endpoint, then one should be a manifest with IsManifest only; and
# the other image should have IsManifestList, Arch, and Os.
podman manifest add --arch amd64 foobar $IMAGE
t GET libpod/images/json 200 .[0].IsManifestList=true\
.[0].Arch=null \
.[0].Os=null \
'.[0].RepoDigests | length=2' \
.[1].IsManifestList=false \
.[1].Arch=amd64 \
.[1].Os=linux

t GET images/json 200 .[0].IsManifestList=null \
.[0].Arch=null \
.[0].Os=null \
.[1].IsManifestList=null \
.[1].Arch=null \
.[1].Os=null \

0 comments on commit 08a4938

Please sign in to comment.