cli: new daemon command and new cli package

This patch creates a new cli package that allows to combine both client
and daemon commands (there is only one daemon command: docker daemon).

The `-d` and `--daemon` top-level flags are deprecated and a special
message is added to prompt the user to use `docker daemon`.

Providing top-level daemon-specific flags for client commands result
in an error message prompting the user to use `docker daemon`.

This patch does not break any old but correct usages.

This also makes `-d` and `--daemon` flags, as well as the `daemon`
command illegal in client-only binaries.

Signed-off-by: Tibor Vass <tibor@docker.com>
This commit is contained in:
Tibor Vass 2015-05-05 00:18:28 -04:00
parent 879067d69e
commit 0cec613de9
2 changed files with 62 additions and 5 deletions

View file

@ -526,7 +526,7 @@ func (f *FlagSet) PrintDefaults() {
names = append(names, name)
}
}
if len(names) > 0 {
if len(names) > 0 && len(flag.Usage) > 0 {
val := flag.DefValue
if home != "" && strings.HasPrefix(val, home) {
@ -1143,3 +1143,53 @@ func (f *FlagSet) Init(name string, errorHandling ErrorHandling) {
f.name = name
f.errorHandling = errorHandling
}
type mergeVal struct {
Value
key string
fset *FlagSet
}
func (v mergeVal) Set(s string) error {
return v.fset.Set(v.key, s)
}
func (v mergeVal) IsBoolFlag() bool {
if b, ok := v.Value.(boolFlag); ok {
return b.IsBoolFlag()
}
return false
}
func Merge(dest *FlagSet, flagsets ...*FlagSet) error {
for _, fset := range flagsets {
for k, f := range fset.formal {
if _, ok := dest.formal[k]; ok {
var err error
if fset.name == "" {
err = fmt.Errorf("flag redefined: %s", k)
} else {
err = fmt.Errorf("%s flag redefined: %s", fset.name, k)
}
fmt.Fprintln(fset.Out(), err.Error())
// Happens only if flags are declared with identical names
switch dest.errorHandling {
case ContinueOnError:
return err
case ExitOnError:
os.Exit(2)
case PanicOnError:
panic(err)
}
}
newF := *f
newF.Value = mergeVal{f.Value, k, fset}
dest.formal[k] = &newF
}
}
return nil
}
func (f *FlagSet) IsEmpty() bool {
return len(f.actual) == 0
}

View file

@ -17,11 +17,18 @@ import (
// Options represents the information needed to create client and server TLS configurations.
type Options struct {
CAFile string
// If either CertFile or KeyFile is empty, Client() will not load them
// preventing the client from authenticating to the server.
// However, Server() requires them and will error out if they are empty.
CertFile string
KeyFile string
// client-only option
InsecureSkipVerify bool
ClientAuth tls.ClientAuthType
CAFile string
CertFile string
KeyFile string
// server-only option
ClientAuth tls.ClientAuthType
}
// Extra (server-side) accepted CBC cipher suites - will phase out in the future