diff --git a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/helpers.go b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/helpers.go index 5c9f1a55509..8d03525474d 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/helpers.go +++ b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/helpers.go @@ -138,35 +138,40 @@ func NestedSlice(obj map[string]interface{}, fields ...string) ([]interface{}, b // NestedStringMap returns a copy of map[string]string value of a nested field. // Returns false if value is not found, is not a map[string]interface{} or contains non-string values in the map. func NestedStringMap(obj map[string]interface{}, fields ...string) (map[string]string, bool) { - val, ok := nestedFieldNoCopy(obj, fields...) + m, ok := nestedMapNoCopy(obj, fields...) if !ok { return nil, false } - if m, ok := val.(map[string]interface{}); ok { - strMap := make(map[string]string, len(m)) - for k, v := range m { - if str, ok := v.(string); ok { - strMap[k] = str - } else { - return nil, false - } + strMap := make(map[string]string, len(m)) + for k, v := range m { + if str, ok := v.(string); ok { + strMap[k] = str + } else { + return nil, false } - return strMap, true } - return nil, false + return strMap, true } // NestedMap returns a deep copy of map[string]interface{} value of a nested field. // Returns false if value is not found or is not a map[string]interface{}. func NestedMap(obj map[string]interface{}, fields ...string) (map[string]interface{}, bool) { + m, ok := nestedMapNoCopy(obj, fields...) + if !ok { + return nil, false + } + return runtime.DeepCopyJSON(m), true +} + +// nestedMapNoCopy returns a map[string]interface{} value of a nested field. +// Returns false if value is not found or is not a map[string]interface{}. +func nestedMapNoCopy(obj map[string]interface{}, fields ...string) (map[string]interface{}, bool) { val, ok := nestedFieldNoCopy(obj, fields...) if !ok { return nil, false } - if m, ok := val.(map[string]interface{}); ok { - return runtime.DeepCopyJSON(m), true - } - return nil, false + m, ok := val.(map[string]interface{}) + return m, ok } // SetNestedField sets the value of a nested field to a deep copy of the value provided. @@ -268,25 +273,6 @@ func extractOwnerReference(v map[string]interface{}) metav1.OwnerReference { } } -func setOwnerReference(src metav1.OwnerReference) map[string]interface{} { - ret := map[string]interface{}{ - "kind": src.Kind, - "name": src.Name, - "apiVersion": src.APIVersion, - "uid": string(src.UID), - } - // 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 { - ret["controller"] = *src.Controller - } - if src.BlockOwnerDeletion != nil { - ret["blockOwnerDeletion"] = *src.BlockOwnerDeletion - } - return ret -} - // UnstructuredJSONScheme is capable of converting JSON data into the Unstructured // type, which can be used for generic access to objects without a predefined scheme. // TODO: move into serializer/json. @@ -444,7 +430,7 @@ func (UnstructuredObjectConverter) Convert(in, out, context interface{}) error { // maybe deep copy the map? It is documented in the // ObjectConverter interface that this function is not - // guaranteeed to not mutate the input. Or maybe set the input + // guaranteed to not mutate the input. Or maybe set the input // object to nil. unstructOut.Object = unstructIn.Object return nil diff --git a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured.go b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured.go index 2ee7dad0e20..36e769bd602 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured.go +++ b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured.go @@ -18,6 +18,7 @@ package unstructured import ( "bytes" + "errors" "fmt" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -50,29 +51,27 @@ var _ runtime.Unstructured = &Unstructured{} func (obj *Unstructured) GetObjectKind() schema.ObjectKind { return obj } func (obj *Unstructured) IsList() bool { - if obj.Object != nil { - _, ok := obj.Object["items"] - return ok + field, ok := obj.Object["items"] + if !ok { + return false } - return false + _, ok = field.([]interface{}) + return ok } func (obj *Unstructured) EachListItem(fn func(runtime.Object) error) error { - if obj.Object == nil { - return fmt.Errorf("content is not a list") - } field, ok := obj.Object["items"] if !ok { - return fmt.Errorf("content is not a list") + return errors.New("content is not a list") } items, ok := field.([]interface{}) if !ok { - return nil + return fmt.Errorf("content is not a list: %T", field) } for _, item := range items { child, ok := item.(map[string]interface{}) if !ok { - return fmt.Errorf("items member is not an object") + return fmt.Errorf("items member is not an object: %T", child) } if err := fn(&Unstructured{Object: child}); err != nil { return err @@ -162,7 +161,12 @@ func (u *Unstructured) GetOwnerReferences() []metav1.OwnerReference { func (u *Unstructured) SetOwnerReferences(references []metav1.OwnerReference) { newReferences := make([]interface{}, 0, len(references)) for _, reference := range references { - newReferences = append(newReferences, setOwnerReference(reference)) + out, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&reference) + if err != nil { + utilruntime.HandleError(fmt.Errorf("unable to convert Owner Reference: %v", err)) + continue + } + newReferences = append(newReferences, out) } u.setNestedField(newReferences, "metadata", "ownerReferences") } @@ -301,10 +305,7 @@ func (u *Unstructured) SetDeletionGracePeriodSeconds(deletionGracePeriodSeconds } func (u *Unstructured) GetLabels() map[string]string { - m, ok := NestedStringMap(u.Object, "metadata", "labels") - if !ok { - return nil - } + m, _ := NestedStringMap(u.Object, "metadata", "labels") return m } @@ -313,10 +314,7 @@ func (u *Unstructured) SetLabels(labels map[string]string) { } func (u *Unstructured) GetAnnotations() map[string]string { - m, ok := NestedStringMap(u.Object, "metadata", "annotations") - if !ok { - return nil - } + m, _ := NestedStringMap(u.Object, "metadata", "annotations") return m } @@ -339,18 +337,14 @@ func (u *Unstructured) GroupVersionKind() schema.GroupVersionKind { } func (u *Unstructured) GetInitializers() *metav1.Initializers { - field, ok := nestedFieldNoCopy(u.Object, "metadata", "initializers") + m, ok := nestedMapNoCopy(u.Object, "metadata", "initializers") if !ok { return nil } - obj, ok := field.(map[string]interface{}) - if !ok { - // expected map[string]interface{}, got something else - return nil - } out := &metav1.Initializers{} - if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj, out); err != nil { + if err := runtime.DefaultUnstructuredConverter.FromUnstructured(m, out); err != nil { utilruntime.HandleError(fmt.Errorf("unable to retrieve initializers for object: %v", err)) + return nil } return out } @@ -368,10 +362,7 @@ func (u *Unstructured) SetInitializers(initializers *metav1.Initializers) { } func (u *Unstructured) GetFinalizers() []string { - val, ok := NestedStringSlice(u.Object, "metadata", "finalizers") - if !ok { - return nil - } + val, _ := NestedStringSlice(u.Object, "metadata", "finalizers") return val }