Skip to content

Commit

Permalink
api,images: add support for LookupManifest to Image remove API
Browse files Browse the repository at this point in the history
ImagesBatchRemoval and ImageRemoval now honors and accepts
`LookupManifest` parameter which further tells libimage to resolve to
manifest list if it exists instead of actual image.

Following PR also makes `podman-remote manifest rm` functional which was
broken till now.

Closes: #14763

Signed-off-by: Aditya R <[email protected]>
  • Loading branch information
flouthoc committed Jun 30, 2022
1 parent 3426d56 commit 7bbfb3e
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 8 deletions.
16 changes: 9 additions & 7 deletions pkg/api/handlers/libpod/images.go
Original file line number Diff line number Diff line change
Expand Up @@ -615,18 +615,19 @@ func ImagesBatchRemove(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
All bool `schema:"all"`
Force bool `schema:"force"`
Ignore bool `schema:"ignore"`
Images []string `schema:"images"`
All bool `schema:"all"`
Force bool `schema:"force"`
Ignore bool `schema:"ignore"`
LookupManifest bool `schema:"lookupManifest"`
Images []string `schema:"images"`
}{}

if err := decoder.Decode(&query, r.URL.Query()); err != nil {
utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}

opts := entities.ImageRemoveOptions{All: query.All, Force: query.Force, Ignore: query.Ignore}
opts := entities.ImageRemoveOptions{All: query.All, Force: query.Force, Ignore: query.Ignore, LookupManifest: query.LookupManifest}
imageEngine := abi.ImageEngine{Libpod: runtime}
rmReport, rmErrors := imageEngine.Remove(r.Context(), query.Images, opts)
strErrs := errorhandling.ErrorsToStrings(rmErrors)
Expand All @@ -639,7 +640,8 @@ func ImagesRemove(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
Force bool `schema:"force"`
Force bool `schema:"force"`
LookupManifest bool `schema:"lookupManifest"`
}{
Force: false,
}
Expand All @@ -649,7 +651,7 @@ func ImagesRemove(w http.ResponseWriter, r *http.Request) {
return
}

opts := entities.ImageRemoveOptions{Force: query.Force}
opts := entities.ImageRemoveOptions{Force: query.Force, LookupManifest: query.LookupManifest}
imageEngine := abi.ImageEngine{Libpod: runtime}
rmReport, rmErrors := imageEngine.Remove(r.Context(), []string{utils.GetName(r)}, opts)

Expand Down
4 changes: 4 additions & 0 deletions pkg/api/server/register_images.go
Original file line number Diff line number Diff line change
Expand Up @@ -948,6 +948,10 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// name: ignore
// description: Ignore if a specified image does not exist and do not throw an error.
// type: boolean
// - in: query
// name: lookupManifest
// description: Resolves to manifest list instead of image.
// type: boolean
// produces:
// - application/json
// responses:
Expand Down
2 changes: 2 additions & 0 deletions pkg/bindings/images/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ type RemoveOptions struct {
Force *bool
// Ignore if a specified image does not exist and do not throw an error.
Ignore *bool
// Confirms if given name is a manifest list and removes it, otherwise returns error.
LookupManifest *bool
}

//go:generate go run ../generator/generator.go DiffOptions
Expand Down
15 changes: 15 additions & 0 deletions pkg/bindings/images/types_remove_options.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pkg/domain/infra/tunnel/images.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func (ir *ImageEngine) Exists(_ context.Context, nameOrID string) (*entities.Boo
}

func (ir *ImageEngine) Remove(ctx context.Context, imagesArg []string, opts entities.ImageRemoveOptions) (*entities.ImageRemoveReport, []error) {
options := new(images.RemoveOptions).WithForce(opts.Force).WithIgnore(opts.Ignore).WithAll(opts.All)
options := new(images.RemoveOptions).WithForce(opts.Force).WithIgnore(opts.Ignore).WithAll(opts.All).WithLookupManifest(opts.LookupManifest)
return images.Remove(ir.ClientCtx, imagesArg, options)
}

Expand Down
28 changes: 28 additions & 0 deletions test/e2e/manifest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -405,4 +405,32 @@ var _ = Describe("Podman manifest", func() {
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
})

It("manifest rm should not remove image and should be able to remove tagged manifest list", func() {
// manifest rm should fail with `image is not a manifest list`
session := podmanTest.Podman([]string{"manifest", "rm", ALPINE})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(125))
Expect(session.ErrorToString()).To(ContainSubstring("image is not a manifest list"))

manifestName := "testmanifest:sometag"
session = podmanTest.Podman([]string{"manifest", "create", manifestName})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))

// verify if manifest exists
session = podmanTest.Podman([]string{"manifest", "exists", manifestName})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))

// manifest rm should be able to remove tagged manifest list
session = podmanTest.Podman([]string{"manifest", "rm", manifestName})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))

// verify that manifest should not exist
session = podmanTest.Podman([]string{"manifest", "exists", manifestName})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(1))
})
})

0 comments on commit 7bbfb3e

Please sign in to comment.