From 900aca112b06f82a6bc219c91ea8ecf8a2936afa Mon Sep 17 00:00:00 2001 From: Jana Radhakrishnan Date: Fri, 18 Sep 2015 14:00:36 -0700 Subject: [PATCH] Push driver config during `Init` Currently the driver configuration is pushed through a separate api. This makes driver configuration possible at any arbitrary time. This unncessarily complicates the driver implementation. More importantly the driver does not get access to it's configuration before it can do the handshake with libnetwork. This make the internal drivers a little bit different to external plugins which can get their configuration before the handshake with libnetwork. This PR attempts to fix that mismatch between internal drivers and external plugins. Signed-off-by: Jana Radhakrishnan --- README.md | 89 +++++++++++++---------------- api/api_test.go | 35 ------------ cmd/ovrouter/ovrouter.go | 12 ++-- cmd/readme_test/readme.go | 10 +--- cmd/test/libnetwork.toml | 12 ---- cmd/test/main.go | 49 ---------------- config/config.go | 8 +++ controller.go | 45 ++------------- driverapi/driverapi.go | 3 - drivers.go | 55 ++++++++++++++++++ drivers/bridge/bridge.go | 33 ++++------- drivers/bridge/bridge_test.go | 32 +++++------ drivers/bridge/network_test.go | 11 ++-- drivers/bridge/port_mapping_test.go | 5 +- drivers/host/host.go | 6 +- drivers/null/null.go | 6 +- drivers/overlay/overlay.go | 18 ++++-- drivers/overlay/overlay_test.go | 34 ++++------- drivers/remote/driver.go | 2 +- drivers/windows/windows.go | 6 +- drivers_freebsd.go | 14 ++--- drivers_linux.go | 22 +++---- drivers_windows.go | 16 ++---- libnetwork_test.go | 21 +++---- sandbox_test.go | 11 ++-- 25 files changed, 208 insertions(+), 347 deletions(-) delete mode 100644 cmd/test/libnetwork.toml delete mode 100644 cmd/test/main.go create mode 100644 drivers.go diff --git a/README.md b/README.md index 62a0205..46dec9b 100644 --- a/README.md +++ b/README.md @@ -17,61 +17,55 @@ There are many networking solutions available to suit a broad range of use-cases ```go - // Create a new controller instance - controller, err := libnetwork.New() - if err != nil { - return - } + // Select and configure the network driver + networkType := "bridge" - // Select and configure the network driver - networkType := "bridge" + // Create a new controller instance + driverOptions := options.Generic{} + genericOption := make(map[string]interface{}) + genericOption[netlabel.GenericData] = driverOptions + controller, err := libnetwork.New(config.OptionDriverConfig(networkType, genericOption)) + if err != nil { + return + } - driverOptions := options.Generic{} - genericOption := make(map[string]interface{}) - genericOption[netlabel.GenericData] = driverOptions - err = controller.ConfigureNetworkDriver(networkType, genericOption) - if err != nil { - return - } + // Create a network for containers to join. + // NewNetwork accepts Variadic optional arguments that libnetwork and Drivers can use. + network, err := controller.NewNetwork(networkType, "network1") + if err != nil { + return + } - // Create a network for containers to join. - // NewNetwork accepts Variadic optional arguments that libnetwork and Drivers can use. - network, err := controller.NewNetwork(networkType, "network1") - if err != nil { - return - } + // For each new container: allocate IP and interfaces. The returned network + // settings will be used for container infos (inspect and such), as well as + // iptables rules for port publishing. This info is contained or accessible + // from the returned endpoint. + ep, err := network.CreateEndpoint("Endpoint1") + if err != nil { + return + } - // For each new container: allocate IP and interfaces. The returned network - // settings will be used for container infos (inspect and such), as well as - // iptables rules for port publishing. This info is contained or accessible - // from the returned endpoint. - ep, err := network.CreateEndpoint("Endpoint1") - if err != nil { - return - } + // Create the sandbox for the containr. + sbx, err := controller.NewSandbox("container1", + libnetwork.OptionHostname("test"), + libnetwork.OptionDomainname("docker.io")) - // Create the sandbox for the containr. - sbx, err := controller.NewSandbox("container1", - libnetwork.OptionHostname("test"), - libnetwork.OptionDomainname("docker.io")) - - // A sandbox can join the endpoint via the join api. - // Join accepts Variadic arguments which libnetwork and Drivers can use. - err = ep.Join(sbx) - if err != nil { - return - } + // A sandbox can join the endpoint via the join api. + // Join accepts Variadic arguments which libnetwork and Drivers can use. + err = ep.Join(sbx) + if err != nil { + return + } - // libnetwork client can check the endpoint's operational data via the Info() API - epInfo, err := ep.DriverInfo() - mapData, ok := epInfo[netlabel.PortMap] + // libnetwork client can check the endpoint's operational data via the Info() API + epInfo, err := ep.DriverInfo() + mapData, ok := epInfo[netlabel.PortMap] + if ok { + portMapping, ok := mapData.([]types.PortBinding) if ok { - portMapping, ok := mapData.([]types.PortBinding) - if ok { - fmt.Printf("Current port mapping for endpoint %s: %v", ep.Name(), portMapping) - } + fmt.Printf("Current port mapping for endpoint %s: %v", ep.Name(), portMapping) } - + } ``` #### Current Status Please watch this space for updates on the progress. @@ -87,4 +81,3 @@ Want to hack on libnetwork? [Docker's contributions guidelines](https://github.c ## Copyright and license Code and documentation copyright 2015 Docker, inc. Code released under the Apache 2.0 license. Docs released under Creative commons. - diff --git a/api/api_test.go b/api/api_test.go index 3cf0726..6477a8d 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -93,11 +93,6 @@ func createTestNetwork(t *testing.T, network string) (libnetwork.NetworkControll t.Fatal(err) } - err = c.ConfigureNetworkDriver(bridgeNetType, nil) - if err != nil { - t.Fatal(err) - } - netOption := options.Generic{ netlabel.GenericData: options.Generic{ "BridgeName": network, @@ -184,10 +179,6 @@ func TestCreateDeleteNetwork(t *testing.T) { if err != nil { t.Fatal(err) } - err = c.ConfigureNetworkDriver(bridgeNetType, nil) - if err != nil { - t.Fatal(err) - } badBody, err := json.Marshal("bad body") if err != nil { @@ -262,10 +253,6 @@ func TestGetNetworksAndEndpoints(t *testing.T) { if err != nil { t.Fatal(err) } - err = c.ConfigureNetworkDriver(bridgeNetType, nil) - if err != nil { - t.Fatal(err) - } ops := options.Generic{ netlabel.GenericData: map[string]string{ @@ -536,11 +523,6 @@ func TestProcGetServices(t *testing.T) { t.Fatal(err) } - err = c.ConfigureNetworkDriver(bridgeNetType, nil) - if err != nil { - t.Fatal(err) - } - // Create 2 networks netName1 := "production" netOption := options.Generic{ @@ -1124,10 +1106,6 @@ func TestCreateDeleteEndpoints(t *testing.T) { if err != nil { t.Fatal(err) } - err = c.ConfigureNetworkDriver(bridgeNetType, nil) - if err != nil { - t.Fatal(err) - } nc := networkCreate{Name: "firstNet", NetworkType: bridgeNetType} body, err := json.Marshal(nc) @@ -1250,10 +1228,6 @@ func TestJoinLeave(t *testing.T) { if err != nil { t.Fatal(err) } - err = c.ConfigureNetworkDriver(bridgeNetType, nil) - if err != nil { - t.Fatal(err) - } nb, err := json.Marshal(networkCreate{Name: "network", NetworkType: bridgeNetType}) if err != nil { @@ -1694,11 +1668,6 @@ func TestHttpHandlerUninit(t *testing.T) { t.Fatal(err) } - err = c.ConfigureNetworkDriver(bridgeNetType, nil) - if err != nil { - t.Fatal(err) - } - h := &httpHandler{c: c} h.initRouter() if h.r == nil { @@ -1796,10 +1765,6 @@ func TestEndToEnd(t *testing.T) { if err != nil { t.Fatal(err) } - err = c.ConfigureNetworkDriver(bridgeNetType, nil) - if err != nil { - t.Fatal(err) - } handleRequest := NewHTTPHandler(c) diff --git a/cmd/ovrouter/ovrouter.go b/cmd/ovrouter/ovrouter.go index 0d0dcc9..787320c 100644 --- a/cmd/ovrouter/ovrouter.go +++ b/cmd/ovrouter/ovrouter.go @@ -65,12 +65,6 @@ func main() { return } - r := &router{} - if err := overlay.Init(r); err != nil { - fmt.Printf("Failed to initialize overlay driver: %v\n", err) - os.Exit(1) - } - opt := make(map[string]interface{}) if len(os.Args) > 1 { opt[netlabel.OverlayBindInterface] = os.Args[1] @@ -85,7 +79,11 @@ func main() { opt[netlabel.KVProviderURL] = os.Args[4] } - r.d.Config(opt) + r := &router{} + if err := overlay.Init(r, opt); err != nil { + fmt.Printf("Failed to initialize overlay driver: %v\n", err) + os.Exit(1) + } if err := r.d.CreateNetwork("testnetwork", map[string]interface{}{}); err != nil { diff --git a/cmd/readme_test/readme.go b/cmd/readme_test/readme.go index 9591aef..5e08525 100644 --- a/cmd/readme_test/readme.go +++ b/cmd/readme_test/readme.go @@ -4,25 +4,21 @@ import ( "fmt" "github.com/docker/libnetwork" + "github.com/docker/libnetwork/config" "github.com/docker/libnetwork/netlabel" "github.com/docker/libnetwork/options" "github.com/docker/libnetwork/types" ) func main() { - // Create a new controller instance - controller, err := libnetwork.New() - if err != nil { - return - } - // Select and configure the network driver networkType := "bridge" + // Create a new controller instance driverOptions := options.Generic{} genericOption := make(map[string]interface{}) genericOption[netlabel.GenericData] = driverOptions - err = controller.ConfigureNetworkDriver(networkType, genericOption) + controller, err := libnetwork.New(config.OptionDriverConfig(networkType, genericOption)) if err != nil { return } diff --git a/cmd/test/libnetwork.toml b/cmd/test/libnetwork.toml deleted file mode 100644 index 4e22516..0000000 --- a/cmd/test/libnetwork.toml +++ /dev/null @@ -1,12 +0,0 @@ -title = "LibNetwork Configuration file" - -[daemon] - debug = false -[cluster] - discovery = "token://22aa23948f4f6b31230687689636959e" - Address = "1.1.1.1" -[datastore] - embedded = false -[datastore.client] - provider = "consul" - Address = "localhost:8500" diff --git a/cmd/test/main.go b/cmd/test/main.go deleted file mode 100644 index 957a0cd..0000000 --- a/cmd/test/main.go +++ /dev/null @@ -1,49 +0,0 @@ -package main - -import ( - "fmt" - "net" - "time" - - log "github.com/Sirupsen/logrus" - - "github.com/docker/libnetwork" - "github.com/docker/libnetwork/options" -) - -func main() { - log.SetLevel(log.DebugLevel) - controller, err := libnetwork.New() - if err != nil { - log.Fatal(err) - } - - netType := "null" - ip, net, _ := net.ParseCIDR("192.168.100.1/24") - net.IP = ip - options := options.Generic{"AddressIPv4": net} - - err = controller.ConfigureNetworkDriver(netType, options) - for i := 0; i < 10; i++ { - netw, err := controller.NewNetwork(netType, fmt.Sprintf("Gordon-%d", i)) - if err != nil { - if _, ok := err.(libnetwork.NetworkNameError); !ok { - log.Fatal(err) - } - } else { - fmt.Println("Network Created Successfully :", netw) - } - netw, _ = controller.NetworkByName(fmt.Sprintf("Gordon-%d", i)) - _, err = netw.CreateEndpoint(fmt.Sprintf("Gordon-Ep-%d", i), nil) - if err != nil { - log.Fatalf("Error creating endpoint 1 %v", err) - } - - _, err = netw.CreateEndpoint(fmt.Sprintf("Gordon-Ep2-%d", i), nil) - if err != nil { - log.Fatalf("Error creating endpoint 2 %v", err) - } - - time.Sleep(2 * time.Second) - } -} diff --git a/config/config.go b/config/config.go index 1935e16..504ce21 100644 --- a/config/config.go +++ b/config/config.go @@ -21,6 +21,7 @@ type DaemonCfg struct { DefaultNetwork string DefaultDriver string Labels []string + DriverCfg map[string]interface{} } // ClusterCfg represents cluster configuration @@ -71,6 +72,13 @@ func OptionDefaultDriver(dd string) Option { } } +// OptionDriverConfig returns an option setter for driver configuration. +func OptionDriverConfig(networkType string, config map[string]interface{}) Option { + return func(c *Config) { + c.Daemon.DriverCfg[networkType] = config + } +} + // OptionLabels function returns an option setter for labels func OptionLabels(labels []string) Option { return func(c *Config) { diff --git a/controller.go b/controller.go index 83f30e7..ae27ff0 100644 --- a/controller.go +++ b/controller.go @@ -47,7 +47,6 @@ import ( "container/heap" "fmt" "net" - "strings" "sync" log "github.com/Sirupsen/logrus" @@ -57,7 +56,6 @@ import ( "github.com/docker/libnetwork/datastore" "github.com/docker/libnetwork/driverapi" "github.com/docker/libnetwork/hostdiscovery" - "github.com/docker/libnetwork/netlabel" "github.com/docker/libnetwork/osl" "github.com/docker/libnetwork/types" ) @@ -68,9 +66,6 @@ type NetworkController interface { // ID provides an unique identity for the controller ID() string - // ConfigureNetworkDriver applies the passed options to the driver instance for the specified network type - ConfigureNetworkDriver(networkType string, options map[string]interface{}) error - // Config method returns the bootup configuration for the controller Config() config.Config @@ -139,7 +134,11 @@ type controller struct { func New(cfgOptions ...config.Option) (NetworkController, error) { var cfg *config.Config if len(cfgOptions) > 0 { - cfg = &config.Config{} + cfg = &config.Config{ + Daemon: config.DaemonCfg{ + DriverCfg: make(map[string]interface{}), + }, + } cfg.ProcessOptions(cfgOptions...) } c := &controller{ @@ -207,16 +206,6 @@ func (c *controller) Config() config.Config { return *c.cfg } -func (c *controller) ConfigureNetworkDriver(networkType string, options map[string]interface{}) error { - c.Lock() - dd, ok := c.drivers[networkType] - c.Unlock() - if !ok { - return NetworkTypeError(networkType) - } - return dd.driver.Config(options) -} - func (c *controller) RegisterDriver(networkType string, driver driverapi.Driver, capability driverapi.Capability) error { if !config.IsValidName(networkType) { return ErrInvalidName(networkType) @@ -228,32 +217,8 @@ func (c *controller) RegisterDriver(networkType string, driver driverapi.Driver, return driverapi.ErrActiveRegistration(networkType) } c.drivers[networkType] = &driverData{driver, capability} - - if c.cfg == nil { - c.Unlock() - return nil - } - - opt := make(map[string]interface{}) - for _, label := range c.cfg.Daemon.Labels { - if strings.HasPrefix(label, netlabel.DriverPrefix+"."+networkType) { - opt[netlabel.Key(label)] = netlabel.Value(label) - } - } - - if capability.Scope == driverapi.GlobalScope && c.validateDatastoreConfig() { - opt[netlabel.KVProvider] = c.cfg.Datastore.Client.Provider - opt[netlabel.KVProviderURL] = c.cfg.Datastore.Client.Address - } - c.Unlock() - if len(opt) != 0 { - if err := driver.Config(opt); err != nil { - return err - } - } - return nil } diff --git a/driverapi/driverapi.go b/driverapi/driverapi.go index bfe44be..694b042 100644 --- a/driverapi/driverapi.go +++ b/driverapi/driverapi.go @@ -7,9 +7,6 @@ const NetworkPluginEndpointType = "NetworkDriver" // Driver is an interface that every plugin driver needs to implement. type Driver interface { - // Push driver specific config to the driver - Config(options map[string]interface{}) error - // CreateNetwork invokes the driver method to create a network passing // the network id and network specific config. The config mechanism will // eventually be replaced with labels which are yet to be introduced. diff --git a/drivers.go b/drivers.go new file mode 100644 index 0000000..4bce703 --- /dev/null +++ b/drivers.go @@ -0,0 +1,55 @@ +package libnetwork + +import ( + "strings" + + "github.com/docker/libnetwork/driverapi" + "github.com/docker/libnetwork/netlabel" +) + +type initializer struct { + fn func(driverapi.DriverCallback, map[string]interface{}) error + ntype string +} + +func initDrivers(c *controller) error { + for _, i := range getInitializers() { + if err := i.fn(c, makeDriverConfig(c, i.ntype)); err != nil { + return err + } + } + + return nil +} + +func makeDriverConfig(c *controller, ntype string) map[string]interface{} { + if c.cfg == nil { + return nil + } + + config := make(map[string]interface{}) + + if c.validateDatastoreConfig() { + config[netlabel.KVProvider] = c.cfg.Datastore.Client.Provider + config[netlabel.KVProviderURL] = c.cfg.Datastore.Client.Address + } + + for _, label := range c.cfg.Daemon.Labels { + if !strings.HasPrefix(netlabel.Key(label), netlabel.DriverPrefix+"."+ntype) { + continue + } + + config[netlabel.Key(label)] = netlabel.Value(label) + } + + drvCfg, ok := c.cfg.Daemon.DriverCfg[ntype] + if !ok { + return config + } + + for k, v := range drvCfg.(map[string]interface{}) { + config[k] = v + } + + return config +} diff --git a/drivers/bridge/bridge.go b/drivers/bridge/bridge.go index 127fe7c..346d866 100644 --- a/drivers/bridge/bridge.go +++ b/drivers/bridge/bridge.go @@ -97,7 +97,6 @@ type bridgeNetwork struct { type driver struct { config *configuration - configured bool network *bridgeNetwork natChain *iptables.ChainInfo filterChain *iptables.ChainInfo @@ -106,13 +105,13 @@ type driver struct { } // New constructs a new bridge driver -func newDriver() driverapi.Driver { +func newDriver() *driver { ipAllocator = ipallocator.New() return &driver{networks: map[string]*bridgeNetwork{}, config: &configuration{}} } // Init registers a new instance of bridge driver -func Init(dc driverapi.DriverCallback) error { +func Init(dc driverapi.DriverCallback, config map[string]interface{}) error { if _, err := os.Stat("/proc/sys/net/bridge"); err != nil { if out, err := exec.Command("modprobe", "-va", "bridge", "br_netfilter").CombinedOutput(); err != nil { logrus.Warnf("Running modprobe bridge br_netfilter failed with message: %s, error: %v", out, err) @@ -128,10 +127,15 @@ func Init(dc driverapi.DriverCallback) error { logrus.Warnf("Failed to remove existing iptables entries in %s : %v", DockerChain, err) } + d := newDriver() + if err := d.configure(config); err != nil { + return err + } + c := driverapi.Capability{ Scope: driverapi.LocalScope, } - return dc.RegisterDriver(networkType, newDriver(), c) + return dc.RegisterDriver(networkType, d, c) } // Validate performs a static validation on the network configuration parameters. @@ -426,17 +430,13 @@ func (c *networkConfiguration) conflictsWithNetworks(id string, others []*bridge return nil } -func (d *driver) Config(option map[string]interface{}) error { +func (d *driver) configure(option map[string]interface{}) error { var config *configuration var err error d.Lock() defer d.Unlock() - if d.configured { - return &ErrConfigExists{} - } - genericData, ok := option[netlabel.GenericData] if !ok || genericData == nil { return nil @@ -469,7 +469,6 @@ func (d *driver) Config(option map[string]interface{}) error { } } - d.configured = true d.config = config return nil } @@ -567,20 +566,12 @@ func (d *driver) getNetworks() []*bridgeNetwork { // Create a new network using bridge plugin func (d *driver) CreateNetwork(id string, option map[string]interface{}) error { - var ( - err error - configLocked bool - ) + var err error defer osl.InitOSContext()() // Sanity checks d.Lock() - if !d.configured { - configLocked = true - d.configured = true - } - if _, ok := d.networks[id]; ok { d.Unlock() return types.ForbiddenErrorf("network %s exists", id) @@ -619,10 +610,6 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}) error { defer func() { if err != nil { d.Lock() - if configLocked { - d.configured = false - } - delete(d.networks, id) d.Unlock() } diff --git a/drivers/bridge/bridge_test.go b/drivers/bridge/bridge_test.go index f0d849a..f2604fb 100644 --- a/drivers/bridge/bridge_test.go +++ b/drivers/bridge/bridge_test.go @@ -44,7 +44,7 @@ func TestCreateFullOptions(t *testing.T) { genericOption := make(map[string]interface{}) genericOption[netlabel.GenericData] = config - if err := d.Config(genericOption); err != nil { + if err := d.configure(genericOption); err != nil { t.Fatalf("Failed to setup driver config: %v", err) } @@ -86,7 +86,7 @@ func TestCreate(t *testing.T) { defer testutils.SetupTestOSContext(t)() d := newDriver() - if err := d.Config(nil); err != nil { + if err := d.configure(nil); err != nil { t.Fatalf("Failed to setup driver config: %v", err) } @@ -119,7 +119,7 @@ func TestCreateFail(t *testing.T) { defer testutils.SetupTestOSContext(t)() d := newDriver() - if err := d.Config(nil); err != nil { + if err := d.configure(nil); err != nil { t.Fatalf("Failed to setup driver config: %v", err) } @@ -135,7 +135,6 @@ func TestCreateFail(t *testing.T) { func TestCreateMultipleNetworks(t *testing.T) { defer testutils.SetupTestOSContext(t)() d := newDriver() - dd, _ := d.(*driver) config := &configuration{ EnableIPTables: true, @@ -143,7 +142,7 @@ func TestCreateMultipleNetworks(t *testing.T) { genericOption := make(map[string]interface{}) genericOption[netlabel.GenericData] = config - if err := d.Config(genericOption); err != nil { + if err := d.configure(genericOption); err != nil { t.Fatalf("Failed to setup driver config: %v", err) } @@ -167,7 +166,7 @@ func TestCreateMultipleNetworks(t *testing.T) { } // Verify the network isolation rules are installed, each network subnet should appear 4 times - verifyV4INCEntries(dd.networks, 4, t) + verifyV4INCEntries(d.networks, 4, t) config4 := &networkConfiguration{BridgeName: "net_test_4", AllowNonDefaultBridge: true} genericOption[netlabel.GenericData] = config4 @@ -176,19 +175,19 @@ func TestCreateMultipleNetworks(t *testing.T) { } // Now 6 times - verifyV4INCEntries(dd.networks, 6, t) + verifyV4INCEntries(d.networks, 6, t) d.DeleteNetwork("1") - verifyV4INCEntries(dd.networks, 4, t) + verifyV4INCEntries(d.networks, 4, t) d.DeleteNetwork("2") - verifyV4INCEntries(dd.networks, 2, t) + verifyV4INCEntries(d.networks, 2, t) d.DeleteNetwork("3") - verifyV4INCEntries(dd.networks, 0, t) + verifyV4INCEntries(d.networks, 0, t) d.DeleteNetwork("4") - verifyV4INCEntries(dd.networks, 0, t) + verifyV4INCEntries(d.networks, 0, t) } func verifyV4INCEntries(networks map[string]*bridgeNetwork, numEntries int, t *testing.T) { @@ -290,7 +289,6 @@ func TestQueryEndpointInfoHairpin(t *testing.T) { func testQueryEndpointInfo(t *testing.T, ulPxyEnabled bool) { defer testutils.SetupTestOSContext(t)() d := newDriver() - dd, _ := d.(*driver) config := &configuration{ EnableIPTables: true, @@ -299,7 +297,7 @@ func testQueryEndpointInfo(t *testing.T, ulPxyEnabled bool) { genericOption := make(map[string]interface{}) genericOption[netlabel.GenericData] = config - if err := d.Config(genericOption); err != nil { + if err := d.configure(genericOption); err != nil { t.Fatalf("Failed to setup driver config: %v", err) } @@ -325,7 +323,7 @@ func testQueryEndpointInfo(t *testing.T, ulPxyEnabled bool) { t.Fatalf("Failed to create an endpoint : %s", err.Error()) } - network, ok := dd.networks["net1"] + network, ok := d.networks["net1"] if !ok { t.Fatalf("Cannot find network %s inside driver", "net1") } @@ -362,7 +360,7 @@ func TestCreateLinkWithOptions(t *testing.T) { defer testutils.SetupTestOSContext(t)() d := newDriver() - if err := d.Config(nil); err != nil { + if err := d.configure(nil); err != nil { t.Fatalf("Failed to setup driver config: %v", err) } @@ -428,7 +426,7 @@ func TestLinkContainers(t *testing.T) { genericOption := make(map[string]interface{}) genericOption[netlabel.GenericData] = config - if err := d.Config(genericOption); err != nil { + if err := d.configure(genericOption); err != nil { t.Fatalf("Failed to setup driver config: %v", err) } @@ -638,7 +636,7 @@ func TestSetDefaultGw(t *testing.T) { defer testutils.SetupTestOSContext(t)() d := newDriver() - if err := d.Config(nil); err != nil { + if err := d.configure(nil); err != nil { t.Fatalf("Failed to setup driver config: %v", err) } diff --git a/drivers/bridge/network_test.go b/drivers/bridge/network_test.go index 769cb8b..8112dd6 100644 --- a/drivers/bridge/network_test.go +++ b/drivers/bridge/network_test.go @@ -12,9 +12,8 @@ import ( func TestLinkCreate(t *testing.T) { defer testutils.SetupTestOSContext(t)() d := newDriver() - dr := d.(*driver) - if err := d.Config(nil); err != nil { + if err := d.configure(nil); err != nil { t.Fatalf("Failed to setup driver config: %v", err) } @@ -79,7 +78,7 @@ func TestLinkCreate(t *testing.T) { t.Fatalf("Could not find source link %s: %v", te.iface.srcName, err) } - n, ok := dr.networks["dummy"] + n, ok := d.networks["dummy"] if !ok { t.Fatalf("Cannot find network %s inside driver", "dummy") } @@ -108,7 +107,7 @@ func TestLinkCreateTwo(t *testing.T) { defer testutils.SetupTestOSContext(t)() d := newDriver() - if err := d.Config(nil); err != nil { + if err := d.configure(nil); err != nil { t.Fatalf("Failed to setup driver config: %v", err) } @@ -144,7 +143,7 @@ func TestLinkCreateNoEnableIPv6(t *testing.T) { defer testutils.SetupTestOSContext(t)() d := newDriver() - if err := d.Config(nil); err != nil { + if err := d.configure(nil); err != nil { t.Fatalf("Failed to setup driver config: %v", err) } @@ -178,7 +177,7 @@ func TestLinkDelete(t *testing.T) { defer testutils.SetupTestOSContext(t)() d := newDriver() - if err := d.Config(nil); err != nil { + if err := d.configure(nil); err != nil { t.Fatalf("Failed to setup driver config: %v", err) } diff --git a/drivers/bridge/port_mapping_test.go b/drivers/bridge/port_mapping_test.go index bb005f8..9e7fa07 100644 --- a/drivers/bridge/port_mapping_test.go +++ b/drivers/bridge/port_mapping_test.go @@ -27,7 +27,7 @@ func TestPortMappingConfig(t *testing.T) { genericOption := make(map[string]interface{}) genericOption[netlabel.GenericData] = config - if err := d.Config(genericOption); err != nil { + if err := d.configure(genericOption); err != nil { t.Fatalf("Failed to setup driver config: %v", err) } @@ -55,8 +55,7 @@ func TestPortMappingConfig(t *testing.T) { t.Fatalf("Failed to create the endpoint: %s", err.Error()) } - dd := d.(*driver) - network, ok := dd.networks["dummy"] + network, ok := d.networks["dummy"] if !ok { t.Fatalf("Cannot find network %s inside driver", "dummy") } diff --git a/drivers/host/host.go b/drivers/host/host.go index 2c9d172..eac1af2 100644 --- a/drivers/host/host.go +++ b/drivers/host/host.go @@ -15,17 +15,13 @@ type driver struct { } // Init registers a new instance of host driver -func Init(dc driverapi.DriverCallback) error { +func Init(dc driverapi.DriverCallback, config map[string]interface{}) error { c := driverapi.Capability{ Scope: driverapi.LocalScope, } return dc.RegisterDriver(networkType, &driver{}, c) } -func (d *driver) Config(option map[string]interface{}) error { - return nil -} - func (d *driver) CreateNetwork(id string, option map[string]interface{}) error { d.Lock() defer d.Unlock() diff --git a/drivers/null/null.go b/drivers/null/null.go index e0bf6b1..4a0e92b 100644 --- a/drivers/null/null.go +++ b/drivers/null/null.go @@ -15,17 +15,13 @@ type driver struct { } // Init registers a new instance of null driver -func Init(dc driverapi.DriverCallback) error { +func Init(dc driverapi.DriverCallback, config map[string]interface{}) error { c := driverapi.Capability{ Scope: driverapi.LocalScope, } return dc.RegisterDriver(networkType, &driver{}, c) } -func (d *driver) Config(option map[string]interface{}) error { - return nil -} - func (d *driver) CreateNetwork(id string, option map[string]interface{}) error { d.Lock() defer d.Unlock() diff --git a/drivers/overlay/overlay.go b/drivers/overlay/overlay.go index 8f55ad6..606e723 100644 --- a/drivers/overlay/overlay.go +++ b/drivers/overlay/overlay.go @@ -67,19 +67,25 @@ func onceInit() { } // Init registers a new instance of overlay driver -func Init(dc driverapi.DriverCallback) error { +func Init(dc driverapi.DriverCallback, config map[string]interface{}) error { once.Do(onceInit) c := driverapi.Capability{ Scope: driverapi.GlobalScope, } - return dc.RegisterDriver(networkType, &driver{ + d := &driver{ networks: networkTable{}, peerDb: peerNetworkMap{ mp: map[string]peerMap{}, }, - }, c) + } + + if err := d.configure(config); err != nil { + return err + } + + return dc.RegisterDriver(networkType, d, c) } // Fini cleans up the driver resources @@ -95,10 +101,14 @@ func Fini(drv driverapi.Driver) { } } -func (d *driver) Config(option map[string]interface{}) error { +func (d *driver) configure(option map[string]interface{}) error { var onceDone bool var err error + if len(option) == 0 { + return nil + } + d.Do(func() { onceDone = true diff --git a/drivers/overlay/overlay_test.go b/drivers/overlay/overlay_test.go index affc0c4..0d8e98f 100644 --- a/drivers/overlay/overlay_test.go +++ b/drivers/overlay/overlay_test.go @@ -5,24 +5,22 @@ import ( "time" "github.com/docker/libnetwork/driverapi" + "github.com/docker/libnetwork/netlabel" _ "github.com/docker/libnetwork/testutils" ) type driverTester struct { t *testing.T - d driverapi.Driver + d *driver } const testNetworkType = "overlay" func setupDriver(t *testing.T) *driverTester { - dt := &driverTester{t: t} - if err := Init(dt); err != nil { - t.Fatal(err) - } - opt := make(map[string]interface{}) - if err := dt.d.Config(opt); err != nil { + opt[netlabel.OverlayBindInterface] = "eth0" + dt := &driverTester{t: t} + if err := Init(dt, opt); err != nil { t.Fatal(err) } @@ -60,14 +58,14 @@ func (dt *driverTester) RegisterDriver(name string, drv driverapi.Driver, } func TestOverlayInit(t *testing.T) { - if err := Init(&driverTester{t: t}); err != nil { + if err := Init(&driverTester{t: t}, nil); err != nil { t.Fatal(err) } } func TestOverlayFiniWithoutConfig(t *testing.T) { dt := &driverTester{t: t} - if err := Init(dt); err != nil { + if err := Init(dt, nil); err != nil { t.Fatal(err) } @@ -76,11 +74,11 @@ func TestOverlayFiniWithoutConfig(t *testing.T) { func TestOverlayNilConfig(t *testing.T) { dt := &driverTester{t: t} - if err := Init(dt); err != nil { + if err := Init(dt, nil); err != nil { t.Fatal(err) } - if err := dt.d.Config(nil); err != nil { + if err := dt.d.configure(nil); err != nil { t.Fatal(err) } @@ -92,7 +90,7 @@ func TestOverlayConfig(t *testing.T) { time.Sleep(1 * time.Second) - d := dt.d.(*driver) + d := dt.d if d.notifyCh == nil { t.Fatal("Driver notify channel wasn't initialzed after Config method") } @@ -108,19 +106,9 @@ func TestOverlayConfig(t *testing.T) { cleanupDriver(t, dt) } -func TestOverlayMultipleConfig(t *testing.T) { - dt := setupDriver(t) - - if err := dt.d.Config(nil); err == nil { - t.Fatal("Expected a failure, instead succeded") - } - - cleanupDriver(t, dt) -} - func TestOverlayType(t *testing.T) { dt := &driverTester{t: t} - if err := Init(dt); err != nil { + if err := Init(dt, nil); err != nil { t.Fatal(err) } diff --git a/drivers/remote/driver.go b/drivers/remote/driver.go index 4d1a134..23ca8f9 100644 --- a/drivers/remote/driver.go +++ b/drivers/remote/driver.go @@ -26,7 +26,7 @@ func newDriver(name string, client *plugins.Client) driverapi.Driver { // Init makes sure a remote driver is registered when a network driver // plugin is activated. -func Init(dc driverapi.DriverCallback) error { +func Init(dc driverapi.DriverCallback, config map[string]interface{}) error { plugins.Handle(driverapi.NetworkPluginEndpointType, func(name string, client *plugins.Client) { // negotiate driver capability with client d := newDriver(name, client) diff --git a/drivers/windows/windows.go b/drivers/windows/windows.go index 80b5c46..efca69a 100644 --- a/drivers/windows/windows.go +++ b/drivers/windows/windows.go @@ -9,17 +9,13 @@ const networkType = "windows" type driver struct{} // Init registers a new instance of null driver -func Init(dc driverapi.DriverCallback) error { +func Init(dc driverapi.DriverCallback, config map[string]interface{}) error { c := driverapi.Capability{ Scope: driverapi.LocalScope, } return dc.RegisterDriver(networkType, &driver{}, c) } -func (d *driver) Config(option map[string]interface{}) error { - return nil -} - func (d *driver) CreateNetwork(id string, option map[string]interface{}) error { return nil } diff --git a/drivers_freebsd.go b/drivers_freebsd.go index 683af06..416bba0 100644 --- a/drivers_freebsd.go +++ b/drivers_freebsd.go @@ -1,19 +1,13 @@ package libnetwork import ( - "github.com/docker/libnetwork/driverapi" "github.com/docker/libnetwork/drivers/null" "github.com/docker/libnetwork/drivers/remote" ) -func initDrivers(dc driverapi.DriverCallback) error { - for _, fn := range [](func(driverapi.DriverCallback) error){ - null.Init, - remote.Init, - } { - if err := fn(dc); err != nil { - return err - } +func getInitializers() []initializer { + return []initializer{ + {null.Init, "null"}, + {remote.Init, "remote"}, } - return nil } diff --git a/drivers_linux.go b/drivers_linux.go index b8294d4..4d31b98 100644 --- a/drivers_linux.go +++ b/drivers_linux.go @@ -1,25 +1,19 @@ package libnetwork import ( - "github.com/docker/libnetwork/driverapi" "github.com/docker/libnetwork/drivers/bridge" "github.com/docker/libnetwork/drivers/host" "github.com/docker/libnetwork/drivers/null" - o "github.com/docker/libnetwork/drivers/overlay" + "github.com/docker/libnetwork/drivers/overlay" "github.com/docker/libnetwork/drivers/remote" ) -func initDrivers(dc driverapi.DriverCallback) error { - for _, fn := range [](func(driverapi.DriverCallback) error){ - bridge.Init, - host.Init, - null.Init, - remote.Init, - o.Init, - } { - if err := fn(dc); err != nil { - return err - } +func getInitializers() []initializer { + return []initializer{ + {bridge.Init, "bridge"}, + {host.Init, "host"}, + {null.Init, "null"}, + {remote.Init, "remote"}, + {overlay.Init, "overlay"}, } - return nil } diff --git a/drivers_windows.go b/drivers_windows.go index 334cd7c..314ff8d 100644 --- a/drivers_windows.go +++ b/drivers_windows.go @@ -1,17 +1,9 @@ package libnetwork -import ( - "github.com/docker/libnetwork/driverapi" - "github.com/docker/libnetwork/drivers/windows" -) +import "github.com/docker/libnetwork/drivers/windows" -func initDrivers(dc driverapi.DriverCallback) error { - for _, fn := range [](func(driverapi.DriverCallback) error){ - windows.Init, - } { - if err := fn(dc); err != nil { - return err - } +func getInitializers() []initializer { + return []initializer{ + {windows.Init, "windows"}, } - return nil } diff --git a/libnetwork_test.go b/libnetwork_test.go index 946fd63..b1245c2 100644 --- a/libnetwork_test.go +++ b/libnetwork_test.go @@ -21,6 +21,7 @@ import ( "github.com/docker/docker/pkg/plugins" "github.com/docker/docker/pkg/reexec" "github.com/docker/libnetwork" + "github.com/docker/libnetwork/config" "github.com/docker/libnetwork/datastore" "github.com/docker/libnetwork/driverapi" "github.com/docker/libnetwork/netlabel" @@ -48,17 +49,6 @@ func TestMain(m *testing.M) { if err := createController(); err != nil { os.Exit(1) } - option := options.Generic{ - "EnableIPForwarding": true, - } - - genericOption := make(map[string]interface{}) - genericOption[netlabel.GenericData] = option - - err := controller.ConfigureNetworkDriver(bridgeNetType, genericOption) - if err != nil { - os.Exit(1) - } libnetwork.SetTestDataStore(controller, datastore.NewCustomDataStore(datastore.NewMockStore())) @@ -68,7 +58,14 @@ func TestMain(m *testing.M) { func createController() error { var err error - controller, err = libnetwork.New() + option := options.Generic{ + "EnableIPForwarding": true, + } + + genericOption := make(map[string]interface{}) + genericOption[netlabel.GenericData] = option + + controller, err = libnetwork.New(config.OptionDriverConfig(bridgeNetType, genericOption)) if err != nil { return err } diff --git a/sandbox_test.go b/sandbox_test.go index 3a74fa1..e573f35 100644 --- a/sandbox_test.go +++ b/sandbox_test.go @@ -3,6 +3,7 @@ package libnetwork import ( "testing" + "github.com/docker/libnetwork/config" "github.com/docker/libnetwork/netlabel" "github.com/docker/libnetwork/options" "github.com/docker/libnetwork/osl" @@ -14,21 +15,19 @@ func createEmptyCtrlr() *controller { } func getTestEnv(t *testing.T) (NetworkController, Network, Network) { - c, err := New() - if err != nil { - t.Fatal(err) - } + netType := "bridge" option := options.Generic{ "EnableIPForwarding": true, } genericOption := make(map[string]interface{}) genericOption[netlabel.GenericData] = option - if err := c.ConfigureNetworkDriver("bridge", genericOption); err != nil { + + c, err := New(config.OptionDriverConfig(netType, genericOption)) + if err != nil { t.Fatal(err) } - netType := "bridge" name1 := "test_nw_1" netOption1 := options.Generic{ netlabel.GenericData: options.Generic{