From e2416af0136b72d369de53ff7928d7cc603d4f46 Mon Sep 17 00:00:00 2001 From: Yong Tang Date: Wed, 7 Dec 2016 14:02:13 -0800 Subject: [PATCH] Add `--filter until=` for `docker container/image prune` This fix is a follow up for comment https://github.com/docker/docker/pull/28535#issuecomment-263215225 This fix provides `--filter until=` for `docker container/image prune`. This fix adds `--filter until=` to `docker container/image prune` so that it is possible to specify a timestamp and prune those containers/images that are earlier than the timestamp. Related docs has been updated Several integration tests have been added to cover changes. This fix fixes #28497. This fix is related to #28535. Signed-off-by: Yong Tang --- command/container/prune.go | 16 ++++++++++------ command/image/prune.go | 16 +++++++++------- command/network/prune.go | 16 ++++++++++------ command/prune/prune.go | 15 ++++++++------- command/system/prune.go | 21 ++++++++++++--------- 5 files changed, 49 insertions(+), 35 deletions(-) diff --git a/command/container/prune.go b/command/container/prune.go index 0aad66e6ee..ca50e2e159 100644 --- a/command/container/prune.go +++ b/command/container/prune.go @@ -3,21 +3,22 @@ package container import ( "fmt" - "github.com/docker/docker/api/types/filters" "github.com/docker/docker/cli" "github.com/docker/docker/cli/command" + "github.com/docker/docker/opts" units "github.com/docker/go-units" "github.com/spf13/cobra" "golang.org/x/net/context" ) type pruneOptions struct { - force bool + force bool + filter opts.FilterOpt } // NewPruneCommand returns a new cobra prune command for containers func NewPruneCommand(dockerCli *command.DockerCli) *cobra.Command { - var opts pruneOptions + opts := pruneOptions{filter: opts.NewFilterOpt()} cmd := &cobra.Command{ Use: "prune [OPTIONS]", @@ -39,6 +40,7 @@ func NewPruneCommand(dockerCli *command.DockerCli) *cobra.Command { flags := cmd.Flags() flags.BoolVarP(&opts.force, "force", "f", false, "Do not prompt for confirmation") + flags.Var(&opts.filter, "filter", "Provide filter values (e.g. 'until=')") return cmd } @@ -47,11 +49,13 @@ const warning = `WARNING! This will remove all stopped containers. Are you sure you want to continue?` func runPrune(dockerCli *command.DockerCli, opts pruneOptions) (spaceReclaimed uint64, output string, err error) { + pruneFilters := opts.filter.Value() + if !opts.force && !command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), warning) { return } - report, err := dockerCli.Client().ContainersPrune(context.Background(), filters.Args{}) + report, err := dockerCli.Client().ContainersPrune(context.Background(), pruneFilters) if err != nil { return } @@ -69,6 +73,6 @@ func runPrune(dockerCli *command.DockerCli, opts pruneOptions) (spaceReclaimed u // RunPrune calls the Container Prune API // This returns the amount of space reclaimed and a detailed output string -func RunPrune(dockerCli *command.DockerCli) (uint64, string, error) { - return runPrune(dockerCli, pruneOptions{force: true}) +func RunPrune(dockerCli *command.DockerCli, filter opts.FilterOpt) (uint64, string, error) { + return runPrune(dockerCli, pruneOptions{force: true, filter: filter}) } diff --git a/command/image/prune.go b/command/image/prune.go index 82c28fcf49..f17aed7410 100644 --- a/command/image/prune.go +++ b/command/image/prune.go @@ -5,21 +5,22 @@ import ( "golang.org/x/net/context" - "github.com/docker/docker/api/types/filters" "github.com/docker/docker/cli" "github.com/docker/docker/cli/command" + "github.com/docker/docker/opts" units "github.com/docker/go-units" "github.com/spf13/cobra" ) type pruneOptions struct { - force bool - all bool + force bool + all bool + filter opts.FilterOpt } // NewPruneCommand returns a new cobra prune command for images func NewPruneCommand(dockerCli *command.DockerCli) *cobra.Command { - var opts pruneOptions + opts := pruneOptions{filter: opts.NewFilterOpt()} cmd := &cobra.Command{ Use: "prune [OPTIONS]", @@ -42,6 +43,7 @@ func NewPruneCommand(dockerCli *command.DockerCli) *cobra.Command { flags := cmd.Flags() flags.BoolVarP(&opts.force, "force", "f", false, "Do not prompt for confirmation") flags.BoolVarP(&opts.all, "all", "a", false, "Remove all unused images, not just dangling ones") + flags.Var(&opts.filter, "filter", "Provide filter values (e.g. 'until=')") return cmd } @@ -54,7 +56,7 @@ Are you sure you want to continue?` ) func runPrune(dockerCli *command.DockerCli, opts pruneOptions) (spaceReclaimed uint64, output string, err error) { - pruneFilters := filters.NewArgs() + pruneFilters := opts.filter.Value() pruneFilters.Add("dangling", fmt.Sprintf("%v", !opts.all)) warning := danglingWarning @@ -87,6 +89,6 @@ func runPrune(dockerCli *command.DockerCli, opts pruneOptions) (spaceReclaimed u // RunPrune calls the Image Prune API // This returns the amount of space reclaimed and a detailed output string -func RunPrune(dockerCli *command.DockerCli, all bool) (uint64, string, error) { - return runPrune(dockerCli, pruneOptions{force: true, all: all}) +func RunPrune(dockerCli *command.DockerCli, all bool, filter opts.FilterOpt) (uint64, string, error) { + return runPrune(dockerCli, pruneOptions{force: true, all: all, filter: filter}) } diff --git a/command/network/prune.go b/command/network/prune.go index 9f1979e6b5..c5c5359926 100644 --- a/command/network/prune.go +++ b/command/network/prune.go @@ -5,19 +5,20 @@ import ( "golang.org/x/net/context" - "github.com/docker/docker/api/types/filters" "github.com/docker/docker/cli" "github.com/docker/docker/cli/command" + "github.com/docker/docker/opts" "github.com/spf13/cobra" ) type pruneOptions struct { - force bool + force bool + filter opts.FilterOpt } // NewPruneCommand returns a new cobra prune command for networks func NewPruneCommand(dockerCli *command.DockerCli) *cobra.Command { - var opts pruneOptions + opts := pruneOptions{filter: opts.NewFilterOpt()} cmd := &cobra.Command{ Use: "prune [OPTIONS]", @@ -38,6 +39,7 @@ func NewPruneCommand(dockerCli *command.DockerCli) *cobra.Command { flags := cmd.Flags() flags.BoolVarP(&opts.force, "force", "f", false, "Do not prompt for confirmation") + flags.Var(&opts.filter, "filter", "Provide filter values (e.g. 'until=')") return cmd } @@ -46,11 +48,13 @@ const warning = `WARNING! This will remove all networks not used by at least one Are you sure you want to continue?` func runPrune(dockerCli *command.DockerCli, opts pruneOptions) (output string, err error) { + pruneFilters := opts.filter.Value() + if !opts.force && !command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), warning) { return } - report, err := dockerCli.Client().NetworksPrune(context.Background(), filters.Args{}) + report, err := dockerCli.Client().NetworksPrune(context.Background(), pruneFilters) if err != nil { return } @@ -67,7 +71,7 @@ func runPrune(dockerCli *command.DockerCli, opts pruneOptions) (output string, e // RunPrune calls the Network Prune API // This returns the amount of space reclaimed and a detailed output string -func RunPrune(dockerCli *command.DockerCli) (uint64, string, error) { - output, err := runPrune(dockerCli, pruneOptions{force: true}) +func RunPrune(dockerCli *command.DockerCli, filter opts.FilterOpt) (uint64, string, error) { + output, err := runPrune(dockerCli, pruneOptions{force: true, filter: filter}) return 0, output, err } diff --git a/command/prune/prune.go b/command/prune/prune.go index a022487fd6..6314718c69 100644 --- a/command/prune/prune.go +++ b/command/prune/prune.go @@ -6,6 +6,7 @@ import ( "github.com/docker/docker/cli/command/image" "github.com/docker/docker/cli/command/network" "github.com/docker/docker/cli/command/volume" + "github.com/docker/docker/opts" "github.com/spf13/cobra" ) @@ -30,21 +31,21 @@ func NewNetworkPruneCommand(dockerCli *command.DockerCli) *cobra.Command { } // RunContainerPrune executes a prune command for containers -func RunContainerPrune(dockerCli *command.DockerCli) (uint64, string, error) { - return container.RunPrune(dockerCli) +func RunContainerPrune(dockerCli *command.DockerCli, filter opts.FilterOpt) (uint64, string, error) { + return container.RunPrune(dockerCli, filter) } // RunVolumePrune executes a prune command for volumes -func RunVolumePrune(dockerCli *command.DockerCli) (uint64, string, error) { +func RunVolumePrune(dockerCli *command.DockerCli, filter opts.FilterOpt) (uint64, string, error) { return volume.RunPrune(dockerCli) } // RunImagePrune executes a prune command for images -func RunImagePrune(dockerCli *command.DockerCli, all bool) (uint64, string, error) { - return image.RunPrune(dockerCli, all) +func RunImagePrune(dockerCli *command.DockerCli, all bool, filter opts.FilterOpt) (uint64, string, error) { + return image.RunPrune(dockerCli, all, filter) } // RunNetworkPrune executes a prune command for networks -func RunNetworkPrune(dockerCli *command.DockerCli) (uint64, string, error) { - return network.RunPrune(dockerCli) +func RunNetworkPrune(dockerCli *command.DockerCli, filter opts.FilterOpt) (uint64, string, error) { + return network.RunPrune(dockerCli, filter) } diff --git a/command/system/prune.go b/command/system/prune.go index 92dddbdca6..46e4316f4a 100644 --- a/command/system/prune.go +++ b/command/system/prune.go @@ -6,18 +6,20 @@ import ( "github.com/docker/docker/cli" "github.com/docker/docker/cli/command" "github.com/docker/docker/cli/command/prune" + "github.com/docker/docker/opts" units "github.com/docker/go-units" "github.com/spf13/cobra" ) type pruneOptions struct { - force bool - all bool + force bool + all bool + filter opts.FilterOpt } // NewPruneCommand creates a new cobra.Command for `docker prune` func NewPruneCommand(dockerCli *command.DockerCli) *cobra.Command { - var opts pruneOptions + opts := pruneOptions{filter: opts.NewFilterOpt()} cmd := &cobra.Command{ Use: "prune [OPTIONS]", @@ -32,6 +34,7 @@ func NewPruneCommand(dockerCli *command.DockerCli) *cobra.Command { flags := cmd.Flags() flags.BoolVarP(&opts.force, "force", "f", false, "Do not prompt for confirmation") flags.BoolVarP(&opts.all, "all", "a", false, "Remove all unused images not just dangling ones") + flags.Var(&opts.filter, "filter", "Provide filter values (e.g. 'until=')") return cmd } @@ -48,27 +51,27 @@ Are you sure you want to continue?` allImageDesc = `- all images without at least one container associated to them` ) -func runPrune(dockerCli *command.DockerCli, opts pruneOptions) error { +func runPrune(dockerCli *command.DockerCli, options pruneOptions) error { var message string - if opts.all { + if options.all { message = fmt.Sprintf(warning, allImageDesc) } else { message = fmt.Sprintf(warning, danglingImageDesc) } - if !opts.force && !command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), message) { + if !options.force && !command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), message) { return nil } var spaceReclaimed uint64 - for _, pruneFn := range []func(dockerCli *command.DockerCli) (uint64, string, error){ + for _, pruneFn := range []func(dockerCli *command.DockerCli, filter opts.FilterOpt) (uint64, string, error){ prune.RunContainerPrune, prune.RunVolumePrune, prune.RunNetworkPrune, } { - spc, output, err := pruneFn(dockerCli) + spc, output, err := pruneFn(dockerCli, options.filter) if err != nil { return err } @@ -78,7 +81,7 @@ func runPrune(dockerCli *command.DockerCli, opts pruneOptions) error { } } - spc, output, err := prune.RunImagePrune(dockerCli, opts.all) + spc, output, err := prune.RunImagePrune(dockerCli, options.all, options.filter) if err != nil { return err }