mirror of https://github.com/docker/cli.git
Merge pull request #3564 from thaJeztah/update_engine_hide_swarm_commands
hide swarm-related commands based on the current swarm status and role
This commit is contained in:
commit
030eed90a8
|
@ -25,7 +25,8 @@ import (
|
||||||
dopts "github.com/docker/cli/opts"
|
dopts "github.com/docker/cli/opts"
|
||||||
"github.com/docker/docker/api"
|
"github.com/docker/docker/api"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
registrytypes "github.com/docker/docker/api/types/registry"
|
"github.com/docker/docker/api/types/registry"
|
||||||
|
"github.com/docker/docker/api/types/swarm"
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
"github.com/docker/go-connections/tlsconfig"
|
"github.com/docker/go-connections/tlsconfig"
|
||||||
"github.com/moby/term"
|
"github.com/moby/term"
|
||||||
|
@ -132,6 +133,7 @@ func (cli *DockerCli) loadConfigFile() {
|
||||||
// ServerInfo returns the server version details for the host this client is
|
// ServerInfo returns the server version details for the host this client is
|
||||||
// connected to
|
// connected to
|
||||||
func (cli *DockerCli) ServerInfo() ServerInfo {
|
func (cli *DockerCli) ServerInfo() ServerInfo {
|
||||||
|
// TODO(thaJeztah) make ServerInfo() lazily load the info (ping only when needed)
|
||||||
return cli.serverInfo
|
return cli.serverInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,7 +172,7 @@ func (cli *DockerCli) ManifestStore() manifeststore.Store {
|
||||||
// RegistryClient returns a client for communicating with a Docker distribution
|
// RegistryClient returns a client for communicating with a Docker distribution
|
||||||
// registry
|
// registry
|
||||||
func (cli *DockerCli) RegistryClient(allowInsecure bool) registryclient.RegistryClient {
|
func (cli *DockerCli) RegistryClient(allowInsecure bool) registryclient.RegistryClient {
|
||||||
resolver := func(ctx context.Context, index *registrytypes.IndexInfo) types.AuthConfig {
|
resolver := func(ctx context.Context, index *registry.IndexInfo) types.AuthConfig {
|
||||||
return ResolveAuthConfig(ctx, cli, index)
|
return ResolveAuthConfig(ctx, cli, index)
|
||||||
}
|
}
|
||||||
return registryclient.NewRegistryClient(resolver, UserAgent(), allowInsecure)
|
return registryclient.NewRegistryClient(resolver, UserAgent(), allowInsecure)
|
||||||
|
@ -336,6 +338,7 @@ func (cli *DockerCli) initializeFromClient() {
|
||||||
HasExperimental: ping.Experimental,
|
HasExperimental: ping.Experimental,
|
||||||
OSType: ping.OSType,
|
OSType: ping.OSType,
|
||||||
BuildkitVersion: ping.BuilderVersion,
|
BuildkitVersion: ping.BuilderVersion,
|
||||||
|
SwarmStatus: ping.SwarmStatus,
|
||||||
}
|
}
|
||||||
cli.client.NegotiateAPIVersionPing(ping)
|
cli.client.NegotiateAPIVersionPing(ping)
|
||||||
}
|
}
|
||||||
|
@ -376,6 +379,15 @@ type ServerInfo struct {
|
||||||
HasExperimental bool
|
HasExperimental bool
|
||||||
OSType string
|
OSType string
|
||||||
BuildkitVersion types.BuilderVersion
|
BuildkitVersion types.BuilderVersion
|
||||||
|
|
||||||
|
// SwarmStatus provides information about the current swarm status of the
|
||||||
|
// engine, obtained from the "Swarm" header in the API response.
|
||||||
|
//
|
||||||
|
// It can be a nil struct if the API version does not provide this header
|
||||||
|
// in the ping response, or if an error occurred, in which case the client
|
||||||
|
// should use other ways to get the current swarm status, such as the /swarm
|
||||||
|
// endpoint.
|
||||||
|
SwarmStatus *swarm.Status
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDockerCli returns a DockerCli instance with all operators applied on it.
|
// NewDockerCli returns a DockerCli instance with all operators applied on it.
|
||||||
|
|
|
@ -159,7 +159,7 @@ func TestInitializeFromClient(t *testing.T) {
|
||||||
|
|
||||||
cli := &DockerCli{client: apiclient}
|
cli := &DockerCli{client: apiclient}
|
||||||
cli.initializeFromClient()
|
cli.initializeFromClient()
|
||||||
assert.DeepEqual(t, cli.serverInfo, testcase.expectedServer)
|
assert.DeepEqual(t, cli.ServerInfo(), testcase.expectedServer)
|
||||||
assert.Equal(t, apiclient.negotiated, testcase.negotiated)
|
assert.Equal(t, apiclient.negotiated, testcase.negotiated)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ func NewConfigCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
RunE: command.ShowHelp(dockerCli.Err()),
|
RunE: command.ShowHelp(dockerCli.Err()),
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
"version": "1.30",
|
"version": "1.30",
|
||||||
"swarm": "",
|
"swarm": "manager",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
cmd.AddCommand(
|
cmd.AddCommand(
|
||||||
|
|
|
@ -20,7 +20,7 @@ func NewNodeCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
RunE: command.ShowHelp(dockerCli.Err()),
|
RunE: command.ShowHelp(dockerCli.Err()),
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
"version": "1.24",
|
"version": "1.24",
|
||||||
"swarm": "",
|
"swarm": "manager",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
cmd.AddCommand(
|
cmd.AddCommand(
|
||||||
|
|
|
@ -16,7 +16,7 @@ func NewSecretCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
RunE: command.ShowHelp(dockerCli.Err()),
|
RunE: command.ShowHelp(dockerCli.Err()),
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
"version": "1.25",
|
"version": "1.25",
|
||||||
"swarm": "",
|
"swarm": "manager",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
cmd.AddCommand(
|
cmd.AddCommand(
|
||||||
|
|
|
@ -16,7 +16,7 @@ func NewServiceCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
RunE: command.ShowHelp(dockerCli.Err()),
|
RunE: command.ShowHelp(dockerCli.Err()),
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
"version": "1.24",
|
"version": "1.24",
|
||||||
"swarm": "",
|
"swarm": "manager",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
cmd.AddCommand(
|
cmd.AddCommand(
|
||||||
|
|
|
@ -17,7 +17,7 @@ func NewStackCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
RunE: command.ShowHelp(dockerCli.Err()),
|
RunE: command.ShowHelp(dockerCli.Err()),
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
"version": "1.25",
|
"version": "1.25",
|
||||||
"swarm": "",
|
"swarm": "manager",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
defaultHelpFunc := cmd.HelpFunc()
|
defaultHelpFunc := cmd.HelpFunc()
|
||||||
|
|
|
@ -35,7 +35,10 @@ func newCACommand(dockerCli command.Cli) *cobra.Command {
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return runCA(dockerCli, cmd.Flags(), opts)
|
return runCA(dockerCli, cmd.Flags(), opts)
|
||||||
},
|
},
|
||||||
Annotations: map[string]string{"version": "1.30"},
|
Annotations: map[string]string{
|
||||||
|
"version": "1.30",
|
||||||
|
"swarm": "manager",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
flags := cmd.Flags()
|
flags := cmd.Flags()
|
||||||
|
|
|
@ -16,7 +16,7 @@ func NewSwarmCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
RunE: command.ShowHelp(dockerCli.Err()),
|
RunE: command.ShowHelp(dockerCli.Err()),
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
"version": "1.24",
|
"version": "1.24",
|
||||||
"swarm": "",
|
"swarm": "", // swarm command itself does not require swarm to be enabled (so swarm init and join is always available on API 1.24 and up)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
cmd.AddCommand(
|
cmd.AddCommand(
|
||||||
|
|
|
@ -39,6 +39,10 @@ func newInitCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return runInit(dockerCli, cmd.Flags(), opts)
|
return runInit(dockerCli, cmd.Flags(), opts)
|
||||||
},
|
},
|
||||||
|
Annotations: map[string]string{
|
||||||
|
"version": "1.24",
|
||||||
|
"swarm": "", // swarm init does not require swarm to be active, and is always available on API 1.24 and up
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
flags := cmd.Flags()
|
flags := cmd.Flags()
|
||||||
|
|
|
@ -36,6 +36,10 @@ func newJoinCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
opts.remote = args[0]
|
opts.remote = args[0]
|
||||||
return runJoin(dockerCli, cmd.Flags(), opts)
|
return runJoin(dockerCli, cmd.Flags(), opts)
|
||||||
},
|
},
|
||||||
|
Annotations: map[string]string{
|
||||||
|
"version": "1.24",
|
||||||
|
"swarm": "", // swarm join does not require swarm to be active, and is always available on API 1.24 and up
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
flags := cmd.Flags()
|
flags := cmd.Flags()
|
||||||
|
|
|
@ -28,6 +28,10 @@ func newJoinTokenCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
opts.role = args[0]
|
opts.role = args[0]
|
||||||
return runJoinToken(dockerCli, opts)
|
return runJoinToken(dockerCli, opts)
|
||||||
},
|
},
|
||||||
|
Annotations: map[string]string{
|
||||||
|
"version": "1.24",
|
||||||
|
"swarm": "manager",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
flags := cmd.Flags()
|
flags := cmd.Flags()
|
||||||
|
|
|
@ -23,6 +23,10 @@ func newLeaveCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return runLeave(dockerCli, opts)
|
return runLeave(dockerCli, opts)
|
||||||
},
|
},
|
||||||
|
Annotations: map[string]string{
|
||||||
|
"version": "1.24",
|
||||||
|
"swarm": "active",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
flags := cmd.Flags()
|
flags := cmd.Flags()
|
||||||
|
|
|
@ -24,6 +24,10 @@ func newUnlockCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return runUnlock(dockerCli)
|
return runUnlock(dockerCli)
|
||||||
},
|
},
|
||||||
|
Annotations: map[string]string{
|
||||||
|
"version": "1.24",
|
||||||
|
"swarm": "manager",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
|
|
|
@ -27,6 +27,10 @@ func newUnlockKeyCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return runUnlockKey(dockerCli, opts)
|
return runUnlockKey(dockerCli, opts)
|
||||||
},
|
},
|
||||||
|
Annotations: map[string]string{
|
||||||
|
"version": "1.24",
|
||||||
|
"swarm": "manager",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
flags := cmd.Flags()
|
flags := cmd.Flags()
|
||||||
|
|
|
@ -28,6 +28,10 @@ func newUpdateCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
|
Annotations: map[string]string{
|
||||||
|
"version": "1.24",
|
||||||
|
"swarm": "manager",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.Flags().BoolVar(&opts.autolock, flagAutolock, false, "Change manager autolocking setting (true|false)")
|
cmd.Flags().BoolVar(&opts.autolock, flagAutolock, false, "Change manager autolocking setting (true|false)")
|
||||||
|
|
|
@ -309,8 +309,33 @@ func hideSubcommandIf(subcmd *cobra.Command, condition func(string) bool, annota
|
||||||
|
|
||||||
func hideUnsupportedFeatures(cmd *cobra.Command, details versionDetails) error {
|
func hideUnsupportedFeatures(cmd *cobra.Command, details versionDetails) error {
|
||||||
var (
|
var (
|
||||||
notExperimental = func(_ string) bool { return !details.ServerInfo().HasExperimental }
|
notExperimental = func(_ string) bool { return !details.ServerInfo().HasExperimental }
|
||||||
notOSType = func(v string) bool { return v != details.ServerInfo().OSType }
|
notOSType = func(v string) bool { return v != details.ServerInfo().OSType }
|
||||||
|
notSwarmStatus = func(v string) bool {
|
||||||
|
s := details.ServerInfo().SwarmStatus
|
||||||
|
if s == nil {
|
||||||
|
// engine did not return swarm status header
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
switch v {
|
||||||
|
case "manager":
|
||||||
|
// requires the node to be a manager
|
||||||
|
return !s.ControlAvailable
|
||||||
|
case "active":
|
||||||
|
// requires swarm to be active on the node (e.g. for swarm leave)
|
||||||
|
// only hide the command if we're sure the node is "inactive"
|
||||||
|
// for any other status, assume the "leave" command can still
|
||||||
|
// be used.
|
||||||
|
return s.NodeState == "inactive"
|
||||||
|
case "":
|
||||||
|
// some swarm commands, such as "swarm init" and "swarm join"
|
||||||
|
// are swarm-related, but do not require swarm to be active
|
||||||
|
return false
|
||||||
|
default:
|
||||||
|
// ignore any other value for the "swarm" annotation
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
versionOlderThan = func(v string) bool { return versions.LessThan(details.Client().ClientVersion(), v) }
|
versionOlderThan = func(v string) bool { return versions.LessThan(details.Client().ClientVersion(), v) }
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -328,12 +353,14 @@ func hideUnsupportedFeatures(cmd *cobra.Command, details versionDetails) error {
|
||||||
|
|
||||||
hideFlagIf(f, notExperimental, "experimental")
|
hideFlagIf(f, notExperimental, "experimental")
|
||||||
hideFlagIf(f, notOSType, "ostype")
|
hideFlagIf(f, notOSType, "ostype")
|
||||||
|
hideFlagIf(f, notSwarmStatus, "swarm")
|
||||||
hideFlagIf(f, versionOlderThan, "version")
|
hideFlagIf(f, versionOlderThan, "version")
|
||||||
})
|
})
|
||||||
|
|
||||||
for _, subcmd := range cmd.Commands() {
|
for _, subcmd := range cmd.Commands() {
|
||||||
hideSubcommandIf(subcmd, notExperimental, "experimental")
|
hideSubcommandIf(subcmd, notExperimental, "experimental")
|
||||||
hideSubcommandIf(subcmd, notOSType, "ostype")
|
hideSubcommandIf(subcmd, notOSType, "ostype")
|
||||||
|
hideSubcommandIf(subcmd, notSwarmStatus, "swarm")
|
||||||
hideSubcommandIf(subcmd, versionOlderThan, "version")
|
hideSubcommandIf(subcmd, versionOlderThan, "version")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
Loading…
Reference in New Issue