Merge pull request #13702 from ghodss/ghodss-yaml-upgrade

Auto commit by PR queue bot
This commit is contained in:
k8s-merge-robot 2015-09-16 22:27:24 -07:00
commit f44432ae7b
6 changed files with 66 additions and 15 deletions

2
Godeps/Godeps.json generated
View File

@ -236,7 +236,7 @@
}, },
{ {
"ImportPath": "github.com/ghodss/yaml", "ImportPath": "github.com/ghodss/yaml",
"Rev": "588cb435e59ee8b6c2795482887755841ad67207" "Rev": "73d445a93680fa1a78ae23a5839bad48f32ba1ee"
}, },
{ {
"ImportPath": "github.com/godbus/dbus", "ImportPath": "github.com/godbus/dbus",

View File

@ -0,0 +1,7 @@
language: go
go:
- 1.3
- 1.4
script:
- go test
- go build

View File

@ -1,5 +1,7 @@
# YAML marshaling and unmarshaling support for Go # YAML marshaling and unmarshaling support for Go
[![Build Status](https://travis-ci.org/ghodss/yaml.svg)](https://travis-ci.org/ghodss/yaml)
## Introduction ## Introduction
A wrapper around [go-yaml](https://github.com/go-yaml/yaml) designed to enable a better way of handling YAML when marshaling to and from structs. A wrapper around [go-yaml](https://github.com/go-yaml/yaml) designed to enable a better way of handling YAML when marshaling to and from structs.

View File

@ -113,12 +113,11 @@ func convertToJSONableObject(yamlObj interface{}, jsonTarget *reflect.Value) (in
} }
} }
// If yamlObj is a number, check if jsonTarget is a string - if so, coerce. // If yamlObj is a number or a boolean, check if jsonTarget is a string -
// Else return normal. // if so, coerce. Else return normal.
// If yamlObj is a map or array, find the field that each key is // If yamlObj is a map or array, find the field that each key is
// unmarshaling to, and when you recurse pass the reflect.Value for that // unmarshaling to, and when you recurse pass the reflect.Value for that
// field back into this function. // field back into this function.
switch typedYAMLObj := yamlObj.(type) { switch typedYAMLObj := yamlObj.(type) {
case map[interface{}]interface{}: case map[interface{}]interface{}:
// JSON does not support arbitrary keys in a map, so we must convert // JSON does not support arbitrary keys in a map, so we must convert
@ -155,14 +154,22 @@ func convertToJSONableObject(yamlObj interface{}, jsonTarget *reflect.Value) (in
s = ".nan" s = ".nan"
} }
keyString = s keyString = s
case bool:
if typedKey {
keyString = "true"
} else {
keyString = "false"
}
default: default:
return nil, fmt.Errorf("Unsupported map key of type: %s, key: %+#v, value: %+#v", return nil, fmt.Errorf("Unsupported map key of type: %s, key: %+#v, value: %+#v",
reflect.TypeOf(k), k, v) reflect.TypeOf(k), k, v)
} }
// If jsonTarget is a struct (which it really should be), find the // jsonTarget should be a struct or a map. If it's a struct, find
// field it's going to map to. If it's not a struct, just pass nil // the field it's going to map to and pass its reflect.Value. If
// - JSON conversion will error for us if it's a real issue. // it's a map, find the element type of the map and pass the
// reflect.Value created from that type. If it's neither, just pass
// nil - JSON conversion will error for us if it's a real issue.
if jsonTarget != nil { if jsonTarget != nil {
t := *jsonTarget t := *jsonTarget
if t.Kind() == reflect.Struct { if t.Kind() == reflect.Struct {
@ -191,6 +198,15 @@ func convertToJSONableObject(yamlObj interface{}, jsonTarget *reflect.Value) (in
} }
continue continue
} }
} else if t.Kind() == reflect.Map {
// Create a zero value of the map's element type to use as
// the JSON target.
jtv := reflect.Zero(t.Type().Elem())
strMap[keyString], err = convertToJSONableObject(v, &jtv)
if err != nil {
return nil, err
}
continue
} }
} }
strMap[keyString], err = convertToJSONableObject(v, nil) strMap[keyString], err = convertToJSONableObject(v, nil)
@ -234,15 +250,21 @@ func convertToJSONableObject(yamlObj interface{}, jsonTarget *reflect.Value) (in
// Based on my reading of go-yaml, it may return int, int64, // Based on my reading of go-yaml, it may return int, int64,
// float64, or uint64. // float64, or uint64.
var s string var s string
switch num := typedYAMLObj.(type) { switch typedVal := typedYAMLObj.(type) {
case int: case int:
s = strconv.FormatInt(int64(num), 10) s = strconv.FormatInt(int64(typedVal), 10)
case int64: case int64:
s = strconv.FormatInt(num, 10) s = strconv.FormatInt(typedVal, 10)
case float64: case float64:
s = strconv.FormatFloat(num, 'g', -1, 32) s = strconv.FormatFloat(typedVal, 'g', -1, 32)
case uint64: case uint64:
s = strconv.FormatUint(num, 10) s = strconv.FormatUint(typedVal, 10)
case bool:
if typedVal {
s = "true"
} else {
s = "false"
}
} }
if len(s) > 0 { if len(s) > 0 {
yamlObj = interface{}(s) yamlObj = interface{}(s)

View File

@ -33,7 +33,12 @@ func TestMarshal(t *testing.T) {
} }
type UnmarshalString struct { type UnmarshalString struct {
A string A string
True string
}
type UnmarshalStringMap struct {
A map[string]string
} }
type UnmarshalNestedString struct { type UnmarshalNestedString struct {
@ -56,7 +61,17 @@ type NestedSlice struct {
func TestUnmarshal(t *testing.T) { func TestUnmarshal(t *testing.T) {
y := []byte("a: 1") y := []byte("a: 1")
s1 := UnmarshalString{} s1 := UnmarshalString{}
e1 := UnmarshalString{"1"} e1 := UnmarshalString{A: "1"}
unmarshal(t, y, &s1, &e1)
y = []byte("a: true")
s1 = UnmarshalString{}
e1 = UnmarshalString{A: "true"}
unmarshal(t, y, &s1, &e1)
y = []byte("true: 1")
s1 = UnmarshalString{}
e1 = UnmarshalString{True: "1"}
unmarshal(t, y, &s1, &e1) unmarshal(t, y, &s1, &e1)
y = []byte("a:\n a: 1") y = []byte("a:\n a: 1")
@ -68,6 +83,11 @@ func TestUnmarshal(t *testing.T) {
s3 := UnmarshalSlice{} s3 := UnmarshalSlice{}
e3 := UnmarshalSlice{[]NestedSlice{NestedSlice{"abc", strPtr("def")}, NestedSlice{"123", strPtr("456")}}} e3 := UnmarshalSlice{[]NestedSlice{NestedSlice{"abc", strPtr("def")}, NestedSlice{"123", strPtr("456")}}}
unmarshal(t, y, &s3, &e3) unmarshal(t, y, &s3, &e3)
y = []byte("a:\n b: 1")
s4 := UnmarshalStringMap{}
e4 := UnmarshalStringMap{map[string]string{"b": "1"}}
unmarshal(t, y, &s4, &e4)
} }
func unmarshal(t *testing.T, y []byte, s, e interface{}) { func unmarshal(t *testing.T, y []byte, s, e interface{}) {

View File

@ -44,7 +44,7 @@ const (
// of expectations, without it the controller could stay asleep forever. This should // of expectations, without it the controller could stay asleep forever. This should
// be set based on the expected latency of watch events. // be set based on the expected latency of watch events.
// //
// Currently an controller can service (create *and* observe the watch events for said // Currently a controller can service (create *and* observe the watch events for said
// creation) about 10-20 pods a second, so it takes about 1 min to service // creation) about 10-20 pods a second, so it takes about 1 min to service
// 500 pods. Just creation is limited to 20qps, and watching happens with ~10-30s // 500 pods. Just creation is limited to 20qps, and watching happens with ~10-30s
// latency/pod at the scale of 3000 pods over 100 nodes. // latency/pod at the scale of 3000 pods over 100 nodes.