fix remote untag

Fix the remote client to untag all tags of the specified image.
Instead of querying the image on the client side, support the
case where both, repo and tag, are empty and remove all tags.

Reuse the ABI implementation where possible.  In retrospective,
the libpod untag endpoint should support a slice of strings to
batch remove tags rather than reaching out for each tag individually.

Enable the skipped test.

Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
This commit is contained in:
Valentin Rothberg
2020-09-30 11:57:31 +02:00
parent b68b6f334d
commit 1a3e409412
4 changed files with 34 additions and 24 deletions

View File

@ -560,24 +560,41 @@ func CommitContainer(w http.ResponseWriter, r *http.Request) {
func UntagImage(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value("runtime").(*libpod.Runtime)
name := utils.GetName(r)
newImage, err := runtime.ImageRuntime().NewFromLocal(name)
if err != nil {
utils.ImageNotFound(w, name, errors.Wrapf(err, "Failed to find image %s", name))
return
}
tag := "latest"
if len(r.Form.Get("tag")) > 0 {
tag = r.Form.Get("tag")
}
if len(r.Form.Get("repo")) < 1 {
tags := []string{} // Note: if empty, all tags will be removed from the image.
repo := r.Form.Get("repo")
tag := r.Form.Get("tag")
// Do the parameter dance.
switch {
// If tag is set, repo must be as well.
case len(repo) == 0 && len(tag) > 0:
utils.Error(w, "repo tag is required", http.StatusBadRequest, errors.New("repo parameter is required to tag an image"))
return
case len(repo) == 0:
break
// If repo is specified, we need to add that to the tags.
default:
if len(tag) == 0 {
// Normalize tag to "latest" if empty.
tag = "latest"
}
tags = append(tags, fmt.Sprintf("%s:%s", repo, tag))
}
repo := r.Form.Get("repo")
tagName := fmt.Sprintf("%s:%s", repo, tag)
if err := newImage.UntagImage(tagName); err != nil {
utils.Error(w, "failed to untag", http.StatusInternalServerError, err)
// Now use the ABI implementation to prevent us from having duplicate
// code.
opts := entities.ImageUntagOptions{}
imageEngine := abi.ImageEngine{Libpod: runtime}
name := utils.GetName(r)
if err := imageEngine.Untag(r.Context(), name, tags, opts); err != nil {
if errors.Cause(err) == define.ErrNoSuchImage {
utils.ImageNotFound(w, name, errors.Wrapf(err, "Failed to find image %s", name))
} else {
utils.Error(w, "failed to untag", http.StatusInternalServerError, err)
}
return
}
utils.WriteResponse(w, http.StatusCreated, "")

View File

@ -1175,7 +1175,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// tags:
// - images
// summary: Untag an image
// description: Untag an image
// description: Untag an image. If not repo and tag are specified, all tags are removed from the image.
// parameters:
// - in: path
// name: name:.*

View File

@ -9,7 +9,6 @@ import (
"github.com/containers/common/pkg/config"
"github.com/containers/image/v5/docker/reference"
"github.com/containers/podman/v2/pkg/bindings"
images "github.com/containers/podman/v2/pkg/bindings/images"
"github.com/containers/podman/v2/pkg/domain/entities"
"github.com/containers/podman/v2/pkg/domain/utils"
@ -139,13 +138,8 @@ func (ir *ImageEngine) Tag(ctx context.Context, nameOrID string, tags []string,
}
func (ir *ImageEngine) Untag(ctx context.Context, nameOrID string, tags []string, options entities.ImageUntagOptions) error {
// Remove all tags if none are provided
if len(tags) == 0 {
newImage, err := images.GetImage(ir.ClientCxt, nameOrID, bindings.PFalse)
if err != nil {
return err
}
tags = newImage.NamesHistory
return images.Untag(ir.ClientCxt, nameOrID, "", "")
}
for _, newTag := range tags {

View File

@ -33,7 +33,6 @@ var _ = Describe("Podman untag", func() {
})
It("podman untag all", func() {
SkipIfRemote("FIXME This should work on podman-remote")
setup := podmanTest.PodmanNoCache([]string{"pull", ALPINE})
setup.WaitWithDefaultTimeout()
Expect(setup.ExitCode()).To(Equal(0))