mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	Fix round-trip of Unstructured.OwnerReferences
Previously setOwnerReference was storing pointers but extractOwnerReference is expecting pointer fields as plain values. Fixes #46817
This commit is contained in:
		@@ -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{}{
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user