mirror of
https://github.com/containers/podman.git
synced 2025-07-04 01:48:28 +08:00
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] https://github.com/containers/podman-desktop/issues/5771 [2] https://www.redhat.com/sysadmin/container-image-short-names Signed-off-by: Valentin Rothberg <vrothberg@redhat.com>
This commit is contained in:
@ -15,6 +15,8 @@ import (
|
||||
"github.com/containers/common/libimage"
|
||||
"github.com/containers/common/pkg/ssh"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/pkg/shortnames"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/containers/podman/v4/libpod"
|
||||
"github.com/containers/podman/v4/libpod/define"
|
||||
"github.com/containers/podman/v4/pkg/api/handlers"
|
||||
@ -720,3 +722,36 @@ func ImageScp(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
utils.WriteResponse(w, http.StatusOK, &reports.ScpReport{Id: rep.Names[0]})
|
||||
}
|
||||
|
||||
// Resolve the passed (short) name to one more candidates it may resolve to.
|
||||
// See https://www.redhat.com/sysadmin/container-image-short-names.
|
||||
//
|
||||
// One user of this endpoint is Podman Desktop which needs to figure out where
|
||||
// an image may resolve to.
|
||||
func ImageResolve(w http.ResponseWriter, r *http.Request) {
|
||||
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
|
||||
name := utils.GetName(r)
|
||||
|
||||
mode := types.ShortNameModeDisabled
|
||||
sys := runtime.SystemContext()
|
||||
sys.ShortNameMode = &mode
|
||||
|
||||
resolved, err := shortnames.Resolve(sys, name)
|
||||
if err != nil {
|
||||
utils.Error(w, http.StatusBadRequest, fmt.Errorf("resolving %q: %w", name, err))
|
||||
return
|
||||
}
|
||||
|
||||
if len(resolved.PullCandidates) == 0 { // Should never happen but let's be defensive.
|
||||
utils.Error(w, http.StatusInternalServerError, fmt.Errorf("name %q did not resolve to any candidate", name))
|
||||
return
|
||||
}
|
||||
|
||||
names := make([]string, 0, len(resolved.PullCandidates))
|
||||
for _, candidate := range resolved.PullCandidates {
|
||||
names = append(names, candidate.Value.String())
|
||||
}
|
||||
|
||||
report := handlers.LibpodImagesResolveReport{Names: names}
|
||||
utils.WriteResponse(w, http.StatusOK, report)
|
||||
}
|
||||
|
@ -34,6 +34,12 @@ type LibpodImagesRemoveReport struct {
|
||||
Errors []string
|
||||
}
|
||||
|
||||
// LibpodImagesResolveReport includes a list of fully-qualified image references.
|
||||
type LibpodImagesResolveReport struct {
|
||||
// Fully-qualified image references.
|
||||
Names []string
|
||||
}
|
||||
|
||||
type ContainersPruneReport struct {
|
||||
docker.ContainersPruneReport
|
||||
}
|
||||
|
@ -1690,5 +1690,27 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
|
||||
// 500:
|
||||
// $ref: '#/responses/internalError'
|
||||
r.Handle(VersionedPath("/libpod/images/scp/{name:.*}"), s.APIHandler(libpod.ImageScp)).Methods(http.MethodPost)
|
||||
// swagger:operation GET /libpod/images/{name}/resolve libpod ImageResolveLibpod
|
||||
// ---
|
||||
// tags:
|
||||
// - images
|
||||
// summary: Resolve an image (short) name
|
||||
// description: Resolve the passed image name to a list of fully-qualified images referring to container registries.
|
||||
// parameters:
|
||||
// - in: path
|
||||
// name: name
|
||||
// type: string
|
||||
// required: true
|
||||
// description: the (short) name to resolve
|
||||
// produces:
|
||||
// - application/json
|
||||
// responses:
|
||||
// 204:
|
||||
// description: resolved image names
|
||||
// 400:
|
||||
// $ref: "#/responses/badParamError"
|
||||
// 500:
|
||||
// $ref: '#/responses/internalError'
|
||||
r.Handle(VersionedPath("/libpod/images/{name:.*}/resolve"), s.APIHandler(libpod.ImageResolve)).Methods(http.MethodGet)
|
||||
return nil
|
||||
}
|
||||
|
@ -325,4 +325,22 @@ t DELETE images/$iid_test2?noprune=false 200
|
||||
t GET libpod/images/$iid_test1/exists 404
|
||||
t GET libpod/images/$iid_test2/exists 404
|
||||
|
||||
# If the /resolve tests fail, make sure to use ../registries.conf for the
|
||||
# podman-service.
|
||||
|
||||
# With an alias, we only get one item back.
|
||||
t GET libpod/images/podman-desktop-test123:this/resolve 200 \
|
||||
.Names[0]="florent.fr/will/like:this"
|
||||
|
||||
# If no alias matches, we will get a candidate for each unqualified-search
|
||||
# registry.
|
||||
t GET libpod/images/no-alias-for-sure/resolve 200 \
|
||||
.Names[0]="docker.io/library/no-alias-for-sure:latest" \
|
||||
.Names[1]="quay.io/no-alias-for-sure:latest" \
|
||||
.Names[2]="registry.fedoraproject.org/no-alias-for-sure:latest"
|
||||
|
||||
# Test invalid input.
|
||||
t GET libpod/images/noCAPITALcharAllowed/resolve 400 \
|
||||
.cause="repository name must be lowercase"
|
||||
|
||||
# vim: filetype=sh
|
||||
|
@ -448,7 +448,8 @@ function start_service() {
|
||||
$PODMAN_BIN unshare true
|
||||
fi
|
||||
|
||||
$PODMAN_BIN \
|
||||
CONTAINERS_REGISTRIES_CONF=$TESTS_DIR/../registries.conf \
|
||||
$PODMAN_BIN \
|
||||
--root $WORKDIR/server_root --syslog=true \
|
||||
system service \
|
||||
--time 0 \
|
||||
|
@ -21,3 +21,7 @@ location="quay.io/libpod"
|
||||
[[registry]]
|
||||
location="localhost:5000"
|
||||
insecure=true
|
||||
|
||||
# Alias used in tests.
|
||||
[aliases]
|
||||
"podman-desktop-test123"="florent.fr/will/like"
|
||||
|
Reference in New Issue
Block a user