cli/command: add Cli.CurrentVersion() function

This internalizes constructing the Client(), which allows us to provide
fallbacks when trying to determin the current API version.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2022-11-04 13:46:36 +01:00
parent cbf052252b
commit a7e2c3ea1e
No known key found for this signature in database
GPG Key ID: 76698F39D527CE8C
5 changed files with 25 additions and 11 deletions

View File

@ -55,6 +55,7 @@ type Cli interface {
ServerInfo() ServerInfo
NotaryClient(imgRefAndAuth trust.ImageRefAndAuth, actions []string) (notaryclient.Repository, error)
DefaultVersion() string
CurrentVersion() string
ManifestStore() manifeststore.Store
RegistryClient(bool) registryclient.RegistryClient
ContentTrustEnabled() bool
@ -86,6 +87,15 @@ func (cli *DockerCli) DefaultVersion() string {
return api.DefaultVersion
}
// CurrentVersion returns the API version currently negotiated, or the default
// version otherwise.
func (cli *DockerCli) CurrentVersion() string {
if cli.client == nil {
return api.DefaultVersion
}
return cli.client.ClientVersion()
}
// Client returns the APIClient
func (cli *DockerCli) Client() client.APIClient {
return cli.client

View File

@ -111,7 +111,7 @@ func runRun(dockerCli command.Cli, flags *pflag.FlagSet, ropts *runOptions, copt
reportError(dockerCli.Err(), "run", err.Error(), true)
return cli.StatusError{StatusCode: 125}
}
if err = validateAPIVersion(containerConfig, dockerCli.Client().ClientVersion()); err != nil {
if err = validateAPIVersion(containerConfig, dockerCli.CurrentVersion()); err != nil {
reportError(dockerCli.Err(), "run", err.Error(), true)
return cli.StatusError{StatusCode: 125}
}

View File

@ -136,7 +136,7 @@ func runVersion(dockerCli command.Cli, opts *versionOptions) error {
Client: clientVersion{
Platform: struct{ Name string }{version.PlatformName},
Version: version.Version,
APIVersion: dockerCli.Client().ClientVersion(),
APIVersion: dockerCli.CurrentVersion(),
DefaultAPIVersion: dockerCli.DefaultVersion(),
GoVersion: runtime.Version(),
GitCommit: version.GitCommit,

View File

@ -14,7 +14,6 @@ import (
cliflags "github.com/docker/cli/cli/flags"
"github.com/docker/cli/cli/version"
"github.com/docker/docker/api/types/versions"
"github.com/docker/docker/client"
"github.com/moby/buildkit/util/appcontext"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@ -274,7 +273,7 @@ func main() {
}
type versionDetails interface {
Client() client.APIClient
CurrentVersion() string
ServerInfo() command.ServerInfo
}
@ -333,7 +332,7 @@ func hideUnsupportedFeatures(cmd *cobra.Command, details versionDetails) error {
return false
}
}
versionOlderThan = func(v string) bool { return versions.LessThan(details.Client().ClientVersion(), v) }
versionOlderThan = func(v string) bool { return versions.LessThan(details.CurrentVersion(), v) }
)
cmd.Flags().VisitAll(func(f *pflag.Flag) {
@ -390,8 +389,8 @@ func areFlagsSupported(cmd *cobra.Command, details versionDetails) error {
if !f.Changed {
return
}
if !isVersionSupported(f, details.Client().ClientVersion()) {
errs = append(errs, fmt.Sprintf(`"--%s" requires API version %s, but the Docker daemon API version is %s`, f.Name, getFlagAnnotation(f, "version"), details.Client().ClientVersion()))
if !isVersionSupported(f, details.CurrentVersion()) {
errs = append(errs, fmt.Sprintf(`"--%s" requires API version %s, but the Docker daemon API version is %s`, f.Name, getFlagAnnotation(f, "version"), details.CurrentVersion()))
return
}
if !isOSTypeSupported(f, details.ServerInfo().OSType) {
@ -417,11 +416,11 @@ 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() {
if cmdVersion, ok := curr.Annotations["version"]; ok && versions.LessThan(details.Client().ClientVersion(), cmdVersion) {
return fmt.Errorf("%s requires API version %s, but the Docker daemon API version is %s", cmd.CommandPath(), cmdVersion, details.Client().ClientVersion())
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())
}
if os, ok := curr.Annotations["ostype"]; ok && os != 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(), os, details.ServerInfo().OSType)
if ost, ok := curr.Annotations["ostype"]; ok && 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 && !details.ServerInfo().HasExperimental {
return fmt.Errorf("%s is only supported on a Docker daemon with experimental features enabled", cmd.CommandPath())

View File

@ -101,6 +101,11 @@ func (c *FakeCli) Client() client.APIClient {
return c.client
}
// CurrentVersion returns the API version used by FakeCli.
func (c *FakeCli) CurrentVersion() string {
return c.DefaultVersion()
}
// Out returns the output stream (stdout) the cli should write on
func (c *FakeCli) Out() *streams.Out {
return c.out