From 2d16187d8c48a15f0c9c966033e8a8cd2096a008 Mon Sep 17 00:00:00 2001 From: Jana Radhakrishnan Date: Thu, 5 Mar 2015 19:04:07 +0000 Subject: [PATCH] Refactor the drivers interface to get rid of reflect way Signed-off-by: Jana Radhakrishnan --- libnetwork/drivers.go | 75 +++++------------------- libnetwork/drivers/bridge/bridge.go | 8 ++- libnetwork/drivers/bridge/bridge_test.go | 9 ++- 3 files changed, 28 insertions(+), 64 deletions(-) diff --git a/libnetwork/drivers.go b/libnetwork/drivers.go index 4781337bbb..5fa9b00140 100644 --- a/libnetwork/drivers.go +++ b/libnetwork/drivers.go @@ -2,15 +2,19 @@ package libnetwork import ( "fmt" - "reflect" "github.com/docker/libnetwork/pkg/options" ) 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{} }{} @@ -18,35 +22,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 } @@ -61,47 +60,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) } diff --git a/libnetwork/drivers/bridge/bridge.go b/libnetwork/drivers/bridge/bridge.go index 728ab8e086..00f3a51927 100644 --- a/libnetwork/drivers/bridge/bridge.go +++ b/libnetwork/drivers/bridge/bridge.go @@ -21,11 +21,15 @@ type Configuration struct { EnableIPForwarding bool } +type driver struct{} + func init() { - libnetwork.RegisterNetworkType(NetworkType, Create, &Configuration{}) + libnetwork.RegisterNetworkType(networkType, &driver{}, &Configuration{}) } -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) diff --git a/libnetwork/drivers/bridge/bridge_test.go b/libnetwork/drivers/bridge/bridge_test.go index f596632978..ff5df4aaf7 100644 --- a/libnetwork/drivers/bridge/bridge_test.go +++ b/libnetwork/drivers/bridge/bridge_test.go @@ -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) }