Fix round-trip of Unstructured.OwnerReferences

Previously setOwnerReference was storing pointers but
extractOwnerReference is expecting pointer fields as plain values.
Fixes #46817
pull/6/head
Mikhail Mazurskiy 2017-06-02 11:13:33 +10:00
parent b9e8d2aee6
commit 427b8cd40b
No known key found for this signature in database
GPG Key ID: 93551ECC96E2F568
2 changed files with 62 additions and 20 deletions

View File

@ -19,6 +19,7 @@ package tests
import (
"fmt"
"reflect"
"strconv"
"strings"
"testing"
"time"
@ -270,20 +271,18 @@ func TestUnstructuredSetters(t *testing.T) {
},
"ownerReferences": []map[string]interface{}{
{
"kind": "Pod",
"name": "poda",
"apiVersion": "v1",
"uid": "1",
"controller": (*bool)(nil),
"blockOwnerDeletion": (*bool)(nil),
"kind": "Pod",
"name": "poda",
"apiVersion": "v1",
"uid": "1",
},
{
"kind": "Pod",
"name": "podb",
"apiVersion": "v1",
"uid": "2",
"controller": &trueVar,
"blockOwnerDeletion": &trueVar,
"controller": true,
"blockOwnerDeletion": true,
},
},
"finalizers": []interface{}{
@ -333,6 +332,52 @@ func TestUnstructuredSetters(t *testing.T) {
}
}
func TestOwnerReferences(t *testing.T) {
t.Parallel()
trueVar := true
falseVar := false
refs := []metav1.OwnerReference{
{
APIVersion: "v2",
Kind: "K2",
Name: "n2",
UID: types.UID("abc1"),
},
{
APIVersion: "v1",
Kind: "K1",
Name: "n1",
UID: types.UID("abc2"),
Controller: &trueVar,
BlockOwnerDeletion: &falseVar,
},
{
APIVersion: "v3",
Kind: "K3",
Name: "n3",
UID: types.UID("abc3"),
Controller: &falseVar,
BlockOwnerDeletion: &trueVar,
},
}
for i, ref := range refs {
ref := ref
t.Run(strconv.Itoa(i), func(t *testing.T) {
t.Parallel()
u1 := unstructured.Unstructured{
Object: make(map[string]interface{}),
}
refsX := []metav1.OwnerReference{ref}
u1.SetOwnerReferences(refsX)
have := u1.GetOwnerReferences()
if !reflect.DeepEqual(have, refsX) {
t.Errorf("Object references are not the same: %#v != %#v", have, refsX)
}
})
}
}
func TestUnstructuredListGetters(t *testing.T) {
unstruct := unstructured.UnstructuredList{
Object: map[string]interface{}{

View File

@ -248,22 +248,19 @@ func extractOwnerReference(src interface{}) metav1.OwnerReference {
func setOwnerReference(src metav1.OwnerReference) map[string]interface{} {
ret := make(map[string]interface{})
controllerPtr := src.Controller
if controllerPtr != nil {
controller := *controllerPtr
controllerPtr = &controller
}
blockOwnerDeletionPtr := src.BlockOwnerDeletion
if blockOwnerDeletionPtr != nil {
blockOwnerDeletion := *blockOwnerDeletionPtr
blockOwnerDeletionPtr = &blockOwnerDeletion
}
setNestedField(ret, src.Kind, "kind")
setNestedField(ret, src.Name, "name")
setNestedField(ret, src.APIVersion, "apiVersion")
setNestedField(ret, string(src.UID), "uid")
setNestedField(ret, controllerPtr, "controller")
setNestedField(ret, blockOwnerDeletionPtr, "blockOwnerDeletion")
// json.Unmarshal() extracts boolean json fields as bool, not as *bool and hence extractOwnerReference()
// expects bool or a missing field, not *bool. So if pointer is nil, fields are omitted from the ret object.
// If pointer is non-nil, they are set to the referenced value.
if src.Controller != nil {
setNestedField(ret, *src.Controller, "controller")
}
if src.BlockOwnerDeletion != nil {
setNestedField(ret, *src.BlockOwnerDeletion, "blockOwnerDeletion")
}
return ret
}