Add /{containers,volumes,images}/prune API endpoint
These new endpoints request the daemon to delete all resources considered "unused" in their respective category: - all stopped containers - all volumes not attached to any containers - images with no associated containers Signed-off-by: Kenfe-Mickael Laventure <mickael.laventure@gmail.com> Upstream-commit: 33f4d68f4dc0506382c31b908905480ab0e559fa Component: engine
This commit is contained in:
@ -62,6 +62,11 @@ type attachBackend interface {
|
||||
ContainerAttach(name string, c *backend.ContainerAttachConfig) error
|
||||
}
|
||||
|
||||
// systemBackend includes functions to implement to provide system wide containers functionality
|
||||
type systemBackend interface {
|
||||
ContainersPrune(config *types.ContainersPruneConfig) (*types.ContainersPruneReport, error)
|
||||
}
|
||||
|
||||
// Backend is all the methods that need to be implemented to provide container specific functionality.
|
||||
type Backend interface {
|
||||
execBackend
|
||||
@ -69,4 +74,5 @@ type Backend interface {
|
||||
stateBackend
|
||||
monitorBackend
|
||||
attachBackend
|
||||
systemBackend
|
||||
}
|
||||
|
||||
@ -68,6 +68,7 @@ func (r *containerRouter) initRoutes() {
|
||||
router.NewPostRoute("/exec/{name:.*}/resize", r.postContainerExecResize),
|
||||
router.NewPostRoute("/containers/{name:.*}/rename", r.postContainerRename),
|
||||
router.NewPostRoute("/containers/{name:.*}/update", r.postContainerUpdate),
|
||||
router.NewPostRoute("/containers/prune", r.postContainersPrune),
|
||||
// PUT
|
||||
router.NewPutRoute("/containers/{name:.*}/archive", r.putContainersArchive),
|
||||
// DELETE
|
||||
|
||||
@ -524,3 +524,24 @@ func (s *containerRouter) wsContainersAttach(ctx context.Context, w http.Respons
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *containerRouter) postContainersPrune(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
if err := httputils.ParseForm(r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := httputils.CheckForJSON(r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var cfg types.ContainersPruneConfig
|
||||
if err := json.NewDecoder(r.Body).Decode(&cfg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pruneReport, err := s.backend.ContainersPrune(&cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return httputils.WriteJSON(w, http.StatusOK, pruneReport)
|
||||
}
|
||||
|
||||
@ -28,6 +28,7 @@ type imageBackend interface {
|
||||
Images(filterArgs string, filter string, all bool, withExtraAttrs bool) ([]*types.Image, error)
|
||||
LookupImage(name string) (*types.ImageInspect, error)
|
||||
TagImage(imageName, repository, tag string) error
|
||||
ImagesPrune(config *types.ImagesPruneConfig) (*types.ImagesPruneReport, error)
|
||||
}
|
||||
|
||||
type importExportBackend interface {
|
||||
|
||||
@ -43,6 +43,7 @@ func (r *imageRouter) initRoutes() {
|
||||
router.Cancellable(router.NewPostRoute("/images/create", r.postImagesCreate)),
|
||||
router.Cancellable(router.NewPostRoute("/images/{name:.*}/push", r.postImagesPush)),
|
||||
router.NewPostRoute("/images/{name:.*}/tag", r.postImagesTag),
|
||||
router.NewPostRoute("/images/prune", r.postImagesPrune),
|
||||
// DELETE
|
||||
router.NewDeleteRoute("/images/{name:.*}", r.deleteImages),
|
||||
}
|
||||
|
||||
@ -314,3 +314,24 @@ func (s *imageRouter) getImagesSearch(ctx context.Context, w http.ResponseWriter
|
||||
}
|
||||
return httputils.WriteJSON(w, http.StatusOK, query.Results)
|
||||
}
|
||||
|
||||
func (s *imageRouter) postImagesPrune(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
if err := httputils.ParseForm(r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := httputils.CheckForJSON(r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var cfg types.ImagesPruneConfig
|
||||
if err := json.NewDecoder(r.Body).Decode(&cfg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pruneReport, err := s.backend.ImagesPrune(&cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return httputils.WriteJSON(w, http.StatusOK, pruneReport)
|
||||
}
|
||||
|
||||
@ -12,4 +12,5 @@ type Backend interface {
|
||||
VolumeInspect(name string) (*types.Volume, error)
|
||||
VolumeCreate(name, driverName string, opts, labels map[string]string) (*types.Volume, error)
|
||||
VolumeRm(name string, force bool) error
|
||||
VolumesPrune(config *types.VolumesPruneConfig) (*types.VolumesPruneReport, error)
|
||||
}
|
||||
|
||||
@ -29,6 +29,7 @@ func (r *volumeRouter) initRoutes() {
|
||||
router.NewGetRoute("/volumes/{name:.*}", r.getVolumeByName),
|
||||
// POST
|
||||
router.NewPostRoute("/volumes/create", r.postVolumesCreate),
|
||||
router.NewPostRoute("/volumes/prune", r.postVolumesPrune),
|
||||
// DELETE
|
||||
router.NewDeleteRoute("/volumes/{name:.*}", r.deleteVolumes),
|
||||
}
|
||||
|
||||
@ -65,3 +65,24 @@ func (v *volumeRouter) deleteVolumes(ctx context.Context, w http.ResponseWriter,
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *volumeRouter) postVolumesPrune(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
if err := httputils.ParseForm(r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := httputils.CheckForJSON(r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var cfg types.VolumesPruneConfig
|
||||
if err := json.NewDecoder(r.Body).Decode(&cfg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pruneReport, err := v.backend.VolumesPrune(&cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return httputils.WriteJSON(w, http.StatusOK, pruneReport)
|
||||
}
|
||||
|
||||
@ -539,3 +539,40 @@ type DiskUsage struct {
|
||||
Containers []*Container
|
||||
Volumes []*Volume
|
||||
}
|
||||
|
||||
// ImagesPruneConfig contains the configuration for Remote API:
|
||||
// POST "/image/prune"
|
||||
type ImagesPruneConfig struct {
|
||||
DanglingOnly bool
|
||||
}
|
||||
|
||||
// ContainersPruneConfig contains the configuration for Remote API:
|
||||
// POST "/image/prune"
|
||||
type ContainersPruneConfig struct {
|
||||
}
|
||||
|
||||
// VolumesPruneConfig contains the configuration for Remote API:
|
||||
// POST "/images/prune"
|
||||
type VolumesPruneConfig struct {
|
||||
}
|
||||
|
||||
// ContainersPruneReport contains the response for Remote API:
|
||||
// POST "/containers/prune"
|
||||
type ContainersPruneReport struct {
|
||||
ContainersDeleted []string
|
||||
SpaceReclaimed uint64
|
||||
}
|
||||
|
||||
// VolumesPruneReport contains the response for Remote API:
|
||||
// POST "/volumes/prune"
|
||||
type VolumesPruneReport struct {
|
||||
VolumesDeleted []string
|
||||
SpaceReclaimed uint64
|
||||
}
|
||||
|
||||
// ImagesPruneReport contains the response for Remote API:
|
||||
// POST "/image/prune"
|
||||
type ImagesPruneReport struct {
|
||||
ImagesDeleted []ImageDelete
|
||||
SpaceReclaimed uint64
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user