mirror of
				https://github.com/moby/moby.git
				synced 2022-11-09 12:21:53 -05:00 
			
		
		
		
	Merge pull request #28627 from yongtang/28624-docker-plugin-ls
Add `--filter enabled=true` for `docker plugin ls`
This commit is contained in:
		
						commit
						4c1b40b9d4
					
				
					 12 changed files with 243 additions and 40 deletions
				
			
		| 
						 | 
				
			
			@ -5,6 +5,7 @@ import (
 | 
			
		|||
	"net/http"
 | 
			
		||||
 | 
			
		||||
	enginetypes "github.com/docker/docker/api/types"
 | 
			
		||||
	"github.com/docker/docker/api/types/filters"
 | 
			
		||||
	"github.com/docker/docker/reference"
 | 
			
		||||
	"golang.org/x/net/context"
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -13,7 +14,7 @@ import (
 | 
			
		|||
type Backend interface {
 | 
			
		||||
	Disable(name string, config *enginetypes.PluginDisableConfig) error
 | 
			
		||||
	Enable(name string, config *enginetypes.PluginEnableConfig) error
 | 
			
		||||
	List() ([]enginetypes.Plugin, error)
 | 
			
		||||
	List(filters.Args) ([]enginetypes.Plugin, error)
 | 
			
		||||
	Inspect(name string) (*enginetypes.Plugin, error)
 | 
			
		||||
	Remove(name string, config *enginetypes.PluginRmConfig) error
 | 
			
		||||
	Set(name string, args []string) error
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,6 +10,7 @@ import (
 | 
			
		|||
	distreference "github.com/docker/distribution/reference"
 | 
			
		||||
	"github.com/docker/docker/api/server/httputils"
 | 
			
		||||
	"github.com/docker/docker/api/types"
 | 
			
		||||
	"github.com/docker/docker/api/types/filters"
 | 
			
		||||
	"github.com/docker/docker/pkg/ioutils"
 | 
			
		||||
	"github.com/docker/docker/pkg/streamformatter"
 | 
			
		||||
	"github.com/docker/docker/reference"
 | 
			
		||||
| 
						 | 
				
			
			@ -253,7 +254,15 @@ func (pr *pluginRouter) setPlugin(ctx context.Context, w http.ResponseWriter, r
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func (pr *pluginRouter) listPlugins(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 | 
			
		||||
	l, err := pr.backend.List()
 | 
			
		||||
	if err := httputils.ParseForm(r); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pluginFilters, err := filters.FromParam(r.Form.Get("filters"))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	l, err := pr.backend.List(pluginFilters)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,6 +4,7 @@ import (
 | 
			
		|||
	"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"
 | 
			
		||||
	"golang.org/x/net/context"
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -12,10 +13,11 @@ type listOptions struct {
 | 
			
		|||
	quiet   bool
 | 
			
		||||
	noTrunc bool
 | 
			
		||||
	format  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]",
 | 
			
		||||
| 
						 | 
				
			
			@ -32,12 +34,13 @@ func newListCommand(dockerCli *command.DockerCli) *cobra.Command {
 | 
			
		|||
	flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Only display plugin IDs")
 | 
			
		||||
	flags.BoolVar(&opts.noTrunc, "no-trunc", false, "Don't truncate output")
 | 
			
		||||
	flags.StringVar(&opts.format, "format", "", "Pretty-print plugins using a Go template")
 | 
			
		||||
	flags.VarP(&opts.filter, "filter", "f", "Provide filter values (e.g. 'enabled=true')")
 | 
			
		||||
 | 
			
		||||
	return cmd
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func runList(dockerCli *command.DockerCli, opts listOptions) error {
 | 
			
		||||
	plugins, err := dockerCli.Client().PluginList(context.Background())
 | 
			
		||||
	plugins, err := dockerCli.Client().PluginList(context.Background(), opts.filter.Value())
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -108,7 +108,7 @@ type NodeAPIClient interface {
 | 
			
		|||
 | 
			
		||||
// PluginAPIClient defines API client methods for the plugins
 | 
			
		||||
type PluginAPIClient interface {
 | 
			
		||||
	PluginList(ctx context.Context) (types.PluginsListResponse, error)
 | 
			
		||||
	PluginList(ctx context.Context, filter filters.Args) (types.PluginsListResponse, error)
 | 
			
		||||
	PluginRemove(ctx context.Context, name string, options types.PluginRemoveOptions) error
 | 
			
		||||
	PluginEnable(ctx context.Context, name string, options types.PluginEnableOptions) error
 | 
			
		||||
	PluginDisable(ctx context.Context, name string, options types.PluginDisableOptions) error
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,15 +2,26 @@ package client
 | 
			
		|||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"net/url"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/docker/api/types"
 | 
			
		||||
	"github.com/docker/docker/api/types/filters"
 | 
			
		||||
	"golang.org/x/net/context"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// PluginList returns the installed plugins
 | 
			
		||||
func (cli *Client) PluginList(ctx context.Context) (types.PluginsListResponse, error) {
 | 
			
		||||
func (cli *Client) PluginList(ctx context.Context, filter filters.Args) (types.PluginsListResponse, error) {
 | 
			
		||||
	var plugins types.PluginsListResponse
 | 
			
		||||
	resp, err := cli.get(ctx, "/plugins", nil, nil)
 | 
			
		||||
	query := url.Values{}
 | 
			
		||||
 | 
			
		||||
	if filter.Len() > 0 {
 | 
			
		||||
		filterJSON, err := filters.ToParamWithVersion(cli.version, filter)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return plugins, err
 | 
			
		||||
		}
 | 
			
		||||
		query.Set("filters", filterJSON)
 | 
			
		||||
	}
 | 
			
		||||
	resp, err := cli.get(ctx, "/plugins", query, nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return plugins, err
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,6 +10,7 @@ import (
 | 
			
		|||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/docker/api/types"
 | 
			
		||||
	"github.com/docker/docker/api/types/filters"
 | 
			
		||||
	"golang.org/x/net/context"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -18,7 +19,7 @@ func TestPluginListError(t *testing.T) {
 | 
			
		|||
		client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, err := client.PluginList(context.Background())
 | 
			
		||||
	_, err := client.PluginList(context.Background(), filters.NewArgs())
 | 
			
		||||
	if err == nil || err.Error() != "Error response from daemon: Server error" {
 | 
			
		||||
		t.Fatalf("expected a Server Error, got %v", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -26,34 +27,81 @@ func TestPluginListError(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
func TestPluginList(t *testing.T) {
 | 
			
		||||
	expectedURL := "/plugins"
 | 
			
		||||
	client := &Client{
 | 
			
		||||
		client: newMockClient(func(req *http.Request) (*http.Response, error) {
 | 
			
		||||
			if !strings.HasPrefix(req.URL.Path, expectedURL) {
 | 
			
		||||
				return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
 | 
			
		||||
			}
 | 
			
		||||
			content, err := json.Marshal([]*types.Plugin{
 | 
			
		||||
				{
 | 
			
		||||
					ID: "plugin_id1",
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					ID: "plugin_id2",
 | 
			
		||||
				},
 | 
			
		||||
			})
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
			return &http.Response{
 | 
			
		||||
				StatusCode: http.StatusOK,
 | 
			
		||||
				Body:       ioutil.NopCloser(bytes.NewReader(content)),
 | 
			
		||||
			}, nil
 | 
			
		||||
		}),
 | 
			
		||||
 | 
			
		||||
	enabledFilters := filters.NewArgs()
 | 
			
		||||
	enabledFilters.Add("enabled", "true")
 | 
			
		||||
 | 
			
		||||
	capabilityFilters := filters.NewArgs()
 | 
			
		||||
	capabilityFilters.Add("capability", "volumedriver")
 | 
			
		||||
	capabilityFilters.Add("capability", "authz")
 | 
			
		||||
 | 
			
		||||
	listCases := []struct {
 | 
			
		||||
		filters             filters.Args
 | 
			
		||||
		expectedQueryParams map[string]string
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			filters: filters.NewArgs(),
 | 
			
		||||
			expectedQueryParams: map[string]string{
 | 
			
		||||
				"all":     "",
 | 
			
		||||
				"filter":  "",
 | 
			
		||||
				"filters": "",
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			filters: enabledFilters,
 | 
			
		||||
			expectedQueryParams: map[string]string{
 | 
			
		||||
				"all":     "",
 | 
			
		||||
				"filter":  "",
 | 
			
		||||
				"filters": `{"enabled":{"true":true}}`,
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			filters: capabilityFilters,
 | 
			
		||||
			expectedQueryParams: map[string]string{
 | 
			
		||||
				"all":     "",
 | 
			
		||||
				"filter":  "",
 | 
			
		||||
				"filters": `{"capability":{"authz":true,"volumedriver":true}}`,
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	plugins, err := client.PluginList(context.Background())
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
	if len(plugins) != 2 {
 | 
			
		||||
		t.Fatalf("expected 2 plugins, got %v", plugins)
 | 
			
		||||
	for _, listCase := range listCases {
 | 
			
		||||
		client := &Client{
 | 
			
		||||
			client: newMockClient(func(req *http.Request) (*http.Response, error) {
 | 
			
		||||
				if !strings.HasPrefix(req.URL.Path, expectedURL) {
 | 
			
		||||
					return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
 | 
			
		||||
				}
 | 
			
		||||
				query := req.URL.Query()
 | 
			
		||||
				for key, expected := range listCase.expectedQueryParams {
 | 
			
		||||
					actual := query.Get(key)
 | 
			
		||||
					if actual != expected {
 | 
			
		||||
						return nil, fmt.Errorf("%s not set in URL query properly. Expected '%s', got %s", key, expected, actual)
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				content, err := json.Marshal([]*types.Plugin{
 | 
			
		||||
					{
 | 
			
		||||
						ID: "plugin_id1",
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						ID: "plugin_id2",
 | 
			
		||||
					},
 | 
			
		||||
				})
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return nil, err
 | 
			
		||||
				}
 | 
			
		||||
				return &http.Response{
 | 
			
		||||
					StatusCode: http.StatusOK,
 | 
			
		||||
					Body:       ioutil.NopCloser(bytes.NewReader(content)),
 | 
			
		||||
				}, nil
 | 
			
		||||
			}),
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		plugins, err := client.PluginList(context.Background(), listCase.filters)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
		if len(plugins) != 2 {
 | 
			
		||||
			t.Fatalf("expected 2 plugins, got %v", plugins)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,7 @@ import (
 | 
			
		|||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/docker/api/types"
 | 
			
		||||
	"github.com/docker/docker/api/types/filters"
 | 
			
		||||
	"github.com/docker/docker/api/types/network"
 | 
			
		||||
	executorpkg "github.com/docker/docker/daemon/cluster/executor"
 | 
			
		||||
	clustertypes "github.com/docker/docker/daemon/cluster/provider"
 | 
			
		||||
| 
						 | 
				
			
			@ -53,7 +54,7 @@ func (e *executor) Describe(ctx context.Context) (*api.NodeDescription, error) {
 | 
			
		|||
	addPlugins("Authorization", info.Plugins.Authorization)
 | 
			
		||||
 | 
			
		||||
	// add v2 plugins
 | 
			
		||||
	v2Plugins, err := e.backend.PluginManager().List()
 | 
			
		||||
	v2Plugins, err := e.backend.PluginManager().List(filters.NewArgs())
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		for _, plgn := range v2Plugins {
 | 
			
		||||
			for _, typ := range plgn.Config.Interface.Types {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -51,9 +51,13 @@ Config provides the base accessible fields for working with V0 plugin format
 | 
			
		|||
 | 
			
		||||
      currently supported:
 | 
			
		||||
 | 
			
		||||
      	- **docker.volumedriver/1.0**
 | 
			
		||||
        - **docker.volumedriver/1.0**
 | 
			
		||||
 | 
			
		||||
      	- **docker.authz/1.0**
 | 
			
		||||
        - **docker.networkdriver/1.0**
 | 
			
		||||
 | 
			
		||||
        - **docker.ipamdriver/1.0**
 | 
			
		||||
 | 
			
		||||
        - **docker.authz/1.0**
 | 
			
		||||
 | 
			
		||||
    - **`socket`** *string*
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,6 +24,7 @@ Aliases:
 | 
			
		|||
  ls, list
 | 
			
		||||
 | 
			
		||||
Options:
 | 
			
		||||
  -f, --filter filter   Provide filter values (e.g. 'enabled=true')
 | 
			
		||||
      --format string   Pretty-print plugins using a Go template
 | 
			
		||||
      --help            Print usage
 | 
			
		||||
      --no-trunc        Don't truncate output
 | 
			
		||||
| 
						 | 
				
			
			@ -32,6 +33,8 @@ Options:
 | 
			
		|||
 | 
			
		||||
Lists all the plugins that are currently installed. You can install plugins
 | 
			
		||||
using the [`docker plugin install`](plugin_install.md) command.
 | 
			
		||||
You can also filter using the `-f` or `--filter` flag.
 | 
			
		||||
Refer to the [filtering](#filtering) section for more information about available filter options.
 | 
			
		||||
 | 
			
		||||
Example output:
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -42,6 +45,35 @@ ID                  NAME                             TAG                 DESCRIP
 | 
			
		|||
69553ca1d123        tiborvass/sample-volume-plugin   latest              A test plugin for Docker   true
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Filtering
 | 
			
		||||
 | 
			
		||||
The filtering flag (`-f` or `--filter`) format is of "key=value". If there is more
 | 
			
		||||
than one filter, then pass multiple flags (e.g., `--filter "foo=bar" --filter "bif=baz"`)
 | 
			
		||||
 | 
			
		||||
The currently supported filters are:
 | 
			
		||||
 | 
			
		||||
* enabled (boolean - true or false, 0 or 1)
 | 
			
		||||
* capability (string - currently `volumedriver`, `networkdriver`, `ipamdriver`, or `authz`)
 | 
			
		||||
 | 
			
		||||
### enabled
 | 
			
		||||
 | 
			
		||||
The `enabled` filter matches on plugins enabled or disabled.
 | 
			
		||||
 | 
			
		||||
### capability
 | 
			
		||||
 | 
			
		||||
The `capability` filter matches on plugin capabilities. One plugin
 | 
			
		||||
might have multiple capabilities. Currently `volumedriver`, `networkdriver`,
 | 
			
		||||
`ipamdriver`, and `authz` are supported capabilities.
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
$ docker plugin install --disable tiborvass/no-remove
 | 
			
		||||
tiborvass/no-remove
 | 
			
		||||
 | 
			
		||||
$ docker plugin ls --filter enabled=true
 | 
			
		||||
NAME                  TAG                 DESCRIPTION                ENABLED
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Formatting
 | 
			
		||||
 | 
			
		||||
The formatting options (`--format`) pretty-prints plugins output
 | 
			
		||||
| 
						 | 
				
			
			@ -68,6 +100,7 @@ $ docker plugin ls --format "{{.ID}}: {{.Name}}"
 | 
			
		|||
4be01827a72e: tiborvass/no-remove
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Related information
 | 
			
		||||
 | 
			
		||||
* [plugin create](plugin_create.md)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -285,3 +285,58 @@ func existsMountpointWithPrefix(mountpointPrefix string) (bool, error) {
 | 
			
		|||
	}
 | 
			
		||||
	return false, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *DockerDaemonSuite) TestPluginListFilterEnabled(c *check.C) {
 | 
			
		||||
	testRequires(c, Network)
 | 
			
		||||
 | 
			
		||||
	s.d.Start(c)
 | 
			
		||||
 | 
			
		||||
	out, err := s.d.Cmd("plugin", "install", "--grant-all-permissions", pNameWithTag, "--disable")
 | 
			
		||||
	c.Assert(err, check.IsNil, check.Commentf(out))
 | 
			
		||||
 | 
			
		||||
	defer func() {
 | 
			
		||||
		if out, err := s.d.Cmd("plugin", "remove", pNameWithTag); err != nil {
 | 
			
		||||
			c.Fatalf("Could not remove plugin: %v %s", err, out)
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	out, err = s.d.Cmd("plugin", "ls", "--filter", "enabled=true")
 | 
			
		||||
	c.Assert(err, checker.IsNil)
 | 
			
		||||
	c.Assert(out, checker.Not(checker.Contains), pName)
 | 
			
		||||
 | 
			
		||||
	out, err = s.d.Cmd("plugin", "ls", "--filter", "enabled=false")
 | 
			
		||||
	c.Assert(err, checker.IsNil)
 | 
			
		||||
	c.Assert(out, checker.Contains, pName)
 | 
			
		||||
	c.Assert(out, checker.Contains, "false")
 | 
			
		||||
 | 
			
		||||
	out, err = s.d.Cmd("plugin", "ls")
 | 
			
		||||
	c.Assert(err, checker.IsNil)
 | 
			
		||||
	c.Assert(out, checker.Contains, pName)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *DockerDaemonSuite) TestPluginListFilterCapability(c *check.C) {
 | 
			
		||||
	testRequires(c, Network)
 | 
			
		||||
 | 
			
		||||
	s.d.Start(c)
 | 
			
		||||
 | 
			
		||||
	out, err := s.d.Cmd("plugin", "install", "--grant-all-permissions", pNameWithTag, "--disable")
 | 
			
		||||
	c.Assert(err, check.IsNil, check.Commentf(out))
 | 
			
		||||
 | 
			
		||||
	defer func() {
 | 
			
		||||
		if out, err := s.d.Cmd("plugin", "remove", pNameWithTag); err != nil {
 | 
			
		||||
			c.Fatalf("Could not remove plugin: %v %s", err, out)
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	out, err = s.d.Cmd("plugin", "ls", "--filter", "capability=volumedriver")
 | 
			
		||||
	c.Assert(err, checker.IsNil)
 | 
			
		||||
	c.Assert(out, checker.Contains, pName)
 | 
			
		||||
 | 
			
		||||
	out, err = s.d.Cmd("plugin", "ls", "--filter", "capability=authz")
 | 
			
		||||
	c.Assert(err, checker.IsNil)
 | 
			
		||||
	c.Assert(out, checker.Not(checker.Contains), pName)
 | 
			
		||||
 | 
			
		||||
	out, err = s.d.Cmd("plugin", "ls")
 | 
			
		||||
	c.Assert(err, checker.IsNil)
 | 
			
		||||
	c.Assert(out, checker.Contains, pName)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,6 +18,7 @@ import (
 | 
			
		|||
	"github.com/Sirupsen/logrus"
 | 
			
		||||
	"github.com/docker/distribution/manifest/schema2"
 | 
			
		||||
	"github.com/docker/docker/api/types"
 | 
			
		||||
	"github.com/docker/docker/api/types/filters"
 | 
			
		||||
	"github.com/docker/docker/distribution"
 | 
			
		||||
	progressutils "github.com/docker/docker/distribution/utils"
 | 
			
		||||
	"github.com/docker/docker/distribution/xfer"
 | 
			
		||||
| 
						 | 
				
			
			@ -33,6 +34,11 @@ import (
 | 
			
		|||
	"golang.org/x/net/context"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var acceptedPluginFilterTags = map[string]bool{
 | 
			
		||||
	"enabled":    true,
 | 
			
		||||
	"capability": true,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Disable deactivates a plugin. This means resources (volumes, networks) cant use them.
 | 
			
		||||
func (pm *Manager) Disable(refOrID string, config *types.PluginDisableConfig) error {
 | 
			
		||||
	p, err := pm.config.Store.GetV2Plugin(refOrID)
 | 
			
		||||
| 
						 | 
				
			
			@ -259,10 +265,41 @@ func (pm *Manager) Pull(ctx context.Context, ref reference.Named, name string, m
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// List displays the list of plugins and associated metadata.
 | 
			
		||||
func (pm *Manager) List() ([]types.Plugin, error) {
 | 
			
		||||
func (pm *Manager) List(pluginFilters filters.Args) ([]types.Plugin, error) {
 | 
			
		||||
	if err := pluginFilters.Validate(acceptedPluginFilterTags); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	enabledOnly := false
 | 
			
		||||
	disabledOnly := false
 | 
			
		||||
	if pluginFilters.Include("enabled") {
 | 
			
		||||
		if pluginFilters.ExactMatch("enabled", "true") {
 | 
			
		||||
			enabledOnly = true
 | 
			
		||||
		} else if pluginFilters.ExactMatch("enabled", "false") {
 | 
			
		||||
			disabledOnly = true
 | 
			
		||||
		} else {
 | 
			
		||||
			return nil, fmt.Errorf("Invalid filter 'enabled=%s'", pluginFilters.Get("enabled"))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	plugins := pm.config.Store.GetAll()
 | 
			
		||||
	out := make([]types.Plugin, 0, len(plugins))
 | 
			
		||||
 | 
			
		||||
next:
 | 
			
		||||
	for _, p := range plugins {
 | 
			
		||||
		if enabledOnly && !p.PluginObj.Enabled {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if disabledOnly && p.PluginObj.Enabled {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if pluginFilters.Include("capability") {
 | 
			
		||||
			for _, f := range p.GetTypes() {
 | 
			
		||||
				if !pluginFilters.Match("capability", f.Capability) {
 | 
			
		||||
					continue next
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		out = append(out, p.PluginObj)
 | 
			
		||||
	}
 | 
			
		||||
	return out, nil
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,6 +8,7 @@ import (
 | 
			
		|||
	"net/http"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/docker/api/types"
 | 
			
		||||
	"github.com/docker/docker/api/types/filters"
 | 
			
		||||
	"github.com/docker/docker/reference"
 | 
			
		||||
	"golang.org/x/net/context"
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -40,7 +41,7 @@ func (pm *Manager) Pull(ctx context.Context, ref reference.Named, name string, m
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// List displays the list of plugins and associated metadata.
 | 
			
		||||
func (pm *Manager) List() ([]types.Plugin, error) {
 | 
			
		||||
func (pm *Manager) List(pluginFilters filters.Args) ([]types.Plugin, error) {
 | 
			
		||||
	return nil, errNotSupported
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue