Change:
Kubernetes version Code from master. What happened: does not return and fields after they are set to non-nil values using . How to reproduce it (as minimally and precisely as possible): See PR
/sig api-machinery
This is a good find and I don't think I saw the notification come through :(

Discussion:
import ( "fmt" "reflect" <ins> "strconv" </ins> "strings" "testing" "time"

}, "ownerReferences": []map[string]interface{}{ { <del> "kind":               "Pod", "name":               "poda", "apiVersion":         "v1", "uid":                "1", "controller":         (*bool)(nil), "blockOwnerDeletion": (*bool)(nil), </del> <ins> "kind":       "Pod", "name":       "poda", "apiVersion": "v1", "uid":        "1", </ins> }, { "kind":               "Pod", "name":               "podb", "apiVersion":         "v1", "uid":                "2", <del> "controller":         &trueVar, "blockOwnerDeletion": &trueVar, </del> <ins> "controller":         true, "blockOwnerDeletion": true, </ins> }, }, "finalizers": []interface{}{

} } <ins> 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) } }) } } </ins> func TestUnstructuredListGetters(t *testing.T) { unstruct := unstructured.UnstructuredList{ Object: map[string]interface{}{

func setOwnerReference(src metav1.OwnerReference) map[string]interface{} { ret := make(map[string]interface{}) <del> controllerPtr := src.Controller if controllerPtr != nil { controller := *controllerPtr controllerPtr = &controller } blockOwnerDeletionPtr := src.BlockOwnerDeletion if blockOwnerDeletionPtr != nil { blockOwnerDeletion := *blockOwnerDeletionPtr blockOwnerDeletionPtr = &blockOwnerDeletion } </del> setNestedField(ret, src.Kind, "kind") setNestedField(ret, src.Name, "name") setNestedField(ret, src.APIVersion, "apiVersion") setNestedField(ret, string(src.UID), "uid") <del> setNestedField(ret, controllerPtr, "controller") setNestedField(ret, blockOwnerDeletionPtr, "blockOwnerDeletion") </del> <ins> // 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") } </ins> return ret }