support componentconfigs with native type aliases

Some componentconfig options are aliased to native convertible types
(e.g. ProxyMode) but FindAndSet() was unable to detect that and so it
wasn't possible to set these values via `--extra-config`.

This change addresses that by using the reflected value's Kind instead
of a type assertion on its interface.

It's also worth noting that any value with the type Duration (e.g.
proxy.IPTablesSyncPeriod) is also unable to be set for the same reason,
but this commit does not address that.

See https://github.com/kubernetes/minikube/issues/1217
pull/1218/head
Eden Li 2017-03-03 01:05:19 -08:00
parent 15c56c2e15
commit c632321122
2 changed files with 28 additions and 21 deletions

View File

@ -47,44 +47,47 @@ func findNestedElement(s string, c interface{}) (reflect.Value, error) {
// setElement sets the supplied element to the value in the supplied string. The string will be coerced to the correct type.
func setElement(e reflect.Value, v string) error {
switch t := e.Interface().(type) {
case int, int32, int64:
switch e.Kind() {
case reflect.Int, reflect.Int32, reflect.Int64:
i, err := strconv.Atoi(v)
if err != nil {
return fmt.Errorf("Error converting input %s to an integer: %s", v, err)
}
e.SetInt(int64(i))
case string:
case reflect.String:
e.SetString(v)
case float32, float64:
case reflect.Float32, reflect.Float64:
f, err := strconv.ParseFloat(v, 64)
if err != nil {
return fmt.Errorf("Error converting input %s to a float: %s", v, err)
}
e.SetFloat(f)
case bool:
case reflect.Bool:
b, err := strconv.ParseBool(v)
if err != nil {
return fmt.Errorf("Error converting input %s to a bool: %s", v, err)
}
e.SetBool(b)
case net.IP:
ip := net.ParseIP(v)
if ip == nil {
return fmt.Errorf("Error converting input %s to an IP.", v)
}
e.Set(reflect.ValueOf(ip))
case utilnet.PortRange:
pr, err := utilnet.ParsePortRange(v)
if err != nil {
return fmt.Errorf("Error converting input %s to PortRange: %s", v, err)
}
e.Set(reflect.ValueOf(*pr))
case []string:
vals := strings.Split(v, ",")
e.Set(reflect.ValueOf(vals))
default:
return fmt.Errorf("Unable to set type %T.", t)
switch t := e.Interface().(type) {
case net.IP:
ip := net.ParseIP(v)
if ip == nil {
return fmt.Errorf("Error converting input %s to an IP.", v)
}
e.Set(reflect.ValueOf(ip))
case utilnet.PortRange:
pr, err := utilnet.ParsePortRange(v)
if err != nil {
return fmt.Errorf("Error converting input %s to PortRange: %s", v, err)
}
e.Set(reflect.ValueOf(*pr))
case []string:
vals := strings.Split(v, ",")
e.Set(reflect.ValueOf(vals))
default:
return fmt.Errorf("Unable to set type %T.", t)
}
}
return nil
}

View File

@ -25,6 +25,8 @@ import (
utilnet "k8s.io/kubernetes/pkg/util/net"
)
type aliasedString string
type testConfig struct {
A string
B int
@ -54,6 +56,7 @@ type subConfig3 struct {
Q net.IP
R utilnet.PortRange
S []string
T aliasedString
}
func buildConfig() testConfig {
@ -172,6 +175,7 @@ func TestSetElement(t *testing.T) {
{"D.I.Q", "11.22.33.44", func(t testConfig) bool { return t.D.I.Q.Equal(net.ParseIP("11.22.33.44")) }},
{"D.I.R", "7-11", func(t testConfig) bool { return t.D.I.R.Base == 7 && t.D.I.R.Size == 5 }},
{"D.I.S", "a,b", func(t testConfig) bool { return reflect.DeepEqual(t.D.I.S, []string{"a", "b"}) }},
{"D.I.T", "foo", func(t testConfig) bool { return t.D.I.T == "foo" }},
} {
a := buildConfig()
if err := FindAndSet(tc.path, &a, tc.newval); err != nil {