mirror of https://github.com/docker/cli.git
Merge pull request #30740 from yongtang/29999-prune-filter-label
Add `label` filter for `docker system prune`
This commit is contained in:
commit
ec9d4dbdc6
|
@ -49,7 +49,7 @@ const warning = `WARNING! This will remove all stopped containers.
|
||||||
Are you sure you want to continue?`
|
Are you sure you want to continue?`
|
||||||
|
|
||||||
func runPrune(dockerCli *command.DockerCli, opts pruneOptions) (spaceReclaimed uint64, output string, err error) {
|
func runPrune(dockerCli *command.DockerCli, opts pruneOptions) (spaceReclaimed uint64, output string, err error) {
|
||||||
pruneFilters := opts.filter.Value()
|
pruneFilters := command.PruneFilters(dockerCli, opts.filter.Value())
|
||||||
|
|
||||||
if !opts.force && !command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), warning) {
|
if !opts.force && !command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), warning) {
|
||||||
return
|
return
|
||||||
|
|
|
@ -58,6 +58,7 @@ Are you sure you want to continue?`
|
||||||
func runPrune(dockerCli *command.DockerCli, opts pruneOptions) (spaceReclaimed uint64, output string, err error) {
|
func runPrune(dockerCli *command.DockerCli, opts pruneOptions) (spaceReclaimed uint64, output string, err error) {
|
||||||
pruneFilters := opts.filter.Value()
|
pruneFilters := opts.filter.Value()
|
||||||
pruneFilters.Add("dangling", fmt.Sprintf("%v", !opts.all))
|
pruneFilters.Add("dangling", fmt.Sprintf("%v", !opts.all))
|
||||||
|
pruneFilters = command.PruneFilters(dockerCli, pruneFilters)
|
||||||
|
|
||||||
warning := danglingWarning
|
warning := danglingWarning
|
||||||
if opts.all {
|
if opts.all {
|
||||||
|
|
|
@ -48,7 +48,7 @@ const warning = `WARNING! This will remove all networks not used by at least one
|
||||||
Are you sure you want to continue?`
|
Are you sure you want to continue?`
|
||||||
|
|
||||||
func runPrune(dockerCli *command.DockerCli, opts pruneOptions) (output string, err error) {
|
func runPrune(dockerCli *command.DockerCli, opts pruneOptions) (output string, err error) {
|
||||||
pruneFilters := opts.filter.Value()
|
pruneFilters := command.PruneFilters(dockerCli, opts.filter.Value())
|
||||||
|
|
||||||
if !opts.force && !command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), warning) {
|
if !opts.force && !command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), warning) {
|
||||||
return
|
return
|
||||||
|
|
|
@ -37,7 +37,7 @@ func RunContainerPrune(dockerCli *command.DockerCli, filter opts.FilterOpt) (uin
|
||||||
|
|
||||||
// RunVolumePrune executes a prune command for volumes
|
// RunVolumePrune executes a prune command for volumes
|
||||||
func RunVolumePrune(dockerCli *command.DockerCli, filter opts.FilterOpt) (uint64, string, error) {
|
func RunVolumePrune(dockerCli *command.DockerCli, filter opts.FilterOpt) (uint64, string, error) {
|
||||||
return volume.RunPrune(dockerCli)
|
return volume.RunPrune(dockerCli, filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunImagePrune executes a prune command for images
|
// RunImagePrune executes a prune command for images
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/docker/docker/api/types/filters"
|
||||||
"github.com/docker/docker/pkg/system"
|
"github.com/docker/docker/pkg/system"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -85,3 +86,34 @@ func PromptForConfirmation(ins *InStream, outs *OutStream, message string) bool
|
||||||
answer, _, _ := reader.ReadLine()
|
answer, _, _ := reader.ReadLine()
|
||||||
return strings.ToLower(string(answer)) == "y"
|
return strings.ToLower(string(answer)) == "y"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PruneFilters returns consolidated prune filters obtained from config.json and cli
|
||||||
|
func PruneFilters(dockerCli Cli, pruneFilters filters.Args) filters.Args {
|
||||||
|
if dockerCli.ConfigFile() == nil {
|
||||||
|
return pruneFilters
|
||||||
|
}
|
||||||
|
for _, f := range dockerCli.ConfigFile().PruneFilters {
|
||||||
|
parts := strings.SplitN(f, "=", 2)
|
||||||
|
if len(parts) != 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if parts[0] == "label" {
|
||||||
|
// CLI label filter supersede config.json.
|
||||||
|
// If CLI label filter conflict with config.json,
|
||||||
|
// skip adding label! filter in config.json.
|
||||||
|
if pruneFilters.Include("label!") && pruneFilters.ExactMatch("label!", parts[1]) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
} else if parts[0] == "label!" {
|
||||||
|
// CLI label! filter supersede config.json.
|
||||||
|
// If CLI label! filter conflict with config.json,
|
||||||
|
// skip adding label filter in config.json.
|
||||||
|
if pruneFilters.Include("label") && pruneFilters.ExactMatch("label", parts[1]) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pruneFilters.Add(parts[0], parts[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
return pruneFilters
|
||||||
|
}
|
||||||
|
|
|
@ -3,9 +3,9 @@ package volume
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/docker/docker/api/types/filters"
|
|
||||||
"github.com/docker/docker/cli"
|
"github.com/docker/docker/cli"
|
||||||
"github.com/docker/docker/cli/command"
|
"github.com/docker/docker/cli/command"
|
||||||
|
"github.com/docker/docker/opts"
|
||||||
units "github.com/docker/go-units"
|
units "github.com/docker/go-units"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
|
@ -13,11 +13,12 @@ import (
|
||||||
|
|
||||||
type pruneOptions struct {
|
type pruneOptions struct {
|
||||||
force bool
|
force bool
|
||||||
|
filter opts.FilterOpt
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPruneCommand returns a new cobra prune command for volumes
|
// NewPruneCommand returns a new cobra prune command for volumes
|
||||||
func NewPruneCommand(dockerCli command.Cli) *cobra.Command {
|
func NewPruneCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
var opts pruneOptions
|
opts := pruneOptions{filter: opts.NewFilterOpt()}
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "prune [OPTIONS]",
|
Use: "prune [OPTIONS]",
|
||||||
|
@ -39,6 +40,7 @@ func NewPruneCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
|
|
||||||
flags := cmd.Flags()
|
flags := cmd.Flags()
|
||||||
flags.BoolVarP(&opts.force, "force", "f", false, "Do not prompt for confirmation")
|
flags.BoolVarP(&opts.force, "force", "f", false, "Do not prompt for confirmation")
|
||||||
|
flags.Var(&opts.filter, "filter", "Provide filter values (e.g. 'label=<label>')")
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
@ -47,11 +49,13 @@ const warning = `WARNING! This will remove all volumes not used by at least one
|
||||||
Are you sure you want to continue?`
|
Are you sure you want to continue?`
|
||||||
|
|
||||||
func runPrune(dockerCli command.Cli, opts pruneOptions) (spaceReclaimed uint64, output string, err error) {
|
func runPrune(dockerCli command.Cli, opts pruneOptions) (spaceReclaimed uint64, output string, err error) {
|
||||||
|
pruneFilters := command.PruneFilters(dockerCli, opts.filter.Value())
|
||||||
|
|
||||||
if !opts.force && !command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), warning) {
|
if !opts.force && !command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), warning) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
report, err := dockerCli.Client().VolumesPrune(context.Background(), filters.Args{})
|
report, err := dockerCli.Client().VolumesPrune(context.Background(), pruneFilters)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -69,6 +73,6 @@ func runPrune(dockerCli command.Cli, opts pruneOptions) (spaceReclaimed uint64,
|
||||||
|
|
||||||
// RunPrune calls the Volume Prune API
|
// RunPrune calls the Volume Prune API
|
||||||
// This returns the amount of space reclaimed and a detailed output string
|
// This returns the amount of space reclaimed and a detailed output string
|
||||||
func RunPrune(dockerCli *command.DockerCli) (uint64, string, error) {
|
func RunPrune(dockerCli *command.DockerCli, filter opts.FilterOpt) (uint64, string, error) {
|
||||||
return runPrune(dockerCli, pruneOptions{force: true})
|
return runPrune(dockerCli, pruneOptions{force: true, filter: filter})
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ type ConfigFile struct {
|
||||||
TasksFormat string `json:"tasksFormat,omitempty"`
|
TasksFormat string `json:"tasksFormat,omitempty"`
|
||||||
SecretFormat string `json:"secretFormat,omitempty"`
|
SecretFormat string `json:"secretFormat,omitempty"`
|
||||||
NodesFormat string `json:"nodesFormat,omitempty"`
|
NodesFormat string `json:"nodesFormat,omitempty"`
|
||||||
|
PruneFilters []string `json:"pruneFilters,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// LegacyLoadFromReader reads the non-nested configuration data given and sets up the
|
// LegacyLoadFromReader reads the non-nested configuration data given and sets up the
|
||||||
|
|
Loading…
Reference in New Issue