mirror of
https://github.com/containers/podman.git
synced 2025-10-17 19:24:04 +08:00
bug: Correct Docker compat REST API image delete endpoint
The Docker `-XDELETE image/$name?force=true` endpoint only removes containers using an image if they are in a non running state. In Podman, when forcefully removing images we also forcefully delete containers using the image including running containers. This patch changes the Docker image force delete compat API to act like the Docker API while maintaining commands like `podman rmi -f $imagename` It also corrects the API return code returned when an image is requested to be deleted with running containers using it. Fixes: https://github.com/containers/podman/issues/25871 Signed-off-by: Lewis Roy <lewis@redhat.com>
This commit is contained in:
@ -8,6 +8,7 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/containers/podman/v5/libpod"
|
||||
"github.com/containers/podman/v5/libpod/define"
|
||||
"github.com/containers/podman/v5/pkg/api/handlers/utils"
|
||||
api "github.com/containers/podman/v5/pkg/api/types"
|
||||
"github.com/containers/podman/v5/pkg/domain/entities"
|
||||
@ -41,9 +42,10 @@ func RemoveImage(w http.ResponseWriter, r *http.Request) {
|
||||
imageEngine := abi.ImageEngine{Libpod: runtime}
|
||||
|
||||
options := entities.ImageRemoveOptions{
|
||||
Force: query.Force,
|
||||
NoPrune: query.NoPrune,
|
||||
Ignore: query.Ignore,
|
||||
Force: query.Force,
|
||||
NoPrune: query.NoPrune,
|
||||
Ignore: query.Ignore,
|
||||
DisableForceRemoveContainers: true,
|
||||
}
|
||||
report, rmerrors := imageEngine.Remove(r.Context(), []string{possiblyNormalizedName}, options)
|
||||
if len(rmerrors) > 0 && rmerrors[0] != nil {
|
||||
@ -56,6 +58,10 @@ func RemoveImage(w http.ResponseWriter, r *http.Request) {
|
||||
utils.Error(w, http.StatusConflict, fmt.Errorf("image %s is in use: %w", name, err))
|
||||
return
|
||||
}
|
||||
if errors.Is(err, define.ErrCtrStateInvalid) {
|
||||
utils.Error(w, http.StatusConflict, fmt.Errorf("image %s is in an invalid state: %w", name, err))
|
||||
return
|
||||
}
|
||||
utils.Error(w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
@ -227,7 +227,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
|
||||
// - in: query
|
||||
// name: force
|
||||
// type: boolean
|
||||
// description: remove the image even if used by containers or has other tags
|
||||
// description: Remove the image even if it is being used by stopped containers or has other tags
|
||||
// - in: query
|
||||
// name: noprune
|
||||
// type: boolean
|
||||
|
@ -64,7 +64,8 @@ type ImageRemoveOptions struct {
|
||||
// Confirms if given name is a manifest list and removes it, otherwise returns error.
|
||||
LookupManifest bool
|
||||
// NoPrune will not remove dangling images
|
||||
NoPrune bool
|
||||
NoPrune bool
|
||||
DisableForceRemoveContainers bool
|
||||
}
|
||||
|
||||
// ImageRemoveReport is the response for removing one or more image(s) from storage
|
||||
@ -73,8 +74,10 @@ type ImageRemoveReport = entitiesTypes.ImageRemoveReport
|
||||
|
||||
type ImageHistoryOptions struct{}
|
||||
|
||||
type ImageHistoryLayer = entitiesTypes.ImageHistoryLayer
|
||||
type ImageHistoryReport = entitiesTypes.ImageHistoryReport
|
||||
type (
|
||||
ImageHistoryLayer = entitiesTypes.ImageHistoryLayer
|
||||
ImageHistoryReport = entitiesTypes.ImageHistoryReport
|
||||
)
|
||||
|
||||
// ImagePullOptions are the arguments for pulling images.
|
||||
type ImagePullOptions struct {
|
||||
@ -255,8 +258,10 @@ type ImagePruneOptions struct {
|
||||
Filter []string `json:"filter" schema:"filter"`
|
||||
}
|
||||
|
||||
type ImageTagOptions struct{}
|
||||
type ImageUntagOptions struct{}
|
||||
type (
|
||||
ImageTagOptions struct{}
|
||||
ImageUntagOptions struct{}
|
||||
)
|
||||
|
||||
// ImageInspectReport is the data when inspecting an image.
|
||||
type ImageInspectReport = entitiesTypes.ImageInspectReport
|
||||
|
@ -58,7 +58,7 @@ func (ir *ImageEngine) Exists(_ context.Context, nameOrID string) (*entities.Boo
|
||||
|
||||
func (ir *ImageEngine) Prune(ctx context.Context, opts entities.ImagePruneOptions) ([]*reports.PruneReport, error) {
|
||||
pruneOptions := &libimage.RemoveImagesOptions{
|
||||
RemoveContainerFunc: ir.Libpod.RemoveContainersForImageCallback(ctx),
|
||||
RemoveContainerFunc: ir.Libpod.RemoveContainersForImageCallback(ctx, true),
|
||||
IsExternalContainerFunc: ir.Libpod.IsExternalContainerCallback(ctx),
|
||||
ExternalContainers: opts.External,
|
||||
Filters: append(opts.Filter, "readonly=false"),
|
||||
@ -666,7 +666,7 @@ func (ir *ImageEngine) Remove(ctx context.Context, images []string, opts entitie
|
||||
if !opts.All {
|
||||
libimageOptions.Filters = append(libimageOptions.Filters, "intermediate=false")
|
||||
}
|
||||
libimageOptions.RemoveContainerFunc = ir.Libpod.RemoveContainersForImageCallback(ctx)
|
||||
libimageOptions.RemoveContainerFunc = ir.Libpod.RemoveContainersForImageCallback(ctx, !opts.DisableForceRemoveContainers)
|
||||
|
||||
libimageReport, libimageErrors := ir.Libpod.LibimageRuntime().RemoveImages(ctx, images, libimageOptions)
|
||||
|
||||
|
Reference in New Issue
Block a user