mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #28535 from yongtang/28497-prune-until
Convert DanglingOnly to Filters for `docker image prune`
This commit is contained in:
commit
745795ef2e
22 changed files with 171 additions and 108 deletions
|
@ -9,6 +9,7 @@ import (
|
|||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/backend"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
)
|
||||
|
||||
|
@ -64,7 +65,7 @@ type attachBackend interface {
|
|||
|
||||
// systemBackend includes functions to implement to provide system wide containers functionality
|
||||
type systemBackend interface {
|
||||
ContainersPrune(config *types.ContainersPruneConfig) (*types.ContainersPruneReport, error)
|
||||
ContainersPrune(pruneFilters filters.Args) (*types.ContainersPruneReport, error)
|
||||
}
|
||||
|
||||
// Backend is all the methods that need to be implemented to provide container specific functionality.
|
||||
|
|
|
@ -541,16 +541,12 @@ func (s *containerRouter) postContainersPrune(ctx context.Context, w http.Respon
|
|||
return err
|
||||
}
|
||||
|
||||
if err := httputils.CheckForJSON(r); err != nil {
|
||||
pruneFilters, err := filters.FromParam(r.Form.Get("filters"))
|
||||
if 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)
|
||||
pruneReport, err := s.backend.ContainersPrune(pruneFilters)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ type imageBackend interface {
|
|||
Images(imageFilters filters.Args, all bool, withExtraAttrs bool) ([]*types.ImageSummary, error)
|
||||
LookupImage(name string) (*types.ImageInspect, error)
|
||||
TagImage(imageName, repository, tag string) error
|
||||
ImagesPrune(config *types.ImagesPruneConfig) (*types.ImagesPruneReport, error)
|
||||
ImagesPrune(pruneFilters filters.Args) (*types.ImagesPruneReport, error)
|
||||
}
|
||||
|
||||
type importExportBackend interface {
|
||||
|
|
|
@ -331,16 +331,12 @@ func (s *imageRouter) postImagesPrune(ctx context.Context, w http.ResponseWriter
|
|||
return err
|
||||
}
|
||||
|
||||
if err := httputils.CheckForJSON(r); err != nil {
|
||||
pruneFilters, err := filters.FromParam(r.Form.Get("filters"))
|
||||
if 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)
|
||||
pruneReport, err := s.backend.ImagesPrune(pruneFilters)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package network
|
|||
|
||||
import (
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/api/types/network"
|
||||
"github.com/docker/libnetwork"
|
||||
)
|
||||
|
@ -17,5 +18,5 @@ type Backend interface {
|
|||
ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error
|
||||
DisconnectContainerFromNetwork(containerName string, networkName string, force bool) error
|
||||
DeleteNetwork(name string) error
|
||||
NetworksPrune(config *types.NetworksPruneConfig) (*types.NetworksPruneReport, error)
|
||||
NetworksPrune(pruneFilters filters.Args) (*types.NetworksPruneReport, error)
|
||||
}
|
||||
|
|
|
@ -297,16 +297,7 @@ func (n *networkRouter) postNetworksPrune(ctx context.Context, w http.ResponseWr
|
|||
return err
|
||||
}
|
||||
|
||||
if err := httputils.CheckForJSON(r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var cfg types.NetworksPruneConfig
|
||||
if err := json.NewDecoder(r.Body).Decode(&cfg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pruneReport, err := n.backend.NetworksPrune(&cfg)
|
||||
pruneReport, err := n.backend.NetworksPrune(filters.Args{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package volume
|
|||
import (
|
||||
// TODO return types need to be refactored into pkg
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
)
|
||||
|
||||
// Backend is the methods that need to be implemented to provide
|
||||
|
@ -12,5 +13,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)
|
||||
VolumesPrune(pruneFilters filters.Args) (*types.VolumesPruneReport, error)
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"net/http"
|
||||
|
||||
"github.com/docker/docker/api/server/httputils"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
volumetypes "github.com/docker/docker/api/types/volume"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
@ -72,16 +72,7 @@ func (v *volumeRouter) postVolumesPrune(ctx context.Context, w http.ResponseWrit
|
|||
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)
|
||||
pruneReport, err := v.backend.VolumesPrune(filters.Args{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -4187,11 +4187,17 @@ paths:
|
|||
/containers/prune:
|
||||
post:
|
||||
summary: "Delete stopped containers"
|
||||
consumes:
|
||||
- "application/json"
|
||||
produces:
|
||||
- "application/json"
|
||||
operationId: "ContainerPrune"
|
||||
parameters:
|
||||
- name: "filters"
|
||||
in: "query"
|
||||
description: |
|
||||
Filters to process on the prune list, encoded as JSON (a `map[string][]string`).
|
||||
|
||||
Available filters:
|
||||
type: "string"
|
||||
responses:
|
||||
200:
|
||||
description: "No error"
|
||||
|
@ -4849,21 +4855,20 @@ paths:
|
|||
/images/prune:
|
||||
post:
|
||||
summary: "Delete unused images"
|
||||
consumes:
|
||||
- "application/json"
|
||||
produces:
|
||||
- "application/json"
|
||||
operationId: "ImagePrune"
|
||||
parameters:
|
||||
- name: "body"
|
||||
in: "body"
|
||||
schema:
|
||||
type: "object"
|
||||
properties:
|
||||
DanglingOnly:
|
||||
description: "Only delete unused *and* untagged images"
|
||||
type: "boolean"
|
||||
default: false
|
||||
- name: "filters"
|
||||
in: "query"
|
||||
description: |
|
||||
Filters to process on the prune list, encoded as JSON (a `map[string][]string`).
|
||||
|
||||
Available filters:
|
||||
- `dangling=<boolean>` When set to `true` (or `1`), prune only
|
||||
unused *and* untagged images. When set to `false`
|
||||
(or `0`), all unused images are pruned.
|
||||
type: "string"
|
||||
responses:
|
||||
200:
|
||||
description: "No error"
|
||||
|
@ -5945,11 +5950,17 @@ paths:
|
|||
/volumes/prune:
|
||||
post:
|
||||
summary: "Delete unused volumes"
|
||||
consumes:
|
||||
- "application/json"
|
||||
produces:
|
||||
- "application/json"
|
||||
operationId: "VolumePrune"
|
||||
parameters:
|
||||
- name: "filters"
|
||||
in: "query"
|
||||
description: |
|
||||
Filters to process on the prune list, encoded as JSON (a `map[string][]string`).
|
||||
|
||||
Available filters:
|
||||
type: "string"
|
||||
responses:
|
||||
200:
|
||||
description: "No error"
|
||||
|
@ -6287,6 +6298,14 @@ paths:
|
|||
produces:
|
||||
- "application/json"
|
||||
operationId: "NetworkPrune"
|
||||
parameters:
|
||||
- name: "filters"
|
||||
in: "query"
|
||||
description: |
|
||||
Filters to process on the prune list, encoded as JSON (a `map[string][]string`).
|
||||
|
||||
Available filters:
|
||||
type: "string"
|
||||
responses:
|
||||
200:
|
||||
description: "No error"
|
||||
|
|
|
@ -509,27 +509,6 @@ type DiskUsage struct {
|
|||
Volumes []*Volume
|
||||
}
|
||||
|
||||
// ImagesPruneConfig contains the configuration for Engine API:
|
||||
// POST "/images/prune"
|
||||
type ImagesPruneConfig struct {
|
||||
DanglingOnly bool
|
||||
}
|
||||
|
||||
// ContainersPruneConfig contains the configuration for Engine API:
|
||||
// POST "/images/prune"
|
||||
type ContainersPruneConfig struct {
|
||||
}
|
||||
|
||||
// VolumesPruneConfig contains the configuration for Engine API:
|
||||
// POST "/images/prune"
|
||||
type VolumesPruneConfig struct {
|
||||
}
|
||||
|
||||
// NetworksPruneConfig contains the configuration for Engine API:
|
||||
// POST "/networks/prune"
|
||||
type NetworksPruneConfig struct {
|
||||
}
|
||||
|
||||
// ContainersPruneReport contains the response for Engine API:
|
||||
// POST "/containers/prune"
|
||||
type ContainersPruneReport struct {
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/cli"
|
||||
"github.com/docker/docker/cli/command"
|
||||
units "github.com/docker/go-units"
|
||||
|
@ -52,7 +52,7 @@ func runPrune(dockerCli *command.DockerCli, opts pruneOptions) (spaceReclaimed u
|
|||
return
|
||||
}
|
||||
|
||||
report, err := dockerCli.Client().ContainersPrune(context.Background(), types.ContainersPruneConfig{})
|
||||
report, err := dockerCli.Client().ContainersPrune(context.Background(), filters.Args{})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/cli"
|
||||
"github.com/docker/docker/cli/command"
|
||||
units "github.com/docker/go-units"
|
||||
|
@ -54,6 +54,9 @@ Are you sure you want to continue?`
|
|||
)
|
||||
|
||||
func runPrune(dockerCli *command.DockerCli, opts pruneOptions) (spaceReclaimed uint64, output string, err error) {
|
||||
pruneFilters := filters.NewArgs()
|
||||
pruneFilters.Add("dangling", fmt.Sprintf("%v", !opts.all))
|
||||
|
||||
warning := danglingWarning
|
||||
if opts.all {
|
||||
warning = allImageWarning
|
||||
|
@ -62,9 +65,7 @@ func runPrune(dockerCli *command.DockerCli, opts pruneOptions) (spaceReclaimed u
|
|||
return
|
||||
}
|
||||
|
||||
report, err := dockerCli.Client().ImagesPrune(context.Background(), types.ImagesPruneConfig{
|
||||
DanglingOnly: !opts.all,
|
||||
})
|
||||
report, err := dockerCli.Client().ImagesPrune(context.Background(), pruneFilters)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/cli"
|
||||
"github.com/docker/docker/cli/command"
|
||||
"github.com/spf13/cobra"
|
||||
|
@ -50,7 +50,7 @@ func runPrune(dockerCli *command.DockerCli, opts pruneOptions) (output string, e
|
|||
return
|
||||
}
|
||||
|
||||
report, err := dockerCli.Client().NetworksPrune(context.Background(), types.NetworksPruneConfig{})
|
||||
report, err := dockerCli.Client().NetworksPrune(context.Background(), filters.Args{})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/cli"
|
||||
"github.com/docker/docker/cli/command"
|
||||
units "github.com/docker/go-units"
|
||||
|
@ -52,7 +52,7 @@ func runPrune(dockerCli *command.DockerCli, opts pruneOptions) (spaceReclaimed u
|
|||
return
|
||||
}
|
||||
|
||||
report, err := dockerCli.Client().VolumesPrune(context.Background(), types.VolumesPruneConfig{})
|
||||
report, err := dockerCli.Client().VolumesPrune(context.Background(), filters.Args{})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -5,18 +5,24 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// ContainersPrune requests the daemon to delete unused data
|
||||
func (cli *Client) ContainersPrune(ctx context.Context, cfg types.ContainersPruneConfig) (types.ContainersPruneReport, error) {
|
||||
func (cli *Client) ContainersPrune(ctx context.Context, pruneFilters filters.Args) (types.ContainersPruneReport, error) {
|
||||
var report types.ContainersPruneReport
|
||||
|
||||
if err := cli.NewVersionError("1.25", "container prune"); err != nil {
|
||||
return report, err
|
||||
}
|
||||
|
||||
serverResp, err := cli.post(ctx, "/containers/prune", nil, cfg, nil)
|
||||
query, err := getFiltersQuery(pruneFilters)
|
||||
if err != nil {
|
||||
return report, err
|
||||
}
|
||||
|
||||
serverResp, err := cli.post(ctx, "/containers/prune", query, nil, nil)
|
||||
if err != nil {
|
||||
return report, err
|
||||
}
|
||||
|
|
|
@ -5,18 +5,24 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// ImagesPrune requests the daemon to delete unused data
|
||||
func (cli *Client) ImagesPrune(ctx context.Context, cfg types.ImagesPruneConfig) (types.ImagesPruneReport, error) {
|
||||
func (cli *Client) ImagesPrune(ctx context.Context, pruneFilters filters.Args) (types.ImagesPruneReport, error) {
|
||||
var report types.ImagesPruneReport
|
||||
|
||||
if err := cli.NewVersionError("1.25", "image prune"); err != nil {
|
||||
return report, err
|
||||
}
|
||||
|
||||
serverResp, err := cli.post(ctx, "/images/prune", nil, cfg, nil)
|
||||
query, err := getFiltersQuery(pruneFilters)
|
||||
if err != nil {
|
||||
return report, err
|
||||
}
|
||||
|
||||
serverResp, err := cli.post(ctx, "/images/prune", query, nil, nil)
|
||||
if err != nil {
|
||||
return report, err
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ type ContainerAPIClient interface {
|
|||
ContainerWait(ctx context.Context, container string) (int64, error)
|
||||
CopyFromContainer(ctx context.Context, container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error)
|
||||
CopyToContainer(ctx context.Context, container, path string, content io.Reader, options types.CopyToContainerOptions) error
|
||||
ContainersPrune(ctx context.Context, cfg types.ContainersPruneConfig) (types.ContainersPruneReport, error)
|
||||
ContainersPrune(ctx context.Context, pruneFilters filters.Args) (types.ContainersPruneReport, error)
|
||||
}
|
||||
|
||||
// ImageAPIClient defines API client methods for the images
|
||||
|
@ -82,7 +82,7 @@ type ImageAPIClient interface {
|
|||
ImageSearch(ctx context.Context, term string, options types.ImageSearchOptions) ([]registry.SearchResult, error)
|
||||
ImageSave(ctx context.Context, images []string) (io.ReadCloser, error)
|
||||
ImageTag(ctx context.Context, image, ref string) error
|
||||
ImagesPrune(ctx context.Context, cfg types.ImagesPruneConfig) (types.ImagesPruneReport, error)
|
||||
ImagesPrune(ctx context.Context, pruneFilter filters.Args) (types.ImagesPruneReport, error)
|
||||
}
|
||||
|
||||
// NetworkAPIClient defines API client methods for the networks
|
||||
|
@ -94,7 +94,7 @@ type NetworkAPIClient interface {
|
|||
NetworkInspectWithRaw(ctx context.Context, networkID string) (types.NetworkResource, []byte, error)
|
||||
NetworkList(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error)
|
||||
NetworkRemove(ctx context.Context, networkID string) error
|
||||
NetworksPrune(ctx context.Context, cfg types.NetworksPruneConfig) (types.NetworksPruneReport, error)
|
||||
NetworksPrune(ctx context.Context, pruneFilter filters.Args) (types.NetworksPruneReport, error)
|
||||
}
|
||||
|
||||
// NodeAPIClient defines API client methods for the nodes
|
||||
|
@ -157,7 +157,7 @@ type VolumeAPIClient interface {
|
|||
VolumeInspectWithRaw(ctx context.Context, volumeID string) (types.Volume, []byte, error)
|
||||
VolumeList(ctx context.Context, filter filters.Args) (volumetypes.VolumesListOKBody, error)
|
||||
VolumeRemove(ctx context.Context, volumeID string, force bool) error
|
||||
VolumesPrune(ctx context.Context, cfg types.VolumesPruneConfig) (types.VolumesPruneReport, error)
|
||||
VolumesPrune(ctx context.Context, pruneFilter filters.Args) (types.VolumesPruneReport, error)
|
||||
}
|
||||
|
||||
// SecretAPIClient defines API client methods for secrets
|
||||
|
|
|
@ -5,14 +5,24 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// NetworksPrune requests the daemon to delete unused networks
|
||||
func (cli *Client) NetworksPrune(ctx context.Context, cfg types.NetworksPruneConfig) (types.NetworksPruneReport, error) {
|
||||
func (cli *Client) NetworksPrune(ctx context.Context, pruneFilters filters.Args) (types.NetworksPruneReport, error) {
|
||||
var report types.NetworksPruneReport
|
||||
|
||||
serverResp, err := cli.post(ctx, "/networks/prune", nil, cfg, nil)
|
||||
if err := cli.NewVersionError("1.25", "network prune"); err != nil {
|
||||
return report, err
|
||||
}
|
||||
|
||||
query, err := getFiltersQuery(pruneFilters)
|
||||
if err != nil {
|
||||
return report, err
|
||||
}
|
||||
|
||||
serverResp, err := cli.post(ctx, "/networks/prune", query, nil, nil)
|
||||
if err != nil {
|
||||
return report, err
|
||||
}
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
package client
|
||||
|
||||
import "regexp"
|
||||
import (
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"net/url"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
var headerRegexp = regexp.MustCompile(`\ADocker/.+\s\((.+)\)\z`)
|
||||
|
||||
|
@ -13,3 +17,17 @@ func getDockerOS(serverHeader string) string {
|
|||
}
|
||||
return osType
|
||||
}
|
||||
|
||||
// getFiltersQuery returns a url query with "filters" query term, based on the
|
||||
// filters provided.
|
||||
func getFiltersQuery(f filters.Args) (url.Values, error) {
|
||||
query := url.Values{}
|
||||
if f.Len() > 0 {
|
||||
filterJSON, err := filters.ToParam(f)
|
||||
if err != nil {
|
||||
return query, err
|
||||
}
|
||||
query.Set("filters", filterJSON)
|
||||
}
|
||||
return query, nil
|
||||
}
|
||||
|
|
|
@ -5,18 +5,24 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// VolumesPrune requests the daemon to delete unused data
|
||||
func (cli *Client) VolumesPrune(ctx context.Context, cfg types.VolumesPruneConfig) (types.VolumesPruneReport, error) {
|
||||
func (cli *Client) VolumesPrune(ctx context.Context, pruneFilters filters.Args) (types.VolumesPruneReport, error) {
|
||||
var report types.VolumesPruneReport
|
||||
|
||||
if err := cli.NewVersionError("1.25", "volume prune"); err != nil {
|
||||
return report, err
|
||||
}
|
||||
|
||||
serverResp, err := cli.post(ctx, "/volumes/prune", nil, cfg, nil)
|
||||
query, err := getFiltersQuery(pruneFilters)
|
||||
if err != nil {
|
||||
return report, err
|
||||
}
|
||||
|
||||
serverResp, err := cli.post(ctx, "/volumes/prune", query, nil, nil)
|
||||
if err != nil {
|
||||
return report, err
|
||||
}
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
package daemon
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/distribution/digest"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/image"
|
||||
"github.com/docker/docker/layer"
|
||||
"github.com/docker/docker/pkg/directory"
|
||||
|
@ -16,7 +18,7 @@ import (
|
|||
)
|
||||
|
||||
// ContainersPrune removes unused containers
|
||||
func (daemon *Daemon) ContainersPrune(config *types.ContainersPruneConfig) (*types.ContainersPruneReport, error) {
|
||||
func (daemon *Daemon) ContainersPrune(pruneFilters filters.Args) (*types.ContainersPruneReport, error) {
|
||||
rep := &types.ContainersPruneReport{}
|
||||
|
||||
allContainers := daemon.List()
|
||||
|
@ -40,7 +42,7 @@ func (daemon *Daemon) ContainersPrune(config *types.ContainersPruneConfig) (*typ
|
|||
}
|
||||
|
||||
// VolumesPrune removes unused local volumes
|
||||
func (daemon *Daemon) VolumesPrune(config *types.VolumesPruneConfig) (*types.VolumesPruneReport, error) {
|
||||
func (daemon *Daemon) VolumesPrune(pruneFilters filters.Args) (*types.VolumesPruneReport, error) {
|
||||
rep := &types.VolumesPruneReport{}
|
||||
|
||||
pruneVols := func(v volume.Volume) error {
|
||||
|
@ -70,11 +72,20 @@ func (daemon *Daemon) VolumesPrune(config *types.VolumesPruneConfig) (*types.Vol
|
|||
}
|
||||
|
||||
// ImagesPrune removes unused images
|
||||
func (daemon *Daemon) ImagesPrune(config *types.ImagesPruneConfig) (*types.ImagesPruneReport, error) {
|
||||
func (daemon *Daemon) ImagesPrune(pruneFilters filters.Args) (*types.ImagesPruneReport, error) {
|
||||
rep := &types.ImagesPruneReport{}
|
||||
|
||||
danglingOnly := true
|
||||
if pruneFilters.Include("dangling") {
|
||||
if pruneFilters.ExactMatch("dangling", "false") || pruneFilters.ExactMatch("dangling", "0") {
|
||||
danglingOnly = false
|
||||
} else if !pruneFilters.ExactMatch("dangling", "true") && !pruneFilters.ExactMatch("dangling", "1") {
|
||||
return nil, fmt.Errorf("Invalid filter 'dangling=%s'", pruneFilters.Get("dangling"))
|
||||
}
|
||||
}
|
||||
|
||||
var allImages map[image.ID]*image.Image
|
||||
if config.DanglingOnly {
|
||||
if danglingOnly {
|
||||
allImages = daemon.imageStore.Heads()
|
||||
} else {
|
||||
allImages = daemon.imageStore.Map()
|
||||
|
@ -106,7 +117,7 @@ func (daemon *Daemon) ImagesPrune(config *types.ImagesPruneConfig) (*types.Image
|
|||
deletedImages := []types.ImageDelete{}
|
||||
refs := daemon.referenceStore.References(dgst)
|
||||
if len(refs) > 0 {
|
||||
if config.DanglingOnly {
|
||||
if danglingOnly {
|
||||
// Not a dangling image
|
||||
continue
|
||||
}
|
||||
|
@ -156,7 +167,7 @@ func (daemon *Daemon) ImagesPrune(config *types.ImagesPruneConfig) (*types.Image
|
|||
}
|
||||
|
||||
// localNetworksPrune removes unused local networks
|
||||
func (daemon *Daemon) localNetworksPrune(config *types.NetworksPruneConfig) (*types.NetworksPruneReport, error) {
|
||||
func (daemon *Daemon) localNetworksPrune(pruneFilters filters.Args) (*types.NetworksPruneReport, error) {
|
||||
rep := &types.NetworksPruneReport{}
|
||||
var err error
|
||||
// When the function returns true, the walk will stop.
|
||||
|
@ -177,7 +188,7 @@ func (daemon *Daemon) localNetworksPrune(config *types.NetworksPruneConfig) (*ty
|
|||
}
|
||||
|
||||
// clusterNetworksPrune removes unused cluster networks
|
||||
func (daemon *Daemon) clusterNetworksPrune(config *types.NetworksPruneConfig) (*types.NetworksPruneReport, error) {
|
||||
func (daemon *Daemon) clusterNetworksPrune(pruneFilters filters.Args) (*types.NetworksPruneReport, error) {
|
||||
rep := &types.NetworksPruneReport{}
|
||||
cluster := daemon.GetCluster()
|
||||
networks, err := cluster.GetNetworks()
|
||||
|
@ -207,15 +218,15 @@ func (daemon *Daemon) clusterNetworksPrune(config *types.NetworksPruneConfig) (*
|
|||
}
|
||||
|
||||
// NetworksPrune removes unused networks
|
||||
func (daemon *Daemon) NetworksPrune(config *types.NetworksPruneConfig) (*types.NetworksPruneReport, error) {
|
||||
func (daemon *Daemon) NetworksPrune(pruneFilters filters.Args) (*types.NetworksPruneReport, error) {
|
||||
rep := &types.NetworksPruneReport{}
|
||||
clusterRep, err := daemon.clusterNetworksPrune(config)
|
||||
clusterRep, err := daemon.clusterNetworksPrune(pruneFilters)
|
||||
if err != nil {
|
||||
logrus.Warnf("could not remove cluster networks: %v", err)
|
||||
} else {
|
||||
rep.NetworksDeleted = append(rep.NetworksDeleted, clusterRep.NetworksDeleted...)
|
||||
}
|
||||
localRep, err := daemon.localNetworksPrune(config)
|
||||
localRep, err := daemon.localNetworksPrune(pruneFilters)
|
||||
if err != nil {
|
||||
logrus.Warnf("could not remove local networks: %v", err)
|
||||
} else {
|
||||
|
|
|
@ -59,3 +59,33 @@ func (s *DockerSwarmSuite) TestPruneNetwork(c *check.C) {
|
|||
waitAndAssert(c, defaultReconciliationTimeout, d.checkActiveContainerCount, checker.Equals, 0)
|
||||
pruneNetworkAndVerify(c, d, []string{}, []string{"n1", "n3"})
|
||||
}
|
||||
|
||||
func (s *DockerDaemonSuite) TestPruneImageDangling(c *check.C) {
|
||||
c.Assert(s.d.StartWithBusybox(), checker.IsNil)
|
||||
|
||||
out, _, err := s.d.buildImageWithOut("test",
|
||||
`FROM busybox
|
||||
LABEL foo=bar`, true, "-q")
|
||||
c.Assert(err, checker.IsNil)
|
||||
id := strings.TrimSpace(out)
|
||||
|
||||
out, err = s.d.Cmd("images", "-q", "--no-trunc")
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(strings.TrimSpace(out), checker.Contains, id)
|
||||
|
||||
out, err = s.d.Cmd("image", "prune", "--force")
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(strings.TrimSpace(out), checker.Not(checker.Contains), id)
|
||||
|
||||
out, err = s.d.Cmd("images", "-q", "--no-trunc")
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(strings.TrimSpace(out), checker.Contains, id)
|
||||
|
||||
out, err = s.d.Cmd("image", "prune", "--force", "--all")
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(strings.TrimSpace(out), checker.Contains, id)
|
||||
|
||||
out, err = s.d.Cmd("images", "-q", "--no-trunc")
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(strings.TrimSpace(out), checker.Not(checker.Contains), id)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue