Merge pull request #1524 from thaJeztah/fix_system_prune_output

Fix "warning" output on docker system prune
This commit is contained in:
Sebastiaan van Stijn 2019-03-18 15:11:22 +01:00 committed by GitHub
commit 69f1727248
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 61 additions and 13 deletions

View File

@ -3,6 +3,7 @@ package system
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"sort"
"text/template" "text/template"
"github.com/docker/cli/cli" "github.com/docker/cli/cli"
@ -14,8 +15,9 @@ import (
"github.com/docker/cli/cli/command/volume" "github.com/docker/cli/cli/command/volume"
"github.com/docker/cli/opts" "github.com/docker/cli/opts"
"github.com/docker/docker/api/types/versions" "github.com/docker/docker/api/types/versions"
units "github.com/docker/go-units" "github.com/docker/go-units"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"vbom.ml/util/sortorder"
) )
type pruneOptions struct { type pruneOptions struct {
@ -53,9 +55,15 @@ func newPruneCommand(dockerCli command.Cli) *cobra.Command {
} }
const confirmationTemplate = `WARNING! This will remove: const confirmationTemplate = `WARNING! This will remove:
{{- range $_, $warning := . }} {{- range $_, $warning := .warnings }}
- {{ $warning }} - {{ $warning }}
{{- end }} {{- end }}
{{if .filters}}
Items to be pruned will be filtered with:
{{- range $_, $filters := .filters }}
- {{ $filters }}
{{- end }}
{{end}}
Are you sure you want to continue?` Are you sure you want to continue?`
func runPrune(dockerCli command.Cli, options pruneOptions) error { func runPrune(dockerCli command.Cli, options pruneOptions) error {
@ -63,7 +71,7 @@ func runPrune(dockerCli command.Cli, options pruneOptions) error {
if options.pruneVolumes && options.filter.Value().Contains("until") { if options.pruneVolumes && options.filter.Value().Contains("until") {
return fmt.Errorf(`ERROR: The "until" filter is not supported with "--volumes"`) return fmt.Errorf(`ERROR: The "until" filter is not supported with "--volumes"`)
} }
if !options.force && !command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), confirmationMessage(options)) { if !options.force && !command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), confirmationMessage(dockerCli, options)) {
return nil return nil
} }
pruneFuncs := []func(dockerCli command.Cli, all bool, filter opts.FilterOpt) (uint64, string, error){ pruneFuncs := []func(dockerCli command.Cli, all bool, filter opts.FilterOpt) (uint64, string, error){
@ -96,7 +104,7 @@ func runPrune(dockerCli command.Cli, options pruneOptions) error {
} }
// confirmationMessage constructs a confirmation message that depends on the cli options. // confirmationMessage constructs a confirmation message that depends on the cli options.
func confirmationMessage(options pruneOptions) string { func confirmationMessage(dockerCli command.Cli, options pruneOptions) string {
t := template.Must(template.New("confirmation message").Parse(confirmationTemplate)) t := template.Must(template.New("confirmation message").Parse(confirmationTemplate))
warnings := []string{ warnings := []string{
@ -118,12 +126,23 @@ func confirmationMessage(options pruneOptions) string {
warnings = append(warnings, "all dangling build cache") warnings = append(warnings, "all dangling build cache")
} }
} }
if len(options.filter.String()) > 0 {
warnings = append(warnings, "Elements to be pruned will be filtered with:") var filters []string
warnings = append(warnings, "label="+options.filter.String()) pruneFilters := command.PruneFilters(dockerCli, options.filter.Value())
if pruneFilters.Len() > 0 {
// TODO remove fixed list of filters, and print all filters instead,
// because the list of filters that is supported by the engine may evolve over time.
for _, name := range []string{"label", "label!", "until"} {
for _, v := range pruneFilters.Get(name) {
filters = append(filters, name+"="+v)
}
}
sort.Slice(filters, func(i, j int) bool {
return sortorder.NaturalLess(filters[i], filters[j])
})
} }
var buffer bytes.Buffer var buffer bytes.Buffer
t.Execute(&buffer, &warnings) t.Execute(&buffer, map[string][]string{"warnings": warnings, "filters": filters})
return buffer.String() return buffer.String()
} }

View File

@ -3,6 +3,7 @@ package system
import ( import (
"testing" "testing"
"github.com/docker/cli/cli/config/configfile"
"github.com/docker/cli/internal/test" "github.com/docker/cli/internal/test"
"gotest.tools/assert" "gotest.tools/assert"
is "gotest.tools/assert/cmp" is "gotest.tools/assert/cmp"
@ -11,12 +12,40 @@ import (
func TestPrunePromptPre131DoesNotIncludeBuildCache(t *testing.T) { func TestPrunePromptPre131DoesNotIncludeBuildCache(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{version: "1.30"}) cli := test.NewFakeCli(&fakeClient{version: "1.30"})
cmd := newPruneCommand(cli) cmd := newPruneCommand(cli)
cmd.SetArgs([]string{})
assert.NilError(t, cmd.Execute()) assert.NilError(t, cmd.Execute())
expected := `WARNING! This will remove: expected := `WARNING! This will remove:
- all stopped containers - all stopped containers
- all networks not used by at least one container - all networks not used by at least one container
- all dangling images - all dangling images
Are you sure you want to continue? [y/N] `
assert.Check(t, is.Equal(expected, cli.OutBuffer().String()))
}
func TestPrunePromptFilters(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{version: "1.31"})
cli.SetConfigFile(&configfile.ConfigFile{
PruneFilters: []string{"label!=never=remove-me", "label=remove=me"},
})
cmd := newPruneCommand(cli)
cmd.SetArgs([]string{"--filter", "until=24h", "--filter", "label=hello-world", "--filter", "label!=foo=bar", "--filter", "label=bar=baz"})
assert.NilError(t, cmd.Execute())
expected := `WARNING! This will remove:
- all stopped containers
- all networks not used by at least one container
- all dangling images
- all dangling build cache
Items to be pruned will be filtered with:
- label!=foo=bar
- label!=never=remove-me
- label=bar=baz
- label=hello-world
- label=remove=me
- until=24h
Are you sure you want to continue? [y/N] ` Are you sure you want to continue? [y/N] `
assert.Check(t, is.Equal(expected, cli.OutBuffer().String())) assert.Check(t, is.Equal(expected, cli.OutBuffer().String()))
} }