Merge pull request #19 from mrjana/master

Refactor the drivers interface to get rid of reflect way
This commit is contained in:
Arnaud Porterie 2015-03-09 08:59:16 -07:00
commit 5345da32c6
3 changed files with 28 additions and 65 deletions

View file

@ -2,7 +2,6 @@ package libnetwork
import (
"fmt"
"reflect"
"github.com/docker/libnetwork/pkg/options"
)
@ -10,8 +9,13 @@ import (
// DriverParams are a generic structure to hold driver specific settings.
type DriverParams options.Generic
// DriverInterface is an interface that every plugin driver needs to implement.
type DriverInterface interface {
CreateNetwork(string, interface{}) (Network, error)
}
var drivers = map[string]struct {
creatorFn interface{}
creatorFn DriverInterface
creatorArg interface{}
}{}
@ -19,35 +23,30 @@ var drivers = map[string]struct {
// new network. It is called by the various network implementations, and used
// upon invokation of the libnetwork.NetNetwork function.
//
// creatorFn must be of type func (creatorArgType) (Network, error), where
// createArgType is the type of the creatorArg argument.
// creatorFn must implement DriverInterface
//
// For example:
//
// func CreateTestNetwork(name string, config *TestNetworkConfig()) (Network, error) {
// type driver struct{}
//
// func (d *driver) CreateNetwork(name string, config *TestNetworkConfig) (Network, error) {
// }
//
// func init() {
// RegisterNetworkType("test", CreateTestNetwork, &TestNetworkConfig{})
// RegisterNetworkType("test", &driver{}, &TestNetworkConfig{})
// }
//
func RegisterNetworkType(name string, creatorFn interface{}, creatorArg interface{}) error {
// Validate the creator function signature.
ctorArg := []reflect.Type{reflect.TypeOf((*string)(nil)), reflect.TypeOf(creatorArg)}
ctorRet := []reflect.Type{reflect.TypeOf((*Network)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()}
if err := validateFunctionSignature(creatorFn, ctorArg, ctorRet); err != nil {
sig := fmt.Sprintf("func (%s) (Network, error)", ctorArg[0].Name())
return fmt.Errorf("invalid signature for %q creator function (expected %s)", name, sig)
}
func RegisterNetworkType(name string, creatorFn DriverInterface, creatorArg interface{}) error {
// Store the new driver information to invoke at creation time.
if _, ok := drivers[name]; ok {
return fmt.Errorf("a driver for network type %q is already registed", name)
}
drivers[name] = struct {
creatorFn interface{}
creatorFn DriverInterface
creatorArg interface{}
}{creatorFn, creatorArg}
return nil
}
@ -62,47 +61,5 @@ func createNetwork(networkType, name string, generic DriverParams) (Network, err
return nil, fmt.Errorf("failed to generate driver config: %v", err)
}
arg := []reflect.Value{reflect.ValueOf(name), reflect.ValueOf(config)}
res := reflect.ValueOf(d.creatorFn).Call(arg)
return makeCreateResult(res)
}
func makeCreateResult(res []reflect.Value) (net Network, err error) {
if !res[0].IsNil() {
net = res[0].Interface().(Network)
}
if !res[1].IsNil() {
err = res[1].Interface().(error)
}
return
}
func validateFunctionSignature(fn interface{}, params []reflect.Type, returns []reflect.Type) error {
// Valid that argument is a function.
fnType := reflect.TypeOf(fn)
if fnType.Kind() != reflect.Func {
return fmt.Errorf("argument is %s, not function", fnType.Name())
}
// Vaidate arguments numbers and types.
if fnType.NumIn() != len(params) {
return fmt.Errorf("expected function with %d arguments, got %d", len(params), fnType.NumIn())
}
for i, argType := range params {
if argType != fnType.In(i) {
return fmt.Errorf("argument %d type should be %s, got %s", i, argType.Name(), fnType.In(i).Name())
}
}
// Validate return values numbers and types.
if fnType.NumOut() != len(returns) {
return fmt.Errorf("expected function with %d return values, got %d", len(params), fnType.NumIn())
}
for i, retType := range returns {
if retType != fnType.Out(i) {
return fmt.Errorf("return value %d type should be %s, got %s", i, retType.Name(), fnType.Out(i).Name())
}
}
return nil
return d.creatorFn.CreateNetwork(name, config)
}

View file

@ -22,12 +22,15 @@ type Configuration struct {
EnableIPForwarding bool
}
type driver struct{}
func init() {
libnetwork.RegisterNetworkType(networkType, Create, &Configuration{})
libnetwork.RegisterNetworkType(networkType, &driver{}, &Configuration{})
}
// Create a new Network managed by the "simplebridge" driver.
func Create(name string, config *Configuration) (libnetwork.Network, error) {
// Create a new network using simplebridge plugin
func (d *driver) CreateNetwork(name string, opaqueConfig interface{}) (libnetwork.Network, error) {
config := opaqueConfig.(*Configuration)
bridgeIntfc := newInterface(config)
bridgeSetup := newBridgeSetup(bridgeIntfc)

View file

@ -9,9 +9,10 @@ import (
func TestCreate(t *testing.T) {
defer libnetwork.SetupTestNetNS(t)()
d := &driver{}
config := &Configuration{BridgeName: DefaultBridgeName}
netw, err := Create("dummy", config)
netw, err := d.CreateNetwork("dummy", config)
if err != nil {
t.Fatalf("Failed to create bridge: %v", err)
}
@ -23,15 +24,17 @@ func TestCreate(t *testing.T) {
func TestCreateFail(t *testing.T) {
defer libnetwork.SetupTestNetNS(t)()
d := &driver{}
config := &Configuration{BridgeName: "dummy0"}
if _, err := Create("dummy", config); err == nil {
if _, err := d.CreateNetwork("dummy", config); err == nil {
t.Fatal("Bridge creation was expected to fail")
}
}
func TestCreateFullOptions(t *testing.T) {
defer libnetwork.SetupTestNetNS(t)()
d := &driver{}
config := &Configuration{
BridgeName: DefaultBridgeName,
@ -42,7 +45,7 @@ func TestCreateFullOptions(t *testing.T) {
}
_, config.FixedCIDRv6, _ = net.ParseCIDR("2001:db8::/48")
netw, err := Create("dummy", config)
netw, err := d.CreateNetwork("dummy", config)
if err != nil {
t.Fatalf("Failed to create bridge: %v", err)
}