Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add duration as a configurable type for localkube #1715

Merged
merged 1 commit into from
Jul 20, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 76 additions & 38 deletions pkg/util/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"reflect"
"strconv"
"strings"
"time"

utilnet "k8s.io/apimachinery/pkg/util/net"
)
Expand All @@ -47,54 +48,91 @@ 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)
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 {
return fmt.Errorf("Error converting input %s to an IP.", v)
}
e.Set(reflect.ValueOf(ip))
case net.IPNet:
_, cidr, err := net.ParseCIDR(v)
if err != nil {
return fmt.Errorf("Error converting input %s to an integer: %s", v, err)
return fmt.Errorf("Error converting input %s to a CIDR: %s", v, err)
}
e.SetInt(int64(i))
case reflect.String:
e.SetString(v)
case reflect.Float32, reflect.Float64:
f, err := strconv.ParseFloat(v, 64)
e.Set(reflect.ValueOf(*cidr))
case utilnet.PortRange:
pr, err := utilnet.ParsePortRange(v)
if err != nil {
return fmt.Errorf("Error converting input %s to a float: %s", v, err)
return fmt.Errorf("Error converting input %s to PortRange: %s", v, err)
}
e.SetFloat(f)
case reflect.Bool:
b, err := strconv.ParseBool(v)
e.Set(reflect.ValueOf(*pr))
case time.Duration:
dur, err := time.ParseDuration(v)
if err != nil {
return fmt.Errorf("Error converting input %s to a bool: %s", v, err)
return fmt.Errorf("Error converting input %s to Duration: %s", v, err)
}
e.SetBool(b)
e.Set(reflect.ValueOf(dur))
case []string:
vals := strings.Split(v, ",")
e.Set(reflect.ValueOf(vals))
default:
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 net.IPNet:
_, cidr, err := net.ParseCIDR(v)
if err != nil {
return fmt.Errorf("Error converting input %s to a CIDR: %s", v, err)
}
e.Set(reflect.ValueOf(*cidr))
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))
// 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.", t)
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
}

Expand Down
4 changes: 4 additions & 0 deletions pkg/util/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"net"
"reflect"
"testing"
"time"

utilnet "k8s.io/apimachinery/pkg/util/net"
)
Expand Down Expand Up @@ -58,6 +59,7 @@ type subConfig3 struct {
S []string
T aliasedString
U net.IPNet
V time.Duration
}

func buildConfig() testConfig {
Expand All @@ -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{
Expand Down Expand Up @@ -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 {
Expand Down