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) { func UntagImage(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value("runtime").(*libpod.Runtime) runtime := r.Context().Value("runtime").(*libpod.Runtime)
name := utils.GetName(r) tags := []string{} // Note: if empty, all tags will be removed from the image.
newImage, err := runtime.ImageRuntime().NewFromLocal(name) repo := r.Form.Get("repo")
if err != nil { tag := r.Form.Get("tag")
utils.ImageNotFound(w, name, errors.Wrapf(err, "Failed to find image %s", name))
return // Do the parameter dance.
} switch {
tag := "latest" // If tag is set, repo must be as well.
if len(r.Form.Get("tag")) > 0 { case len(repo) == 0 && len(tag) > 0:
tag = r.Form.Get("tag")
}
if len(r.Form.Get("repo")) < 1 {
utils.Error(w, "repo tag is required", http.StatusBadRequest, errors.New("repo parameter is required to tag an image")) utils.Error(w, "repo tag is required", http.StatusBadRequest, errors.New("repo parameter is required to tag an image"))
return 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) // Now use the ABI implementation to prevent us from having duplicate
if err := newImage.UntagImage(tagName); err != nil { // code.
utils.Error(w, "failed to untag", http.StatusInternalServerError, err) 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 return
} }
utils.WriteResponse(w, http.StatusCreated, "") utils.WriteResponse(w, http.StatusCreated, "")

View File

@ -1175,7 +1175,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// tags: // tags:
// - images // - images
// summary: Untag an image // 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: // parameters:
// - in: path // - in: path
// name: name:.* // name: name:.*

View File

@ -9,7 +9,6 @@ import (
"github.com/containers/common/pkg/config" "github.com/containers/common/pkg/config"
"github.com/containers/image/v5/docker/reference" "github.com/containers/image/v5/docker/reference"
"github.com/containers/podman/v2/pkg/bindings"
images "github.com/containers/podman/v2/pkg/bindings/images" images "github.com/containers/podman/v2/pkg/bindings/images"
"github.com/containers/podman/v2/pkg/domain/entities" "github.com/containers/podman/v2/pkg/domain/entities"
"github.com/containers/podman/v2/pkg/domain/utils" "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 { 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 { if len(tags) == 0 {
newImage, err := images.GetImage(ir.ClientCxt, nameOrID, bindings.PFalse) return images.Untag(ir.ClientCxt, nameOrID, "", "")
if err != nil {
return err
}
tags = newImage.NamesHistory
} }
for _, newTag := range tags { for _, newTag := range tags {

View File

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