Ignore certificate expiry error for top-level inspect

The top-level `docker inspect` command could return
an error if the nodes Swarm certificates were expired.

In situations where the user did not explicitly
ask for an object-type (`--type=foo`), we should
ignore these errors, and consider them equal to
"node is not a swarm manager".

This change makes `docker inspect` ignore these
errors if no type was specified.

As a further optimization, the "swarm status"
result is now stored in a variable, so that
other swarm-specific API calls can be skipped.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2016-12-08 12:04:22 +01:00
parent ded2ece9ad
commit 518b65c6f5
1 changed files with 74 additions and 19 deletions

View File

@ -2,7 +2,6 @@ package system
import ( import (
"fmt" "fmt"
"strings"
"golang.org/x/net/context" "golang.org/x/net/context"
@ -103,38 +102,94 @@ func inspectPlugin(ctx context.Context, dockerCli *command.DockerCli) inspect.Ge
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
IsSizeSupported bool isSizeSupported bool
ObjectInspector func(string) (interface{}, []byte, error) isSwarmObject bool
objectInspector func(string) (interface{}, []byte, error)
}{ }{
{"container", true, inspectContainers(ctx, dockerCli, getSize)}, {
{"image", false, inspectImages(ctx, dockerCli)}, objectType: "container",
{"network", false, inspectNetwork(ctx, dockerCli)}, isSizeSupported: true,
{"volume", false, inspectVolume(ctx, dockerCli)}, objectInspector: inspectContainers(ctx, dockerCli, getSize),
{"service", false, inspectService(ctx, dockerCli)}, },
{"task", false, inspectTasks(ctx, dockerCli)}, {
{"node", false, inspectNode(ctx, dockerCli)}, objectType: "image",
{"plugin", false, inspectPlugin(ctx, dockerCli)}, objectInspector: inspectImages(ctx, dockerCli),
},
{
objectType: "network",
objectInspector: inspectNetwork(ctx, dockerCli),
},
{
objectType: "volume",
objectInspector: inspectVolume(ctx, dockerCli),
},
{
objectType: "service",
isSwarmObject: true,
objectInspector: inspectService(ctx, dockerCli),
},
{
objectType: "task",
isSwarmObject: true,
objectInspector: inspectTasks(ctx, dockerCli),
},
{
objectType: "node",
isSwarmObject: true,
objectInspector: inspectNode(ctx, dockerCli),
},
{
objectType: "plugin",
objectInspector: inspectPlugin(ctx, dockerCli),
},
} }
isErrNotSwarmManager := func(err error) bool { // isSwarmManager does an Info API call to verify that the daemon is
return strings.Contains(err.Error(), "This node is not a swarm manager") // a swarm manager.
isSwarmManager := func() bool {
info, err := dockerCli.Client().Info(ctx)
if err != nil {
fmt.Fprintln(dockerCli.Err(), err)
return false
}
return info.Swarm.ControlAvailable
} }
return func(ref string) (interface{}, []byte, error) { return func(ref string) (interface{}, []byte, error) {
const (
swarmSupportUnknown = iota
swarmSupported
swarmUnsupported
)
isSwarmSupported := swarmSupportUnknown
for _, inspectData := range inspectAutodetect { for _, inspectData := range inspectAutodetect {
if typeConstraint != "" && inspectData.ObjectType != typeConstraint { if typeConstraint != "" && inspectData.objectType != typeConstraint {
continue continue
} }
v, raw, err := inspectData.ObjectInspector(ref) if typeConstraint == "" && inspectData.isSwarmObject {
if isSwarmSupported == swarmSupportUnknown {
if isSwarmManager() {
isSwarmSupported = swarmSupported
} else {
isSwarmSupported = swarmUnsupported
}
}
if isSwarmSupported == swarmUnsupported {
continue
}
}
v, raw, err := inspectData.objectInspector(ref)
if err != nil { if err != nil {
if typeConstraint == "" && (apiclient.IsErrNotFound(err) || isErrNotSwarmManager(err)) { if typeConstraint == "" && apiclient.IsErrNotFound(err) {
continue continue
} }
return v, raw, err return v, raw, err
} }
if getSize && !inspectData.IsSizeSupported { if getSize && !inspectData.isSizeSupported {
fmt.Fprintf(dockerCli.Err(), "WARNING: --size ignored for %s\n", inspectData.ObjectType) fmt.Fprintf(dockerCli.Err(), "WARNING: --size ignored for %s\n", inspectData.objectType)
} }
return v, raw, err return v, raw, err
} }