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