Use opts.FilterOpt for filter flags.

Signed-off-by: Daniel Nephin <dnephin@docker.com>
This commit is contained in:
Daniel Nephin 2016-09-13 14:53:11 -04:00
parent 62f513507e
commit d9cb421d69
7 changed files with 48 additions and 121 deletions

View File

@ -1,16 +1,15 @@
package container package container
import ( import (
"io/ioutil"
"golang.org/x/net/context" "golang.org/x/net/context"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"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/cli/command/formatter" "github.com/docker/docker/cli/command/formatter"
"github.com/docker/docker/opts"
"io/ioutil"
"github.com/docker/docker/utils/templates" "github.com/docker/docker/utils/templates"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -23,12 +22,12 @@ type psOptions struct {
nLatest bool nLatest bool
last int last int
format string format string
filter []string filter opts.FilterOpt
} }
// NewPsCommand creates a new cobra.Command for `docker ps` // NewPsCommand creates a new cobra.Command for `docker ps`
func NewPsCommand(dockerCli *command.DockerCli) *cobra.Command { func NewPsCommand(dockerCli *command.DockerCli) *cobra.Command {
var opts psOptions opts := psOptions{filter: opts.NewFilterOpt()}
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "ps [OPTIONS]", 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.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.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.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 return cmd
} }
@ -65,26 +64,17 @@ func (p *preProcessor) Size() bool {
} }
func buildContainerListOptions(opts *psOptions) (*types.ContainerListOptions, error) { func buildContainerListOptions(opts *psOptions) (*types.ContainerListOptions, error) {
options := &types.ContainerListOptions{ options := &types.ContainerListOptions{
All: opts.all, All: opts.all,
Limit: opts.last, Limit: opts.last,
Size: opts.size, Size: opts.size,
Filter: filters.NewArgs(), Filter: opts.filter.Value(),
} }
if opts.nLatest && opts.last == -1 { if opts.nLatest && opts.last == -1 {
options.Limit = 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 // Currently only used with Size, so we can determine if the user
// put {{.Size}} in their format. // put {{.Size}} in their format.
pre := &preProcessor{opts: options} pre := &preProcessor{opts: options}

View File

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

View File

@ -4,10 +4,10 @@ import (
"golang.org/x/net/context" "golang.org/x/net/context"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"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/cli/command/formatter" "github.com/docker/docker/cli/command/formatter"
"github.com/docker/docker/opts"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -19,12 +19,12 @@ type imagesOptions struct {
noTrunc bool noTrunc bool
showDigests bool showDigests bool
format string format string
filter []string filter opts.FilterOpt
} }
// NewImagesCommand creates a new `docker images` command // NewImagesCommand creates a new `docker images` command
func NewImagesCommand(dockerCli *command.DockerCli) *cobra.Command { func NewImagesCommand(dockerCli *command.DockerCli) *cobra.Command {
var opts imagesOptions opts := imagesOptions{filter: opts.NewFilterOpt()}
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "images [OPTIONS] [REPOSITORY[:TAG]]", 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.noTrunc, "no-trunc", false, "Don't truncate output")
flags.BoolVar(&opts.showDigests, "digests", false, "Show digests") flags.BoolVar(&opts.showDigests, "digests", false, "Show digests")
flags.StringVar(&opts.format, "format", "", "Pretty-print images using a Go template") 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 return cmd
} }
@ -53,23 +53,10 @@ func NewImagesCommand(dockerCli *command.DockerCli) *cobra.Command {
func runImages(dockerCli *command.DockerCli, opts imagesOptions) error { func runImages(dockerCli *command.DockerCli, opts imagesOptions) error {
ctx := context.Background() 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{ options := types.ImageListOptions{
MatchName: matchName, MatchName: opts.matchName,
All: opts.all, All: opts.all,
Filters: imageFilterArgs, Filters: opts.filter.Value(),
} }
images, err := dockerCli.Client().ImageList(ctx, options) images, err := dockerCli.Client().ImageList(ctx, options)

View File

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

View File

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

View File

@ -11,9 +11,9 @@ import (
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
eventtypes "github.com/docker/docker/api/types/events" 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"
"github.com/docker/docker/cli/command" "github.com/docker/docker/cli/command"
"github.com/docker/docker/opts"
"github.com/docker/docker/pkg/jsonlog" "github.com/docker/docker/pkg/jsonlog"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -21,12 +21,12 @@ import (
type eventsOptions struct { type eventsOptions struct {
since string since string
until string until string
filter []string filter opts.FilterOpt
} }
// NewEventsCommand creates a new cobra.Command for `docker events` // NewEventsCommand creates a new cobra.Command for `docker events`
func NewEventsCommand(dockerCli *command.DockerCli) *cobra.Command { func NewEventsCommand(dockerCli *command.DockerCli) *cobra.Command {
var opts eventsOptions opts := eventsOptions{filter: opts.NewFilterOpt()}
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "events [OPTIONS]", Use: "events [OPTIONS]",
@ -40,28 +40,16 @@ func NewEventsCommand(dockerCli *command.DockerCli) *cobra.Command {
flags := cmd.Flags() flags := cmd.Flags()
flags.StringVar(&opts.since, "since", "", "Show all events created since timestamp") flags.StringVar(&opts.since, "since", "", "Show all events created since timestamp")
flags.StringVar(&opts.until, "until", "", "Stream events until this 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 return cmd
} }
func runEvents(dockerCli *command.DockerCli, opts *eventsOptions) error { 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{ options := types.EventsOptions{
Since: opts.since, Since: opts.since,
Until: opts.until, Until: opts.until,
Filters: eventFilterArgs, Filters: opts.filter.Value(),
} }
responseBody, err := dockerCli.Client().Events(context.Background(), options) responseBody, err := dockerCli.Client().Events(context.Background(), options)

View File

@ -6,10 +6,10 @@ import (
"golang.org/x/net/context" "golang.org/x/net/context"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"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/cli/command/formatter" "github.com/docker/docker/cli/command/formatter"
"github.com/docker/docker/opts"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -24,11 +24,11 @@ func (r byVolumeName) Less(i, j int) bool {
type listOptions struct { type listOptions struct {
quiet bool quiet bool
format string format string
filter []string filter opts.FilterOpt
} }
func newListCommand(dockerCli *command.DockerCli) *cobra.Command { func newListCommand(dockerCli *command.DockerCli) *cobra.Command {
var opts listOptions opts := listOptions{filter: opts.NewFilterOpt()}
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "ls [OPTIONS]", Use: "ls [OPTIONS]",
@ -44,24 +44,14 @@ func newListCommand(dockerCli *command.DockerCli) *cobra.Command {
flags := cmd.Flags() flags := cmd.Flags()
flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Only display volume names") flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Only display volume names")
flags.StringVar(&opts.format, "format", "", "Pretty-print volumes using a Go template") 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 return cmd
} }
func runList(dockerCli *command.DockerCli, opts listOptions) error { func runList(dockerCli *command.DockerCli, opts listOptions) error {
client := dockerCli.Client() client := dockerCli.Client()
volumes, err := client.VolumeList(context.Background(), opts.filter.Value())
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)
if err != nil { if err != nil {
return err return err
} }