Add duration as a configurable type for localkube

pull/1715/head
Matt Rickard 2017-07-19 14:16:33 -07:00
parent 9e8ef22e93
commit d56d41b956
2 changed files with 81 additions and 39 deletions

View File

@ -22,6 +22,7 @@ import (
"reflect"
"strconv"
"strings"
"time"
utilnet "k8s.io/apimachinery/pkg/util/net"
)
@ -47,29 +48,15 @@ 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 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 reflect.String:
e.SetString(v)
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 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)
default:
switch t := e.Interface().(type) {
switch e.Interface().(type) {
case int, int32, int64:
return convertInt(e, v)
case string:
return convertString(e, v)
case float32, float64:
return convertFloat(e, v)
case bool:
return convertBool(e, v)
case net.IP:
ip := net.ParseIP(v)
if ip == nil {
@ -88,13 +75,64 @@ func setElement(e reflect.Value, v string) error {
return fmt.Errorf("Error converting input %s to PortRange: %s", v, err)
}
e.Set(reflect.ValueOf(*pr))
case time.Duration:
dur, err := time.ParseDuration(v)
if err != nil {
return fmt.Errorf("Error converting input %s to Duration: %s", v, err)
}
e.Set(reflect.ValueOf(dur))
case []string:
vals := strings.Split(v, ",")
e.Set(reflect.ValueOf(vals))
default:
return fmt.Errorf("Unable to set type %T.", t)
// Last ditch attempt to convert anything based on its underlying kind.
// This covers any types that are aliased to a native type
switch e.Kind() {
case reflect.Int, reflect.Int32, reflect.Int64:
return convertInt(e, v)
case reflect.String:
return convertString(e, v)
case reflect.Float32, reflect.Float64:
return convertFloat(e, v)
case reflect.Bool:
return convertBool(e, v)
default:
return fmt.Errorf("Unable to set type %T.", e.Kind())
}
}
return nil
}
func convertInt(e reflect.Value, v string) error {
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))
return nil
}
func convertString(e reflect.Value, v string) error {
e.SetString(v)
return nil
}
func convertFloat(e reflect.Value, v string) error {
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)
return nil
}
func convertBool(e reflect.Value, v string) error {
b, err := strconv.ParseBool(v)
if err != nil {
return fmt.Errorf("Error converting input %s to a bool: %s", v, err)
}
e.SetBool(b)
return nil
}

View File

@ -21,6 +21,7 @@ import (
"net"
"reflect"
"testing"
"time"
utilnet "k8s.io/apimachinery/pkg/util/net"
)
@ -58,6 +59,7 @@ type subConfig3 struct {
S []string
T aliasedString
U net.IPNet
V time.Duration
}
func buildConfig() testConfig {
@ -78,6 +80,7 @@ func buildConfig() testConfig {
Q: net.ParseIP("12.34.56.78"),
R: utilnet.PortRange{Base: 2, Size: 4},
U: *cidr,
V: 5 * time.Second,
},
},
E: &subConfig2{
@ -180,6 +183,7 @@ func TestSetElement(t *testing.T) {
{"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" }},
{"D.I.U", "11.22.0.0/16", func(t testConfig) bool { return t.D.I.U.String() == "11.22.0.0/16" }},
{"D.I.V", "5s", func(t testConfig) bool { return t.D.I.V == 5*time.Second }},
} {
a := buildConfig()
if err := FindAndSet(tc.path, &a, tc.newval); err != nil {