Skip to content

Commit fb83394

Browse files
committedAug 25, 2016
Convert dockerd to use cobra and pflag
Signed-off-by: Daniel Nephin <[email protected]>
1 parent ac40179 commit fb83394

15 files changed

+253
-233
lines changed
 

‎cli/flags/client.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package flags
22

3-
import flag "github.com/docker/docker/pkg/mflag"
3+
import (
4+
"github.com/spf13/pflag"
5+
)
46

57
// ClientFlags represents flags for the docker client.
68
type ClientFlags struct {
7-
FlagSet *flag.FlagSet
8-
Common *CommonFlags
9+
FlagSet *pflag.FlagSet
10+
Common *CommonOptions
911
PostParse func()
1012

1113
ConfigDir string

‎cli/flags/common.go

+35-40
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import (
88
"github.com/Sirupsen/logrus"
99
"github.com/docker/docker/cliconfig"
1010
"github.com/docker/docker/opts"
11-
flag "github.com/docker/docker/pkg/mflag"
1211
"github.com/docker/go-connections/tlsconfig"
12+
"github.com/spf13/pflag"
1313
)
1414

1515
const (
@@ -21,20 +21,17 @@ const (
2121
DefaultKeyFile = "key.pem"
2222
// DefaultCertFile is the default filename for the cert pem file
2323
DefaultCertFile = "cert.pem"
24-
// TLSVerifyKey is the default flag name for the tls verification option
25-
TLSVerifyKey = "tlsverify"
24+
// FlagTLSVerify is the flag name for the tls verification option
25+
FlagTLSVerify = "tlsverify"
2626
)
2727

2828
var (
2929
dockerCertPath = os.Getenv("DOCKER_CERT_PATH")
3030
dockerTLSVerify = os.Getenv("DOCKER_TLS_VERIFY") != ""
3131
)
3232

33-
// CommonFlags are flags common to both the client and the daemon.
34-
type CommonFlags struct {
35-
FlagSet *flag.FlagSet
36-
PostParse func()
37-
33+
// CommonOptions are options common to both the client and the daemon.
34+
type CommonOptions struct {
3835
Debug bool
3936
Hosts []string
4037
LogLevel string
@@ -44,62 +41,60 @@ type CommonFlags struct {
4441
TrustKey string
4542
}
4643

47-
// InitCommonFlags initializes flags common to both client and daemon
48-
func InitCommonFlags() *CommonFlags {
49-
var commonFlags = &CommonFlags{FlagSet: new(flag.FlagSet)}
44+
// NewCommonOptions returns a new CommonOptions
45+
func NewCommonOptions() *CommonOptions {
46+
return &CommonOptions{
47+
TLSOptions: &tlsconfig.Options{},
48+
}
49+
}
5050

51+
// InstallFlags adds flags for the common options on the FlagSet
52+
func (commonOpts *CommonOptions) InstallFlags(flags *pflag.FlagSet) {
5153
if dockerCertPath == "" {
5254
dockerCertPath = cliconfig.ConfigDir()
5355
}
5456

55-
commonFlags.PostParse = func() { postParseCommon(commonFlags) }
56-
57-
cmd := commonFlags.FlagSet
57+
flags.BoolVarP(&commonOpts.Debug, "debug", "D", false, "Enable debug mode")
58+
flags.StringVarP(&commonOpts.LogLevel, "log-level", "l", "info", "Set the logging level")
59+
flags.BoolVar(&commonOpts.TLS, "tls", false, "Use TLS; implied by --tlsverify")
60+
flags.BoolVar(&commonOpts.TLSVerify, FlagTLSVerify, dockerTLSVerify, "Use TLS and verify the remote")
5861

59-
cmd.BoolVar(&commonFlags.Debug, []string{"D", "-debug"}, false, "Enable debug mode")
60-
cmd.StringVar(&commonFlags.LogLevel, []string{"l", "-log-level"}, "info", "Set the logging level")
61-
cmd.BoolVar(&commonFlags.TLS, []string{"-tls"}, false, "Use TLS; implied by --tlsverify")
62-
cmd.BoolVar(&commonFlags.TLSVerify, []string{"-tlsverify"}, dockerTLSVerify, "Use TLS and verify the remote")
62+
// TODO use flag flags.String("identity"}, "i", "", "Path to libtrust key file")
6363

64-
// TODO use flag flag.String([]string{"i", "-identity"}, "", "Path to libtrust key file")
64+
tlsOptions := commonOpts.TLSOptions
65+
flags.StringVar(&tlsOptions.CAFile, "tlscacert", filepath.Join(dockerCertPath, DefaultCaFile), "Trust certs signed only by this CA")
66+
flags.StringVar(&tlsOptions.CertFile, "tlscert", filepath.Join(dockerCertPath, DefaultCertFile), "Path to TLS certificate file")
67+
flags.StringVar(&tlsOptions.KeyFile, "tlskey", filepath.Join(dockerCertPath, DefaultKeyFile), "Path to TLS key file")
6568

66-
var tlsOptions tlsconfig.Options
67-
commonFlags.TLSOptions = &tlsOptions
68-
cmd.StringVar(&tlsOptions.CAFile, []string{"-tlscacert"}, filepath.Join(dockerCertPath, DefaultCaFile), "Trust certs signed only by this CA")
69-
cmd.StringVar(&tlsOptions.CertFile, []string{"-tlscert"}, filepath.Join(dockerCertPath, DefaultCertFile), "Path to TLS certificate file")
70-
cmd.StringVar(&tlsOptions.KeyFile, []string{"-tlskey"}, filepath.Join(dockerCertPath, DefaultKeyFile), "Path to TLS key file")
71-
72-
cmd.Var(opts.NewNamedListOptsRef("hosts", &commonFlags.Hosts, opts.ValidateHost), []string{"H", "-host"}, "Daemon socket(s) to connect to")
73-
return commonFlags
69+
hostOpt := opts.NewNamedListOptsRef("hosts", &commonOpts.Hosts, opts.ValidateHost)
70+
flags.VarP(hostOpt, "-host", "H", "Daemon socket(s) to connect to")
7471
}
7572

76-
func postParseCommon(commonFlags *CommonFlags) {
77-
cmd := commonFlags.FlagSet
78-
79-
SetDaemonLogLevel(commonFlags.LogLevel)
80-
73+
// SetDefaultOptions sets default values for options after flag parsing is
74+
// complete
75+
func (commonOpts *CommonOptions) SetDefaultOptions(flags *pflag.FlagSet) {
8176
// Regardless of whether the user sets it to true or false, if they
8277
// specify --tlsverify at all then we need to turn on tls
8378
// TLSVerify can be true even if not set due to DOCKER_TLS_VERIFY env var, so we need
8479
// to check that here as well
85-
if cmd.IsSet("-"+TLSVerifyKey) || commonFlags.TLSVerify {
86-
commonFlags.TLS = true
80+
if flags.Changed(FlagTLSVerify) || commonOpts.TLSVerify {
81+
commonOpts.TLS = true
8782
}
8883

89-
if !commonFlags.TLS {
90-
commonFlags.TLSOptions = nil
84+
if !commonOpts.TLS {
85+
commonOpts.TLSOptions = nil
9186
} else {
92-
tlsOptions := commonFlags.TLSOptions
93-
tlsOptions.InsecureSkipVerify = !commonFlags.TLSVerify
87+
tlsOptions := commonOpts.TLSOptions
88+
tlsOptions.InsecureSkipVerify = !commonOpts.TLSVerify
9489

9590
// Reset CertFile and KeyFile to empty string if the user did not specify
9691
// the respective flags and the respective default files were not found.
97-
if !cmd.IsSet("-tlscert") {
92+
if !flags.Changed("tlscert") {
9893
if _, err := os.Stat(tlsOptions.CertFile); os.IsNotExist(err) {
9994
tlsOptions.CertFile = ""
10095
}
10196
}
102-
if !cmd.IsSet("-tlskey") {
97+
if !flags.Changed("tlskey") {
10398
if _, err := os.Stat(tlsOptions.KeyFile); os.IsNotExist(err) {
10499
tlsOptions.KeyFile = ""
105100
}

‎cmd/docker/docker.go

+1
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ func initClientFlags(commonFlags *cliflags.CommonFlags) *cliflags.ClientFlags {
101101

102102
clientFlags.PostParse = func() {
103103
clientFlags.Common.PostParse()
104+
cliflags.SetDaemonLogLevel(commonOpts.LogLevel)
104105

105106
if clientFlags.ConfigDir != "" {
106107
cliconfig.SetConfigDir(clientFlags.ConfigDir)

‎cmd/dockerd/daemon.go

+37-54
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"io"
77
"os"
88
"path/filepath"
9-
"runtime"
109
"strings"
1110
"time"
1211

@@ -31,58 +30,38 @@ import (
3130
"github.com/docker/docker/daemon/logger"
3231
"github.com/docker/docker/dockerversion"
3332
"github.com/docker/docker/libcontainerd"
34-
"github.com/docker/docker/opts"
33+
dopts "github.com/docker/docker/opts"
3534
"github.com/docker/docker/pkg/authorization"
3635
"github.com/docker/docker/pkg/jsonlog"
3736
"github.com/docker/docker/pkg/listeners"
38-
flag "github.com/docker/docker/pkg/mflag"
3937
"github.com/docker/docker/pkg/pidfile"
4038
"github.com/docker/docker/pkg/signal"
4139
"github.com/docker/docker/pkg/system"
4240
"github.com/docker/docker/registry"
4341
"github.com/docker/docker/runconfig"
4442
"github.com/docker/docker/utils"
4543
"github.com/docker/go-connections/tlsconfig"
44+
"github.com/spf13/pflag"
4645
)
4746

4847
const (
49-
daemonConfigFileFlag = "-config-file"
48+
flagDaemonConfigFile = "config-file"
5049
)
5150

5251
// DaemonCli represents the daemon CLI.
5352
type DaemonCli struct {
5453
*daemon.Config
55-
commonFlags *cliflags.CommonFlags
56-
configFile *string
54+
configFile *string
55+
flags *pflag.FlagSet
5756

5857
api *apiserver.Server
5958
d *daemon.Daemon
6059
authzMiddleware *authorization.Middleware // authzMiddleware enables to dynamically reload the authorization plugins
6160
}
6261

63-
func presentInHelp(usage string) string { return usage }
64-
func absentFromHelp(string) string { return "" }
65-
66-
// NewDaemonCli returns a pre-configured daemon CLI
62+
// NewDaemonCli returns a daemon CLI
6763
func NewDaemonCli() *DaemonCli {
68-
// TODO(tiborvass): remove InstallFlags?
69-
daemonConfig := new(daemon.Config)
70-
daemonConfig.LogConfig.Config = make(map[string]string)
71-
daemonConfig.ClusterOpts = make(map[string]string)
72-
73-
daemonConfig.InstallFlags(flag.CommandLine, presentInHelp)
74-
configFile := flag.CommandLine.String([]string{daemonConfigFileFlag}, defaultDaemonConfigFile, "Daemon configuration file")
75-
flag.CommandLine.Require(flag.Exact, 0)
76-
77-
if runtime.GOOS != "linux" {
78-
daemonConfig.V2Only = true
79-
}
80-
81-
return &DaemonCli{
82-
Config: daemonConfig,
83-
commonFlags: cliflags.InitCommonFlags(),
84-
configFile: configFile,
85-
}
64+
return &DaemonCli{}
8665
}
8766

8867
func migrateKey() (err error) {
@@ -126,24 +105,25 @@ func migrateKey() (err error) {
126105
return nil
127106
}
128107

129-
func (cli *DaemonCli) start() (err error) {
108+
func (cli *DaemonCli) start(opts daemonOptions) (err error) {
130109
stopc := make(chan bool)
131110
defer close(stopc)
132111

133112
// warn from uuid package when running the daemon
134113
uuid.Loggerf = logrus.Warnf
135114

136-
flags := flag.CommandLine
137-
cli.commonFlags.PostParse()
115+
opts.common.SetDefaultOptions(opts.flags)
138116

139-
if cli.commonFlags.TrustKey == "" {
140-
cli.commonFlags.TrustKey = filepath.Join(getDaemonConfDir(), cliflags.DefaultTrustKeyFile)
117+
if opts.common.TrustKey == "" {
118+
opts.common.TrustKey = filepath.Join(
119+
getDaemonConfDir(),
120+
cliflags.DefaultTrustKeyFile)
141121
}
142-
cliConfig, err := loadDaemonCliConfig(cli.Config, flags, cli.commonFlags, *cli.configFile)
143-
if err != nil {
122+
if cli.Config, err = loadDaemonCliConfig(opts); err != nil {
144123
return err
145124
}
146-
cli.Config = cliConfig
125+
cli.configFile = &opts.configFile
126+
cli.flags = opts.flags
147127

148128
if cli.Config.Debug {
149129
utils.EnableDebug()
@@ -215,7 +195,7 @@ func (cli *DaemonCli) start() (err error) {
215195

216196
for i := 0; i < len(cli.Config.Hosts); i++ {
217197
var err error
218-
if cli.Config.Hosts[i], err = opts.ParseHost(cli.Config.TLS, cli.Config.Hosts[i]); err != nil {
198+
if cli.Config.Hosts[i], err = dopts.ParseHost(cli.Config.TLS, cli.Config.Hosts[i]); err != nil {
219199
return fmt.Errorf("error parsing -H %s : %v", cli.Config.Hosts[i], err)
220200
}
221201

@@ -250,7 +230,8 @@ func (cli *DaemonCli) start() (err error) {
250230
if err := migrateKey(); err != nil {
251231
return err
252232
}
253-
cli.TrustKeyPath = cli.commonFlags.TrustKey
233+
// FIXME: why is this down here instead of with the other TrustKey logic above?
234+
cli.TrustKeyPath = opts.common.TrustKey
254235

255236
registryService := registry.NewService(cli.Config.ServiceOptions)
256237
containerdRemote, err := libcontainerd.New(cli.getLibcontainerdRoot(), cli.getPlatformRemoteOptions()...)
@@ -341,7 +322,7 @@ func (cli *DaemonCli) reloadConfig() {
341322
}
342323
}
343324

344-
if err := daemon.ReloadConfiguration(*cli.configFile, flag.CommandLine, reload); err != nil {
325+
if err := daemon.ReloadConfiguration(*cli.configFile, cli.flags, reload); err != nil {
345326
logrus.Error(err)
346327
}
347328
}
@@ -367,25 +348,27 @@ func shutdownDaemon(d *daemon.Daemon, timeout time.Duration) {
367348
}
368349
}
369350

370-
func loadDaemonCliConfig(config *daemon.Config, flags *flag.FlagSet, commonConfig *cliflags.CommonFlags, configFile string) (*daemon.Config, error) {
371-
config.Debug = commonConfig.Debug
372-
config.Hosts = commonConfig.Hosts
373-
config.LogLevel = commonConfig.LogLevel
374-
config.TLS = commonConfig.TLS
375-
config.TLSVerify = commonConfig.TLSVerify
351+
func loadDaemonCliConfig(opts daemonOptions) (*daemon.Config, error) {
352+
config := opts.daemonConfig
353+
flags := opts.flags
354+
config.Debug = opts.common.Debug
355+
config.Hosts = opts.common.Hosts
356+
config.LogLevel = opts.common.LogLevel
357+
config.TLS = opts.common.TLS
358+
config.TLSVerify = opts.common.TLSVerify
376359
config.CommonTLSOptions = daemon.CommonTLSOptions{}
377360

378-
if commonConfig.TLSOptions != nil {
379-
config.CommonTLSOptions.CAFile = commonConfig.TLSOptions.CAFile
380-
config.CommonTLSOptions.CertFile = commonConfig.TLSOptions.CertFile
381-
config.CommonTLSOptions.KeyFile = commonConfig.TLSOptions.KeyFile
361+
if opts.common.TLSOptions != nil {
362+
config.CommonTLSOptions.CAFile = opts.common.TLSOptions.CAFile
363+
config.CommonTLSOptions.CertFile = opts.common.TLSOptions.CertFile
364+
config.CommonTLSOptions.KeyFile = opts.common.TLSOptions.KeyFile
382365
}
383366

384-
if configFile != "" {
385-
c, err := daemon.MergeDaemonConfigurations(config, flags, configFile)
367+
if opts.configFile != "" {
368+
c, err := daemon.MergeDaemonConfigurations(config, flags, opts.configFile)
386369
if err != nil {
387-
if flags.IsSet(daemonConfigFileFlag) || !os.IsNotExist(err) {
388-
return nil, fmt.Errorf("unable to configure the Docker daemon with file %s: %v\n", configFile, err)
370+
if flags.Changed(flagDaemonConfigFile) || !os.IsNotExist(err) {
371+
return nil, fmt.Errorf("unable to configure the Docker daemon with file %s: %v\n", opts.configFile, err)
389372
}
390373
}
391374
// the merged configuration can be nil if the config file didn't exist.
@@ -401,7 +384,7 @@ func loadDaemonCliConfig(config *daemon.Config, flags *flag.FlagSet, commonConfi
401384

402385
// Regardless of whether the user sets it to true or false, if they
403386
// specify TLSVerify at all then we need to turn on TLS
404-
if config.IsValueSet(cliflags.TLSVerifyKey) {
387+
if config.IsValueSet(cliflags.FlagTLSVerify) {
405388
config.TLS = true
406389
}
407390

‎cmd/dockerd/docker.go

+62-44
Original file line numberDiff line numberDiff line change
@@ -2,59 +2,61 @@ package main
22

33
import (
44
"fmt"
5-
"os"
65

76
"github.com/Sirupsen/logrus"
7+
"github.com/docker/docker/cli"
8+
cliflags "github.com/docker/docker/cli/flags"
9+
"github.com/docker/docker/daemon"
810
"github.com/docker/docker/dockerversion"
9-
flag "github.com/docker/docker/pkg/mflag"
1011
"github.com/docker/docker/pkg/reexec"
1112
"github.com/docker/docker/pkg/term"
1213
"github.com/docker/docker/utils"
14+
"github.com/spf13/cobra"
15+
"github.com/spf13/pflag"
1316
)
1417

15-
var (
16-
daemonCli = NewDaemonCli()
17-
flHelp = flag.Bool([]string{"h", "-help"}, false, "Print usage")
18-
flVersion = flag.Bool([]string{"v", "-version"}, false, "Print version information and quit")
19-
)
18+
type daemonOptions struct {
19+
version bool
20+
configFile string
21+
daemonConfig *daemon.Config
22+
common *cliflags.CommonOptions
23+
flags *pflag.FlagSet
24+
}
2025

21-
func main() {
22-
if reexec.Init() {
23-
return
26+
func newDaemonCommand() *cobra.Command {
27+
opts := daemonOptions{
28+
daemonConfig: daemon.NewConfig(),
29+
common: cliflags.NewCommonOptions(),
2430
}
2531

26-
// Set terminal emulation based on platform as required.
27-
_, stdout, stderr := term.StdStreams()
28-
29-
logrus.SetOutput(stderr)
30-
31-
flag.Merge(flag.CommandLine, daemonCli.commonFlags.FlagSet)
32-
33-
flag.Usage = func() {
34-
fmt.Fprint(stdout, "Usage: dockerd [OPTIONS]\n\n")
35-
fmt.Fprint(stdout, "A self-sufficient runtime for containers.\n\nOptions:\n")
36-
37-
flag.CommandLine.SetOutput(stdout)
38-
flag.PrintDefaults()
39-
}
40-
flag.CommandLine.ShortUsage = func() {
41-
fmt.Fprint(stderr, "\nUsage:\tdockerd [OPTIONS]\n")
32+
cmd := &cobra.Command{
33+
Use: "dockerd [OPTIONS]",
34+
Short: "A self-sufficient runtime for containers.",
35+
SilenceUsage: true,
36+
SilenceErrors: true,
37+
Args: cli.NoArgs,
38+
RunE: func(cmd *cobra.Command, args []string) error {
39+
opts.flags = cmd.Flags()
40+
return runDaemon(opts)
41+
},
4242
}
43+
// TODO: SetUsageTemplate, SetHelpTemplate, SetFlagErrorFunc
4344

44-
if err := flag.CommandLine.ParseFlags(os.Args[1:], false); err != nil {
45-
os.Exit(1)
46-
}
45+
flags := cmd.Flags()
46+
flags.BoolP("help", "h", false, "Print usage")
47+
flags.MarkShorthandDeprecated("help", "please use --help")
48+
flags.BoolVarP(&opts.version, "version", "v", false, "Print version information and quit")
49+
flags.StringVar(&opts.configFile, flagDaemonConfigFile, defaultDaemonConfigFile, "Daemon configuration file")
50+
opts.common.InstallFlags(flags)
51+
opts.daemonConfig.InstallFlags(flags)
4752

48-
if *flVersion {
49-
showVersion()
50-
return
51-
}
53+
return cmd
54+
}
5255

53-
if *flHelp {
54-
// if global flag --help is present, regardless of what other options and commands there are,
55-
// just print the usage.
56-
flag.Usage()
57-
return
56+
func runDaemon(opts daemonOptions) error {
57+
if opts.version {
58+
showVersion()
59+
return nil
5860
}
5961

6062
// On Windows, this may be launching as a service or with an option to
@@ -64,13 +66,13 @@ func main() {
6466
logrus.Fatal(err)
6567
}
6668

67-
if !stop {
68-
err = daemonCli.start()
69-
notifyShutdown(err)
70-
if err != nil {
71-
logrus.Fatal(err)
72-
}
69+
if stop {
70+
return nil
7371
}
72+
73+
err = NewDaemonCli().start(opts)
74+
notifyShutdown(err)
75+
return err
7476
}
7577

7678
func showVersion() {
@@ -80,3 +82,19 @@ func showVersion() {
8082
fmt.Printf("Docker version %s, build %s\n", dockerversion.Version, dockerversion.GitCommit)
8183
}
8284
}
85+
86+
func main() {
87+
if reexec.Init() {
88+
return
89+
}
90+
91+
// Set terminal emulation based on platform as required.
92+
_, stdout, stderr := term.StdStreams()
93+
logrus.SetOutput(stderr)
94+
95+
cmd := newDaemonCommand()
96+
cmd.SetOutput(stdout)
97+
if err := cmd.Execute(); err != nil {
98+
logrus.Fatal(err)
99+
}
100+
}

‎daemon/config.go

+49-38
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,16 @@ import (
66
"fmt"
77
"io"
88
"io/ioutil"
9+
"runtime"
910
"strings"
1011
"sync"
1112

1213
"github.com/Sirupsen/logrus"
1314
"github.com/docker/docker/opts"
1415
"github.com/docker/docker/pkg/discovery"
15-
flag "github.com/docker/docker/pkg/mflag"
1616
"github.com/docker/docker/registry"
1717
"github.com/imdario/mergo"
18+
"github.com/spf13/pflag"
1819
)
1920

2021
const (
@@ -145,37 +146,35 @@ type CommonConfig struct {
145146
valuesSet map[string]interface{}
146147
}
147148

148-
// InstallCommonFlags adds command-line options to the top-level flag parser for
149-
// the current process.
150-
// Subsequent calls to `flag.Parse` will populate config with values parsed
151-
// from the command-line.
152-
func (config *Config) InstallCommonFlags(cmd *flag.FlagSet, usageFn func(string) string) {
149+
// InstallCommonFlags adds flags to the pflag.FlagSet to configure the daemon
150+
func (config *Config) InstallCommonFlags(flags *pflag.FlagSet) {
153151
var maxConcurrentDownloads, maxConcurrentUploads int
154152

155-
config.ServiceOptions.InstallCliFlags(cmd, usageFn)
156-
157-
cmd.Var(opts.NewNamedListOptsRef("storage-opts", &config.GraphOptions, nil), []string{"-storage-opt"}, usageFn("Storage driver options"))
158-
cmd.Var(opts.NewNamedListOptsRef("authorization-plugins", &config.AuthorizationPlugins, nil), []string{"-authorization-plugin"}, usageFn("Authorization plugins to load"))
159-
cmd.Var(opts.NewNamedListOptsRef("exec-opts", &config.ExecOptions, nil), []string{"-exec-opt"}, usageFn("Runtime execution options"))
160-
cmd.StringVar(&config.Pidfile, []string{"p", "-pidfile"}, defaultPidFile, usageFn("Path to use for daemon PID file"))
161-
cmd.StringVar(&config.Root, []string{"g", "-graph"}, defaultGraph, usageFn("Root of the Docker runtime"))
162-
cmd.BoolVar(&config.AutoRestart, []string{"#r", "#-restart"}, true, usageFn("--restart on the daemon has been deprecated in favor of --restart policies on docker run"))
163-
cmd.StringVar(&config.GraphDriver, []string{"s", "-storage-driver"}, "", usageFn("Storage driver to use"))
164-
cmd.IntVar(&config.Mtu, []string{"#mtu", "-mtu"}, 0, usageFn("Set the containers network MTU"))
165-
cmd.BoolVar(&config.RawLogs, []string{"-raw-logs"}, false, usageFn("Full timestamps without ANSI coloring"))
153+
config.ServiceOptions.InstallCliFlags(flags)
154+
155+
flags.Var(opts.NewNamedListOptsRef("storage-opts", &config.GraphOptions, nil), "storage-opt", "Storage driver options")
156+
flags.Var(opts.NewNamedListOptsRef("authorization-plugins", &config.AuthorizationPlugins, nil), "authorization-plugin", "Authorization plugins to load")
157+
flags.Var(opts.NewNamedListOptsRef("exec-opts", &config.ExecOptions, nil), "exec-opt", "Runtime execution options")
158+
flags.StringVarP(&config.Pidfile, "pidfile", "p", defaultPidFile, "Path to use for daemon PID file")
159+
flags.StringVarP(&config.Root, "graph", "g", defaultGraph, "Root of the Docker runtime")
160+
flags.BoolVarP(&config.AutoRestart, "restart", "r", true, "--restart on the daemon has been deprecated in favor of --restart policies on docker run")
161+
flags.MarkDeprecated("restart", "Please use a restart policy on ducker run")
162+
flags.StringVarP(&config.GraphDriver, "storage-driver", "s", "", "Storage driver to use")
163+
flags.IntVar(&config.Mtu, "mtu", 0, "Set the containers network MTU")
164+
flags.BoolVar(&config.RawLogs, "raw-logs", false, "Full timestamps without ANSI coloring")
166165
// FIXME: why the inconsistency between "hosts" and "sockets"?
167-
cmd.Var(opts.NewListOptsRef(&config.DNS, opts.ValidateIPAddress), []string{"#dns", "-dns"}, usageFn("DNS server to use"))
168-
cmd.Var(opts.NewNamedListOptsRef("dns-opts", &config.DNSOptions, nil), []string{"-dns-opt"}, usageFn("DNS options to use"))
169-
cmd.Var(opts.NewListOptsRef(&config.DNSSearch, opts.ValidateDNSSearch), []string{"-dns-search"}, usageFn("DNS search domains to use"))
170-
cmd.Var(opts.NewNamedListOptsRef("labels", &config.Labels, opts.ValidateLabel), []string{"-label"}, usageFn("Set key=value labels to the daemon"))
171-
cmd.StringVar(&config.LogConfig.Type, []string{"-log-driver"}, "json-file", usageFn("Default driver for container logs"))
172-
cmd.Var(opts.NewNamedMapOpts("log-opts", config.LogConfig.Config, nil), []string{"-log-opt"}, usageFn("Default log driver options for containers"))
173-
cmd.StringVar(&config.ClusterAdvertise, []string{"-cluster-advertise"}, "", usageFn("Address or interface name to advertise"))
174-
cmd.StringVar(&config.ClusterStore, []string{"-cluster-store"}, "", usageFn("URL of the distributed storage backend"))
175-
cmd.Var(opts.NewNamedMapOpts("cluster-store-opts", config.ClusterOpts, nil), []string{"-cluster-store-opt"}, usageFn("Set cluster store options"))
176-
cmd.StringVar(&config.CorsHeaders, []string{"-api-cors-header"}, "", usageFn("Set CORS headers in the remote API"))
177-
cmd.IntVar(&maxConcurrentDownloads, []string{"-max-concurrent-downloads"}, defaultMaxConcurrentDownloads, usageFn("Set the max concurrent downloads for each pull"))
178-
cmd.IntVar(&maxConcurrentUploads, []string{"-max-concurrent-uploads"}, defaultMaxConcurrentUploads, usageFn("Set the max concurrent uploads for each push"))
166+
flags.Var(opts.NewListOptsRef(&config.DNS, opts.ValidateIPAddress), "dns", "DNS server to use")
167+
flags.Var(opts.NewNamedListOptsRef("dns-opts", &config.DNSOptions, nil), "dns-opt", "DNS options to use")
168+
flags.Var(opts.NewListOptsRef(&config.DNSSearch, opts.ValidateDNSSearch), "dns-search", "DNS search domains to use")
169+
flags.Var(opts.NewNamedListOptsRef("labels", &config.Labels, opts.ValidateLabel), "label", "Set key=value labels to the daemon")
170+
flags.StringVar(&config.LogConfig.Type, "log-driver", "json-file", "Default driver for container logs")
171+
flags.Var(opts.NewNamedMapOpts("log-opts", config.LogConfig.Config, nil), "log-opt", "Default log driver options for containers")
172+
flags.StringVar(&config.ClusterAdvertise, "cluster-advertise", "", "Address or interface name to advertise")
173+
flags.StringVar(&config.ClusterStore, "cluster-store", "", "URL of the distributed storage backend")
174+
flags.Var(opts.NewNamedMapOpts("cluster-store-opts", config.ClusterOpts, nil), "cluster-store-opt", "Set cluster store options")
175+
flags.StringVar(&config.CorsHeaders, "api-cors-header", "", "Set CORS headers in the remote API")
176+
flags.IntVar(&maxConcurrentDownloads, "max-concurrent-downloads", defaultMaxConcurrentDownloads, "Set the max concurrent downloads for each pull")
177+
flags.IntVar(&maxConcurrentUploads, "max-concurrent-uploads", defaultMaxConcurrentUploads, "Set the max concurrent uploads for each push")
179178

180179
cmd.StringVar(&config.SwarmDefaultAdvertiseAddr, []string{"-swarm-default-advertise-addr"}, "", usageFn("Set default address or interface for swarm advertised address"))
181180

@@ -193,6 +192,18 @@ func (config *Config) IsValueSet(name string) bool {
193192
return ok
194193
}
195194

195+
// NewConfig returns a new fully initialized Config struct
196+
func NewConfig() *Config {
197+
config := Config{}
198+
config.LogConfig.Config = make(map[string]string)
199+
config.ClusterOpts = make(map[string]string)
200+
201+
if runtime.GOOS != "linux" {
202+
config.V2Only = true
203+
}
204+
return &config
205+
}
206+
196207
func parseClusterAdvertiseSettings(clusterStore, clusterAdvertise string) (string, error) {
197208
if clusterAdvertise == "" {
198209
return "", errDiscoveryDisabled
@@ -209,7 +220,7 @@ func parseClusterAdvertiseSettings(clusterStore, clusterAdvertise string) (strin
209220
}
210221

211222
// ReloadConfiguration reads the configuration in the host and reloads the daemon and server.
212-
func ReloadConfiguration(configFile string, flags *flag.FlagSet, reload func(*Config)) error {
223+
func ReloadConfiguration(configFile string, flags *pflag.FlagSet, reload func(*Config)) error {
213224
logrus.Infof("Got signal to reload configuration, reloading from: %s", configFile)
214225
newConfig, err := getConflictFreeConfiguration(configFile, flags)
215226
if err != nil {
@@ -234,7 +245,7 @@ type boolValue interface {
234245
// loads the file configuration in an isolated structure,
235246
// and merges the configuration provided from flags on top
236247
// if there are no conflicts.
237-
func MergeDaemonConfigurations(flagsConfig *Config, flags *flag.FlagSet, configFile string) (*Config, error) {
248+
func MergeDaemonConfigurations(flagsConfig *Config, flags *pflag.FlagSet, configFile string) (*Config, error) {
238249
fileConfig, err := getConflictFreeConfiguration(configFile, flags)
239250
if err != nil {
240251
return nil, err
@@ -261,7 +272,7 @@ func MergeDaemonConfigurations(flagsConfig *Config, flags *flag.FlagSet, configF
261272
// getConflictFreeConfiguration loads the configuration from a JSON file.
262273
// It compares that configuration with the one provided by the flags,
263274
// and returns an error if there are conflicts.
264-
func getConflictFreeConfiguration(configFile string, flags *flag.FlagSet) (*Config, error) {
275+
func getConflictFreeConfiguration(configFile string, flags *pflag.FlagSet) (*Config, error) {
265276
b, err := ioutil.ReadFile(configFile)
266277
if err != nil {
267278
return nil, err
@@ -301,7 +312,7 @@ func getConflictFreeConfiguration(configFile string, flags *flag.FlagSet) (*Conf
301312
}
302313
if len(namedOptions) > 0 {
303314
// set also default for mergeVal flags that are boolValue at the same time.
304-
flags.VisitAll(func(f *flag.Flag) {
315+
flags.VisitAll(func(f *pflag.Flag) {
305316
if opt, named := f.Value.(opts.NamedOption); named {
306317
v, set := namedOptions[opt.Name()]
307318
_, boolean := f.Value.(boolValue)
@@ -339,7 +350,7 @@ func configValuesSet(config map[string]interface{}) map[string]interface{} {
339350
// findConfigurationConflicts iterates over the provided flags searching for
340351
// duplicated configurations and unknown keys. It returns an error with all the conflicts if
341352
// it finds any.
342-
func findConfigurationConflicts(config map[string]interface{}, flags *flag.FlagSet) error {
353+
func findConfigurationConflicts(config map[string]interface{}, flags *pflag.FlagSet) error {
343354
// 1. Search keys from the file that we don't recognize as flags.
344355
unknownKeys := make(map[string]interface{})
345356
for key, value := range config {
@@ -352,7 +363,7 @@ func findConfigurationConflicts(config map[string]interface{}, flags *flag.FlagS
352363
// 2. Discard values that implement NamedOption.
353364
// Their configuration name differs from their flag name, like `labels` and `label`.
354365
if len(unknownKeys) > 0 {
355-
unknownNamedConflicts := func(f *flag.Flag) {
366+
unknownNamedConflicts := func(f *pflag.Flag) {
356367
if namedOption, ok := f.Value.(opts.NamedOption); ok {
357368
if _, valid := unknownKeys[namedOption.Name()]; valid {
358369
delete(unknownKeys, namedOption.Name())
@@ -376,15 +387,15 @@ func findConfigurationConflicts(config map[string]interface{}, flags *flag.FlagS
376387
}
377388

378389
// 3. Search keys that are present as a flag and as a file option.
379-
duplicatedConflicts := func(f *flag.Flag) {
390+
duplicatedConflicts := func(f *pflag.Flag) {
380391
// search option name in the json configuration payload if the value is a named option
381392
if namedOption, ok := f.Value.(opts.NamedOption); ok {
382393
if optsValue, ok := config[namedOption.Name()]; ok {
383394
conflicts = append(conflicts, printConflict(namedOption.Name(), f.Value.String(), optsValue))
384395
}
385396
} else {
386-
// search flag name in the json configuration payload without trailing dashes
387-
for _, name := range f.Names {
397+
// search flag name in the json configuration payload
398+
for _, name := range []string{f.Name, f.Shorthand} {
388399
name = strings.TrimLeft(name, "-")
389400

390401
if value, ok := config[name]; ok {

‎daemon/config_experimental.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
package daemon
44

5-
import flag "github.com/docker/docker/pkg/mflag"
5+
import (
6+
"github.com/spf13/pflag"
7+
)
68

7-
func (config *Config) attachExperimentalFlags(cmd *flag.FlagSet, usageFn func(string) string) {
9+
func (config *Config) attachExperimentalFlags(cmd *pflag.FlagSet) {
810
}

‎daemon/config_solaris.go

+4-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package daemon
22

33
import (
4-
flag "github.com/docker/docker/pkg/mflag"
4+
"github.com/spf13/pflag"
55
)
66

77
var (
@@ -28,14 +28,12 @@ type bridgeConfig struct {
2828

2929
// InstallFlags adds command-line options to the top-level flag parser for
3030
// the current process.
31-
// Subsequent calls to `flag.Parse` will populate config with values parsed
32-
// from the command-line.
33-
func (config *Config) InstallFlags(cmd *flag.FlagSet, usageFn func(string) string) {
31+
func (config *Config) InstallFlags(flags *pflag.FlagSet) {
3432
// First handle install flags which are consistent cross-platform
35-
config.InstallCommonFlags(cmd, usageFn)
33+
config.InstallCommonFlags(flags)
3634

3735
// Then platform-specific install flags
38-
config.attachExperimentalFlags(cmd, usageFn)
36+
config.attachExperimentalFlags(flags)
3937
}
4038

4139
// GetExecRoot returns the user configured Exec-root

‎daemon/config_stub.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
package daemon
44

5-
import flag "github.com/docker/docker/pkg/mflag"
5+
import (
6+
"github.com/spf13/pflag"
7+
)
68

7-
func (config *Config) attachExperimentalFlags(cmd *flag.FlagSet, usageFn func(string) string) {
9+
func (config *Config) attachExperimentalFlags(cmd *pflag.FlagSet) {
810
}

‎daemon/config_unix.go

+33-35
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ import (
77
"net"
88

99
"github.com/docker/docker/opts"
10-
flag "github.com/docker/docker/pkg/mflag"
1110
runconfigopts "github.com/docker/docker/runconfig/opts"
1211
"github.com/docker/engine-api/types"
13-
"github.com/docker/go-units"
12+
units "github.com/docker/go-units"
13+
"github.com/spf13/pflag"
1414
)
1515

1616
var (
@@ -56,44 +56,42 @@ type bridgeConfig struct {
5656
InterContainerCommunication bool `json:"icc,omitempty"`
5757
}
5858

59-
// InstallFlags adds command-line options to the top-level flag parser for
60-
// the current process.
61-
// Subsequent calls to `flag.Parse` will populate config with values parsed
62-
// from the command-line.
63-
func (config *Config) InstallFlags(cmd *flag.FlagSet, usageFn func(string) string) {
59+
// InstallFlags adds flags to the pflag.FlagSet to configure the daemon
60+
func (config *Config) InstallFlags(flags *pflag.FlagSet) {
6461
// First handle install flags which are consistent cross-platform
65-
config.InstallCommonFlags(cmd, usageFn)
62+
config.InstallCommonFlags(flags)
6663

67-
// Then platform-specific install flags
68-
cmd.BoolVar(&config.EnableSelinuxSupport, []string{"-selinux-enabled"}, false, usageFn("Enable selinux support"))
69-
cmd.StringVar(&config.SocketGroup, []string{"G", "-group"}, "docker", usageFn("Group for the unix socket"))
7064
config.Ulimits = make(map[string]*units.Ulimit)
71-
cmd.Var(runconfigopts.NewUlimitOpt(&config.Ulimits), []string{"-default-ulimit"}, usageFn("Default ulimits for containers"))
72-
cmd.BoolVar(&config.bridgeConfig.EnableIPTables, []string{"#iptables", "-iptables"}, true, usageFn("Enable addition of iptables rules"))
73-
cmd.BoolVar(&config.bridgeConfig.EnableIPForward, []string{"#ip-forward", "-ip-forward"}, true, usageFn("Enable net.ipv4.ip_forward"))
74-
cmd.BoolVar(&config.bridgeConfig.EnableIPMasq, []string{"-ip-masq"}, true, usageFn("Enable IP masquerading"))
75-
cmd.BoolVar(&config.bridgeConfig.EnableIPv6, []string{"-ipv6"}, false, usageFn("Enable IPv6 networking"))
76-
cmd.StringVar(&config.ExecRoot, []string{"-exec-root"}, defaultExecRoot, usageFn("Root directory for execution state files"))
77-
cmd.StringVar(&config.bridgeConfig.IP, []string{"#bip", "-bip"}, "", usageFn("Specify network bridge IP"))
78-
cmd.StringVar(&config.bridgeConfig.Iface, []string{"b", "-bridge"}, "", usageFn("Attach containers to a network bridge"))
79-
cmd.StringVar(&config.bridgeConfig.FixedCIDR, []string{"-fixed-cidr"}, "", usageFn("IPv4 subnet for fixed IPs"))
80-
cmd.StringVar(&config.bridgeConfig.FixedCIDRv6, []string{"-fixed-cidr-v6"}, "", usageFn("IPv6 subnet for fixed IPs"))
81-
cmd.Var(opts.NewIPOpt(&config.bridgeConfig.DefaultGatewayIPv4, ""), []string{"-default-gateway"}, usageFn("Container default gateway IPv4 address"))
82-
cmd.Var(opts.NewIPOpt(&config.bridgeConfig.DefaultGatewayIPv6, ""), []string{"-default-gateway-v6"}, usageFn("Container default gateway IPv6 address"))
83-
cmd.BoolVar(&config.bridgeConfig.InterContainerCommunication, []string{"#icc", "-icc"}, true, usageFn("Enable inter-container communication"))
84-
cmd.Var(opts.NewIPOpt(&config.bridgeConfig.DefaultIP, "0.0.0.0"), []string{"#ip", "-ip"}, usageFn("Default IP when binding container ports"))
85-
cmd.BoolVar(&config.bridgeConfig.EnableUserlandProxy, []string{"-userland-proxy"}, true, usageFn("Use userland proxy for loopback traffic"))
86-
cmd.BoolVar(&config.EnableCors, []string{"#api-enable-cors", "#-api-enable-cors"}, false, usageFn("Enable CORS headers in the remote API, this is deprecated by --api-cors-header"))
87-
cmd.StringVar(&config.CgroupParent, []string{"-cgroup-parent"}, "", usageFn("Set parent cgroup for all containers"))
88-
cmd.StringVar(&config.RemappedRoot, []string{"-userns-remap"}, "", usageFn("User/Group setting for user namespaces"))
89-
cmd.StringVar(&config.ContainerdAddr, []string{"-containerd"}, "", usageFn("Path to containerd socket"))
90-
cmd.BoolVar(&config.LiveRestoreEnabled, []string{"-live-restore"}, false, usageFn("Enable live restore of docker when containers are still running"))
9165
config.Runtimes = make(map[string]types.Runtime)
92-
cmd.Var(runconfigopts.NewNamedRuntimeOpt("runtimes", &config.Runtimes, stockRuntimeName), []string{"-add-runtime"}, usageFn("Register an additional OCI compatible runtime"))
93-
cmd.StringVar(&config.DefaultRuntime, []string{"-default-runtime"}, stockRuntimeName, usageFn("Default OCI runtime for containers"))
94-
cmd.IntVar(&config.OOMScoreAdjust, []string{"-oom-score-adjust"}, -500, usageFn("Set the oom_score_adj for the daemon"))
9566

96-
config.attachExperimentalFlags(cmd, usageFn)
67+
// Then platform-specific install flags
68+
flags.BoolVar(&config.EnableSelinuxSupport, "selinux-enabled", false, "Enable selinux support")
69+
flags.Var(runconfigopts.NewUlimitOpt(&config.Ulimits), "default-ulimit", "Default ulimits for containers")
70+
flags.BoolVar(&config.bridgeConfig.EnableIPTables, "iptables", true, "Enable addition of iptables rules")
71+
flags.BoolVar(&config.bridgeConfig.EnableIPForward, "ip-forward", true, "Enable net.ipv4.ip_forward")
72+
flags.BoolVar(&config.bridgeConfig.EnableIPMasq, "ip-masq", true, "Enable IP masquerading")
73+
flags.BoolVar(&config.bridgeConfig.EnableIPv6, "ipv6", false, "Enable IPv6 networking")
74+
flags.StringVar(&config.ExecRoot, "exec-root", defaultExecRoot, "Root directory for execution state files")
75+
flags.StringVar(&config.bridgeConfig.IP, "bip", "", "Specify network bridge IP")
76+
flags.StringVarP(&config.bridgeConfig.Iface, "bridge", "b", "", "Attach containers to a network bridge")
77+
flags.StringVar(&config.bridgeConfig.FixedCIDR, "fixed-cidr", "", "IPv4 subnet for fixed IPs")
78+
flags.StringVar(&config.bridgeConfig.FixedCIDRv6, "fixed-cidr-v6", "", "IPv6 subnet for fixed IPs")
79+
flags.Var(opts.NewIPOpt(&config.bridgeConfig.DefaultGatewayIPv4, ""), "default-gateway", "Container default gateway IPv4 address")
80+
flags.Var(opts.NewIPOpt(&config.bridgeConfig.DefaultGatewayIPv6, ""), "default-gateway-v6", "Container default gateway IPv6 address")
81+
flags.BoolVar(&config.bridgeConfig.InterContainerCommunication, "icc", true, "Enable inter-container communication")
82+
flags.Var(opts.NewIPOpt(&config.bridgeConfig.DefaultIP, "0.0.0.0"), "ip", "Default IP when binding container ports")
83+
flags.BoolVar(&config.bridgeConfig.EnableUserlandProxy, "userland-proxy", true, "Use userland proxy for loopback traffic")
84+
flags.BoolVar(&config.EnableCors, "api-enable-cors", false, "Enable CORS headers in the remote API, this is deprecated by --api-cors-header")
85+
flags.MarkDeprecated("api-enable-cors", "Please use --api-cors-header")
86+
flags.StringVar(&config.CgroupParent, "cgroup-parent", "", "Set parent cgroup for all containers")
87+
flags.StringVar(&config.RemappedRoot, "userns-remap", "", "User/Group setting for user namespaces")
88+
flags.StringVar(&config.ContainerdAddr, "containerd", "", "Path to containerd socket")
89+
flags.BoolVar(&config.LiveRestoreEnabled, "live-restore", false, "Enable live restore of docker when containers are still running")
90+
flags.Var(runconfigopts.NewNamedRuntimeOpt("runtimes", &config.Runtimes, stockRuntimeName), "add-runtime", "Register an additional OCI compatible runtime")
91+
flags.StringVar(&config.DefaultRuntime, "default-runtime", stockRuntimeName, "Default OCI runtime for containers")
92+
flags.IntVar(&config.OOMScoreAdjust, "oom-score-adjust", -500, "Set the oom_score_adj for the daemon")
93+
94+
config.attachExperimentalFlags(flags)
9795
}
9896

9997
// GetRuntime returns the runtime path and arguments for a given

‎opts/ip.go

+5
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,8 @@ func (o *IPOpt) String() string {
4040
}
4141
return o.IP.String()
4242
}
43+
44+
// Type returns the type of the option
45+
func (o *IPOpt) Type() string {
46+
return "ip"
47+
}

‎registry/config.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ import (
88
"strings"
99

1010
"github.com/docker/docker/opts"
11-
flag "github.com/docker/docker/pkg/mflag"
1211
"github.com/docker/docker/reference"
1312
registrytypes "github.com/docker/engine-api/types/registry"
13+
"github.com/spf13/pflag"
1414
)
1515

1616
// ServiceOptions holds command line options.
@@ -70,14 +70,14 @@ var lookupIP = net.LookupIP
7070

7171
// InstallCliFlags adds command-line options to the top-level flag parser for
7272
// the current process.
73-
func (options *ServiceOptions) InstallCliFlags(cmd *flag.FlagSet, usageFn func(string) string) {
73+
func (options *ServiceOptions) InstallCliFlags(flags *pflag.FlagSet) {
7474
mirrors := opts.NewNamedListOptsRef("registry-mirrors", &options.Mirrors, ValidateMirror)
75-
cmd.Var(mirrors, []string{"-registry-mirror"}, usageFn("Preferred Docker registry mirror"))
76-
7775
insecureRegistries := opts.NewNamedListOptsRef("insecure-registries", &options.InsecureRegistries, ValidateIndexName)
78-
cmd.Var(insecureRegistries, []string{"-insecure-registry"}, usageFn("Enable insecure registry communication"))
7976

80-
options.installCliPlatformFlags(cmd, usageFn)
77+
flags.Var(mirrors, "registry-mirror", "Preferred Docker registry mirror")
78+
flags.Var(insecureRegistries, "insecure-registry", "Enable insecure registry communication")
79+
80+
options.installCliPlatformFlags(flags)
8181
}
8282

8383
// newServiceConfig returns a new instance of ServiceConfig

‎registry/config_unix.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@ func cleanPath(s string) string {
2020
}
2121

2222
// installCliPlatformFlags handles any platform specific flags for the service.
23-
func (options *ServiceOptions) installCliPlatformFlags(cmd *flag.FlagSet, usageFn func(string) string) {
24-
cmd.BoolVar(&options.V2Only, []string{"-disable-legacy-registry"}, false, usageFn("Disable contacting legacy registries"))
23+
func (options *ServiceOptions) installCliPlatformFlags(flags *flag.FlagSet) string) {
24+
flags.BoolVar(&options.V2Only, "disable-legacy-registry", false, "Disable contacting legacy registries")
2525
}

‎registry/config_windows.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@ func cleanPath(s string) string {
2020
}
2121

2222
// installCliPlatformFlags handles any platform specific flags for the service.
23-
func (options *ServiceOptions) installCliPlatformFlags(cmd *flag.FlagSet, usageFn func(string) string) {
23+
func (options *ServiceOptions) installCliPlatformFlags(flags *flag.FlagSet) string) {
2424
// No Windows specific flags.
2525
}

‎runconfig/opts/runtime.go

+5
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,8 @@ func (o *RuntimeOpt) GetMap() map[string]types.Runtime {
7272

7373
return map[string]types.Runtime{}
7474
}
75+
76+
// Type returns the type of the option
77+
func (o *RuntimeOpt) Type() string {
78+
return "runtime"
79+
}

0 commit comments

Comments
 (0)
Please sign in to comment.