podmanV2: implement pull

Implement pulling images for the v2 client.  What I _really_ don't like
is the fact that we are now having a near identical code clone among
`pkg/domain/infra/abi` and `pkg/api/handlers/libpod`.  Partly because we
don't yet have a higher-level pull function and partly because we have
redudancy among `pkg/domain` and `pkg/api`.  Pull might be a high
outlier but I am concerned already by the potential of introducing more
redundancy.  I'd love to `infra/abi` and `pkg/abi` to really use the
same code in the future.

Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
This commit is contained in:
Valentin Rothberg
2020-03-30 12:13:50 +02:00
parent 598bb53d46
commit 3bdad6fa2a
8 changed files with 356 additions and 5 deletions

View File

@ -303,6 +303,10 @@ func ImagesImport(w http.ResponseWriter, r *http.Request) {
utils.WriteResponse(w, http.StatusOK, handlers.LibpodImagesImportReport{ID: importedImage})
}
// ImagesPull is the v2 libpod endpoint for pulling images. Note that the
// mandatory `reference` must be a reference to a registry (i.e., of docker
// transport or be normalized to one). Other transports are rejected as they
// do not make sense in a remote context.
func ImagesPull(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value("runtime").(*libpod.Runtime)
decoder := r.Context().Value("decoder").(*schema.Decoder)
@ -328,10 +332,11 @@ func ImagesPull(w http.ResponseWriter, r *http.Request) {
return
}
// Enforce the docker transport. This is just a precaution as some callers
// might accustomed to using the "transport:reference" notation. Using
// might be accustomed to using the "transport:reference" notation. Using
// another than the "docker://" transport does not really make sense for a
// remote case. For loading tarballs, the load and import endpoints should
// be used.
dockerPrefix := fmt.Sprintf("%s://", docker.Transport.Name())
imageRef, err := alltransports.ParseImageName(query.Reference)
if err == nil && imageRef.Transport().Name() != docker.Transport.Name() {
utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
@ -339,7 +344,7 @@ func ImagesPull(w http.ResponseWriter, r *http.Request) {
return
} else if err != nil {
origErr := err
imageRef, err = alltransports.ParseImageName(fmt.Sprintf("%s://%s", docker.Transport.Name(), query.Reference))
imageRef, err = alltransports.ParseImageName(fmt.Sprintf("%s%s", dockerPrefix, query.Reference))
if err != nil {
utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
errors.Wrapf(origErr, "reference %q must be a docker reference", query.Reference))
@ -347,16 +352,19 @@ func ImagesPull(w http.ResponseWriter, r *http.Request) {
}
}
// Trim the docker-transport prefix.
rawImage := strings.TrimPrefix(query.Reference, dockerPrefix)
// all-tags doesn't work with a tagged reference, so let's check early
namedRef, err := reference.Parse(query.Reference)
namedRef, err := reference.Parse(rawImage)
if err != nil {
utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
errors.Wrapf(err, "error parsing reference %q", query.Reference))
errors.Wrapf(err, "error parsing reference %q", rawImage))
return
}
if _, isTagged := namedRef.(reference.Tagged); isTagged && query.AllTags {
utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
errors.Errorf("reference %q must not have a tag for all-tags", query.Reference))
errors.Errorf("reference %q must not have a tag for all-tags", rawImage))
return
}