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>
This commit is contained in:
Yong Tang 2016-11-29 17:31:29 -08:00
parent bed5a0bc2c
commit 90bb2cdb9f
6 changed files with 66 additions and 4 deletions

View File

@ -45,7 +45,7 @@ func NewInspectCommand(dockerCli *command.DockerCli) *cobra.Command {
func runInspect(dockerCli *command.DockerCli, opts inspectOptions) error {
var elementSearcher inspect.GetRefFunc
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)
default:
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 {
var inspectAutodetect = []struct {
ObjectType string
@ -108,6 +114,7 @@ func inspectAll(ctx context.Context, dockerCli *command.DockerCli, getSize bool,
{"service", false, inspectService(ctx, dockerCli)},
{"task", false, inspectTasks(ctx, dockerCli)},
{"node", false, inspectNode(ctx, dockerCli)},
{"plugin", false, inspectPlugin(ctx, dockerCli)},
}
isErrNotSwarmManager := func(err error) bool {

View File

@ -255,3 +255,24 @@ func IsErrSecretNotFound(err error) bool {
_, ok := err.(secretNotFoundError)
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)
}

View File

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

View File

@ -417,3 +417,33 @@ func (s *DockerSuite) TestInspectAmpersand(c *check.C) {
out, _ = dockerCmd(c, "inspect", name)
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)
}

View File

@ -62,10 +62,10 @@ func (s *DockerSuite) TestRenameCheckNames(c *check.C) {
name := inspectField(c, newName, "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{
ExitCode: 1,
Err: "No such object: first_name",
Err: "No such container: first_name",
})
}

View File

@ -84,7 +84,7 @@ func (pm *Manager) Inspect(refOrID string) (tp types.Plugin, err error) {
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) {