...

Source file src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured.go

Documentation: k8s.io/apimachinery/pkg/apis/meta/v1/unstructured

     1  /*
     2  Copyright 2015 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package unstructured
    18  
    19  import (
    20  	"bytes"
    21  	"errors"
    22  	"fmt"
    23  
    24  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    25  	"k8s.io/apimachinery/pkg/runtime"
    26  	"k8s.io/apimachinery/pkg/runtime/schema"
    27  	"k8s.io/apimachinery/pkg/types"
    28  	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
    29  )
    30  
    31  // Unstructured allows objects that do not have Golang structs registered to be manipulated
    32  // generically. This can be used to deal with the API objects from a plug-in. Unstructured
    33  // objects still have functioning TypeMeta features-- kind, version, etc.
    34  //
    35  // WARNING: This object has accessors for the v1 standard metadata. You *MUST NOT* use this
    36  // type if you are dealing with objects that are not in the server meta v1 schema.
    37  //
    38  // TODO: make the serialization part of this type distinct from the field accessors.
    39  // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
    40  // +k8s:deepcopy-gen=true
    41  type Unstructured struct {
    42  	// Object is a JSON compatible map with string, float, int, bool, []interface{}, or
    43  	// map[string]interface{}
    44  	// children.
    45  	Object map[string]interface{}
    46  }
    47  
    48  var _ metav1.Object = &Unstructured{}
    49  var _ runtime.Unstructured = &Unstructured{}
    50  var _ metav1.ListInterface = &Unstructured{}
    51  
    52  func (obj *Unstructured) GetObjectKind() schema.ObjectKind { return obj }
    53  
    54  func (obj *Unstructured) IsList() bool {
    55  	field, ok := obj.Object["items"]
    56  	if !ok {
    57  		return false
    58  	}
    59  	_, ok = field.([]interface{})
    60  	return ok
    61  }
    62  func (obj *Unstructured) ToList() (*UnstructuredList, error) {
    63  	if !obj.IsList() {
    64  		// return an empty list back
    65  		return &UnstructuredList{Object: obj.Object}, nil
    66  	}
    67  
    68  	ret := &UnstructuredList{}
    69  	ret.Object = obj.Object
    70  
    71  	err := obj.EachListItem(func(item runtime.Object) error {
    72  		castItem := item.(*Unstructured)
    73  		ret.Items = append(ret.Items, *castItem)
    74  		return nil
    75  	})
    76  	if err != nil {
    77  		return nil, err
    78  	}
    79  
    80  	return ret, nil
    81  }
    82  
    83  func (obj *Unstructured) EachListItem(fn func(runtime.Object) error) error {
    84  	field, ok := obj.Object["items"]
    85  	if !ok {
    86  		return errors.New("content is not a list")
    87  	}
    88  	items, ok := field.([]interface{})
    89  	if !ok {
    90  		return fmt.Errorf("content is not a list: %T", field)
    91  	}
    92  	for _, item := range items {
    93  		child, ok := item.(map[string]interface{})
    94  		if !ok {
    95  			return fmt.Errorf("items member is not an object: %T", child)
    96  		}
    97  		if err := fn(&Unstructured{Object: child}); err != nil {
    98  			return err
    99  		}
   100  	}
   101  	return nil
   102  }
   103  
   104  func (obj *Unstructured) EachListItemWithAlloc(fn func(runtime.Object) error) error {
   105  	// EachListItem has allocated a new Object for the user, we can use it directly.
   106  	return obj.EachListItem(fn)
   107  }
   108  
   109  func (obj *Unstructured) UnstructuredContent() map[string]interface{} {
   110  	if obj.Object == nil {
   111  		return make(map[string]interface{})
   112  	}
   113  	return obj.Object
   114  }
   115  
   116  func (obj *Unstructured) SetUnstructuredContent(content map[string]interface{}) {
   117  	obj.Object = content
   118  }
   119  
   120  // MarshalJSON ensures that the unstructured object produces proper
   121  // JSON when passed to Go's standard JSON library.
   122  func (u *Unstructured) MarshalJSON() ([]byte, error) {
   123  	var buf bytes.Buffer
   124  	err := UnstructuredJSONScheme.Encode(u, &buf)
   125  	return buf.Bytes(), err
   126  }
   127  
   128  // UnmarshalJSON ensures that the unstructured object properly decodes
   129  // JSON when passed to Go's standard JSON library.
   130  func (u *Unstructured) UnmarshalJSON(b []byte) error {
   131  	_, _, err := UnstructuredJSONScheme.Decode(b, nil, u)
   132  	return err
   133  }
   134  
   135  // NewEmptyInstance returns a new instance of the concrete type containing only kind/apiVersion and no other data.
   136  // This should be called instead of reflect.New() for unstructured types because the go type alone does not preserve kind/apiVersion info.
   137  func (in *Unstructured) NewEmptyInstance() runtime.Unstructured {
   138  	out := new(Unstructured)
   139  	if in != nil {
   140  		out.GetObjectKind().SetGroupVersionKind(in.GetObjectKind().GroupVersionKind())
   141  	}
   142  	return out
   143  }
   144  
   145  func (in *Unstructured) DeepCopy() *Unstructured {
   146  	if in == nil {
   147  		return nil
   148  	}
   149  	out := new(Unstructured)
   150  	*out = *in
   151  	out.Object = runtime.DeepCopyJSON(in.Object)
   152  	return out
   153  }
   154  
   155  func (u *Unstructured) setNestedField(value interface{}, fields ...string) {
   156  	if u.Object == nil {
   157  		u.Object = make(map[string]interface{})
   158  	}
   159  	SetNestedField(u.Object, value, fields...)
   160  }
   161  
   162  func (u *Unstructured) setNestedStringSlice(value []string, fields ...string) {
   163  	if u.Object == nil {
   164  		u.Object = make(map[string]interface{})
   165  	}
   166  	SetNestedStringSlice(u.Object, value, fields...)
   167  }
   168  
   169  func (u *Unstructured) setNestedSlice(value []interface{}, fields ...string) {
   170  	if u.Object == nil {
   171  		u.Object = make(map[string]interface{})
   172  	}
   173  	SetNestedSlice(u.Object, value, fields...)
   174  }
   175  
   176  func (u *Unstructured) setNestedMap(value map[string]string, fields ...string) {
   177  	if u.Object == nil {
   178  		u.Object = make(map[string]interface{})
   179  	}
   180  	SetNestedStringMap(u.Object, value, fields...)
   181  }
   182  
   183  func (u *Unstructured) GetOwnerReferences() []metav1.OwnerReference {
   184  	field, found, err := NestedFieldNoCopy(u.Object, "metadata", "ownerReferences")
   185  	if !found || err != nil {
   186  		return nil
   187  	}
   188  	original, ok := field.([]interface{})
   189  	if !ok {
   190  		return nil
   191  	}
   192  	ret := make([]metav1.OwnerReference, 0, len(original))
   193  	for _, obj := range original {
   194  		o, ok := obj.(map[string]interface{})
   195  		if !ok {
   196  			// expected map[string]interface{}, got something else
   197  			return nil
   198  		}
   199  		ret = append(ret, extractOwnerReference(o))
   200  	}
   201  	return ret
   202  }
   203  
   204  func (u *Unstructured) SetOwnerReferences(references []metav1.OwnerReference) {
   205  	if references == nil {
   206  		RemoveNestedField(u.Object, "metadata", "ownerReferences")
   207  		return
   208  	}
   209  
   210  	newReferences := make([]interface{}, 0, len(references))
   211  	for _, reference := range references {
   212  		out, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&reference)
   213  		if err != nil {
   214  			utilruntime.HandleError(fmt.Errorf("unable to convert Owner Reference: %v", err))
   215  			continue
   216  		}
   217  		newReferences = append(newReferences, out)
   218  	}
   219  	u.setNestedField(newReferences, "metadata", "ownerReferences")
   220  }
   221  
   222  func (u *Unstructured) GetAPIVersion() string {
   223  	return getNestedString(u.Object, "apiVersion")
   224  }
   225  
   226  func (u *Unstructured) SetAPIVersion(version string) {
   227  	u.setNestedField(version, "apiVersion")
   228  }
   229  
   230  func (u *Unstructured) GetKind() string {
   231  	return getNestedString(u.Object, "kind")
   232  }
   233  
   234  func (u *Unstructured) SetKind(kind string) {
   235  	u.setNestedField(kind, "kind")
   236  }
   237  
   238  func (u *Unstructured) GetNamespace() string {
   239  	return getNestedString(u.Object, "metadata", "namespace")
   240  }
   241  
   242  func (u *Unstructured) SetNamespace(namespace string) {
   243  	if len(namespace) == 0 {
   244  		RemoveNestedField(u.Object, "metadata", "namespace")
   245  		return
   246  	}
   247  	u.setNestedField(namespace, "metadata", "namespace")
   248  }
   249  
   250  func (u *Unstructured) GetName() string {
   251  	return getNestedString(u.Object, "metadata", "name")
   252  }
   253  
   254  func (u *Unstructured) SetName(name string) {
   255  	if len(name) == 0 {
   256  		RemoveNestedField(u.Object, "metadata", "name")
   257  		return
   258  	}
   259  	u.setNestedField(name, "metadata", "name")
   260  }
   261  
   262  func (u *Unstructured) GetGenerateName() string {
   263  	return getNestedString(u.Object, "metadata", "generateName")
   264  }
   265  
   266  func (u *Unstructured) SetGenerateName(generateName string) {
   267  	if len(generateName) == 0 {
   268  		RemoveNestedField(u.Object, "metadata", "generateName")
   269  		return
   270  	}
   271  	u.setNestedField(generateName, "metadata", "generateName")
   272  }
   273  
   274  func (u *Unstructured) GetUID() types.UID {
   275  	return types.UID(getNestedString(u.Object, "metadata", "uid"))
   276  }
   277  
   278  func (u *Unstructured) SetUID(uid types.UID) {
   279  	if len(string(uid)) == 0 {
   280  		RemoveNestedField(u.Object, "metadata", "uid")
   281  		return
   282  	}
   283  	u.setNestedField(string(uid), "metadata", "uid")
   284  }
   285  
   286  func (u *Unstructured) GetResourceVersion() string {
   287  	return getNestedString(u.Object, "metadata", "resourceVersion")
   288  }
   289  
   290  func (u *Unstructured) SetResourceVersion(resourceVersion string) {
   291  	if len(resourceVersion) == 0 {
   292  		RemoveNestedField(u.Object, "metadata", "resourceVersion")
   293  		return
   294  	}
   295  	u.setNestedField(resourceVersion, "metadata", "resourceVersion")
   296  }
   297  
   298  func (u *Unstructured) GetGeneration() int64 {
   299  	val, found, err := NestedInt64(u.Object, "metadata", "generation")
   300  	if !found || err != nil {
   301  		return 0
   302  	}
   303  	return val
   304  }
   305  
   306  func (u *Unstructured) SetGeneration(generation int64) {
   307  	if generation == 0 {
   308  		RemoveNestedField(u.Object, "metadata", "generation")
   309  		return
   310  	}
   311  	u.setNestedField(generation, "metadata", "generation")
   312  }
   313  
   314  func (u *Unstructured) GetSelfLink() string {
   315  	return getNestedString(u.Object, "metadata", "selfLink")
   316  }
   317  
   318  func (u *Unstructured) SetSelfLink(selfLink string) {
   319  	if len(selfLink) == 0 {
   320  		RemoveNestedField(u.Object, "metadata", "selfLink")
   321  		return
   322  	}
   323  	u.setNestedField(selfLink, "metadata", "selfLink")
   324  }
   325  
   326  func (u *Unstructured) GetContinue() string {
   327  	return getNestedString(u.Object, "metadata", "continue")
   328  }
   329  
   330  func (u *Unstructured) SetContinue(c string) {
   331  	if len(c) == 0 {
   332  		RemoveNestedField(u.Object, "metadata", "continue")
   333  		return
   334  	}
   335  	u.setNestedField(c, "metadata", "continue")
   336  }
   337  
   338  func (u *Unstructured) GetRemainingItemCount() *int64 {
   339  	return getNestedInt64Pointer(u.Object, "metadata", "remainingItemCount")
   340  }
   341  
   342  func (u *Unstructured) SetRemainingItemCount(c *int64) {
   343  	if c == nil {
   344  		RemoveNestedField(u.Object, "metadata", "remainingItemCount")
   345  	} else {
   346  		u.setNestedField(*c, "metadata", "remainingItemCount")
   347  	}
   348  }
   349  
   350  func (u *Unstructured) GetCreationTimestamp() metav1.Time {
   351  	var timestamp metav1.Time
   352  	timestamp.UnmarshalQueryParameter(getNestedString(u.Object, "metadata", "creationTimestamp"))
   353  	return timestamp
   354  }
   355  
   356  func (u *Unstructured) SetCreationTimestamp(timestamp metav1.Time) {
   357  	ts, _ := timestamp.MarshalQueryParameter()
   358  	if len(ts) == 0 || timestamp.Time.IsZero() {
   359  		RemoveNestedField(u.Object, "metadata", "creationTimestamp")
   360  		return
   361  	}
   362  	u.setNestedField(ts, "metadata", "creationTimestamp")
   363  }
   364  
   365  func (u *Unstructured) GetDeletionTimestamp() *metav1.Time {
   366  	var timestamp metav1.Time
   367  	timestamp.UnmarshalQueryParameter(getNestedString(u.Object, "metadata", "deletionTimestamp"))
   368  	if timestamp.IsZero() {
   369  		return nil
   370  	}
   371  	return &timestamp
   372  }
   373  
   374  func (u *Unstructured) SetDeletionTimestamp(timestamp *metav1.Time) {
   375  	if timestamp == nil {
   376  		RemoveNestedField(u.Object, "metadata", "deletionTimestamp")
   377  		return
   378  	}
   379  	ts, _ := timestamp.MarshalQueryParameter()
   380  	u.setNestedField(ts, "metadata", "deletionTimestamp")
   381  }
   382  
   383  func (u *Unstructured) GetDeletionGracePeriodSeconds() *int64 {
   384  	val, found, err := NestedInt64(u.Object, "metadata", "deletionGracePeriodSeconds")
   385  	if !found || err != nil {
   386  		return nil
   387  	}
   388  	return &val
   389  }
   390  
   391  func (u *Unstructured) SetDeletionGracePeriodSeconds(deletionGracePeriodSeconds *int64) {
   392  	if deletionGracePeriodSeconds == nil {
   393  		RemoveNestedField(u.Object, "metadata", "deletionGracePeriodSeconds")
   394  		return
   395  	}
   396  	u.setNestedField(*deletionGracePeriodSeconds, "metadata", "deletionGracePeriodSeconds")
   397  }
   398  
   399  func (u *Unstructured) GetLabels() map[string]string {
   400  	m, _, _ := NestedStringMap(u.Object, "metadata", "labels")
   401  	return m
   402  }
   403  
   404  func (u *Unstructured) SetLabels(labels map[string]string) {
   405  	if labels == nil {
   406  		RemoveNestedField(u.Object, "metadata", "labels")
   407  		return
   408  	}
   409  	u.setNestedMap(labels, "metadata", "labels")
   410  }
   411  
   412  func (u *Unstructured) GetAnnotations() map[string]string {
   413  	m, _, _ := NestedStringMap(u.Object, "metadata", "annotations")
   414  	return m
   415  }
   416  
   417  func (u *Unstructured) SetAnnotations(annotations map[string]string) {
   418  	if annotations == nil {
   419  		RemoveNestedField(u.Object, "metadata", "annotations")
   420  		return
   421  	}
   422  	u.setNestedMap(annotations, "metadata", "annotations")
   423  }
   424  
   425  func (u *Unstructured) SetGroupVersionKind(gvk schema.GroupVersionKind) {
   426  	u.SetAPIVersion(gvk.GroupVersion().String())
   427  	u.SetKind(gvk.Kind)
   428  }
   429  
   430  func (u *Unstructured) GroupVersionKind() schema.GroupVersionKind {
   431  	gv, err := schema.ParseGroupVersion(u.GetAPIVersion())
   432  	if err != nil {
   433  		return schema.GroupVersionKind{}
   434  	}
   435  	gvk := gv.WithKind(u.GetKind())
   436  	return gvk
   437  }
   438  
   439  func (u *Unstructured) GetFinalizers() []string {
   440  	val, _, _ := NestedStringSlice(u.Object, "metadata", "finalizers")
   441  	return val
   442  }
   443  
   444  func (u *Unstructured) SetFinalizers(finalizers []string) {
   445  	if finalizers == nil {
   446  		RemoveNestedField(u.Object, "metadata", "finalizers")
   447  		return
   448  	}
   449  	u.setNestedStringSlice(finalizers, "metadata", "finalizers")
   450  }
   451  
   452  func (u *Unstructured) GetManagedFields() []metav1.ManagedFieldsEntry {
   453  	items, found, err := NestedSlice(u.Object, "metadata", "managedFields")
   454  	if !found || err != nil {
   455  		return nil
   456  	}
   457  	managedFields := []metav1.ManagedFieldsEntry{}
   458  	for _, item := range items {
   459  		m, ok := item.(map[string]interface{})
   460  		if !ok {
   461  			utilruntime.HandleError(fmt.Errorf("unable to retrieve managedFields for object, item %v is not a map", item))
   462  			return nil
   463  		}
   464  		out := metav1.ManagedFieldsEntry{}
   465  		if err := runtime.DefaultUnstructuredConverter.FromUnstructured(m, &out); err != nil {
   466  			utilruntime.HandleError(fmt.Errorf("unable to retrieve managedFields for object: %v", err))
   467  			return nil
   468  		}
   469  		managedFields = append(managedFields, out)
   470  	}
   471  	return managedFields
   472  }
   473  
   474  func (u *Unstructured) SetManagedFields(managedFields []metav1.ManagedFieldsEntry) {
   475  	if managedFields == nil {
   476  		RemoveNestedField(u.Object, "metadata", "managedFields")
   477  		return
   478  	}
   479  	items := []interface{}{}
   480  	for _, managedFieldsEntry := range managedFields {
   481  		out, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&managedFieldsEntry)
   482  		if err != nil {
   483  			utilruntime.HandleError(fmt.Errorf("unable to set managedFields for object: %v", err))
   484  			return
   485  		}
   486  		items = append(items, out)
   487  	}
   488  	u.setNestedSlice(items, "metadata", "managedFields")
   489  }
   490  

View as plain text