Sfoglia il codice sorgente

Minor API modifications

* Modified NB API with self referential var-aarg for future proofing the APIs
* Modified Driver API's option parameter to be a Map of interface{}

Signed-off-by: Madhu Venugopal <madhu@docker.com>
Madhu Venugopal 10 anni fa
parent
commit
cc4f27f6af

+ 40 - 25
libnetwork/README.md

@@ -21,31 +21,46 @@ There are many networking solutions available to suit a broad range of use-cases
 
 
 
 
 ```go
 ```go
-    // Create a new controller instance
-    controller := libnetwork.New()
-
-    // This option is only needed for in-tree drivers. Plugins(in future) will get
-    // their options through plugin infrastructure.
-    option := options.Generic{}
-    err := controller.NewNetworkDriver("bridge", option)
-    if err != nil {
-        return
-    }
-
-    netOptions := options.Generic{}
-    // Create a network for containers to join.
-    network, err := controller.NewNetwork("bridge", "network1", netOptions)
-    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.
-    ep, err := network.CreateEndpoint("Endpoint1", nil)
-    if err != nil {
-	    return
-    }
+        // Create a new controller instance
+        controller := libnetwork.New()
+
+        // Select and configure the network driver
+        networkType := "bridge"
+
+        driverOptions := options.Generic{}
+        genericOption := make(map[string]interface{})
+        genericOption[options.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 make of
+        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
+        }
+
+        // A container can join the endpoint by providing the container ID to the join
+        // api which returns the sandbox key which can be used to access the sandbox
+        // created for the container during join.
+        // Join acceps Variadic arguments which will be made use of by libnetwork and Drivers
+        _, err = ep.Join("container1",
+                libnetwork.JoinOptionHostname("test"),
+                libnetwork.JoinOptionDomainname("docker.io"))
+        if err != nil {
+                return
+        }
 ```
 ```
 
 
 ## Future
 ## Future

+ 12 - 6
libnetwork/cmd/readme_test/readme.go

@@ -11,15 +11,18 @@ func main() {
 
 
 	// Select and configure the network driver
 	// Select and configure the network driver
 	networkType := "bridge"
 	networkType := "bridge"
-	option := options.Generic{}
-	err := controller.ConfigureNetworkDriver(networkType, option)
+
+	driverOptions := options.Generic{}
+	genericOption := make(map[string]interface{})
+	genericOption[options.GenericData] = driverOptions
+	err := controller.ConfigureNetworkDriver(networkType, genericOption)
 	if err != nil {
 	if err != nil {
 		return
 		return
 	}
 	}
 
 
-	netOptions := options.Generic{}
 	// Create a network for containers to join.
 	// Create a network for containers to join.
-	network, err := controller.NewNetwork(networkType, "network1", netOptions)
+	// NewNetwork accepts Variadic optional arguments that libnetwork and Drivers can make of
+	network, err := controller.NewNetwork(networkType, "network1")
 	if err != nil {
 	if err != nil {
 		return
 		return
 	}
 	}
@@ -28,7 +31,7 @@ func main() {
 	// settings will be used for container infos (inspect and such), as well as
 	// settings will be used for container infos (inspect and such), as well as
 	// iptables rules for port publishing. This info is contained or accessible
 	// iptables rules for port publishing. This info is contained or accessible
 	// from the returned endpoint.
 	// from the returned endpoint.
-	ep, err := network.CreateEndpoint("Endpoint1", nil)
+	ep, err := network.CreateEndpoint("Endpoint1")
 	if err != nil {
 	if err != nil {
 		return
 		return
 	}
 	}
@@ -36,7 +39,10 @@ func main() {
 	// A container can join the endpoint by providing the container ID to the join
 	// A container can join the endpoint by providing the container ID to the join
 	// api which returns the sandbox key which can be used to access the sandbox
 	// api which returns the sandbox key which can be used to access the sandbox
 	// created for the container during join.
 	// created for the container during join.
-	_, err = ep.Join("container1")
+	// Join acceps Variadic arguments which will be made use of by libnetwork and Drivers
+	_, err = ep.Join("container1",
+		libnetwork.JoinOptionHostname("test"),
+		libnetwork.JoinOptionDomainname("docker.io"))
 	if err != nil {
 	if err != nil {
 		return
 		return
 	}
 	}

+ 1 - 1
libnetwork/cmd/test/main.go

@@ -17,7 +17,7 @@ func main() {
 	controller := libnetwork.New()
 	controller := libnetwork.New()
 	netType := "bridge"
 	netType := "bridge"
 	err := controller.ConfigureNetworkDriver(netType, options)
 	err := controller.ConfigureNetworkDriver(netType, options)
-	netw, err := controller.NewNetwork(netType, "dummy", "")
+	netw, err := controller.NewNetwork(netType, "dummy")
 	if err != nil {
 	if err != nil {
 		log.Fatal(err)
 		log.Fatal(err)
 	}
 	}

+ 46 - 39
libnetwork/controller.go

@@ -2,40 +2,46 @@
 Package libnetwork provides the basic functionality and extension points to
 Package libnetwork provides the basic functionality and extension points to
 create network namespaces and allocate interfaces for containers to use.
 create network namespaces and allocate interfaces for containers to use.
 
 
-	// Create a new controller instance
-	controller := libnetwork.New()
-
-	// Select and configure the network driver
-	networkType := "bridge"
-	option := options.Generic{}
-	err := controller.ConfigureNetworkDriver(networkType, option)
-	if err != nil {
-		return
-	}
-
-	netOptions := options.Generic{}
-	// Create a network for containers to join.
-	network, err := controller.NewNetwork(networkType, "network1", netOptions)
-	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", nil)
-	if err != nil {
-		return
-	}
-
-	// A container can join the endpoint by providing the container ID to the join
-	// api which returns the sandbox key which can be used to access the sandbox
-	// created for the container during join.
-	_, err = ep.Join("container1")
-	if err != nil {
-		return
-	}
+        // Create a new controller instance
+        controller := libnetwork.New()
+
+        // Select and configure the network driver
+        networkType := "bridge"
+
+        driverOptions := options.Generic{}
+        genericOption := make(map[string]interface{})
+        genericOption[options.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 make of
+        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
+        }
+
+        // A container can join the endpoint by providing the container ID to the join
+        // api which returns the sandbox key which can be used to access the sandbox
+        // created for the container during join.
+        // Join acceps Variadic arguments which will be made use of by libnetwork and Drivers
+        _, err = ep.Join("container1",
+                libnetwork.JoinOptionHostname("test"),
+                libnetwork.JoinOptionDomainname("docker.io"))
+        if err != nil {
+                return
+        }
 */
 */
 package libnetwork
 package libnetwork
 
 
@@ -51,11 +57,11 @@ import (
 // networks.
 // networks.
 type NetworkController interface {
 type NetworkController interface {
 	// ConfigureNetworkDriver applies the passed options to the driver instance for the specified network type
 	// ConfigureNetworkDriver applies the passed options to the driver instance for the specified network type
-	ConfigureNetworkDriver(networkType string, options interface{}) error
+	ConfigureNetworkDriver(networkType string, options map[string]interface{}) error
 
 
 	// Create a new network. The options parameter carries network specific options.
 	// Create a new network. The options parameter carries network specific options.
 	// Labels support will be added in the near future.
 	// Labels support will be added in the near future.
-	NewNetwork(networkType, name string, options interface{}) (Network, error)
+	NewNetwork(networkType, name string, options ...NetworkOption) (Network, error)
 
 
 	// Networks returns the list of Network(s) managed by this controller.
 	// Networks returns the list of Network(s) managed by this controller.
 	Networks() []Network
 	Networks() []Network
@@ -95,7 +101,7 @@ func New() NetworkController {
 	return &controller{networkTable{}, enumerateDrivers(), sandboxTable{}, sync.Mutex{}}
 	return &controller{networkTable{}, enumerateDrivers(), sandboxTable{}, sync.Mutex{}}
 }
 }
 
 
-func (c *controller) ConfigureNetworkDriver(networkType string, options interface{}) error {
+func (c *controller) ConfigureNetworkDriver(networkType string, options map[string]interface{}) error {
 	d, ok := c.drivers[networkType]
 	d, ok := c.drivers[networkType]
 	if !ok {
 	if !ok {
 		return NetworkTypeError(networkType)
 		return NetworkTypeError(networkType)
@@ -105,7 +111,7 @@ func (c *controller) ConfigureNetworkDriver(networkType string, options interfac
 
 
 // NewNetwork creates a new network of the specified network type. The options
 // NewNetwork creates a new network of the specified network type. The options
 // are network specific and modeled in a generic way.
 // are network specific and modeled in a generic way.
-func (c *controller) NewNetwork(networkType, name string, options interface{}) (Network, error) {
+func (c *controller) NewNetwork(networkType, name string, options ...NetworkOption) (Network, error) {
 	// Check if a driver for the specified network type is available
 	// Check if a driver for the specified network type is available
 	d, ok := c.drivers[networkType]
 	d, ok := c.drivers[networkType]
 	if !ok {
 	if !ok {
@@ -131,8 +137,9 @@ func (c *controller) NewNetwork(networkType, name string, options interface{}) (
 		endpoints: endpointTable{},
 		endpoints: endpointTable{},
 	}
 	}
 
 
+	network.processOptions(options...)
 	// Create the network
 	// Create the network
-	if err := d.CreateNetwork(network.id, options); err != nil {
+	if err := d.CreateNetwork(network.id, network.generic); err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
 
 

+ 3 - 3
libnetwork/driverapi/driverapi.go

@@ -19,12 +19,12 @@ var (
 // Driver is an interface that every plugin driver needs to implement.
 // Driver is an interface that every plugin driver needs to implement.
 type Driver interface {
 type Driver interface {
 	// Push driver specific config to the driver
 	// Push driver specific config to the driver
-	Config(config interface{}) error
+	Config(options map[string]interface{}) error
 
 
 	// CreateNetwork invokes the driver method to create a network passing
 	// CreateNetwork invokes the driver method to create a network passing
 	// the network id and network specific config. The config mechanism will
 	// the network id and network specific config. The config mechanism will
 	// eventually be replaced with labels which are yet to be introduced.
 	// eventually be replaced with labels which are yet to be introduced.
-	CreateNetwork(nid types.UUID, config interface{}) error
+	CreateNetwork(nid types.UUID, options map[string]interface{}) error
 
 
 	// DeleteNetwork invokes the driver method to delete network passing
 	// DeleteNetwork invokes the driver method to delete network passing
 	// the network id.
 	// the network id.
@@ -34,7 +34,7 @@ type Driver interface {
 	// passing the network id, endpoint id and driver
 	// passing the network id, endpoint id and driver
 	// specific config. The config mechanism will eventually be replaced
 	// specific config. The config mechanism will eventually be replaced
 	// with labels which are yet to be introduced.
 	// with labels which are yet to be introduced.
-	CreateEndpoint(nid, eid types.UUID, config interface{}) (*sandbox.Info, error)
+	CreateEndpoint(nid, eid types.UUID, options map[string]interface{}) (*sandbox.Info, error)
 
 
 	// DeleteEndpoint invokes the driver method to delete an endpoint
 	// DeleteEndpoint invokes the driver method to delete an endpoint
 	// passing the network id and endpoint id.
 	// passing the network id and endpoint id.

+ 26 - 18
libnetwork/drivers/bridge/bridge.go

@@ -133,7 +133,7 @@ func (n *bridgeNetwork) getEndpoint(eid types.UUID) (*bridgeEndpoint, error) {
 	return nil, nil
 	return nil, nil
 }
 }
 
 
-func (d *driver) Config(option interface{}) error {
+func (d *driver) Config(option map[string]interface{}) error {
 	var config *Configuration
 	var config *Configuration
 
 
 	d.Lock()
 	d.Lock()
@@ -143,28 +143,32 @@ func (d *driver) Config(option interface{}) error {
 		return ErrConfigExists
 		return ErrConfigExists
 	}
 	}
 
 
-	switch opt := option.(type) {
-	case options.Generic:
-		opaqueConfig, err := options.GenerateFromModel(opt, &Configuration{})
-		if err != nil {
-			return err
+	genericData := option[options.GenericData]
+	if genericData != nil {
+		switch opt := genericData.(type) {
+		case options.Generic:
+			opaqueConfig, err := options.GenerateFromModel(opt, &Configuration{})
+			if err != nil {
+				return err
+			}
+			config = opaqueConfig.(*Configuration)
+		case *Configuration:
+			config = opt
+		default:
+			return ErrInvalidDriverConfig
 		}
 		}
-		config = opaqueConfig.(*Configuration)
-	case *Configuration:
-		config = opt
-	}
 
 
-	if err := config.Validate(); err != nil {
-		return err
+		if err := config.Validate(); err != nil {
+			return err
+		}
+		d.config = config
 	}
 	}
 
 
-	d.config = config
-
 	return nil
 	return nil
 }
 }
 
 
 // Create a new network using bridge plugin
 // Create a new network using bridge plugin
-func (d *driver) CreateNetwork(id types.UUID, option interface{}) error {
+func (d *driver) CreateNetwork(id types.UUID, option map[string]interface{}) error {
 	var err error
 	var err error
 
 
 	// Driver must be configured
 	// Driver must be configured
@@ -297,7 +301,7 @@ func (d *driver) DeleteNetwork(nid types.UUID) error {
 	return err
 	return err
 }
 }
 
 
-func (d *driver) CreateEndpoint(nid, eid types.UUID, epOptions interface{}) (*sandbox.Info, error) {
+func (d *driver) CreateEndpoint(nid, eid types.UUID, epOptions map[string]interface{}) (*sandbox.Info, error) {
 	var (
 	var (
 		ipv6Addr *net.IPNet
 		ipv6Addr *net.IPNet
 		err      error
 		err      error
@@ -554,11 +558,15 @@ func (d *driver) Type() string {
 	return networkType
 	return networkType
 }
 }
 
 
-func parseEndpointOptions(epOptions interface{}) (*EndpointConfiguration, error) {
+func parseEndpointOptions(epOptions map[string]interface{}) (*EndpointConfiguration, error) {
 	if epOptions == nil {
 	if epOptions == nil {
 		return nil, nil
 		return nil, nil
 	}
 	}
-	switch opt := epOptions.(type) {
+	genericData := epOptions[options.GenericData]
+	if genericData == nil {
+		return nil, nil
+	}
+	switch opt := genericData.(type) {
 	case options.Generic:
 	case options.Generic:
 		opaqueConfig, err := options.GenerateFromModel(opt, &EndpointConfiguration{})
 		opaqueConfig, err := options.GenerateFromModel(opt, &EndpointConfiguration{})
 		if err != nil {
 		if err != nil {

+ 27 - 10
libnetwork/drivers/bridge/bridge_test.go

@@ -6,6 +6,7 @@ import (
 	"testing"
 	"testing"
 
 
 	"github.com/docker/libnetwork/netutils"
 	"github.com/docker/libnetwork/netutils"
+	"github.com/docker/libnetwork/pkg/options"
 	"github.com/vishvananda/netlink"
 	"github.com/vishvananda/netlink"
 )
 )
 
 
@@ -14,11 +15,14 @@ func TestCreate(t *testing.T) {
 	_, d := New()
 	_, d := New()
 
 
 	config := &Configuration{BridgeName: DefaultBridgeName}
 	config := &Configuration{BridgeName: DefaultBridgeName}
-	if err := d.Config(config); err != nil {
+	genericOption := make(map[string]interface{})
+	genericOption[options.GenericData] = config
+
+	if err := d.Config(genericOption); err != nil {
 		t.Fatalf("Failed to setup driver config: %v", err)
 		t.Fatalf("Failed to setup driver config: %v", err)
 	}
 	}
 
 
-	if err := d.CreateNetwork("dummy", ""); err != nil {
+	if err := d.CreateNetwork("dummy", nil); err != nil {
 		t.Fatalf("Failed to create bridge: %v", err)
 		t.Fatalf("Failed to create bridge: %v", err)
 	}
 	}
 }
 }
@@ -28,11 +32,14 @@ func TestCreateFail(t *testing.T) {
 	_, d := New()
 	_, d := New()
 
 
 	config := &Configuration{BridgeName: "dummy0"}
 	config := &Configuration{BridgeName: "dummy0"}
-	if err := d.Config(config); err != nil {
+	genericOption := make(map[string]interface{})
+	genericOption[options.GenericData] = config
+
+	if err := d.Config(genericOption); err != nil {
 		t.Fatalf("Failed to setup driver config: %v", err)
 		t.Fatalf("Failed to setup driver config: %v", err)
 	}
 	}
 
 
-	if err := d.CreateNetwork("dummy", ""); err == nil {
+	if err := d.CreateNetwork("dummy", nil); err == nil {
 		t.Fatal("Bridge creation was expected to fail")
 		t.Fatal("Bridge creation was expected to fail")
 	}
 	}
 }
 }
@@ -49,11 +56,14 @@ func TestCreateFullOptions(t *testing.T) {
 		EnableIPForwarding: true,
 		EnableIPForwarding: true,
 	}
 	}
 	_, config.FixedCIDRv6, _ = net.ParseCIDR("2001:db8::/48")
 	_, config.FixedCIDRv6, _ = net.ParseCIDR("2001:db8::/48")
-	if err := d.Config(config); err != nil {
+	genericOption := make(map[string]interface{})
+	genericOption[options.GenericData] = config
+
+	if err := d.Config(genericOption); err != nil {
 		t.Fatalf("Failed to setup driver config: %v", err)
 		t.Fatalf("Failed to setup driver config: %v", err)
 	}
 	}
 
 
-	err := d.CreateNetwork("dummy", "")
+	err := d.CreateNetwork("dummy", nil)
 	if err != nil {
 	if err != nil {
 		t.Fatalf("Failed to create bridge: %v", err)
 		t.Fatalf("Failed to create bridge: %v", err)
 	}
 	}
@@ -64,19 +74,23 @@ func TestCreateLinkWithOptions(t *testing.T) {
 	_, d := New()
 	_, d := New()
 
 
 	config := &Configuration{BridgeName: DefaultBridgeName}
 	config := &Configuration{BridgeName: DefaultBridgeName}
-	if err := d.Config(config); err != nil {
+	genericOption := make(map[string]interface{})
+	genericOption[options.GenericData] = config
+
+	if err := d.Config(genericOption); err != nil {
 		t.Fatalf("Failed to setup driver config: %v", err)
 		t.Fatalf("Failed to setup driver config: %v", err)
 	}
 	}
 
 
-	err := d.CreateNetwork("net1", "")
+	err := d.CreateNetwork("net1", nil)
 	if err != nil {
 	if err != nil {
 		t.Fatalf("Failed to create bridge: %v", err)
 		t.Fatalf("Failed to create bridge: %v", err)
 	}
 	}
 
 
 	mac := net.HardwareAddr([]byte{0x1e, 0x67, 0x66, 0x44, 0x55, 0x66})
 	mac := net.HardwareAddr([]byte{0x1e, 0x67, 0x66, 0x44, 0x55, 0x66})
 	epConf := &EndpointConfiguration{MacAddress: mac}
 	epConf := &EndpointConfiguration{MacAddress: mac}
+	genericOption[options.GenericData] = epConf
 
 
-	sinfo, err := d.CreateEndpoint("net1", "ep", epConf)
+	sinfo, err := d.CreateEndpoint("net1", "ep", genericOption)
 	if err != nil {
 	if err != nil {
 		t.Fatalf("Failed to create a link: %s", err.Error())
 		t.Fatalf("Failed to create a link: %s", err.Error())
 	}
 	}
@@ -198,7 +212,10 @@ func TestSetDefaultGw(t *testing.T) {
 		DefaultGatewayIPv6: gw6,
 		DefaultGatewayIPv6: gw6,
 	}
 	}
 
 
-	if err := d.Config(config); err != nil {
+	genericOption := make(map[string]interface{})
+	genericOption[options.GenericData] = config
+
+	if err := d.Config(genericOption); err != nil {
 		t.Fatalf("Failed to setup driver config: %v", err)
 		t.Fatalf("Failed to setup driver config: %v", err)
 	}
 	}
 
 

+ 3 - 0
libnetwork/drivers/bridge/error.go

@@ -10,6 +10,9 @@ var (
 	// ErrConfigExists error is returned when driver already has a config applied.
 	// ErrConfigExists error is returned when driver already has a config applied.
 	ErrConfigExists = errors.New("configuration already exists, bridge configuration can be applied only once")
 	ErrConfigExists = errors.New("configuration already exists, bridge configuration can be applied only once")
 
 
+	// ErrInvalidDriverConfig error is returned when Bridge Driver is passed an invalid config
+	ErrInvalidDriverConfig = errors.New("Invalid configuration passed to Bridge Driver")
+
 	// ErrInvalidConfig error is returned when a network is created on a driver without valid config.
 	// ErrInvalidConfig error is returned when a network is created on a driver without valid config.
 	ErrInvalidConfig = errors.New("trying to create a network on a driver without valid config")
 	ErrInvalidConfig = errors.New("trying to create a network on a driver without valid config")
 
 

+ 19 - 8
libnetwork/drivers/bridge/network_test.go

@@ -5,6 +5,7 @@ import (
 
 
 	"github.com/docker/libnetwork/driverapi"
 	"github.com/docker/libnetwork/driverapi"
 	"github.com/docker/libnetwork/netutils"
 	"github.com/docker/libnetwork/netutils"
+	"github.com/docker/libnetwork/pkg/options"
 	"github.com/vishvananda/netlink"
 	"github.com/vishvananda/netlink"
 )
 )
 
 
@@ -19,11 +20,13 @@ func TestLinkCreate(t *testing.T) {
 		Mtu:        mtu,
 		Mtu:        mtu,
 		EnableIPv6: true,
 		EnableIPv6: true,
 	}
 	}
-	if err := d.Config(config); err != nil {
+	genericOption := make(map[string]interface{})
+	genericOption[options.GenericData] = config
+	if err := d.Config(genericOption); err != nil {
 		t.Fatalf("Failed to setup driver config: %v", err)
 		t.Fatalf("Failed to setup driver config: %v", err)
 	}
 	}
 
 
-	err := d.CreateNetwork("dummy", "")
+	err := d.CreateNetwork("dummy", nil)
 	if err != nil {
 	if err != nil {
 		t.Fatalf("Failed to create bridge: %v", err)
 		t.Fatalf("Failed to create bridge: %v", err)
 	}
 	}
@@ -102,11 +105,13 @@ func TestLinkCreateTwo(t *testing.T) {
 	config := &Configuration{
 	config := &Configuration{
 		BridgeName: DefaultBridgeName,
 		BridgeName: DefaultBridgeName,
 		EnableIPv6: true}
 		EnableIPv6: true}
-	if err := d.Config(config); err != nil {
+	genericOption := make(map[string]interface{})
+	genericOption[options.GenericData] = config
+	if err := d.Config(genericOption); err != nil {
 		t.Fatalf("Failed to setup driver config: %v", err)
 		t.Fatalf("Failed to setup driver config: %v", err)
 	}
 	}
 
 
-	err := d.CreateNetwork("dummy", "")
+	err := d.CreateNetwork("dummy", nil)
 	if err != nil {
 	if err != nil {
 		t.Fatalf("Failed to create bridge: %v", err)
 		t.Fatalf("Failed to create bridge: %v", err)
 	}
 	}
@@ -132,11 +137,14 @@ func TestLinkCreateNoEnableIPv6(t *testing.T) {
 
 
 	config := &Configuration{
 	config := &Configuration{
 		BridgeName: DefaultBridgeName}
 		BridgeName: DefaultBridgeName}
-	if err := d.Config(config); err != nil {
+	genericOption := make(map[string]interface{})
+	genericOption[options.GenericData] = config
+
+	if err := d.Config(genericOption); err != nil {
 		t.Fatalf("Failed to setup driver config: %v", err)
 		t.Fatalf("Failed to setup driver config: %v", err)
 	}
 	}
 
 
-	err := d.CreateNetwork("dummy", "")
+	err := d.CreateNetwork("dummy", nil)
 	if err != nil {
 	if err != nil {
 		t.Fatalf("Failed to create bridge: %v", err)
 		t.Fatalf("Failed to create bridge: %v", err)
 	}
 	}
@@ -163,11 +171,14 @@ func TestLinkDelete(t *testing.T) {
 	config := &Configuration{
 	config := &Configuration{
 		BridgeName: DefaultBridgeName,
 		BridgeName: DefaultBridgeName,
 		EnableIPv6: true}
 		EnableIPv6: true}
-	if err := d.Config(config); err != nil {
+	genericOption := make(map[string]interface{})
+	genericOption[options.GenericData] = config
+
+	if err := d.Config(genericOption); err != nil {
 		t.Fatalf("Failed to setup driver config: %v", err)
 		t.Fatalf("Failed to setup driver config: %v", err)
 	}
 	}
 
 
-	err := d.CreateNetwork("dummy", "")
+	err := d.CreateNetwork("dummy", nil)
 	if err != nil {
 	if err != nil {
 		t.Fatalf("Failed to create bridge: %v", err)
 		t.Fatalf("Failed to create bridge: %v", err)
 	}
 	}

+ 3 - 3
libnetwork/drivers/null/null.go

@@ -15,11 +15,11 @@ func New() (string, driverapi.Driver) {
 	return networkType, &driver{}
 	return networkType, &driver{}
 }
 }
 
 
-func (d *driver) Config(option interface{}) error {
+func (d *driver) Config(option map[string]interface{}) error {
 	return nil
 	return nil
 }
 }
 
 
-func (d *driver) CreateNetwork(id types.UUID, option interface{}) error {
+func (d *driver) CreateNetwork(id types.UUID, option map[string]interface{}) error {
 	return nil
 	return nil
 }
 }
 
 
@@ -27,7 +27,7 @@ func (d *driver) DeleteNetwork(nid types.UUID) error {
 	return nil
 	return nil
 }
 }
 
 
-func (d *driver) CreateEndpoint(nid, eid types.UUID, epOptions interface{}) (*sandbox.Info, error) {
+func (d *driver) CreateEndpoint(nid, eid types.UUID, epOptions map[string]interface{}) (*sandbox.Info, error) {
 	return nil, nil
 	return nil, nil
 }
 }
 
 

+ 28 - 5
libnetwork/endpoint.go

@@ -5,6 +5,7 @@ import (
 	"path/filepath"
 	"path/filepath"
 
 
 	"github.com/docker/docker/pkg/etchosts"
 	"github.com/docker/docker/pkg/etchosts"
+	"github.com/docker/libnetwork/pkg/options"
 	"github.com/docker/libnetwork/sandbox"
 	"github.com/docker/libnetwork/sandbox"
 	"github.com/docker/libnetwork/types"
 	"github.com/docker/libnetwork/types"
 )
 )
@@ -65,6 +66,7 @@ type endpoint struct {
 	sandboxInfo *sandbox.Info
 	sandboxInfo *sandbox.Info
 	sandBox     sandbox.Sandbox
 	sandBox     sandbox.Sandbox
 	container   *containerInfo
 	container   *containerInfo
+	generic     options.Generic
 }
 }
 
 
 const prefix = "/var/lib/docker/network/files"
 const prefix = "/var/lib/docker/network/files"
@@ -88,6 +90,27 @@ func (ep *endpoint) SandboxInfo() *sandbox.Info {
 	return ep.sandboxInfo.GetCopy()
 	return ep.sandboxInfo.GetCopy()
 }
 }
 
 
+// EndpointOption is a option setter function type used to pass various options to
+// CreateEndpoint method. The various setter functions of type EndpointOption are
+// provided by libnetwork, they look like EndpointOptionXXXX(...)
+type EndpointOption func(ep *endpoint)
+
+// EndpointOptionGeneric function returns an option setter for a Generic option defined
+// in a Dictionary of Key-Value pair
+func EndpointOptionGeneric(generic map[string]interface{}) EndpointOption {
+	return func(ep *endpoint) {
+		ep.generic = generic
+	}
+}
+
+func (ep *endpoint) processOptions(options ...EndpointOption) {
+	for _, opt := range options {
+		if opt != nil {
+			opt(ep)
+		}
+	}
+}
+
 func createBasePath(dir string) error {
 func createBasePath(dir string) error {
 	err := os.MkdirAll(dir, 0644)
 	err := os.MkdirAll(dir, 0644)
 	if err != nil && !os.IsExist(err) {
 	if err != nil && !os.IsExist(err) {
@@ -132,9 +155,7 @@ func (ep *endpoint) Join(containerID string, options ...JoinOption) (*ContainerD
 		}
 		}
 	}()
 	}()
 
 
-	if options != nil {
-		ep.processOptions(options...)
-	}
+	ep.processJoinOptions(options...)
 
 
 	ep.container.Data.HostsPath = prefix + "/" + containerID + "/hosts"
 	ep.container.Data.HostsPath = prefix + "/" + containerID + "/hosts"
 	err = createHostsFile(ep.container.Data.HostsPath)
 	err = createHostsFile(ep.container.Data.HostsPath)
@@ -255,8 +276,10 @@ func JoinOptionDomainname(name string) JoinOption {
 	}
 	}
 }
 }
 
 
-func (ep *endpoint) processOptions(options ...JoinOption) {
+func (ep *endpoint) processJoinOptions(options ...JoinOption) {
 	for _, opt := range options {
 	for _, opt := range options {
-		opt(ep)
+		if opt != nil {
+			opt(ep)
+		}
 	}
 	}
 }
 }

+ 40 - 33
libnetwork/libnetwork_test.go

@@ -17,13 +17,15 @@ const (
 
 
 func createTestNetwork(networkType, networkName string, option options.Generic) (libnetwork.Network, error) {
 func createTestNetwork(networkType, networkName string, option options.Generic) (libnetwork.Network, error) {
 	controller := libnetwork.New()
 	controller := libnetwork.New()
+	genericOption := make(map[string]interface{})
+	genericOption[options.GenericData] = option
 
 
-	err := controller.ConfigureNetworkDriver(networkType, option)
+	err := controller.ConfigureNetworkDriver(networkType, genericOption)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
 
 
-	network, err := controller.NewNetwork(networkType, networkName, "")
+	network, err := controller.NewNetwork(networkType, networkName)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
@@ -31,13 +33,19 @@ func createTestNetwork(networkType, networkName string, option options.Generic)
 	return network, nil
 	return network, nil
 }
 }
 
 
+func getEmptyGenericOption() map[string]interface{} {
+	genericOption := make(map[string]interface{})
+	genericOption[options.GenericData] = options.Generic{}
+	return genericOption
+}
+
 func TestNull(t *testing.T) {
 func TestNull(t *testing.T) {
 	network, err := createTestNetwork("null", "testnetwork", options.Generic{})
 	network, err := createTestNetwork("null", "testnetwork", options.Generic{})
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
-	ep, err := network.CreateEndpoint("testep", nil)
+	ep, err := network.CreateEndpoint("testep")
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
@@ -101,7 +109,7 @@ func TestBridge(t *testing.T) {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
-	ep, err := network.CreateEndpoint("testep", nil)
+	ep, err := network.CreateEndpoint("testep")
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
@@ -131,8 +139,8 @@ func TestUnknownDriver(t *testing.T) {
 func TestNilDriver(t *testing.T) {
 func TestNilDriver(t *testing.T) {
 	controller := libnetwork.New()
 	controller := libnetwork.New()
 
 
-	option := options.Generic{}
-	_, err := controller.NewNetwork("framerelay", "dummy", option)
+	_, err := controller.NewNetwork("framerelay", "dummy",
+		libnetwork.NetworkOptionGeneric(getEmptyGenericOption()))
 	if err == nil {
 	if err == nil {
 		t.Fatal("Expected to fail. But instead succeeded")
 		t.Fatal("Expected to fail. But instead succeeded")
 	}
 	}
@@ -145,8 +153,8 @@ func TestNilDriver(t *testing.T) {
 func TestNoInitDriver(t *testing.T) {
 func TestNoInitDriver(t *testing.T) {
 	controller := libnetwork.New()
 	controller := libnetwork.New()
 
 
-	option := options.Generic{}
-	_, err := controller.NewNetwork("ppp", "dummy", option)
+	_, err := controller.NewNetwork("ppp", "dummy",
+		libnetwork.NetworkOptionGeneric(getEmptyGenericOption()))
 	if err == nil {
 	if err == nil {
 		t.Fatal("Expected to fail. But instead succeeded")
 		t.Fatal("Expected to fail. But instead succeeded")
 	}
 	}
@@ -160,18 +168,20 @@ func TestDuplicateNetwork(t *testing.T) {
 	defer netutils.SetupTestNetNS(t)()
 	defer netutils.SetupTestNetNS(t)()
 	controller := libnetwork.New()
 	controller := libnetwork.New()
 
 
-	option := options.Generic{}
-	err := controller.ConfigureNetworkDriver(netType, option)
+	genericOption := make(map[string]interface{})
+	genericOption[options.GenericData] = options.Generic{}
+
+	err := controller.ConfigureNetworkDriver(netType, genericOption)
 	if err != nil {
 	if err != nil {
-		t.Fatal(err)
+		t.Fatal(err.Error())
 	}
 	}
 
 
-	_, err = controller.NewNetwork(netType, "testnetwork", "")
+	_, err = controller.NewNetwork(netType, "testnetwork", nil)
 	if err != nil {
 	if err != nil {
-		t.Fatal(err)
+		t.Fatal("Expected to fail. But instead succeeded")
 	}
 	}
 
 
-	_, err = controller.NewNetwork(netType, "testnetwork", "")
+	_, err = controller.NewNetwork(netType, "testnetwork")
 	if err == nil {
 	if err == nil {
 		t.Fatal("Expected to fail. But instead succeeded")
 		t.Fatal("Expected to fail. But instead succeeded")
 	}
 	}
@@ -231,7 +241,7 @@ func TestDeleteNetworkWithActiveEndpoints(t *testing.T) {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
-	ep, err := network.CreateEndpoint("testep", nil)
+	ep, err := network.CreateEndpoint("testep")
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
@@ -299,7 +309,7 @@ func TestUnknownEndpoint(t *testing.T) {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
-	ep, err := network.CreateEndpoint("testep", nil)
+	ep, err := network.CreateEndpoint("testep")
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
@@ -329,22 +339,21 @@ func TestNetworkEndpointsWalkers(t *testing.T) {
 	controller := libnetwork.New()
 	controller := libnetwork.New()
 	netType := "bridge"
 	netType := "bridge"
 
 
-	option := options.Generic{}
-	err := controller.ConfigureNetworkDriver(netType, option)
+	err := controller.ConfigureNetworkDriver(netType, getEmptyGenericOption())
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
 	// Create network 1 and add 2 endpoint: ep11, ep12
 	// Create network 1 and add 2 endpoint: ep11, ep12
-	net1, err := controller.NewNetwork(netType, "network1", "")
+	net1, err := controller.NewNetwork(netType, "network1")
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
-	ep11, err := net1.CreateEndpoint("ep11", nil)
+	ep11, err := net1.CreateEndpoint("ep11")
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
-	ep12, err := net1.CreateEndpoint("ep12", nil)
+	ep12, err := net1.CreateEndpoint("ep12")
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
@@ -409,14 +418,13 @@ func TestControllerQuery(t *testing.T) {
 	controller := libnetwork.New()
 	controller := libnetwork.New()
 	netType := "bridge"
 	netType := "bridge"
 
 
-	option := options.Generic{}
-	err := controller.ConfigureNetworkDriver(netType, option)
+	err := controller.ConfigureNetworkDriver(netType, getEmptyGenericOption())
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
 	// Create network 1
 	// Create network 1
-	net1, err := controller.NewNetwork(netType, "network1", "")
+	net1, err := controller.NewNetwork(netType, "network1")
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
@@ -455,22 +463,21 @@ func TestNetworkQuery(t *testing.T) {
 	controller := libnetwork.New()
 	controller := libnetwork.New()
 	netType := "bridge"
 	netType := "bridge"
 
 
-	option := options.Generic{}
-	err := controller.ConfigureNetworkDriver(netType, option)
+	err := controller.ConfigureNetworkDriver(netType, getEmptyGenericOption())
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
 	// Create network 1 and add 2 endpoint: ep11, ep12
 	// Create network 1 and add 2 endpoint: ep11, ep12
-	net1, err := controller.NewNetwork(netType, "network1", "")
+	net1, err := controller.NewNetwork(netType, "network1")
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
-	ep11, err := net1.CreateEndpoint("ep11", nil)
+	ep11, err := net1.CreateEndpoint("ep11")
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
-	ep12, err := net1.CreateEndpoint("ep12", nil)
+	ep12, err := net1.CreateEndpoint("ep12")
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
@@ -512,7 +519,7 @@ func TestEndpointJoin(t *testing.T) {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
-	ep, err := n.CreateEndpoint("ep1", nil)
+	ep, err := n.CreateEndpoint("ep1")
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
@@ -538,7 +545,7 @@ func TestEndpointJoinInvalidContainerId(t *testing.T) {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
-	ep, err := n.CreateEndpoint("ep1", nil)
+	ep, err := n.CreateEndpoint("ep1")
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
@@ -561,7 +568,7 @@ func TestEndpointMultipleJoins(t *testing.T) {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
-	ep, err := n.CreateEndpoint("ep1", nil)
+	ep, err := n.CreateEndpoint("ep1")
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
@@ -597,7 +604,7 @@ func TestEndpointInvalidLeave(t *testing.T) {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
-	ep, err := n.CreateEndpoint("ep1", nil)
+	ep, err := n.CreateEndpoint("ep1")
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}

+ 27 - 3
libnetwork/network.go

@@ -5,6 +5,7 @@ import (
 
 
 	"github.com/docker/docker/pkg/stringid"
 	"github.com/docker/docker/pkg/stringid"
 	"github.com/docker/libnetwork/driverapi"
 	"github.com/docker/libnetwork/driverapi"
+	"github.com/docker/libnetwork/pkg/options"
 	"github.com/docker/libnetwork/types"
 	"github.com/docker/libnetwork/types"
 )
 )
 
 
@@ -23,7 +24,7 @@ type Network interface {
 	// Create a new endpoint to this network symbolically identified by the
 	// Create a new endpoint to this network symbolically identified by the
 	// specified unique name. The options parameter carry driver specific options.
 	// specified unique name. The options parameter carry driver specific options.
 	// Labels support will be added in the near future.
 	// Labels support will be added in the near future.
-	CreateEndpoint(name string, options interface{}) (Endpoint, error)
+	CreateEndpoint(name string, options ...EndpointOption) (Endpoint, error)
 
 
 	// Delete the network.
 	// Delete the network.
 	Delete() error
 	Delete() error
@@ -52,6 +53,7 @@ type network struct {
 	id          types.UUID
 	id          types.UUID
 	driver      driverapi.Driver
 	driver      driverapi.Driver
 	endpoints   endpointTable
 	endpoints   endpointTable
+	generic     options.Generic
 	sync.Mutex
 	sync.Mutex
 }
 }
 
 
@@ -71,6 +73,27 @@ func (n *network) Type() string {
 	return n.driver.Type()
 	return n.driver.Type()
 }
 }
 
 
+// NetworkOption is a option setter function type used to pass varios options to
+// NewNetwork method. The various setter functions of type NetworkOption are
+// provided by libnetwork, they look like NetworkOptionXXXX(...)
+type NetworkOption func(n *network)
+
+// NetworkOptionGeneric function returns an option setter for a Generic option defined
+// in a Dictionary of Key-Value pair
+func NetworkOptionGeneric(generic map[string]interface{}) NetworkOption {
+	return func(n *network) {
+		n.generic = generic
+	}
+}
+
+func (n *network) processOptions(options ...NetworkOption) {
+	for _, opt := range options {
+		if opt != nil {
+			opt(n)
+		}
+	}
+}
+
 func (n *network) Delete() error {
 func (n *network) Delete() error {
 	var err error
 	var err error
 
 
@@ -103,13 +126,14 @@ func (n *network) Delete() error {
 	return err
 	return err
 }
 }
 
 
-func (n *network) CreateEndpoint(name string, options interface{}) (Endpoint, error) {
+func (n *network) CreateEndpoint(name string, options ...EndpointOption) (Endpoint, error) {
 	ep := &endpoint{name: name}
 	ep := &endpoint{name: name}
 	ep.id = types.UUID(stringid.GenerateRandomID())
 	ep.id = types.UUID(stringid.GenerateRandomID())
 	ep.network = n
 	ep.network = n
+	ep.processOptions(options...)
 
 
 	d := n.driver
 	d := n.driver
-	sinfo, err := d.CreateEndpoint(n.id, ep.id, options)
+	sinfo, err := d.CreateEndpoint(n.id, ep.id, ep.generic)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}

+ 9 - 0
libnetwork/pkg/options/options.go

@@ -7,6 +7,15 @@ import (
 	"reflect"
 	"reflect"
 )
 )
 
 
+const (
+	// GenericData constant that helps to identify an option as a Generic constant
+	GenericData = "io.docker.network.generic"
+	// PortMap constant represents Port Mapping
+	PortMap = "io.docker.network.endpoint.portmap"
+	// MacAddress constant represents Mac Address config of a Container
+	MacAddress = "io.docker.network.endpoint.macaddress"
+)
+
 // NoSuchFieldError is the error returned when the generic parameters hold a
 // NoSuchFieldError is the error returned when the generic parameters hold a
 // value for a field absent from the destination structure.
 // value for a field absent from the destination structure.
 type NoSuchFieldError struct {
 type NoSuchFieldError struct {