From 518b65c6f5f2de65932a715d161324305cbdc693 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Thu, 8 Dec 2016 12:04:22 +0100 Subject: [PATCH] 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 --- command/system/inspect.go | 93 +++++++++++++++++++++++++++++++-------- 1 file changed, 74 insertions(+), 19 deletions(-) diff --git a/command/system/inspect.go b/command/system/inspect.go index dee4efcfec..cb5a1213af 100644 --- a/command/system/inspect.go +++ b/command/system/inspect.go @@ -2,7 +2,6 @@ package system import ( "fmt" - "strings" "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 { var inspectAutodetect = []struct { - ObjectType string - IsSizeSupported bool - ObjectInspector func(string) (interface{}, []byte, error) + objectType string + isSizeSupported bool + isSwarmObject bool + objectInspector func(string) (interface{}, []byte, error) }{ - {"container", true, inspectContainers(ctx, dockerCli, getSize)}, - {"image", false, inspectImages(ctx, dockerCli)}, - {"network", false, inspectNetwork(ctx, dockerCli)}, - {"volume", false, inspectVolume(ctx, dockerCli)}, - {"service", false, inspectService(ctx, dockerCli)}, - {"task", false, inspectTasks(ctx, dockerCli)}, - {"node", false, inspectNode(ctx, dockerCli)}, - {"plugin", false, inspectPlugin(ctx, dockerCli)}, + { + objectType: "container", + isSizeSupported: true, + objectInspector: inspectContainers(ctx, dockerCli, getSize), + }, + { + objectType: "image", + 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 { - return strings.Contains(err.Error(), "This node is not a swarm manager") + // isSwarmManager does an Info API call to verify that the daemon is + // 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) { + const ( + swarmSupportUnknown = iota + swarmSupported + swarmUnsupported + ) + + isSwarmSupported := swarmSupportUnknown + for _, inspectData := range inspectAutodetect { - if typeConstraint != "" && inspectData.ObjectType != typeConstraint { + if typeConstraint != "" && inspectData.objectType != typeConstraint { 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 typeConstraint == "" && (apiclient.IsErrNotFound(err) || isErrNotSwarmManager(err)) { + if typeConstraint == "" && apiclient.IsErrNotFound(err) { continue } return v, raw, err } - if getSize && !inspectData.IsSizeSupported { - fmt.Fprintf(dockerCli.Err(), "WARNING: --size ignored for %s\n", inspectData.ObjectType) + if getSize && !inspectData.isSizeSupported { + fmt.Fprintf(dockerCli.Err(), "WARNING: --size ignored for %s\n", inspectData.objectType) } return v, raw, err }