diff --git a/drivers.go b/drivers.go index c443955..16dd185 100644 --- a/drivers.go +++ b/drivers.go @@ -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) } diff --git a/drivers/bridge/bridge.go b/drivers/bridge/bridge.go index 558bbbb..0ae7d5b 100644 --- a/drivers/bridge/bridge.go +++ b/drivers/bridge/bridge.go @@ -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) diff --git a/drivers/bridge/bridge_test.go b/drivers/bridge/bridge_test.go index 30212ee..50529f5 100644 --- a/drivers/bridge/bridge_test.go +++ b/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) }