From c539be88332815aeb2d466a973443127c1c676a6 Mon Sep 17 00:00:00 2001 From: David Calavera Date: Mon, 25 Jan 2016 16:30:33 -0500 Subject: [PATCH] Allow network configuration via daemon config file. Signed-off-by: David Calavera --- daemon/config.go | 2 +- daemon/config_unix.go | 52 +++++++++++++------------- daemon/config_windows.go | 4 +- daemon/container_operations_unix.go | 2 +- daemon/container_operations_windows.go | 2 +- daemon/daemon_unix.go | 52 +++++++++++++------------- daemon/daemon_windows.go | 4 +- docker/daemon_unix_test.go | 43 +++++++++++++++++++++ docs/reference/commandline/daemon.md | 15 +++++++- 9 files changed, 116 insertions(+), 60 deletions(-) create mode 100644 docker/daemon_unix_test.go diff --git a/daemon/config.go b/daemon/config.go index ee0d41694c..932d535e57 100644 --- a/daemon/config.go +++ b/daemon/config.go @@ -45,7 +45,6 @@ type CommonTLSOptions struct { type CommonConfig struct { AuthorizationPlugins []string `json:"authorization-plugins,omitempty"` // AuthorizationPlugins holds list of authorization plugins AutoRestart bool `json:"-"` - Bridge bridgeConfig `json:"-"` // Bridge holds bridge network specific configuration. Context map[string][]string `json:"-"` DisableBridge bool `json:"-"` DNS []string `json:"dns,omitempty"` @@ -85,6 +84,7 @@ type CommonConfig struct { // deserialization without the full struct. CommonTLSOptions LogConfig + bridgeConfig // bridgeConfig holds bridge network specific configuration. reloadLock sync.Mutex valuesSet map[string]interface{} diff --git a/daemon/config_unix.go b/daemon/config_unix.go index 60fb3a9b54..daf236d6bb 100644 --- a/daemon/config_unix.go +++ b/daemon/config_unix.go @@ -37,19 +37,19 @@ type Config struct { // bridgeConfig stores all the bridge driver specific // configuration. type bridgeConfig struct { - EnableIPv6 bool - EnableIPTables bool - EnableIPForward bool - EnableIPMasq bool - EnableUserlandProxy bool - DefaultIP net.IP - Iface string - IP string - FixedCIDR string - FixedCIDRv6 string - DefaultGatewayIPv4 net.IP - DefaultGatewayIPv6 net.IP - InterContainerCommunication bool + EnableIPv6 bool `json:"ipv6,omitempty"` + EnableIPTables bool `json:"iptables,omitempty"` + EnableIPForward bool `json:"ip-forward,omitempty"` + EnableIPMasq bool `json:"ip-mask,omitempty"` + EnableUserlandProxy bool `json:"userland-proxy,omitempty"` + DefaultIP net.IP `json:"ip,omitempty"` + Iface string `json:"bridge,omitempty"` + IP string `json:"bip,omitempty"` + FixedCIDR string `json:"fixed-cidr,omitempty"` + FixedCIDRv6 string `json:"fixed-cidr-v6,omitempty"` + DefaultGatewayIPv4 net.IP `json:"default-gateway,omitempty"` + DefaultGatewayIPv6 net.IP `json:"default-gateway-v6,omitempty"` + InterContainerCommunication bool `json:"icc,omitempty"` } // InstallFlags adds command-line options to the top-level flag parser for @@ -65,19 +65,19 @@ func (config *Config) InstallFlags(cmd *flag.FlagSet, usageFn func(string) strin cmd.StringVar(&config.SocketGroup, []string{"G", "-group"}, "docker", usageFn("Group for the unix socket")) config.Ulimits = make(map[string]*units.Ulimit) cmd.Var(runconfigopts.NewUlimitOpt(&config.Ulimits), []string{"-default-ulimit"}, usageFn("Set default ulimits for containers")) - cmd.BoolVar(&config.Bridge.EnableIPTables, []string{"#iptables", "-iptables"}, true, usageFn("Enable addition of iptables rules")) - cmd.BoolVar(&config.Bridge.EnableIPForward, []string{"#ip-forward", "-ip-forward"}, true, usageFn("Enable net.ipv4.ip_forward")) - cmd.BoolVar(&config.Bridge.EnableIPMasq, []string{"-ip-masq"}, true, usageFn("Enable IP masquerading")) - cmd.BoolVar(&config.Bridge.EnableIPv6, []string{"-ipv6"}, false, usageFn("Enable IPv6 networking")) - cmd.StringVar(&config.Bridge.IP, []string{"#bip", "-bip"}, "", usageFn("Specify network bridge IP")) - cmd.StringVar(&config.Bridge.Iface, []string{"b", "-bridge"}, "", usageFn("Attach containers to a network bridge")) - cmd.StringVar(&config.Bridge.FixedCIDR, []string{"-fixed-cidr"}, "", usageFn("IPv4 subnet for fixed IPs")) - cmd.StringVar(&config.Bridge.FixedCIDRv6, []string{"-fixed-cidr-v6"}, "", usageFn("IPv6 subnet for fixed IPs")) - cmd.Var(opts.NewIPOpt(&config.Bridge.DefaultGatewayIPv4, ""), []string{"-default-gateway"}, usageFn("Container default gateway IPv4 address")) - cmd.Var(opts.NewIPOpt(&config.Bridge.DefaultGatewayIPv6, ""), []string{"-default-gateway-v6"}, usageFn("Container default gateway IPv6 address")) - cmd.BoolVar(&config.Bridge.InterContainerCommunication, []string{"#icc", "-icc"}, true, usageFn("Enable inter-container communication")) - cmd.Var(opts.NewIPOpt(&config.Bridge.DefaultIP, "0.0.0.0"), []string{"#ip", "-ip"}, usageFn("Default IP when binding container ports")) - cmd.BoolVar(&config.Bridge.EnableUserlandProxy, []string{"-userland-proxy"}, true, usageFn("Use userland proxy for loopback traffic")) + cmd.BoolVar(&config.bridgeConfig.EnableIPTables, []string{"#iptables", "-iptables"}, true, usageFn("Enable addition of iptables rules")) + cmd.BoolVar(&config.bridgeConfig.EnableIPForward, []string{"#ip-forward", "-ip-forward"}, true, usageFn("Enable net.ipv4.ip_forward")) + cmd.BoolVar(&config.bridgeConfig.EnableIPMasq, []string{"-ip-masq"}, true, usageFn("Enable IP masquerading")) + cmd.BoolVar(&config.bridgeConfig.EnableIPv6, []string{"-ipv6"}, false, usageFn("Enable IPv6 networking")) + cmd.StringVar(&config.bridgeConfig.IP, []string{"#bip", "-bip"}, "", usageFn("Specify network bridge IP")) + cmd.StringVar(&config.bridgeConfig.Iface, []string{"b", "-bridge"}, "", usageFn("Attach containers to a network bridge")) + cmd.StringVar(&config.bridgeConfig.FixedCIDR, []string{"-fixed-cidr"}, "", usageFn("IPv4 subnet for fixed IPs")) + cmd.StringVar(&config.bridgeConfig.FixedCIDRv6, []string{"-fixed-cidr-v6"}, "", usageFn("IPv6 subnet for fixed IPs")) + cmd.Var(opts.NewIPOpt(&config.bridgeConfig.DefaultGatewayIPv4, ""), []string{"-default-gateway"}, usageFn("Container default gateway IPv4 address")) + cmd.Var(opts.NewIPOpt(&config.bridgeConfig.DefaultGatewayIPv6, ""), []string{"-default-gateway-v6"}, usageFn("Container default gateway IPv6 address")) + cmd.BoolVar(&config.bridgeConfig.InterContainerCommunication, []string{"#icc", "-icc"}, true, usageFn("Enable inter-container communication")) + cmd.Var(opts.NewIPOpt(&config.bridgeConfig.DefaultIP, "0.0.0.0"), []string{"#ip", "-ip"}, usageFn("Default IP when binding container ports")) + cmd.BoolVar(&config.bridgeConfig.EnableUserlandProxy, []string{"-userland-proxy"}, true, usageFn("Use userland proxy for loopback traffic")) 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")) cmd.StringVar(&config.CorsHeaders, []string{"-api-cors-header"}, "", usageFn("Set CORS headers in the remote API")) cmd.StringVar(&config.CgroupParent, []string{"-cgroup-parent"}, "", usageFn("Set parent cgroup for all containers")) diff --git a/daemon/config_windows.go b/daemon/config_windows.go index bc0833aa9e..9918d45d00 100644 --- a/daemon/config_windows.go +++ b/daemon/config_windows.go @@ -15,7 +15,7 @@ var ( // bridgeConfig stores all the bridge driver specific // configuration. type bridgeConfig struct { - VirtualSwitchName string + VirtualSwitchName string `json:"bridge,omitempty"` } // Config defines the configuration of a docker daemon. @@ -37,5 +37,5 @@ func (config *Config) InstallFlags(cmd *flag.FlagSet, usageFn func(string) strin config.InstallCommonFlags(cmd, usageFn) // Then platform-specific install flags. - cmd.StringVar(&config.Bridge.VirtualSwitchName, []string{"b", "-bridge"}, "", "Attach containers to a virtual switch") + cmd.StringVar(&config.bridgeConfig.VirtualSwitchName, []string{"b", "-bridge"}, "", "Attach containers to a virtual switch") } diff --git a/daemon/container_operations_unix.go b/daemon/container_operations_unix.go index 8df163d0a5..a5fc6ca162 100644 --- a/daemon/container_operations_unix.go +++ b/daemon/container_operations_unix.go @@ -513,7 +513,7 @@ func (daemon *Daemon) updateEndpointNetworkSettings(container *container.Contain } if container.HostConfig.NetworkMode == containertypes.NetworkMode("bridge") { - container.NetworkSettings.Bridge = daemon.configStore.Bridge.Iface + container.NetworkSettings.Bridge = daemon.configStore.bridgeConfig.Iface } return nil diff --git a/daemon/container_operations_windows.go b/daemon/container_operations_windows.go index 8c3ae27e60..23bc6459cd 100644 --- a/daemon/container_operations_windows.go +++ b/daemon/container_operations_windows.go @@ -54,7 +54,7 @@ func (daemon *Daemon) populateCommand(c *container.Container, env []string) erro if !c.Config.NetworkDisabled { en.Interface = &execdriver.NetworkInterface{ MacAddress: c.Config.MacAddress, - Bridge: daemon.configStore.Bridge.VirtualSwitchName, + Bridge: daemon.configStore.bridgeConfig.VirtualSwitchName, PortBindings: c.HostConfig.PortBindings, // TODO Windows. Include IPAddress. There already is a diff --git a/daemon/daemon_unix.go b/daemon/daemon_unix.go index 3533345c45..a0992c7dac 100644 --- a/daemon/daemon_unix.go +++ b/daemon/daemon_unix.go @@ -412,14 +412,14 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes. // checkConfigOptions checks for mutually incompatible config options func checkConfigOptions(config *Config) error { // Check for mutually incompatible config options - if config.Bridge.Iface != "" && config.Bridge.IP != "" { + if config.bridgeConfig.Iface != "" && config.bridgeConfig.IP != "" { return fmt.Errorf("You specified -b & --bip, mutually exclusive options. Please specify only one.") } - if !config.Bridge.EnableIPTables && !config.Bridge.InterContainerCommunication { + if !config.bridgeConfig.EnableIPTables && !config.bridgeConfig.InterContainerCommunication { return fmt.Errorf("You specified --iptables=false with --icc=false. ICC=false uses iptables to function. Please set --icc or --iptables to true.") } - if !config.Bridge.EnableIPTables && config.Bridge.EnableIPMasq { - config.Bridge.EnableIPMasq = false + if !config.bridgeConfig.EnableIPTables && config.bridgeConfig.EnableIPMasq { + config.bridgeConfig.EnableIPMasq = false } return nil } @@ -451,7 +451,7 @@ func configureKernelSecuritySupport(config *Config, driverName string) error { } func isBridgeNetworkDisabled(config *Config) bool { - return config.Bridge.Iface == disableNetworkBridge + return config.bridgeConfig.Iface == disableNetworkBridge } func (daemon *Daemon) networkOptions(dconfig *Config) ([]nwconfig.Option, error) { @@ -525,9 +525,9 @@ func (daemon *Daemon) initNetworkController(config *Config) (libnetwork.NetworkC func driverOptions(config *Config) []nwconfig.Option { bridgeConfig := options.Generic{ - "EnableIPForwarding": config.Bridge.EnableIPForward, - "EnableIPTables": config.Bridge.EnableIPTables, - "EnableUserlandProxy": config.Bridge.EnableUserlandProxy} + "EnableIPForwarding": config.bridgeConfig.EnableIPForward, + "EnableIPTables": config.bridgeConfig.EnableIPTables, + "EnableUserlandProxy": config.bridgeConfig.EnableUserlandProxy} bridgeOption := options.Generic{netlabel.GenericData: bridgeConfig} dOptions := []nwconfig.Option{} @@ -543,20 +543,20 @@ func initBridgeDriver(controller libnetwork.NetworkController, config *Config) e } bridgeName := bridge.DefaultBridgeName - if config.Bridge.Iface != "" { - bridgeName = config.Bridge.Iface + if config.bridgeConfig.Iface != "" { + bridgeName = config.bridgeConfig.Iface } netOption := map[string]string{ bridge.BridgeName: bridgeName, bridge.DefaultBridge: strconv.FormatBool(true), netlabel.DriverMTU: strconv.Itoa(config.Mtu), - bridge.EnableIPMasquerade: strconv.FormatBool(config.Bridge.EnableIPMasq), - bridge.EnableICC: strconv.FormatBool(config.Bridge.InterContainerCommunication), + bridge.EnableIPMasquerade: strconv.FormatBool(config.bridgeConfig.EnableIPMasq), + bridge.EnableICC: strconv.FormatBool(config.bridgeConfig.InterContainerCommunication), } // --ip processing - if config.Bridge.DefaultIP != nil { - netOption[bridge.DefaultBindingIP] = config.Bridge.DefaultIP.String() + if config.bridgeConfig.DefaultIP != nil { + netOption[bridge.DefaultBindingIP] = config.bridgeConfig.DefaultIP.String() } var ( @@ -575,9 +575,9 @@ func initBridgeDriver(controller libnetwork.NetworkController, config *Config) e } } - if config.Bridge.IP != "" { - ipamV4Conf.PreferredPool = config.Bridge.IP - ip, _, err := net.ParseCIDR(config.Bridge.IP) + if config.bridgeConfig.IP != "" { + ipamV4Conf.PreferredPool = config.bridgeConfig.IP + ip, _, err := net.ParseCIDR(config.bridgeConfig.IP) if err != nil { return err } @@ -586,8 +586,8 @@ func initBridgeDriver(controller libnetwork.NetworkController, config *Config) e logrus.Infof("Default bridge (%s) is assigned with an IP address %s. Daemon option --bip can be used to set a preferred IP address", bridgeName, ipamV4Conf.PreferredPool) } - if config.Bridge.FixedCIDR != "" { - _, fCIDR, err := net.ParseCIDR(config.Bridge.FixedCIDR) + if config.bridgeConfig.FixedCIDR != "" { + _, fCIDR, err := net.ParseCIDR(config.bridgeConfig.FixedCIDR) if err != nil { return err } @@ -595,13 +595,13 @@ func initBridgeDriver(controller libnetwork.NetworkController, config *Config) e ipamV4Conf.SubPool = fCIDR.String() } - if config.Bridge.DefaultGatewayIPv4 != nil { - ipamV4Conf.AuxAddresses["DefaultGatewayIPv4"] = config.Bridge.DefaultGatewayIPv4.String() + if config.bridgeConfig.DefaultGatewayIPv4 != nil { + ipamV4Conf.AuxAddresses["DefaultGatewayIPv4"] = config.bridgeConfig.DefaultGatewayIPv4.String() } var deferIPv6Alloc bool - if config.Bridge.FixedCIDRv6 != "" { - _, fCIDRv6, err := net.ParseCIDR(config.Bridge.FixedCIDRv6) + if config.bridgeConfig.FixedCIDRv6 != "" { + _, fCIDRv6, err := net.ParseCIDR(config.bridgeConfig.FixedCIDRv6) if err != nil { return err } @@ -631,11 +631,11 @@ func initBridgeDriver(controller libnetwork.NetworkController, config *Config) e } } - if config.Bridge.DefaultGatewayIPv6 != nil { + if config.bridgeConfig.DefaultGatewayIPv6 != nil { if ipamV6Conf == nil { ipamV6Conf = &libnetwork.IpamConf{AuxAddresses: make(map[string]string)} } - ipamV6Conf.AuxAddresses["DefaultGatewayIPv6"] = config.Bridge.DefaultGatewayIPv6.String() + ipamV6Conf.AuxAddresses["DefaultGatewayIPv6"] = config.bridgeConfig.DefaultGatewayIPv6.String() } v4Conf := []*libnetwork.IpamConf{ipamV4Conf} @@ -647,7 +647,7 @@ func initBridgeDriver(controller libnetwork.NetworkController, config *Config) e _, err = controller.NewNetwork("bridge", "bridge", libnetwork.NetworkOptionGeneric(options.Generic{ netlabel.GenericData: netOption, - netlabel.EnableIPv6: config.Bridge.EnableIPv6, + netlabel.EnableIPv6: config.bridgeConfig.EnableIPv6, }), libnetwork.NetworkOptionIpam("default", "", v4Conf, v6Conf, nil), libnetwork.NetworkOptionDeferIPv6Alloc(deferIPv6Alloc)) diff --git a/daemon/daemon_windows.go b/daemon/daemon_windows.go index 3b571b6c1b..45b0975c08 100644 --- a/daemon/daemon_windows.go +++ b/daemon/daemon_windows.go @@ -121,8 +121,8 @@ func isBridgeNetworkDisabled(config *Config) bool { func (daemon *Daemon) initNetworkController(config *Config) (libnetwork.NetworkController, error) { // Set the name of the virtual switch if not specified by -b on daemon start - if config.Bridge.VirtualSwitchName == "" { - config.Bridge.VirtualSwitchName = defaultVirtualSwitch + if config.bridgeConfig.VirtualSwitchName == "" { + config.bridgeConfig.VirtualSwitchName = defaultVirtualSwitch } return nil, nil } diff --git a/docker/daemon_unix_test.go b/docker/daemon_unix_test.go new file mode 100644 index 0000000000..889482b007 --- /dev/null +++ b/docker/daemon_unix_test.go @@ -0,0 +1,43 @@ +// +build daemon,!windows + +package main + +import ( + "io/ioutil" + "testing" + + "github.com/docker/docker/cli" + "github.com/docker/docker/daemon" + "github.com/docker/docker/pkg/mflag" +) + +func TestLoadDaemonConfigWithNetwork(t *testing.T) { + c := &daemon.Config{} + common := &cli.CommonFlags{} + flags := mflag.NewFlagSet("test", mflag.ContinueOnError) + flags.String([]string{"-bip"}, "", "") + flags.String([]string{"-ip"}, "", "") + + f, err := ioutil.TempFile("", "docker-config-") + if err != nil { + t.Fatal(err) + } + + configFile := f.Name() + f.Write([]byte(`{"bip": "127.0.0.2", "ip": "127.0.0.1"}`)) + f.Close() + + loadedConfig, err := loadDaemonCliConfig(c, flags, common, configFile) + if err != nil { + t.Fatal(err) + } + if loadedConfig == nil { + t.Fatalf("expected configuration %v, got nil", c) + } + if loadedConfig.IP != "127.0.0.2" { + t.Fatalf("expected IP 127.0.0.2, got %v", loadedConfig.IP) + } + if loadedConfig.DefaultIP.String() != "127.0.0.1" { + t.Fatalf("expected DefaultIP 127.0.0.1, got %s", loadedConfig.DefaultIP) + } +} diff --git a/docs/reference/commandline/daemon.md b/docs/reference/commandline/daemon.md index b84b097bbf..7d950affd4 100644 --- a/docs/reference/commandline/daemon.md +++ b/docs/reference/commandline/daemon.md @@ -859,7 +859,20 @@ This is a full example of the allowed configuration options in the file: "userns-remap": "", "group": "", "cgroup-parent": "", - "default-ulimits": {} + "default-ulimits": {}, + "ipv6": false, + "iptables": false, + "ip-forward": false, + "ip-mask": false, + "userland-proxy": false, + "ip": "0.0.0.0", + "bridge": "", + "bip": "", + "fixed-cidr": "", + "fixed-cidr-v6": "", + "default-gateway": "", + "default-gateway-v6": "", + "icc": false } ```