diff --git a/libnetwork/options/options.go b/libnetwork/options/options.go index e0e93ff9b7..8512ce83f3 100644 --- a/libnetwork/options/options.go +++ b/libnetwork/options/options.go @@ -29,6 +29,18 @@ func (e CannotSetFieldError) Error() string { return fmt.Sprintf("cannot set field %q of type %q", e.Field, e.Type) } +// TypeMismatchError is the error returned when the type of the generic value +// for a field mismatches the type of the destination structure. +type TypeMismatchError struct { + Field string + ExpectType string + ActualType string +} + +func (e TypeMismatchError) Error() string { + return fmt.Sprintf("type mismatch, field %s require type %v, actual type %v", e.Field, e.ExpectType, e.ActualType) +} + // Generic is an basic type to store arbitrary settings. type Generic map[string]interface{} @@ -62,6 +74,9 @@ func GenerateFromModel(options Generic, model interface{}) (interface{}, error) if !field.CanSet() { return nil, CannotSetFieldError{name, resType.String()} } + if reflect.TypeOf(value) != field.Type() { + return nil, TypeMismatchError{name, field.Type().String(), reflect.TypeOf(value).String()} + } field.Set(reflect.ValueOf(value)) } diff --git a/libnetwork/options/options_test.go b/libnetwork/options/options_test.go index ecd3b3b311..b618f2f4a5 100644 --- a/libnetwork/options/options_test.go +++ b/libnetwork/options/options_test.go @@ -95,3 +95,14 @@ func TestFieldCannotBeSet(t *testing.T) { t.Fatalf("expected %q in error message, got %s", expected, err.Error()) } } + +func TestTypeMismatchError(t *testing.T) { + type Model struct{ Foo int } + _, err := GenerateFromModel(Generic{"Foo": "bar"}, Model{}) + + if _, ok := err.(TypeMismatchError); !ok { + t.Fatalf("expected TypeMismatchError, got %#v", err) + } else if expected := "type mismatch"; !strings.Contains(err.Error(), expected) { + t.Fatalf("expected %q in error message, got %s", expected, err.Error()) + } +}