mirror of https://github.com/k3s-io/k3s
export unstructured helper function nestedFieldNoCopy and add unit tests
Signed-off-by: Steve Kriss <steve@heptio.com>pull/8/head
parent
d4ded15f8a
commit
d2e28006e3
|
@ -34,14 +34,17 @@ import (
|
|||
// Returns false if the value is missing.
|
||||
// No error is returned for a nil field.
|
||||
func NestedFieldCopy(obj map[string]interface{}, fields ...string) (interface{}, bool, error) {
|
||||
val, found, err := nestedFieldNoCopy(obj, fields...)
|
||||
val, found, err := NestedFieldNoCopy(obj, fields...)
|
||||
if !found || err != nil {
|
||||
return nil, found, err
|
||||
}
|
||||
return runtime.DeepCopyJSONValue(val), true, nil
|
||||
}
|
||||
|
||||
func nestedFieldNoCopy(obj map[string]interface{}, fields ...string) (interface{}, bool, error) {
|
||||
// NestedFieldNoCopy returns a reference to a nested field.
|
||||
// Returns false if value is not found and an error if unable
|
||||
// to traverse obj.
|
||||
func NestedFieldNoCopy(obj map[string]interface{}, fields ...string) (interface{}, bool, error) {
|
||||
var val interface{} = obj
|
||||
|
||||
for i, field := range fields {
|
||||
|
@ -60,7 +63,7 @@ func nestedFieldNoCopy(obj map[string]interface{}, fields ...string) (interface{
|
|||
// NestedString returns the string value of a nested field.
|
||||
// Returns false if value is not found and an error if not a string.
|
||||
func NestedString(obj map[string]interface{}, fields ...string) (string, bool, error) {
|
||||
val, found, err := nestedFieldNoCopy(obj, fields...)
|
||||
val, found, err := NestedFieldNoCopy(obj, fields...)
|
||||
if !found || err != nil {
|
||||
return "", found, err
|
||||
}
|
||||
|
@ -74,7 +77,7 @@ func NestedString(obj map[string]interface{}, fields ...string) (string, bool, e
|
|||
// NestedBool returns the bool value of a nested field.
|
||||
// Returns false if value is not found and an error if not a bool.
|
||||
func NestedBool(obj map[string]interface{}, fields ...string) (bool, bool, error) {
|
||||
val, found, err := nestedFieldNoCopy(obj, fields...)
|
||||
val, found, err := NestedFieldNoCopy(obj, fields...)
|
||||
if !found || err != nil {
|
||||
return false, found, err
|
||||
}
|
||||
|
@ -88,7 +91,7 @@ func NestedBool(obj map[string]interface{}, fields ...string) (bool, bool, error
|
|||
// NestedFloat64 returns the float64 value of a nested field.
|
||||
// Returns false if value is not found and an error if not a float64.
|
||||
func NestedFloat64(obj map[string]interface{}, fields ...string) (float64, bool, error) {
|
||||
val, found, err := nestedFieldNoCopy(obj, fields...)
|
||||
val, found, err := NestedFieldNoCopy(obj, fields...)
|
||||
if !found || err != nil {
|
||||
return 0, found, err
|
||||
}
|
||||
|
@ -102,7 +105,7 @@ func NestedFloat64(obj map[string]interface{}, fields ...string) (float64, bool,
|
|||
// NestedInt64 returns the int64 value of a nested field.
|
||||
// Returns false if value is not found and an error if not an int64.
|
||||
func NestedInt64(obj map[string]interface{}, fields ...string) (int64, bool, error) {
|
||||
val, found, err := nestedFieldNoCopy(obj, fields...)
|
||||
val, found, err := NestedFieldNoCopy(obj, fields...)
|
||||
if !found || err != nil {
|
||||
return 0, found, err
|
||||
}
|
||||
|
@ -116,7 +119,7 @@ func NestedInt64(obj map[string]interface{}, fields ...string) (int64, bool, err
|
|||
// NestedStringSlice returns a copy of []string value of a nested field.
|
||||
// Returns false if value is not found and an error if not a []interface{} or contains non-string items in the slice.
|
||||
func NestedStringSlice(obj map[string]interface{}, fields ...string) ([]string, bool, error) {
|
||||
val, found, err := nestedFieldNoCopy(obj, fields...)
|
||||
val, found, err := NestedFieldNoCopy(obj, fields...)
|
||||
if !found || err != nil {
|
||||
return nil, found, err
|
||||
}
|
||||
|
@ -138,7 +141,7 @@ func NestedStringSlice(obj map[string]interface{}, fields ...string) ([]string,
|
|||
// NestedSlice returns a deep copy of []interface{} value of a nested field.
|
||||
// Returns false if value is not found and an error if not a []interface{}.
|
||||
func NestedSlice(obj map[string]interface{}, fields ...string) ([]interface{}, bool, error) {
|
||||
val, found, err := nestedFieldNoCopy(obj, fields...)
|
||||
val, found, err := NestedFieldNoCopy(obj, fields...)
|
||||
if !found || err != nil {
|
||||
return nil, found, err
|
||||
}
|
||||
|
@ -180,7 +183,7 @@ func NestedMap(obj map[string]interface{}, fields ...string) (map[string]interfa
|
|||
// nestedMapNoCopy returns a map[string]interface{} value of a nested field.
|
||||
// Returns false if value is not found and an error if not a map[string]interface{}.
|
||||
func nestedMapNoCopy(obj map[string]interface{}, fields ...string) (map[string]interface{}, bool, error) {
|
||||
val, found, err := nestedFieldNoCopy(obj, fields...)
|
||||
val, found, err := NestedFieldNoCopy(obj, fields...)
|
||||
if !found || err != nil {
|
||||
return nil, found, err
|
||||
}
|
||||
|
|
|
@ -58,3 +58,79 @@ func TestRemoveNestedField(t *testing.T) {
|
|||
RemoveNestedField(obj, "x") // Remove of a non-existent field
|
||||
assert.Empty(t, obj)
|
||||
}
|
||||
|
||||
func TestNestedFieldNoCopy(t *testing.T) {
|
||||
target := map[string]interface{}{"foo": "bar"}
|
||||
|
||||
obj := map[string]interface{}{
|
||||
"a": map[string]interface{}{
|
||||
"b": target,
|
||||
"c": nil,
|
||||
"d": []interface{}{"foo"},
|
||||
},
|
||||
}
|
||||
|
||||
// case 1: field exists and is non-nil
|
||||
res, exists, err := NestedFieldNoCopy(obj, "a", "b")
|
||||
assert.True(t, exists)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, target, res)
|
||||
target["foo"] = "baz"
|
||||
assert.Equal(t, target["foo"], res.(map[string]interface{})["foo"], "result should be a reference to the expected item")
|
||||
|
||||
// case 2: field exists and is nil
|
||||
res, exists, err = NestedFieldNoCopy(obj, "a", "c")
|
||||
assert.True(t, exists)
|
||||
assert.Nil(t, err)
|
||||
assert.Nil(t, res)
|
||||
|
||||
// case 3: error traversing obj
|
||||
res, exists, err = NestedFieldNoCopy(obj, "a", "d", "foo")
|
||||
assert.False(t, exists)
|
||||
assert.NotNil(t, err)
|
||||
assert.Nil(t, res)
|
||||
|
||||
// case 4: field does not exist
|
||||
res, exists, err = NestedFieldNoCopy(obj, "a", "e")
|
||||
assert.False(t, exists)
|
||||
assert.Nil(t, err)
|
||||
assert.Nil(t, res)
|
||||
}
|
||||
|
||||
func TestNestedFieldCopy(t *testing.T) {
|
||||
target := map[string]interface{}{"foo": "bar"}
|
||||
|
||||
obj := map[string]interface{}{
|
||||
"a": map[string]interface{}{
|
||||
"b": target,
|
||||
"c": nil,
|
||||
"d": []interface{}{"foo"},
|
||||
},
|
||||
}
|
||||
|
||||
// case 1: field exists and is non-nil
|
||||
res, exists, err := NestedFieldCopy(obj, "a", "b")
|
||||
assert.True(t, exists)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, target, res)
|
||||
target["foo"] = "baz"
|
||||
assert.NotEqual(t, target["foo"], res.(map[string]interface{})["foo"], "result should be a copy of the expected item")
|
||||
|
||||
// case 2: field exists and is nil
|
||||
res, exists, err = NestedFieldCopy(obj, "a", "c")
|
||||
assert.True(t, exists)
|
||||
assert.Nil(t, err)
|
||||
assert.Nil(t, res)
|
||||
|
||||
// case 3: error traversing obj
|
||||
res, exists, err = NestedFieldCopy(obj, "a", "d", "foo")
|
||||
assert.False(t, exists)
|
||||
assert.NotNil(t, err)
|
||||
assert.Nil(t, res)
|
||||
|
||||
// case 4: field does not exist
|
||||
res, exists, err = NestedFieldCopy(obj, "a", "e")
|
||||
assert.False(t, exists)
|
||||
assert.Nil(t, err)
|
||||
assert.Nil(t, res)
|
||||
}
|
||||
|
|
|
@ -138,7 +138,7 @@ func (u *Unstructured) setNestedMap(value map[string]string, fields ...string) {
|
|||
}
|
||||
|
||||
func (u *Unstructured) GetOwnerReferences() []metav1.OwnerReference {
|
||||
field, found, err := nestedFieldNoCopy(u.Object, "metadata", "ownerReferences")
|
||||
field, found, err := NestedFieldNoCopy(u.Object, "metadata", "ownerReferences")
|
||||
if !found || err != nil {
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue