Unstructured cleanups

This commit is contained in:
Mikhail Mazurskiy 2017-11-19 19:12:26 +11:00
parent d52d160239
commit 160cf97fa4
No known key found for this signature in database
GPG Key ID: 93551ECC96E2F568
2 changed files with 42 additions and 65 deletions

View File

@ -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

View File

@ -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
}