From 482534ff5fe9899aa4acaeeee2932f836e3117b1 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 (cherry picked from commit 66cf4cc7f7942b049e0c99c21b84ab07aa80c777) Signed-off-by: Victor Vieux --- cli/command/system/inspect.go | 92 ++++++++++++++++++++++++++++------- 1 file changed, 74 insertions(+), 18 deletions(-) diff --git a/cli/command/system/inspect.go b/cli/command/system/inspect.go index f7172ae3c6..c86e858a29 100644 --- a/cli/command/system/inspect.go +++ b/cli/command/system/inspect.go @@ -103,22 +103,58 @@ 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 } isErrNotSupported := func(err error) bool { @@ -126,19 +162,39 @@ func inspectAll(ctx context.Context, dockerCli *command.DockerCli, getSize bool, } 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) || isErrNotSupported(err)) { + if typeConstraint == "" && (apiclient.IsErrNotFound(err) || isErrNotSupported(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 }