From 006c9463894581a69845d3f25131acf15b73727f Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Tue, 6 Dec 2022 10:09:34 +0100 Subject: [PATCH] cmd/docker: make feature detection lazy again Commit 20ba591b7f36c2ab24e4b3c78aaeae2836d2aea4 fixed incorrect feature detection in the CLI, but introduced a regression; previously the "ping" would only be executed if needed (see b39739123b845f872549e91be184cc583f5b387c), but by not inlining the call to `ServerInfo()` would now always be called. This patch inlines the code again to only execute the "ping" conditionally, which allows it to be executed lazily (and omitted for commands that don't require a daemon connection). Signed-off-by: Sebastiaan van Stijn --- cmd/docker/docker.go | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/cmd/docker/docker.go b/cmd/docker/docker.go index 8755511a2e..78336bea24 100644 --- a/cmd/docker/docker.go +++ b/cmd/docker/docker.go @@ -416,14 +416,21 @@ func areFlagsSupported(cmd *cobra.Command, details versionDetails) error { func areSubcommandsSupported(cmd *cobra.Command, details versionDetails) error { // Check recursively so that, e.g., `docker stack ls` returns the same output as `docker stack` for curr := cmd; curr != nil; curr = curr.Parent() { + // Important: in the code below, calls to "details.CurrentVersion()" and + // "details.ServerInfo()" are deliberately executed inline to make them + // be executed "lazily". This is to prevent making a connection with the + // daemon to perform a "ping" (even for commands that do not require a + // daemon connection). + // + // See commit b39739123b845f872549e91be184cc583f5b387c for details. + if cmdVersion, ok := curr.Annotations["version"]; ok && versions.LessThan(details.CurrentVersion(), cmdVersion) { return fmt.Errorf("%s requires API version %s, but the Docker daemon API version is %s", cmd.CommandPath(), cmdVersion, details.CurrentVersion()) } - si := details.ServerInfo() - if ost, ok := curr.Annotations["ostype"]; ok && si.OSType != "" && ost != si.OSType { - return fmt.Errorf("%s is only supported on a Docker daemon running on %s, but the Docker daemon is running on %s", cmd.CommandPath(), ost, si.OSType) + if ost, ok := curr.Annotations["ostype"]; ok && details.ServerInfo().OSType != "" && ost != details.ServerInfo().OSType { + return fmt.Errorf("%s is only supported on a Docker daemon running on %s, but the Docker daemon is running on %s", cmd.CommandPath(), ost, details.ServerInfo().OSType) } - if _, ok := curr.Annotations["experimental"]; ok && !si.HasExperimental { + if _, ok := curr.Annotations["experimental"]; ok && !details.ServerInfo().HasExperimental { return fmt.Errorf("%s is only supported on a Docker daemon with experimental features enabled", cmd.CommandPath()) } }