Skip to content

Commit f7afaf9

Browse files
Merge pull request #21455 from vrothberg/resolve-endpoint
add new libpod/images/$name/resolve endpoint
2 parents 1a8cb15 + b028f6a commit f7afaf9

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)