Explorar el Código

Support plugins in `docker inspect`

This fix tries to address the proposal raised in 28946
to support plugins in `docker inspect`.

The command `docker inspect` already supports
"container", "image", "node", "network", "service", "volume", "task".
However, `--type plugin` is not supported yet at the moment.

This fix address this issue by adding the support of `--type plugin`
for `docker inspect`.

An additional integration test has been added to cover the changes.

This fix fixes 28946.

Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
Yong Tang hace 8 años
padre
commit
90bb2cdb9f

+ 8 - 1
cli/command/system/inspect.go

@@ -45,7 +45,7 @@ func NewInspectCommand(dockerCli *command.DockerCli) *cobra.Command {
 func runInspect(dockerCli *command.DockerCli, opts inspectOptions) error {
 func runInspect(dockerCli *command.DockerCli, opts inspectOptions) error {
 	var elementSearcher inspect.GetRefFunc
 	var elementSearcher inspect.GetRefFunc
 	switch opts.inspectType {
 	switch opts.inspectType {
-	case "", "container", "image", "node", "network", "service", "volume", "task":
+	case "", "container", "image", "node", "network", "service", "volume", "task", "plugin":
 		elementSearcher = inspectAll(context.Background(), dockerCli, opts.size, opts.inspectType)
 		elementSearcher = inspectAll(context.Background(), dockerCli, opts.size, opts.inspectType)
 	default:
 	default:
 		return fmt.Errorf("%q is not a valid value for --type", opts.inspectType)
 		return fmt.Errorf("%q is not a valid value for --type", opts.inspectType)
@@ -95,6 +95,12 @@ func inspectVolume(ctx context.Context, dockerCli *command.DockerCli) inspect.Ge
 	}
 	}
 }
 }
 
 
+func inspectPlugin(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc {
+	return func(ref string) (interface{}, []byte, error) {
+		return dockerCli.Client().PluginInspectWithRaw(ctx, ref)
+	}
+}
+
 func inspectAll(ctx context.Context, dockerCli *command.DockerCli, getSize bool, typeConstraint string) inspect.GetRefFunc {
 func inspectAll(ctx context.Context, dockerCli *command.DockerCli, getSize bool, typeConstraint string) inspect.GetRefFunc {
 	var inspectAutodetect = []struct {
 	var inspectAutodetect = []struct {
 		ObjectType      string
 		ObjectType      string
@@ -108,6 +114,7 @@ func inspectAll(ctx context.Context, dockerCli *command.DockerCli, getSize bool,
 		{"service", false, inspectService(ctx, dockerCli)},
 		{"service", false, inspectService(ctx, dockerCli)},
 		{"task", false, inspectTasks(ctx, dockerCli)},
 		{"task", false, inspectTasks(ctx, dockerCli)},
 		{"node", false, inspectNode(ctx, dockerCli)},
 		{"node", false, inspectNode(ctx, dockerCli)},
+		{"plugin", false, inspectPlugin(ctx, dockerCli)},
 	}
 	}
 
 
 	isErrNotSwarmManager := func(err error) bool {
 	isErrNotSwarmManager := func(err error) bool {

+ 21 - 0
client/errors.go

@@ -255,3 +255,24 @@ func IsErrSecretNotFound(err error) bool {
 	_, ok := err.(secretNotFoundError)
 	_, ok := err.(secretNotFoundError)
 	return ok
 	return ok
 }
 }
+
+// pluginNotFoundError implements an error returned when a plugin is not in the docker host.
+type pluginNotFoundError struct {
+	name string
+}
+
+// NotFound indicates that this error type is of NotFound
+func (e pluginNotFoundError) NotFound() bool {
+	return true
+}
+
+// Error returns a string representation of a pluginNotFoundError
+func (e pluginNotFoundError) Error() string {
+	return fmt.Sprintf("Error: No such plugin: %s", e.name)
+}
+
+// IsErrPluginNotFound returns true if the error is caused
+// when a plugin is not found in the docker host.
+func IsErrPluginNotFound(err error) bool {
+	return IsErrNotFound(err)
+}

+ 4 - 0
client/plugin_inspect.go

@@ -4,6 +4,7 @@ import (
 	"bytes"
 	"bytes"
 	"encoding/json"
 	"encoding/json"
 	"io/ioutil"
 	"io/ioutil"
+	"net/http"
 
 
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types"
 	"golang.org/x/net/context"
 	"golang.org/x/net/context"
@@ -13,6 +14,9 @@ import (
 func (cli *Client) PluginInspectWithRaw(ctx context.Context, name string) (*types.Plugin, []byte, error) {
 func (cli *Client) PluginInspectWithRaw(ctx context.Context, name string) (*types.Plugin, []byte, error) {
 	resp, err := cli.get(ctx, "/plugins/"+name, nil, nil)
 	resp, err := cli.get(ctx, "/plugins/"+name, nil, nil)
 	if err != nil {
 	if err != nil {
+		if resp.statusCode == http.StatusNotFound {
+			return nil, nil, pluginNotFoundError{name}
+		}
 		return nil, nil, err
 		return nil, nil, err
 	}
 	}
 
 

+ 30 - 0
integration-cli/docker_cli_inspect_test.go

@@ -417,3 +417,33 @@ func (s *DockerSuite) TestInspectAmpersand(c *check.C) {
 	out, _ = dockerCmd(c, "inspect", name)
 	out, _ = dockerCmd(c, "inspect", name)
 	c.Assert(out, checker.Contains, `soanni&rtr`)
 	c.Assert(out, checker.Contains, `soanni&rtr`)
 }
 }
+
+func (s *DockerSuite) TestInspectPlugin(c *check.C) {
+	testRequires(c, DaemonIsLinux, Network)
+	_, _, err := dockerCmdWithError("plugin", "install", "--grant-all-permissions", pNameWithTag)
+	c.Assert(err, checker.IsNil)
+
+	out, _, err := dockerCmdWithError("inspect", "--type", "plugin", "--format", "{{.Name}}", pNameWithTag)
+	c.Assert(err, checker.IsNil)
+	c.Assert(strings.TrimSpace(out), checker.Equals, pName)
+
+	out, _, err = dockerCmdWithError("inspect", "--format", "{{.Name}}", pNameWithTag)
+	c.Assert(err, checker.IsNil)
+	c.Assert(strings.TrimSpace(out), checker.Equals, pName)
+
+	// Even without tag the inspect still work
+	out, _, err = dockerCmdWithError("inspect", "--type", "plugin", "--format", "{{.Name}}", pName)
+	c.Assert(err, checker.IsNil)
+	c.Assert(strings.TrimSpace(out), checker.Equals, pName)
+
+	out, _, err = dockerCmdWithError("inspect", "--format", "{{.Name}}", pName)
+	c.Assert(err, checker.IsNil)
+	c.Assert(strings.TrimSpace(out), checker.Equals, pName)
+
+	_, _, err = dockerCmdWithError("plugin", "disable", pNameWithTag)
+	c.Assert(err, checker.IsNil)
+
+	out, _, err = dockerCmdWithError("plugin", "remove", pNameWithTag)
+	c.Assert(err, checker.IsNil)
+	c.Assert(out, checker.Contains, pNameWithTag)
+}

+ 2 - 2
integration-cli/docker_cli_rename_test.go

@@ -62,10 +62,10 @@ func (s *DockerSuite) TestRenameCheckNames(c *check.C) {
 	name := inspectField(c, newName, "Name")
 	name := inspectField(c, newName, "Name")
 	c.Assert(name, checker.Equals, "/"+newName, check.Commentf("Failed to rename container %s", name))
 	c.Assert(name, checker.Equals, "/"+newName, check.Commentf("Failed to rename container %s", name))
 
 
-	result := dockerCmdWithResult("inspect", "-f={{.Name}}", "first_name")
+	result := dockerCmdWithResult("inspect", "-f={{.Name}}", "--type=container", "first_name")
 	c.Assert(result, icmd.Matches, icmd.Expected{
 	c.Assert(result, icmd.Matches, icmd.Expected{
 		ExitCode: 1,
 		ExitCode: 1,
-		Err:      "No such object: first_name",
+		Err:      "No such container: first_name",
 	})
 	})
 }
 }
 
 

+ 1 - 1
plugin/backend_linux.go

@@ -84,7 +84,7 @@ func (pm *Manager) Inspect(refOrID string) (tp types.Plugin, err error) {
 		return tp, err
 		return tp, err
 	}
 	}
 
 
-	return tp, fmt.Errorf("no plugin name or ID associated with %q", refOrID)
+	return tp, fmt.Errorf("no such plugin name or ID associated with %q", refOrID)
 }
 }
 
 
 func (pm *Manager) pull(ref reference.Named, metaHeader http.Header, authConfig *types.AuthConfig, pluginID string) (types.PluginPrivileges, error) {
 func (pm *Manager) pull(ref reference.Named, metaHeader http.Header, authConfig *types.AuthConfig, pluginID string) (types.PluginPrivileges, error) {