mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Hide command options that are related to Windows
Signed-off-by: Boaz Shuster <ripcurld.github@gmail.com>
This commit is contained in:
parent
8b02a15d52
commit
7199522ea2
6 changed files with 43 additions and 17 deletions
|
@ -43,6 +43,7 @@ func (v VersionMiddleware) WrapHandler(handler func(ctx context.Context, w http.
|
||||||
header := fmt.Sprintf("Docker/%s (%s)", v.serverVersion, runtime.GOOS)
|
header := fmt.Sprintf("Docker/%s (%s)", v.serverVersion, runtime.GOOS)
|
||||||
w.Header().Set("Server", header)
|
w.Header().Set("Server", header)
|
||||||
w.Header().Set("API-Version", v.defaultVersion)
|
w.Header().Set("API-Version", v.defaultVersion)
|
||||||
|
w.Header().Set("OSType", runtime.GOOS)
|
||||||
ctx = context.WithValue(ctx, "api-version", apiVersion)
|
ctx = context.WithValue(ctx, "api-version", apiVersion)
|
||||||
return handler(ctx, w, r, vars)
|
return handler(ctx, w, r, vars)
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,6 +97,7 @@ type ContainerStats struct {
|
||||||
// GET "/_ping"
|
// GET "/_ping"
|
||||||
type Ping struct {
|
type Ping struct {
|
||||||
APIVersion string
|
APIVersion string
|
||||||
|
OSType string
|
||||||
Experimental bool
|
Experimental bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,7 @@ type DockerCli struct {
|
||||||
keyFile string
|
keyFile string
|
||||||
client client.APIClient
|
client client.APIClient
|
||||||
hasExperimental bool
|
hasExperimental bool
|
||||||
|
osType string
|
||||||
defaultVersion string
|
defaultVersion string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,6 +60,11 @@ func (cli *DockerCli) HasExperimental() bool {
|
||||||
return cli.hasExperimental
|
return cli.hasExperimental
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OSType returns the operating system the daemon is running on.
|
||||||
|
func (cli *DockerCli) OSType() string {
|
||||||
|
return cli.osType
|
||||||
|
}
|
||||||
|
|
||||||
// DefaultVersion returns api.defaultVersion of DOCKER_API_VERSION if specified.
|
// DefaultVersion returns api.defaultVersion of DOCKER_API_VERSION if specified.
|
||||||
func (cli *DockerCli) DefaultVersion() string {
|
func (cli *DockerCli) DefaultVersion() string {
|
||||||
return cli.defaultVersion
|
return cli.defaultVersion
|
||||||
|
@ -166,6 +172,7 @@ func (cli *DockerCli) Initialize(opts *cliflags.ClientOptions) error {
|
||||||
|
|
||||||
if ping, err := cli.client.Ping(context.Background()); err == nil {
|
if ping, err := cli.client.Ping(context.Background()); err == nil {
|
||||||
cli.hasExperimental = ping.Experimental
|
cli.hasExperimental = ping.Experimental
|
||||||
|
cli.osType = ping.OSType
|
||||||
|
|
||||||
// since the new header was added in 1.25, assume server is 1.24 if header is not present.
|
// since the new header was added in 1.25, assume server is 1.24 if header is not present.
|
||||||
if ping.APIVersion == "" {
|
if ping.APIVersion == "" {
|
||||||
|
|
|
@ -189,6 +189,7 @@ func addFlags(flags *pflag.FlagSet) *containerOptions {
|
||||||
flags.Var(&copts.securityOpt, "security-opt", "Security Options")
|
flags.Var(&copts.securityOpt, "security-opt", "Security Options")
|
||||||
flags.StringVar(&copts.usernsMode, "userns", "", "User namespace to use")
|
flags.StringVar(&copts.usernsMode, "userns", "", "User namespace to use")
|
||||||
flags.StringVar(&copts.credentialSpec, "credentialspec", "", "Credential spec for managed service account (Windows only)")
|
flags.StringVar(&copts.credentialSpec, "credentialspec", "", "Credential spec for managed service account (Windows only)")
|
||||||
|
flags.SetAnnotation("credentialspec", "ostype", []string{"windows"})
|
||||||
|
|
||||||
// Network and port publishing flag
|
// Network and port publishing flag
|
||||||
flags.Var(&copts.extraHosts, "add-host", "Add a custom host-to-IP mapping (host:ip)")
|
flags.Var(&copts.extraHosts, "add-host", "Add a custom host-to-IP mapping (host:ip)")
|
||||||
|
@ -239,7 +240,9 @@ func addFlags(flags *pflag.FlagSet) *containerOptions {
|
||||||
flags.StringVar(&copts.cpusetCpus, "cpuset-cpus", "", "CPUs in which to allow execution (0-3, 0,1)")
|
flags.StringVar(&copts.cpusetCpus, "cpuset-cpus", "", "CPUs in which to allow execution (0-3, 0,1)")
|
||||||
flags.StringVar(&copts.cpusetMems, "cpuset-mems", "", "MEMs in which to allow execution (0-3, 0,1)")
|
flags.StringVar(&copts.cpusetMems, "cpuset-mems", "", "MEMs in which to allow execution (0-3, 0,1)")
|
||||||
flags.Int64Var(&copts.cpuCount, "cpu-count", 0, "CPU count (Windows only)")
|
flags.Int64Var(&copts.cpuCount, "cpu-count", 0, "CPU count (Windows only)")
|
||||||
|
flags.SetAnnotation("cpu-count", "ostype", []string{"windows"})
|
||||||
flags.Int64Var(&copts.cpuPercent, "cpu-percent", 0, "CPU percent (Windows only)")
|
flags.Int64Var(&copts.cpuPercent, "cpu-percent", 0, "CPU percent (Windows only)")
|
||||||
|
flags.SetAnnotation("cpu-percent", "ostype", []string{"windows"})
|
||||||
flags.Int64Var(&copts.cpuPeriod, "cpu-period", 0, "Limit CPU CFS (Completely Fair Scheduler) period")
|
flags.Int64Var(&copts.cpuPeriod, "cpu-period", 0, "Limit CPU CFS (Completely Fair Scheduler) period")
|
||||||
flags.Int64Var(&copts.cpuQuota, "cpu-quota", 0, "Limit CPU CFS (Completely Fair Scheduler) quota")
|
flags.Int64Var(&copts.cpuQuota, "cpu-quota", 0, "Limit CPU CFS (Completely Fair Scheduler) quota")
|
||||||
flags.Int64Var(&copts.cpuRealtimePeriod, "cpu-rt-period", 0, "Limit CPU real-time period in microseconds")
|
flags.Int64Var(&copts.cpuRealtimePeriod, "cpu-rt-period", 0, "Limit CPU real-time period in microseconds")
|
||||||
|
@ -254,7 +257,9 @@ func addFlags(flags *pflag.FlagSet) *containerOptions {
|
||||||
flags.Var(&copts.deviceWriteBps, "device-write-bps", "Limit write rate (bytes per second) to a device")
|
flags.Var(&copts.deviceWriteBps, "device-write-bps", "Limit write rate (bytes per second) to a device")
|
||||||
flags.Var(&copts.deviceWriteIOps, "device-write-iops", "Limit write rate (IO per second) to a device")
|
flags.Var(&copts.deviceWriteIOps, "device-write-iops", "Limit write rate (IO per second) to a device")
|
||||||
flags.Var(&copts.ioMaxBandwidth, "io-maxbandwidth", "Maximum IO bandwidth limit for the system drive (Windows only)")
|
flags.Var(&copts.ioMaxBandwidth, "io-maxbandwidth", "Maximum IO bandwidth limit for the system drive (Windows only)")
|
||||||
|
flags.SetAnnotation("io-maxbandwidth", "ostype", []string{"windows"})
|
||||||
flags.Uint64Var(&copts.ioMaxIOps, "io-maxiops", 0, "Maximum IOps limit for the system drive (Windows only)")
|
flags.Uint64Var(&copts.ioMaxIOps, "io-maxiops", 0, "Maximum IOps limit for the system drive (Windows only)")
|
||||||
|
flags.SetAnnotation("io-maxiops", "ostype", []string{"windows"})
|
||||||
flags.Var(&copts.kernelMemory, "kernel-memory", "Kernel memory limit")
|
flags.Var(&copts.kernelMemory, "kernel-memory", "Kernel memory limit")
|
||||||
flags.VarP(&copts.memory, "memory", "m", "Memory limit")
|
flags.VarP(&copts.memory, "memory", "m", "Memory limit")
|
||||||
flags.Var(&copts.memoryReservation, "memory-reservation", "Memory soft limit")
|
flags.Var(&copts.memoryReservation, "memory-reservation", "Memory soft limit")
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Ping pings the server and returns the value of the "Docker-Experimental" & "API-Version" headers
|
// Ping pings the server and returns the value of the "Docker-Experimental", "OS-Type" & "API-Version" headers
|
||||||
func (cli *Client) Ping(ctx context.Context) (types.Ping, error) {
|
func (cli *Client) Ping(ctx context.Context) (types.Ping, error) {
|
||||||
var ping types.Ping
|
var ping types.Ping
|
||||||
req, err := cli.buildRequest("GET", fmt.Sprintf("%s/_ping", cli.basePath), nil, nil)
|
req, err := cli.buildRequest("GET", fmt.Sprintf("%s/_ping", cli.basePath), nil, nil)
|
||||||
|
@ -26,5 +26,7 @@ func (cli *Client) Ping(ctx context.Context) (types.Ping, error) {
|
||||||
ping.Experimental = true
|
ping.Experimental = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ping.OSType = serverResp.header.Get("OSType")
|
||||||
|
|
||||||
return ping, nil
|
return ping, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ func newDockerCommand(dockerCli *command.DockerCli) *cobra.Command {
|
||||||
if err := dockerCli.Initialize(opts); err != nil {
|
if err := dockerCli.Initialize(opts); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return isSupported(cmd, dockerCli.Client().ClientVersion(), dockerCli.HasExperimental())
|
return isSupported(cmd, dockerCli.Client().ClientVersion(), dockerCli.OSType(), dockerCli.HasExperimental())
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
cli.SetupRootCommand(cmd)
|
cli.SetupRootCommand(cmd)
|
||||||
|
@ -80,7 +80,7 @@ func setFlagErrorFunc(dockerCli *command.DockerCli, cmd *cobra.Command, flags *p
|
||||||
flagErrorFunc := cmd.FlagErrorFunc()
|
flagErrorFunc := cmd.FlagErrorFunc()
|
||||||
cmd.SetFlagErrorFunc(func(cmd *cobra.Command, err error) error {
|
cmd.SetFlagErrorFunc(func(cmd *cobra.Command, err error) error {
|
||||||
initializeDockerCli(dockerCli, flags, opts)
|
initializeDockerCli(dockerCli, flags, opts)
|
||||||
if err := isSupported(cmd, dockerCli.Client().ClientVersion(), dockerCli.HasExperimental()); err != nil {
|
if err := isSupported(cmd, dockerCli.Client().ClientVersion(), dockerCli.OSType(), dockerCli.HasExperimental()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return flagErrorFunc(cmd, err)
|
return flagErrorFunc(cmd, err)
|
||||||
|
@ -90,12 +90,12 @@ func setFlagErrorFunc(dockerCli *command.DockerCli, cmd *cobra.Command, flags *p
|
||||||
func setHelpFunc(dockerCli *command.DockerCli, cmd *cobra.Command, flags *pflag.FlagSet, opts *cliflags.ClientOptions) {
|
func setHelpFunc(dockerCli *command.DockerCli, cmd *cobra.Command, flags *pflag.FlagSet, opts *cliflags.ClientOptions) {
|
||||||
cmd.SetHelpFunc(func(ccmd *cobra.Command, args []string) {
|
cmd.SetHelpFunc(func(ccmd *cobra.Command, args []string) {
|
||||||
initializeDockerCli(dockerCli, flags, opts)
|
initializeDockerCli(dockerCli, flags, opts)
|
||||||
if err := isSupported(ccmd, dockerCli.Client().ClientVersion(), dockerCli.HasExperimental()); err != nil {
|
if err := isSupported(ccmd, dockerCli.Client().ClientVersion(), dockerCli.OSType(), dockerCli.HasExperimental()); err != nil {
|
||||||
ccmd.Println(err)
|
ccmd.Println(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
hideUnsupportedFeatures(ccmd, dockerCli.Client().ClientVersion(), dockerCli.HasExperimental())
|
hideUnsupportedFeatures(ccmd, dockerCli.Client().ClientVersion(), dockerCli.OSType(), dockerCli.HasExperimental())
|
||||||
|
|
||||||
if err := ccmd.Help(); err != nil {
|
if err := ccmd.Help(); err != nil {
|
||||||
ccmd.Println(err)
|
ccmd.Println(err)
|
||||||
|
@ -122,7 +122,7 @@ func setValidateArgs(dockerCli *command.DockerCli, cmd *cobra.Command, flags *pf
|
||||||
cmdArgs := ccmd.Args
|
cmdArgs := ccmd.Args
|
||||||
ccmd.Args = func(cmd *cobra.Command, args []string) error {
|
ccmd.Args = func(cmd *cobra.Command, args []string) error {
|
||||||
initializeDockerCli(dockerCli, flags, opts)
|
initializeDockerCli(dockerCli, flags, opts)
|
||||||
if err := isSupported(cmd, dockerCli.Client().ClientVersion(), dockerCli.HasExperimental()); err != nil {
|
if err := isSupported(cmd, dockerCli.Client().ClientVersion(), dockerCli.OSType(), dockerCli.HasExperimental()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return cmdArgs(cmd, args)
|
return cmdArgs(cmd, args)
|
||||||
|
@ -198,7 +198,7 @@ func dockerPreRun(opts *cliflags.ClientOptions) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func hideUnsupportedFeatures(cmd *cobra.Command, clientVersion string, hasExperimental bool) {
|
func hideUnsupportedFeatures(cmd *cobra.Command, clientVersion, osType string, hasExperimental bool) {
|
||||||
cmd.Flags().VisitAll(func(f *pflag.Flag) {
|
cmd.Flags().VisitAll(func(f *pflag.Flag) {
|
||||||
// hide experimental flags
|
// hide experimental flags
|
||||||
if !hasExperimental {
|
if !hasExperimental {
|
||||||
|
@ -208,10 +208,9 @@ func hideUnsupportedFeatures(cmd *cobra.Command, clientVersion string, hasExperi
|
||||||
}
|
}
|
||||||
|
|
||||||
// hide flags not supported by the server
|
// hide flags not supported by the server
|
||||||
if !isFlagSupported(f, clientVersion) {
|
if !isOSTypeSupported(f, osType) || !isVersionSupported(f, clientVersion) {
|
||||||
f.Hidden = true
|
f.Hidden = true
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
for _, subcmd := range cmd.Commands() {
|
for _, subcmd := range cmd.Commands() {
|
||||||
|
@ -229,7 +228,7 @@ func hideUnsupportedFeatures(cmd *cobra.Command, clientVersion string, hasExperi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func isSupported(cmd *cobra.Command, clientVersion string, hasExperimental bool) error {
|
func isSupported(cmd *cobra.Command, clientVersion, osType string, hasExperimental bool) error {
|
||||||
// We check recursively so that, e.g., `docker stack ls` will return the same output as `docker stack`
|
// We check recursively so that, e.g., `docker stack ls` will return the same output as `docker stack`
|
||||||
if !hasExperimental {
|
if !hasExperimental {
|
||||||
for curr := cmd; curr != nil; curr = curr.Parent() {
|
for curr := cmd; curr != nil; curr = curr.Parent() {
|
||||||
|
@ -247,8 +246,12 @@ func isSupported(cmd *cobra.Command, clientVersion string, hasExperimental bool)
|
||||||
|
|
||||||
cmd.Flags().VisitAll(func(f *pflag.Flag) {
|
cmd.Flags().VisitAll(func(f *pflag.Flag) {
|
||||||
if f.Changed {
|
if f.Changed {
|
||||||
if !isFlagSupported(f, clientVersion) {
|
if !isVersionSupported(f, clientVersion) {
|
||||||
errs = append(errs, fmt.Sprintf("\"--%s\" requires API version %s, but the Docker daemon API version is %s", f.Name, getFlagVersion(f), clientVersion))
|
errs = append(errs, fmt.Sprintf("\"--%s\" requires API version %s, but the Docker daemon API version is %s", f.Name, getFlagAnnotation(f, "version"), clientVersion))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !isOSTypeSupported(f, osType) {
|
||||||
|
errs = append(errs, fmt.Sprintf("\"--%s\" requires the Docker daemon to run on %s, but the Docker daemon is running on %s", f.Name, getFlagAnnotation(f, "ostype"), osType))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if _, ok := f.Annotations["experimental"]; ok && !hasExperimental {
|
if _, ok := f.Annotations["experimental"]; ok && !hasExperimental {
|
||||||
|
@ -263,20 +266,27 @@ func isSupported(cmd *cobra.Command, clientVersion string, hasExperimental bool)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getFlagVersion(f *pflag.Flag) string {
|
func getFlagAnnotation(f *pflag.Flag, annotation string) string {
|
||||||
if flagVersion, ok := f.Annotations["version"]; ok && len(flagVersion) == 1 {
|
if value, ok := f.Annotations[annotation]; ok && len(value) == 1 {
|
||||||
return flagVersion[0]
|
return value[0]
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func isFlagSupported(f *pflag.Flag, clientVersion string) bool {
|
func isVersionSupported(f *pflag.Flag, clientVersion string) bool {
|
||||||
if v := getFlagVersion(f); v != "" {
|
if v := getFlagAnnotation(f, "version"); v != "" {
|
||||||
return versions.GreaterThanOrEqualTo(clientVersion, v)
|
return versions.GreaterThanOrEqualTo(clientVersion, v)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isOSTypeSupported(f *pflag.Flag, osType string) bool {
|
||||||
|
if v := getFlagAnnotation(f, "ostype"); v != "" && osType != "" {
|
||||||
|
return osType == v
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// hasTags return true if any of the command's parents has tags
|
// hasTags return true if any of the command's parents has tags
|
||||||
func hasTags(cmd *cobra.Command) bool {
|
func hasTags(cmd *cobra.Command) bool {
|
||||||
for curr := cmd; curr != nil; curr = curr.Parent() {
|
for curr := cmd; curr != nil; curr = curr.Parent() {
|
||||||
|
|
Loading…
Reference in a new issue