mirror of
https://github.com/clearlinux/libnetwork.git
synced 2026-08-25 16:55:58 +00:00
Generic argument passing to drivers
Signed-off-by: Arnaud Porterie <arnaud.porterie@docker.com>
This commit is contained in:
+1
-1
@@ -13,7 +13,7 @@ type bridgeConfiguration struct {
|
||||
}
|
||||
|
||||
func init() {
|
||||
libnetwork.RegisterNetworkType(networkType, Create, bridgeConfiguration{})
|
||||
libnetwork.RegisterNetworkType(networkType, Create, &bridgeConfiguration{})
|
||||
}
|
||||
|
||||
func Create(config *bridgeConfiguration) (libnetwork.Network, error) {
|
||||
|
||||
+60
-8
@@ -10,21 +10,43 @@ import (
|
||||
type DriverParams options.Generic
|
||||
|
||||
var drivers = map[string]struct {
|
||||
ctor interface{}
|
||||
config interface{}
|
||||
creatorFn interface{}
|
||||
creatorArg interface{}
|
||||
}{}
|
||||
|
||||
// RegisterNetworkType associates a textual identifier with a way to create a
|
||||
// new network. It is called by the various network implementations, and used
|
||||
// upon invokation of the libnetwork.NetNetwork function.
|
||||
func RegisterNetworkType(name string, ctor interface{}, config interface{}) error {
|
||||
//
|
||||
// creatorFn must be of type func (creatorArgType) (Network, error), where
|
||||
// createArgType is the type of the creatorArg argument.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// func CreateTestNetwork(config *TestNetworkConfig()) (Network, error) {
|
||||
// }
|
||||
//
|
||||
// func init() {
|
||||
// RegisterNetworkType("test", CreateTestNetwork, &TestNetworkConfig{})
|
||||
// }
|
||||
//
|
||||
func RegisterNetworkType(name string, creatorFn interface{}, creatorArg interface{}) error {
|
||||
// Validate the creator function signature.
|
||||
ctorArg := []reflect.Type{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)
|
||||
}
|
||||
|
||||
// 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 {
|
||||
ctor interface{}
|
||||
config interface{}
|
||||
}{ctor, config}
|
||||
creatorFn interface{}
|
||||
creatorArg interface{}
|
||||
}{creatorFn, creatorArg}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -34,13 +56,13 @@ func createNetwork(name string, generic DriverParams) (Network, error) {
|
||||
return nil, fmt.Errorf("unknown driver %q", name)
|
||||
}
|
||||
|
||||
config, err := options.GenerateFromModel(options.Generic(generic), d.config)
|
||||
config, err := options.GenerateFromModel(options.Generic(generic), d.creatorArg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to generate driver config: %v", err)
|
||||
}
|
||||
|
||||
arg := []reflect.Value{reflect.ValueOf(config)}
|
||||
res := reflect.ValueOf(d.ctor).Call(arg)
|
||||
res := reflect.ValueOf(d.creatorFn).Call(arg)
|
||||
return makeCreateResult(res)
|
||||
}
|
||||
|
||||
@@ -53,3 +75,33 @@ func makeCreateResult(res []reflect.Value) (net Network, err 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
|
||||
}
|
||||
|
||||
+16
-2
@@ -32,7 +32,16 @@ func NewGeneric() Generic {
|
||||
}
|
||||
|
||||
func GenerateFromModel(options Generic, model interface{}) (interface{}, error) {
|
||||
res := reflect.New(reflect.TypeOf(model))
|
||||
modType := reflect.TypeOf(model)
|
||||
|
||||
// If the model is of pointer type, we need to dereference for New.
|
||||
resType := reflect.TypeOf(model)
|
||||
if modType.Kind() == reflect.Ptr {
|
||||
resType = resType.Elem()
|
||||
}
|
||||
|
||||
// Populate the result structure with the generic layout content.
|
||||
res := reflect.New(resType)
|
||||
for name, value := range options {
|
||||
field := res.Elem().FieldByName(name)
|
||||
if !field.IsValid() {
|
||||
@@ -43,5 +52,10 @@ func GenerateFromModel(options Generic, model interface{}) (interface{}, error)
|
||||
}
|
||||
field.Set(reflect.ValueOf(value))
|
||||
}
|
||||
return res.Interface(), nil
|
||||
|
||||
// If the model is not of pointer type, return content of the result.
|
||||
if modType.Kind() == reflect.Ptr {
|
||||
return res.Interface(), nil
|
||||
}
|
||||
return res.Elem().Interface(), nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user