瀏覽代碼

Use opts.FilterOpt for filter flags.

Signed-off-by: Daniel Nephin <dnephin@docker.com>
Daniel Nephin 8 年之前
父節點
當前提交
a07be9be38

+ 7 - 17
cli/command/container/ps.go

@@ -1,16 +1,15 @@
 package container
 
 import (
+	"io/ioutil"
+
 	"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/docker/docker/cli/command/formatter"
-
-	"io/ioutil"
-
+	"github.com/docker/docker/opts"
 	"github.com/docker/docker/utils/templates"
 	"github.com/spf13/cobra"
 )
@@ -23,12 +22,12 @@ type psOptions struct {
 	nLatest bool
 	last    int
 	format  string
-	filter  []string
+	filter  opts.FilterOpt
 }
 
 // NewPsCommand creates a new cobra.Command for `docker ps`
 func NewPsCommand(dockerCli *command.DockerCli) *cobra.Command {
-	var opts psOptions
+	opts := psOptions{filter: opts.NewFilterOpt()}
 
 	cmd := &cobra.Command{
 		Use:   "ps [OPTIONS]",
@@ -48,7 +47,7 @@ func NewPsCommand(dockerCli *command.DockerCli) *cobra.Command {
 	flags.BoolVarP(&opts.nLatest, "latest", "l", false, "Show the latest created container (includes all states)")
 	flags.IntVarP(&opts.last, "last", "n", -1, "Show n last created containers (includes all states)")
 	flags.StringVarP(&opts.format, "format", "", "", "Pretty-print containers using a Go template")
-	flags.StringSliceVarP(&opts.filter, "filter", "f", []string{}, "Filter output based on conditions provided")
+	flags.VarP(&opts.filter, "filter", "f", "Filter output based on conditions provided")
 
 	return cmd
 }
@@ -65,26 +64,17 @@ func (p *preProcessor) Size() bool {
 }
 
 func buildContainerListOptions(opts *psOptions) (*types.ContainerListOptions, error) {
-
 	options := &types.ContainerListOptions{
 		All:    opts.all,
 		Limit:  opts.last,
 		Size:   opts.size,
-		Filter: filters.NewArgs(),
+		Filter: opts.filter.Value(),
 	}
 
 	if opts.nLatest && opts.last == -1 {
 		options.Limit = 1
 	}
 
-	for _, f := range opts.filter {
-		var err error
-		options.Filter, err = filters.ParseFlag(f, options.Filter)
-		if err != nil {
-			return nil, err
-		}
-	}
-
 	// Currently only used with Size, so we can determine if the user
 	// put {{.Size}} in their format.
 	pre := &preProcessor{opts: options}

+ 15 - 22
cli/command/container/ps_test.go

@@ -1,8 +1,16 @@
 package container
 
-import "testing"
+import (
+	"testing"
+
+	"github.com/docker/docker/opts"
+	"github.com/docker/docker/pkg/testutil/assert"
+)
 
 func TestBuildContainerListOptions(t *testing.T) {
+	filters := opts.NewFilterOpt()
+	assert.NilError(t, filters.Set("foo=bar"))
+	assert.NilError(t, filters.Set("baz=foo"))
 
 	contexts := []struct {
 		psOpts          *psOptions
@@ -16,7 +24,7 @@ func TestBuildContainerListOptions(t *testing.T) {
 				all:    true,
 				size:   true,
 				last:   5,
-				filter: []string{"foo=bar", "baz=foo"},
+				filter: filters,
 			},
 			expectedAll:   true,
 			expectedSize:  true,
@@ -42,27 +50,12 @@ func TestBuildContainerListOptions(t *testing.T) {
 
 	for _, c := range contexts {
 		options, err := buildContainerListOptions(c.psOpts)
-		if err != nil {
-			t.Fatal(err)
-		}
-
-		if c.expectedAll != options.All {
-			t.Fatalf("Expected All to be %t but got %t", c.expectedAll, options.All)
-		}
-
-		if c.expectedSize != options.Size {
-			t.Fatalf("Expected Size to be %t but got %t", c.expectedSize, options.Size)
-		}
-
-		if c.expectedLimit != options.Limit {
-			t.Fatalf("Expected Limit to be %d but got %d", c.expectedLimit, options.Limit)
-		}
+		assert.NilError(t, err)
 
-		f := options.Filter
-
-		if f.Len() != len(c.expectedFilters) {
-			t.Fatalf("Expected %d filters but got %d", len(c.expectedFilters), f.Len())
-		}
+		assert.Equal(t, c.expectedAll, options.All)
+		assert.Equal(t, c.expectedSize, options.Size)
+		assert.Equal(t, c.expectedLimit, options.Limit)
+		assert.Equal(t, options.Filter.Len(), len(c.expectedFilters))
 
 		for k, v := range c.expectedFilters {
 			f := options.Filter

+ 6 - 19
cli/command/image/images.go

@@ -4,10 +4,10 @@ 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/docker/docker/cli/command/formatter"
+	"github.com/docker/docker/opts"
 	"github.com/spf13/cobra"
 )
 
@@ -19,12 +19,12 @@ type imagesOptions struct {
 	noTrunc     bool
 	showDigests bool
 	format      string
-	filter      []string
+	filter      opts.FilterOpt
 }
 
 // NewImagesCommand creates a new `docker images` command
 func NewImagesCommand(dockerCli *command.DockerCli) *cobra.Command {
-	var opts imagesOptions
+	opts := imagesOptions{filter: opts.NewFilterOpt()}
 
 	cmd := &cobra.Command{
 		Use:   "images [OPTIONS] [REPOSITORY[:TAG]]",
@@ -45,7 +45,7 @@ func NewImagesCommand(dockerCli *command.DockerCli) *cobra.Command {
 	flags.BoolVar(&opts.noTrunc, "no-trunc", false, "Don't truncate output")
 	flags.BoolVar(&opts.showDigests, "digests", false, "Show digests")
 	flags.StringVar(&opts.format, "format", "", "Pretty-print images using a Go template")
-	flags.StringSliceVarP(&opts.filter, "filter", "f", []string{}, "Filter output based on conditions provided")
+	flags.VarP(&opts.filter, "filter", "f", "Filter output based on conditions provided")
 
 	return cmd
 }
@@ -53,23 +53,10 @@ func NewImagesCommand(dockerCli *command.DockerCli) *cobra.Command {
 func runImages(dockerCli *command.DockerCli, opts imagesOptions) error {
 	ctx := context.Background()
 
-	// Consolidate all filter flags, and sanity check them early.
-	// They'll get process in the daemon/server.
-	imageFilterArgs := filters.NewArgs()
-	for _, f := range opts.filter {
-		var err error
-		imageFilterArgs, err = filters.ParseFlag(f, imageFilterArgs)
-		if err != nil {
-			return err
-		}
-	}
-
-	matchName := opts.matchName
-
 	options := types.ImageListOptions{
-		MatchName: matchName,
+		MatchName: opts.matchName,
 		All:       opts.all,
-		Filters:   imageFilterArgs,
+		Filters:   opts.filter.Value(),
 	}
 
 	images, err := dockerCli.Client().ImageList(ctx, options)

+ 5 - 14
cli/command/image/search.go

@@ -9,10 +9,10 @@ import (
 	"golang.org/x/net/context"
 
 	"github.com/docker/docker/api/types"
-	"github.com/docker/docker/api/types/filters"
 	registrytypes "github.com/docker/docker/api/types/registry"
 	"github.com/docker/docker/cli"
 	"github.com/docker/docker/cli/command"
+	"github.com/docker/docker/opts"
 	"github.com/docker/docker/pkg/stringutils"
 	"github.com/docker/docker/registry"
 	"github.com/spf13/cobra"
@@ -22,7 +22,7 @@ type searchOptions struct {
 	term    string
 	noTrunc bool
 	limit   int
-	filter  []string
+	filter  opts.FilterOpt
 
 	// Deprecated
 	stars     uint
@@ -31,7 +31,7 @@ type searchOptions struct {
 
 // NewSearchCommand creates a new `docker search` command
 func NewSearchCommand(dockerCli *command.DockerCli) *cobra.Command {
-	var opts searchOptions
+	opts := searchOptions{filter: opts.NewFilterOpt()}
 
 	cmd := &cobra.Command{
 		Use:   "search [OPTIONS] TERM",
@@ -46,7 +46,7 @@ func NewSearchCommand(dockerCli *command.DockerCli) *cobra.Command {
 	flags := cmd.Flags()
 
 	flags.BoolVar(&opts.noTrunc, "no-trunc", false, "Don't truncate output")
-	flags.StringSliceVarP(&opts.filter, "filter", "f", []string{}, "Filter output based on conditions provided")
+	flags.VarP(&opts.filter, "filter", "f", "Filter output based on conditions provided")
 	flags.IntVar(&opts.limit, "limit", registry.DefaultSearchLimit, "Max number of search results")
 
 	flags.BoolVar(&opts.automated, "automated", false, "Only show automated builds")
@@ -74,19 +74,10 @@ func runSearch(dockerCli *command.DockerCli, opts searchOptions) error {
 		return err
 	}
 
-	searchFilters := filters.NewArgs()
-	for _, f := range opts.filter {
-		var err error
-		searchFilters, err = filters.ParseFlag(f, searchFilters)
-		if err != nil {
-			return err
-		}
-	}
-
 	options := types.ImageSearchOptions{
 		RegistryAuth:  encodedAuth,
 		PrivilegeFunc: requestPrivilege,
-		Filters:       searchFilters,
+		Filters:       opts.filter.Value(),
 		Limit:         opts.limit,
 	}
 

+ 5 - 17
cli/command/network/list.go

@@ -6,10 +6,10 @@ 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/docker/docker/cli/command/formatter"
+	"github.com/docker/docker/opts"
 	"github.com/spf13/cobra"
 )
 
@@ -23,11 +23,11 @@ type listOptions struct {
 	quiet   bool
 	noTrunc bool
 	format  string
-	filter  []string
+	filter  opts.FilterOpt
 }
 
 func newListCommand(dockerCli *command.DockerCli) *cobra.Command {
-	var opts listOptions
+	opts := listOptions{filter: opts.NewFilterOpt()}
 
 	cmd := &cobra.Command{
 		Use:     "ls [OPTIONS]",
@@ -43,7 +43,7 @@ func newListCommand(dockerCli *command.DockerCli) *cobra.Command {
 	flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Only display network IDs")
 	flags.BoolVar(&opts.noTrunc, "no-trunc", false, "Do not truncate the output")
 	flags.StringVar(&opts.format, "format", "", "Pretty-print networks using a Go template")
-	flags.StringSliceVarP(&opts.filter, "filter", "f", []string{}, "Provide filter values (i.e. 'dangling=true')")
+	flags.VarP(&opts.filter, "filter", "f", "Provide filter values (i.e. 'dangling=true')")
 
 	return cmd
 }
@@ -51,19 +51,7 @@ func newListCommand(dockerCli *command.DockerCli) *cobra.Command {
 func runList(dockerCli *command.DockerCli, opts listOptions) error {
 	client := dockerCli.Client()
 
-	netFilterArgs := filters.NewArgs()
-	for _, f := range opts.filter {
-		var err error
-		netFilterArgs, err = filters.ParseFlag(f, netFilterArgs)
-		if err != nil {
-			return err
-		}
-	}
-
-	options := types.NetworkListOptions{
-		Filters: netFilterArgs,
-	}
-
+	options := types.NetworkListOptions{Filters: opts.filter.Value()}
 	networkResources, err := client.NetworkList(context.Background(), options)
 	if err != nil {
 		return err

+ 5 - 17
cli/command/system/events.go

@@ -11,9 +11,9 @@ import (
 
 	"github.com/docker/docker/api/types"
 	eventtypes "github.com/docker/docker/api/types/events"
-	"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/docker/docker/pkg/jsonlog"
 	"github.com/spf13/cobra"
 )
@@ -21,12 +21,12 @@ import (
 type eventsOptions struct {
 	since  string
 	until  string
-	filter []string
+	filter opts.FilterOpt
 }
 
 // NewEventsCommand creates a new cobra.Command for `docker events`
 func NewEventsCommand(dockerCli *command.DockerCli) *cobra.Command {
-	var opts eventsOptions
+	opts := eventsOptions{filter: opts.NewFilterOpt()}
 
 	cmd := &cobra.Command{
 		Use:   "events [OPTIONS]",
@@ -40,28 +40,16 @@ func NewEventsCommand(dockerCli *command.DockerCli) *cobra.Command {
 	flags := cmd.Flags()
 	flags.StringVar(&opts.since, "since", "", "Show all events created since timestamp")
 	flags.StringVar(&opts.until, "until", "", "Stream events until this timestamp")
-	flags.StringSliceVarP(&opts.filter, "filter", "f", []string{}, "Filter output based on conditions provided")
+	flags.VarP(&opts.filter, "filter", "f", "Filter output based on conditions provided")
 
 	return cmd
 }
 
 func runEvents(dockerCli *command.DockerCli, opts *eventsOptions) error {
-	eventFilterArgs := filters.NewArgs()
-
-	// Consolidate all filter flags, and sanity check them early.
-	// They'll get process in the daemon/server.
-	for _, f := range opts.filter {
-		var err error
-		eventFilterArgs, err = filters.ParseFlag(f, eventFilterArgs)
-		if err != nil {
-			return err
-		}
-	}
-
 	options := types.EventsOptions{
 		Since:   opts.since,
 		Until:   opts.until,
-		Filters: eventFilterArgs,
+		Filters: opts.filter.Value(),
 	}
 
 	responseBody, err := dockerCli.Client().Events(context.Background(), options)

+ 5 - 15
cli/command/volume/list.go

@@ -6,10 +6,10 @@ 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/docker/docker/cli/command/formatter"
+	"github.com/docker/docker/opts"
 	"github.com/spf13/cobra"
 )
 
@@ -24,11 +24,11 @@ func (r byVolumeName) Less(i, j int) bool {
 type listOptions struct {
 	quiet  bool
 	format string
-	filter []string
+	filter opts.FilterOpt
 }
 
 func newListCommand(dockerCli *command.DockerCli) *cobra.Command {
-	var opts listOptions
+	opts := listOptions{filter: opts.NewFilterOpt()}
 
 	cmd := &cobra.Command{
 		Use:     "ls [OPTIONS]",
@@ -44,24 +44,14 @@ func newListCommand(dockerCli *command.DockerCli) *cobra.Command {
 	flags := cmd.Flags()
 	flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Only display volume names")
 	flags.StringVar(&opts.format, "format", "", "Pretty-print volumes using a Go template")
-	flags.StringSliceVarP(&opts.filter, "filter", "f", []string{}, "Provide filter values (e.g. 'dangling=true')")
+	flags.VarP(&opts.filter, "filter", "f", "Provide filter values (e.g. 'dangling=true')")
 
 	return cmd
 }
 
 func runList(dockerCli *command.DockerCli, opts listOptions) error {
 	client := dockerCli.Client()
-
-	volFilterArgs := filters.NewArgs()
-	for _, f := range opts.filter {
-		var err error
-		volFilterArgs, err = filters.ParseFlag(f, volFilterArgs)
-		if err != nil {
-			return err
-		}
-	}
-
-	volumes, err := client.VolumeList(context.Background(), volFilterArgs)
+	volumes, err := client.VolumeList(context.Background(), opts.filter.Value())
 	if err != nil {
 		return err
 	}

+ 3 - 3
integration-cli/docker_cli_by_digest_test.go

@@ -344,7 +344,7 @@ func (s *DockerRegistrySuite) TestListDanglingImagesWithDigests(c *check.C) {
 	dockerCmd(c, "pull", imageReference2)
 
 	// list images
-	out, _ = dockerCmd(c, "images", "--digests", "--filter=\"dangling=true\"")
+	out, _ = dockerCmd(c, "images", "--digests", "--filter=dangling=true")
 
 	// make sure repo shown, tag=<none>, digest = $digest1
 	c.Assert(re1.MatchString(out), checker.True, check.Commentf("expected %q: %s", re1.String(), out))
@@ -357,7 +357,7 @@ func (s *DockerRegistrySuite) TestListDanglingImagesWithDigests(c *check.C) {
 	dockerCmd(c, "pull", repoName+":dangle1")
 
 	// list images
-	out, _ = dockerCmd(c, "images", "--digests", "--filter=\"dangling=true\"")
+	out, _ = dockerCmd(c, "images", "--digests", "--filter=dangling=true")
 
 	// make sure image 1 has repo, tag, <none> AND repo, <none>, digest
 	reWithDigest1 := regexp.MustCompile(`\s*` + repoName + `\s*dangle1\s*` + digest1.String() + `\s`)
@@ -379,7 +379,7 @@ func (s *DockerRegistrySuite) TestListDanglingImagesWithDigests(c *check.C) {
 	c.Assert(reWithDigest2.MatchString(out), checker.True, check.Commentf("expected %q: %s", reWithDigest2.String(), out))
 
 	// list images, no longer dangling, should not match
-	out, _ = dockerCmd(c, "images", "--digests", "--filter=\"dangling=true\"")
+	out, _ = dockerCmd(c, "images", "--digests", "--filter=dangling=true")
 
 	// make sure image 1 has repo, tag, digest
 	c.Assert(reWithDigest1.MatchString(out), checker.False, check.Commentf("unexpected %q: %s", reWithDigest1.String(), out))