diff --git a/pkg/util/config.go b/pkg/util/config.go deleted file mode 100644 index 6d043e1e61..0000000000 --- a/pkg/util/config.go +++ /dev/null @@ -1,189 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package util - -import ( - "fmt" - "net" - "reflect" - "strconv" - "strings" - "time" - - utilnet "k8s.io/apimachinery/pkg/util/net" -) - -// findNestedElement uses reflection to find the element corresponding to the dot-separated string parameter. -func findNestedElement(s string, c interface{}) (reflect.Value, error) { - fields := strings.Split(s, ".") - - // Take the ValueOf to get a pointer, so we can actually mutate the element. - e := reflect.Indirect(reflect.ValueOf(c).Elem()) - - for _, field := range fields { - e = reflect.Indirect(e.FieldByName(field)) - - // FieldByName returns the zero value if the field does not exist. - if e == (reflect.Value{}) { - return e, fmt.Errorf("unable to find field by name: %s", field) - } - // Start the loop again, on the next level. - } - return e, nil -} - -// 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.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: - return convertIP(e, v) - case net.IPNet: - return convertCIDR(e, v) - case utilnet.PortRange: - return convertPortRange(e, v) - case time.Duration: - return convertDuration(e, v) - case []string: - vals := strings.Split(v, ",") - e.Set(reflect.ValueOf(vals)) - case map[string]string: - return convertMap(e, v) - default: - // Last ditch attempt to convert anything based on its underlying kind. - // This covers any types that are aliased to a native type - return convertKind(e, v) - } - - return nil -} - -func convertMap(e reflect.Value, v string) error { - if e.IsNil() { - e.Set(reflect.MakeMap(e.Type())) - } - vals := strings.Split(v, ",") - for _, subitem := range vals { - subvals := strings.FieldsFunc(subitem, func(c rune) bool { - return c == '<' || c == '=' || c == '>' - }) - if len(subvals) != 2 { - return fmt.Errorf("unparsable %s", v) - } - e.SetMapIndex(reflect.ValueOf(subvals[0]), reflect.ValueOf(subvals[1])) - } - return nil -} - -func convertKind(e reflect.Value, v string) error { - 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()) - } -} - -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: %v", 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: %v", 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: %v", v, err) - } - e.SetBool(b) - return nil -} - -func convertIP(e reflect.Value, v string) error { - ip := net.ParseIP(v) - if ip == nil { - return fmt.Errorf("error converting input %s to an IP", v) - } - e.Set(reflect.ValueOf(ip)) - return nil -} - -func convertCIDR(e reflect.Value, v string) error { - _, cidr, err := net.ParseCIDR(v) - if err != nil { - return fmt.Errorf("error converting input %s to a CIDR: %v", v, err) - } - e.Set(reflect.ValueOf(*cidr)) - return nil -} - -func convertPortRange(e reflect.Value, v string) error { - pr, err := utilnet.ParsePortRange(v) - if err != nil { - return fmt.Errorf("error converting input %s to PortRange: %v", v, err) - } - e.Set(reflect.ValueOf(*pr)) - return nil -} - -func convertDuration(e reflect.Value, v string) error { - dur, err := time.ParseDuration(v) - if err != nil { - return fmt.Errorf("error converting input %s to Duration: %v", v, err) - } - e.Set(reflect.ValueOf(dur)) - return nil -} - -// FindAndSet sets the nested value. -func FindAndSet(path string, c interface{}, value string) error { - elem, err := findNestedElement(path, c) - if err != nil { - return err - } - return setElement(elem, value) -} diff --git a/pkg/util/config_test.go b/pkg/util/config_test.go deleted file mode 100644 index 2ca74c95ac..0000000000 --- a/pkg/util/config_test.go +++ /dev/null @@ -1,197 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package util - -import ( - "math" - "net" - "reflect" - "testing" - "time" - - utilnet "k8s.io/apimachinery/pkg/util/net" -) - -type aliasedString string - -type testConfig struct { - A string - B int - C float32 - D subConfig1 - E *subConfig2 -} - -type subConfig1 struct { - F string - G int - H float32 - I subConfig3 -} - -type subConfig2 struct { - J string - K int - L float32 -} - -type subConfig3 struct { - M string - N int - O float32 - P bool - Q net.IP - R utilnet.PortRange - S []string - T aliasedString - U net.IPNet - V time.Duration -} - -func buildConfig() testConfig { - _, cidr, _ := net.ParseCIDR("12.34.56.78/16") - return testConfig{ - A: "foo", - B: 1, - C: 1.1, - D: subConfig1{ - F: "bar", - G: 2, - H: 2.2, - I: subConfig3{ - M: "baz", - N: 3, - O: 3.3, - P: false, - Q: net.ParseIP("12.34.56.78"), - R: utilnet.PortRange{Base: 2, Size: 4}, - U: *cidr, - V: 5 * time.Second, - }, - }, - E: &subConfig2{ - J: "bat", - K: 4, - L: 4.4, - }, - } -} - -func TestFindNestedStrings(t *testing.T) { - a := buildConfig() - for _, tc := range []struct { - input string - output string - }{ - {"A", "foo"}, - {"D.F", "bar"}, - {"D.I.M", "baz"}, - {"E.J", "bat"}, - } { - v, err := findNestedElement(tc.input, &a) - if err != nil { - t.Fatalf("Did not expect error. Got: %v", err) - } - if v.String() != tc.output { - t.Fatalf("Expected: %s, got %s", tc.output, v.String()) - } - } -} - -func TestFindNestedInts(t *testing.T) { - a := buildConfig() - - for _, tc := range []struct { - input string - output int64 - }{ - {"B", 1}, - {"D.G", 2}, - {"D.I.N", 3}, - {"E.K", 4}, - } { - v, err := findNestedElement(tc.input, &a) - if err != nil { - t.Fatalf("Did not expect error. Got: %v", err) - } - if v.Int() != tc.output { - t.Fatalf("Expected: %d, got %d", tc.output, v.Int()) - } - } -} - -func checkFloats(f1, f2 float64) bool { - return math.Abs(f1-f2) < .00001 -} - -func TestFindNestedFloats(t *testing.T) { - a := buildConfig() - for _, tc := range []struct { - input string - output float64 - }{ - {"C", 1.1}, - {"D.H", 2.2}, - {"D.I.O", 3.3}, - {"E.L", 4.4}, - } { - v, err := findNestedElement(tc.input, &a) - if err != nil { - t.Fatalf("Did not expect error. Got: %v", err) - } - - // Floating point comparison is tricky. - if !checkFloats(tc.output, v.Float()) { - t.Fatalf("Expected: %v, got %v", tc.output, v.Float()) - } - } -} - -func TestSetElement(t *testing.T) { - for _, tc := range []struct { - path string - newval string - checker func(testConfig) bool - }{ - {"A", "newstring", func(t testConfig) bool { return t.A == "newstring" }}, - {"B", "13", func(t testConfig) bool { return t.B == 13 }}, - {"C", "3.14", func(t testConfig) bool { return checkFloats(float64(t.C), 3.14) }}, - {"D.F", "fizzbuzz", func(t testConfig) bool { return t.D.F == "fizzbuzz" }}, - {"D.G", "4", func(t testConfig) bool { return t.D.G == 4 }}, - {"D.H", "7.3", func(t testConfig) bool { return checkFloats(float64(t.D.H), 7.3) }}, - {"E.J", "otherstring", func(t testConfig) bool { return t.E.J == "otherstring" }}, - {"E.K", "17", func(t testConfig) bool { return t.E.K == 17 }}, - {"E.L", "1.234", func(t testConfig) bool { return checkFloats(float64(t.E.L), 1.234) }}, - {"D.I.P", "true", func(t testConfig) bool { return t.D.I.P == true }}, - {"D.I.P", "false", func(t testConfig) bool { return t.D.I.P == false }}, - {"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" }}, - {"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 { - t.Fatalf("Error setting value: %v", err) - } - if !tc.checker(a) { - t.Fatalf("Error, values not correct: %v, %s, %s", a, tc.newval, tc.path) - } - - } -}