github.com/spotmaxtech/k8s-apimachinery-v0260@v0.0.1/pkg/apis/meta/v1/helpers.go (about)

     1  /*
     2  Copyright 2016 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 v1
    18  
    19  import (
    20  	"bytes"
    21  	"encoding/json"
    22  	"errors"
    23  	"fmt"
    24  
    25  	"github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/fields"
    26  	"github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/labels"
    27  	"github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/selection"
    28  	"github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/types"
    29  )
    30  
    31  // LabelSelectorAsSelector converts the LabelSelector api type into a struct that implements
    32  // labels.Selector
    33  // Note: This function should be kept in sync with the selector methods in pkg/labels/selector.go
    34  func LabelSelectorAsSelector(ps *LabelSelector) (labels.Selector, error) {
    35  	if ps == nil {
    36  		return labels.Nothing(), nil
    37  	}
    38  	if len(ps.MatchLabels)+len(ps.MatchExpressions) == 0 {
    39  		return labels.Everything(), nil
    40  	}
    41  	requirements := make([]labels.Requirement, 0, len(ps.MatchLabels)+len(ps.MatchExpressions))
    42  	for k, v := range ps.MatchLabels {
    43  		r, err := labels.NewRequirement(k, selection.Equals, []string{v})
    44  		if err != nil {
    45  			return nil, err
    46  		}
    47  		requirements = append(requirements, *r)
    48  	}
    49  	for _, expr := range ps.MatchExpressions {
    50  		var op selection.Operator
    51  		switch expr.Operator {
    52  		case LabelSelectorOpIn:
    53  			op = selection.In
    54  		case LabelSelectorOpNotIn:
    55  			op = selection.NotIn
    56  		case LabelSelectorOpExists:
    57  			op = selection.Exists
    58  		case LabelSelectorOpDoesNotExist:
    59  			op = selection.DoesNotExist
    60  		default:
    61  			return nil, fmt.Errorf("%q is not a valid label selector operator", expr.Operator)
    62  		}
    63  		r, err := labels.NewRequirement(expr.Key, op, append([]string(nil), expr.Values...))
    64  		if err != nil {
    65  			return nil, err
    66  		}
    67  		requirements = append(requirements, *r)
    68  	}
    69  	selector := labels.NewSelector()
    70  	selector = selector.Add(requirements...)
    71  	return selector, nil
    72  }
    73  
    74  // LabelSelectorAsMap converts the LabelSelector api type into a map of strings, ie. the
    75  // original structure of a label selector. Operators that cannot be converted into plain
    76  // labels (Exists, DoesNotExist, NotIn, and In with more than one value) will result in
    77  // an error.
    78  func LabelSelectorAsMap(ps *LabelSelector) (map[string]string, error) {
    79  	if ps == nil {
    80  		return nil, nil
    81  	}
    82  	selector := map[string]string{}
    83  	for k, v := range ps.MatchLabels {
    84  		selector[k] = v
    85  	}
    86  	for _, expr := range ps.MatchExpressions {
    87  		switch expr.Operator {
    88  		case LabelSelectorOpIn:
    89  			if len(expr.Values) != 1 {
    90  				return selector, fmt.Errorf("operator %q without a single value cannot be converted into the old label selector format", expr.Operator)
    91  			}
    92  			// Should we do anything in case this will override a previous key-value pair?
    93  			selector[expr.Key] = expr.Values[0]
    94  		case LabelSelectorOpNotIn, LabelSelectorOpExists, LabelSelectorOpDoesNotExist:
    95  			return selector, fmt.Errorf("operator %q cannot be converted into the old label selector format", expr.Operator)
    96  		default:
    97  			return selector, fmt.Errorf("%q is not a valid selector operator", expr.Operator)
    98  		}
    99  	}
   100  	return selector, nil
   101  }
   102  
   103  // ParseToLabelSelector parses a string representing a selector into a LabelSelector object.
   104  // Note: This function should be kept in sync with the parser in pkg/labels/selector.go
   105  func ParseToLabelSelector(selector string) (*LabelSelector, error) {
   106  	reqs, err := labels.ParseToRequirements(selector)
   107  	if err != nil {
   108  		return nil, fmt.Errorf("couldn't parse the selector string \"%s\": %v", selector, err)
   109  	}
   110  
   111  	labelSelector := &LabelSelector{
   112  		MatchLabels:      map[string]string{},
   113  		MatchExpressions: []LabelSelectorRequirement{},
   114  	}
   115  	for _, req := range reqs {
   116  		var op LabelSelectorOperator
   117  		switch req.Operator() {
   118  		case selection.Equals, selection.DoubleEquals:
   119  			vals := req.Values()
   120  			if vals.Len() != 1 {
   121  				return nil, fmt.Errorf("equals operator must have exactly one value")
   122  			}
   123  			val, ok := vals.PopAny()
   124  			if !ok {
   125  				return nil, fmt.Errorf("equals operator has exactly one value but it cannot be retrieved")
   126  			}
   127  			labelSelector.MatchLabels[req.Key()] = val
   128  			continue
   129  		case selection.In:
   130  			op = LabelSelectorOpIn
   131  		case selection.NotIn:
   132  			op = LabelSelectorOpNotIn
   133  		case selection.Exists:
   134  			op = LabelSelectorOpExists
   135  		case selection.DoesNotExist:
   136  			op = LabelSelectorOpDoesNotExist
   137  		case selection.GreaterThan, selection.LessThan:
   138  			// Adding a separate case for these operators to indicate that this is deliberate
   139  			return nil, fmt.Errorf("%q isn't supported in label selectors", req.Operator())
   140  		default:
   141  			return nil, fmt.Errorf("%q is not a valid label selector operator", req.Operator())
   142  		}
   143  		labelSelector.MatchExpressions = append(labelSelector.MatchExpressions, LabelSelectorRequirement{
   144  			Key:      req.Key(),
   145  			Operator: op,
   146  			Values:   req.Values().List(),
   147  		})
   148  	}
   149  	return labelSelector, nil
   150  }
   151  
   152  // SetAsLabelSelector converts the labels.Set object into a LabelSelector api object.
   153  func SetAsLabelSelector(ls labels.Set) *LabelSelector {
   154  	if ls == nil {
   155  		return nil
   156  	}
   157  
   158  	selector := &LabelSelector{
   159  		MatchLabels: make(map[string]string, len(ls)),
   160  	}
   161  	for label, value := range ls {
   162  		selector.MatchLabels[label] = value
   163  	}
   164  
   165  	return selector
   166  }
   167  
   168  // FormatLabelSelector convert labelSelector into plain string
   169  func FormatLabelSelector(labelSelector *LabelSelector) string {
   170  	selector, err := LabelSelectorAsSelector(labelSelector)
   171  	if err != nil {
   172  		return "<error>"
   173  	}
   174  
   175  	l := selector.String()
   176  	if len(l) == 0 {
   177  		l = "<none>"
   178  	}
   179  	return l
   180  }
   181  
   182  func ExtractGroupVersions(l *APIGroupList) []string {
   183  	var groupVersions []string
   184  	for _, g := range l.Groups {
   185  		for _, gv := range g.Versions {
   186  			groupVersions = append(groupVersions, gv.GroupVersion)
   187  		}
   188  	}
   189  	return groupVersions
   190  }
   191  
   192  // HasAnnotation returns a bool if passed in annotation exists
   193  func HasAnnotation(obj ObjectMeta, ann string) bool {
   194  	_, found := obj.Annotations[ann]
   195  	return found
   196  }
   197  
   198  // SetMetaDataAnnotation sets the annotation and value
   199  func SetMetaDataAnnotation(obj *ObjectMeta, ann string, value string) {
   200  	if obj.Annotations == nil {
   201  		obj.Annotations = make(map[string]string)
   202  	}
   203  	obj.Annotations[ann] = value
   204  }
   205  
   206  // HasLabel returns a bool if passed in label exists
   207  func HasLabel(obj ObjectMeta, label string) bool {
   208  	_, found := obj.Labels[label]
   209  	return found
   210  }
   211  
   212  // SetMetaDataLabel sets the label and value
   213  func SetMetaDataLabel(obj *ObjectMeta, label string, value string) {
   214  	if obj.Labels == nil {
   215  		obj.Labels = make(map[string]string)
   216  	}
   217  	obj.Labels[label] = value
   218  }
   219  
   220  // SingleObject returns a ListOptions for watching a single object.
   221  func SingleObject(meta ObjectMeta) ListOptions {
   222  	return ListOptions{
   223  		FieldSelector:   fields.OneTermEqualSelector("metadata.name", meta.Name).String(),
   224  		ResourceVersion: meta.ResourceVersion,
   225  	}
   226  }
   227  
   228  // NewDeleteOptions returns a DeleteOptions indicating the resource should
   229  // be deleted within the specified grace period. Use zero to indicate
   230  // immediate deletion. If you would prefer to use the default grace period,
   231  // use &metav1.DeleteOptions{} directly.
   232  func NewDeleteOptions(grace int64) *DeleteOptions {
   233  	return &DeleteOptions{GracePeriodSeconds: &grace}
   234  }
   235  
   236  // NewPreconditionDeleteOptions returns a DeleteOptions with a UID precondition set.
   237  func NewPreconditionDeleteOptions(uid string) *DeleteOptions {
   238  	u := types.UID(uid)
   239  	p := Preconditions{UID: &u}
   240  	return &DeleteOptions{Preconditions: &p}
   241  }
   242  
   243  // NewUIDPreconditions returns a Preconditions with UID set.
   244  func NewUIDPreconditions(uid string) *Preconditions {
   245  	u := types.UID(uid)
   246  	return &Preconditions{UID: &u}
   247  }
   248  
   249  // NewRVDeletionPrecondition returns a DeleteOptions with a ResourceVersion precondition set.
   250  func NewRVDeletionPrecondition(rv string) *DeleteOptions {
   251  	p := Preconditions{ResourceVersion: &rv}
   252  	return &DeleteOptions{Preconditions: &p}
   253  }
   254  
   255  // HasObjectMetaSystemFieldValues returns true if fields that are managed by the system on ObjectMeta have values.
   256  func HasObjectMetaSystemFieldValues(meta Object) bool {
   257  	return !meta.GetCreationTimestamp().Time.IsZero() ||
   258  		len(meta.GetUID()) != 0
   259  }
   260  
   261  // ResetObjectMetaForStatus forces the meta fields for a status update to match the meta fields
   262  // for a pre-existing object. This is opt-in for new objects with Status subresource.
   263  func ResetObjectMetaForStatus(meta, existingMeta Object) {
   264  	meta.SetDeletionTimestamp(existingMeta.GetDeletionTimestamp())
   265  	meta.SetGeneration(existingMeta.GetGeneration())
   266  	meta.SetSelfLink(existingMeta.GetSelfLink())
   267  	meta.SetLabels(existingMeta.GetLabels())
   268  	meta.SetAnnotations(existingMeta.GetAnnotations())
   269  	meta.SetFinalizers(existingMeta.GetFinalizers())
   270  	meta.SetOwnerReferences(existingMeta.GetOwnerReferences())
   271  	// managedFields must be preserved since it's been modified to
   272  	// track changed fields in the status update.
   273  	//meta.SetManagedFields(existingMeta.GetManagedFields())
   274  }
   275  
   276  // MarshalJSON implements json.Marshaler
   277  // MarshalJSON may get called on pointers or values, so implement MarshalJSON on value.
   278  // http://stackoverflow.com/questions/21390979/custom-marshaljson-never-gets-called-in-go
   279  func (f FieldsV1) MarshalJSON() ([]byte, error) {
   280  	if f.Raw == nil {
   281  		return []byte("null"), nil
   282  	}
   283  	return f.Raw, nil
   284  }
   285  
   286  // UnmarshalJSON implements json.Unmarshaler
   287  func (f *FieldsV1) UnmarshalJSON(b []byte) error {
   288  	if f == nil {
   289  		return errors.New("metav1.Fields: UnmarshalJSON on nil pointer")
   290  	}
   291  	if !bytes.Equal(b, []byte("null")) {
   292  		f.Raw = append(f.Raw[0:0], b...)
   293  	}
   294  	return nil
   295  }
   296  
   297  var _ json.Marshaler = FieldsV1{}
   298  var _ json.Unmarshaler = &FieldsV1{}