cmd/dockerd: normalize hosts when loading config
Previously, hosts were de-duplicated and normalized when starting the API server (in `loadListeners()`), which meant that errors could occur in that step (but not detected when using `dockerd --validate`), as well as the list of hosts in the config not matching what would actually be used (i.e., if duplicates were present). This patch extracts the de-duplicating to a separate function, and executes it as part of loading the daemon configuration, so that we can fail early. Moving this code also showed that some of this validation depended on `newAPIServerConfig()` modifying the configuration (adding an empty host if none was set) in order to have the parsing set a default. This code was moved elsewhere, but a TODO comment added as this logic is somewhat sketchy. Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
parent
7b3463f2c5
commit
57c20c1b79
1 changed files with 45 additions and 22 deletions
|
@ -8,6 +8,7 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -435,6 +436,10 @@ func loadDaemonCliConfig(opts *daemonOptions) (*config.Config, error) {
|
|||
}
|
||||
}
|
||||
|
||||
if err := normalizeHosts(conf); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := config.Validate(conf); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -469,6 +474,41 @@ func loadDaemonCliConfig(opts *daemonOptions) (*config.Config, error) {
|
|||
return conf, nil
|
||||
}
|
||||
|
||||
// normalizeHosts normalizes the configured config.Hosts and remove duplicates.
|
||||
// It returns an error if it fails to parse a host.
|
||||
func normalizeHosts(config *config.Config) error {
|
||||
if len(config.Hosts) == 0 {
|
||||
// if no hosts are configured, create a single entry slice, so that the
|
||||
// default is used.
|
||||
//
|
||||
// TODO(thaJeztah) implement a cleaner way for this; this depends on a
|
||||
// side-effect of how we parse empty/partial hosts.
|
||||
config.Hosts = make([]string, 1)
|
||||
}
|
||||
hosts := make([]string, 0, len(config.Hosts))
|
||||
seen := make(map[string]struct{}, len(config.Hosts))
|
||||
|
||||
useTLS := DefaultTLSValue
|
||||
if config.TLS != nil {
|
||||
useTLS = *config.TLS
|
||||
}
|
||||
|
||||
for _, h := range config.Hosts {
|
||||
host, err := dopts.ParseHost(useTLS, honorXDG, h)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, ok := seen[host]; ok {
|
||||
continue
|
||||
}
|
||||
seen[host] = struct{}{}
|
||||
hosts = append(hosts, host)
|
||||
}
|
||||
sort.Strings(hosts)
|
||||
config.Hosts = hosts
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkDeprecatedOptions(config *config.Config) error {
|
||||
// Overlay networks with external k/v stores have been deprecated
|
||||
if config.ClusterAdvertise != "" || len(config.ClusterOpts) > 0 || config.ClusterStore != "" {
|
||||
|
@ -591,10 +631,6 @@ func newAPIServerConfig(cli *DaemonCli) (*apiserver.Config, error) {
|
|||
serverConfig.TLSConfig = tlsConfig
|
||||
}
|
||||
|
||||
if len(cli.Config.Hosts) == 0 {
|
||||
cli.Config.Hosts = make([]string, 1)
|
||||
}
|
||||
|
||||
return serverConfig, nil
|
||||
}
|
||||
|
||||
|
@ -624,32 +660,19 @@ func checkTLSAuthOK(c *config.Config) bool {
|
|||
}
|
||||
|
||||
func loadListeners(cli *DaemonCli, serverConfig *apiserver.Config) ([]string, error) {
|
||||
var hosts []string
|
||||
seen := make(map[string]struct{}, len(cli.Config.Hosts))
|
||||
|
||||
useTLS := DefaultTLSValue
|
||||
if cli.Config.TLS != nil {
|
||||
useTLS = *cli.Config.TLS
|
||||
if len(cli.Config.Hosts) == 0 {
|
||||
return nil, errors.New("no hosts configured")
|
||||
}
|
||||
var hosts []string
|
||||
|
||||
for i := 0; i < len(cli.Config.Hosts); i++ {
|
||||
var err error
|
||||
if cli.Config.Hosts[i], err = dopts.ParseHost(useTLS, honorXDG, cli.Config.Hosts[i]); err != nil {
|
||||
return nil, errors.Wrapf(err, "error parsing -H %s", cli.Config.Hosts[i])
|
||||
}
|
||||
if _, ok := seen[cli.Config.Hosts[i]]; ok {
|
||||
continue
|
||||
}
|
||||
seen[cli.Config.Hosts[i]] = struct{}{}
|
||||
|
||||
protoAddr := cli.Config.Hosts[i]
|
||||
protoAddrParts := strings.SplitN(protoAddr, "://", 2)
|
||||
protoAddrParts := strings.SplitN(cli.Config.Hosts[i], "://", 2)
|
||||
if len(protoAddrParts) != 2 {
|
||||
return nil, fmt.Errorf("bad format %s, expected PROTO://ADDR", protoAddr)
|
||||
}
|
||||
|
||||
proto := protoAddrParts[0]
|
||||
addr := protoAddrParts[1]
|
||||
proto, addr := protoAddrParts[0], protoAddrParts[1]
|
||||
|
||||
// It's a bad idea to bind to TCP without tlsverify.
|
||||
authEnabled := serverConfig.TLSConfig != nil && serverConfig.TLSConfig.ClientAuth == tls.RequireAndVerifyClientCert
|
||||
|
|
Loading…
Add table
Reference in a new issue