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 b4c1645db5
commit a07be9be38
8 changed files with 51 additions and 124 deletions

View File

@ -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}

View File

@ -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)
}
assert.NilError(t, 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)
}
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

View File

@ -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)

View File

@ -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,
}

View File

@ -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

View File

@ -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)

View File

@ -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
}

View File

@ -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))