Skip to content

Commit b028f6a

Browse files
committed
add new libpod/images/$name/resolve endpoint
Podman Desktop [1] is looking into improving the user experience which requires to know the source of an image. Consider the user triggers an image pull and Podman Desktop wants to figure out whether the image name refers to a Red Hat registry, for instance, to prompt installing the RH auth extension. Since the input values of images may be a short name [2], Podman Desktop has no means to figure out the (potential) source of the image. Hence, add a new `/resolve` endpoint to allow external callers to figure out the (potential) fully-qualified image name of a given value. With the new endpoint, Podman Desktop can ask Podman directly to resolve the image name and then make an informed decision whether to prompt the user to perform certain tasks or not. This for sure can also be used for any other registry (e.g., Quay, Docker Hub). [1] podman-desktop/podman-desktop#5771 [2] https://www.redhat.com/sysadmin/container-image-short-names Signed-off-by: Valentin Rothberg <[email protected]>
1 parent 0655bf3 commit b028f6a

File tree

6 files changed

+87
-1
lines changed

6 files changed

+87
-1
lines changed

pkg/api/handlers/libpod/images.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ import (
1515
"github.com/containers/common/libimage"
1616
"github.com/containers/common/pkg/ssh"
1717
"github.com/containers/image/v5/manifest"
18+
"github.com/containers/image/v5/pkg/shortnames"
19+
"github.com/containers/image/v5/types"
1820
"github.com/containers/podman/v4/libpod"
1921
"github.com/containers/podman/v4/libpod/define"
2022
"github.com/containers/podman/v4/pkg/api/handlers"
@@ -720,3 +722,36 @@ func ImageScp(w http.ResponseWriter, r *http.Request) {
720722

721723
utils.WriteResponse(w, http.StatusOK, &reports.ScpReport{Id: rep.Names[0]})
722724
}
725+
726+
// Resolve the passed (short) name to one more candidates it may resolve to.
727+
// See https://www.redhat.com/sysadmin/container-image-short-names.
728+
//
729+
// One user of this endpoint is Podman Desktop which needs to figure out where
730+
// an image may resolve to.
731+
func ImageResolve(w http.ResponseWriter, r *http.Request) {
732+
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
733+
name := utils.GetName(r)
734+
735+
mode := types.ShortNameModeDisabled
736+
sys := runtime.SystemContext()
737+
sys.ShortNameMode = &mode
738+
739+
resolved, err := shortnames.Resolve(sys, name)
740+
if err != nil {
741+
utils.Error(w, http.StatusBadRequest, fmt.Errorf("resolving %q: %w", name, err))
742+
return
743+
}
744+
745+
if len(resolved.PullCandidates) == 0 { // Should never happen but let's be defensive.
746+
utils.Error(w, http.StatusInternalServerError, fmt.Errorf("name %q did not resolve to any candidate", name))
747+
return
748+
}
749+
750+
names := make([]string, 0, len(resolved.PullCandidates))
751+
for _, candidate := range resolved.PullCandidates {
752+
names = append(names, candidate.Value.String())
753+
}
754+
755+
report := handlers.LibpodImagesResolveReport{Names: names}
756+
utils.WriteResponse(w, http.StatusOK, report)
757+
}

pkg/api/handlers/types.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ type LibpodImagesRemoveReport struct {
3434
Errors []string
3535
}
3636

37+
// LibpodImagesResolveReport includes a list of fully-qualified image references.
38+
type LibpodImagesResolveReport struct {
39+
// Fully-qualified image references.
40+
Names []string
41+
}
42+
3743
type ContainersPruneReport struct {
3844
docker.ContainersPruneReport
3945
}

pkg/api/server/register_images.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1690,5 +1690,27 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
16901690
// 500:
16911691
// $ref: '#/responses/internalError'
16921692
r.Handle(VersionedPath("/libpod/images/scp/{name:.*}"), s.APIHandler(libpod.ImageScp)).Methods(http.MethodPost)
1693+
// swagger:operation GET /libpod/images/{name}/resolve libpod ImageResolveLibpod
1694+
// ---
1695+
// tags:
1696+
// - images
1697+
// summary: Resolve an image (short) name
1698+
// description: Resolve the passed image name to a list of fully-qualified images referring to container registries.
1699+
// parameters:
1700+
// - in: path
1701+
// name: name
1702+
// type: string
1703+
// required: true
1704+
// description: the (short) name to resolve
1705+
// produces:
1706+
// - application/json
1707+
// responses:
1708+
// 204:
1709+
// description: resolved image names
1710+
// 400:
1711+
// $ref: "#/responses/badParamError"
1712+
// 500:
1713+
// $ref: '#/responses/internalError'
1714+
r.Handle(VersionedPath("/libpod/images/{name:.*}/resolve"), s.APIHandler(libpod.ImageResolve)).Methods(http.MethodGet)
16931715
return nil
16941716
}

test/apiv2/10-images.at

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,4 +325,22 @@ t DELETE images/$iid_test2?noprune=false 200
325325
t GET libpod/images/$iid_test1/exists 404
326326
t GET libpod/images/$iid_test2/exists 404
327327

328+
# If the /resolve tests fail, make sure to use ../registries.conf for the
329+
# podman-service.
330+
331+
# With an alias, we only get one item back.
332+
t GET libpod/images/podman-desktop-test123:this/resolve 200 \
333+
.Names[0]="florent.fr/will/like:this"
334+
335+
# If no alias matches, we will get a candidate for each unqualified-search
336+
# registry.
337+
t GET libpod/images/no-alias-for-sure/resolve 200 \
338+
.Names[0]="docker.io/library/no-alias-for-sure:latest" \
339+
.Names[1]="quay.io/no-alias-for-sure:latest" \
340+
.Names[2]="registry.fedoraproject.org/no-alias-for-sure:latest"
341+
342+
# Test invalid input.
343+
t GET libpod/images/noCAPITALcharAllowed/resolve 400 \
344+
.cause="repository name must be lowercase"
345+
328346
# vim: filetype=sh

test/apiv2/test-apiv2

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,8 @@ function start_service() {
448448
$PODMAN_BIN unshare true
449449
fi
450450

451-
$PODMAN_BIN \
451+
CONTAINERS_REGISTRIES_CONF=$TESTS_DIR/../registries.conf \
452+
$PODMAN_BIN \
452453
--root $WORKDIR/server_root --syslog=true \
453454
system service \
454455
--time 0 \

test/registries.conf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,7 @@ location="quay.io/libpod"
2121
[[registry]]
2222
location="localhost:5000"
2323
insecure=true
24+
25+
# Alias used in tests.
26+
[aliases]
27+
"podman-desktop-test123"="florent.fr/will/like"

0 commit comments

Comments
 (0)