github.com/aclisp/heapster@v0.19.2-0.20160613100040-51756f899a96/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/meta/meta.go (about) 1 /* 2 Copyright 2014 The Kubernetes Authors All rights reserved. 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 meta 18 19 import ( 20 "fmt" 21 "reflect" 22 23 "k8s.io/kubernetes/pkg/api/unversioned" 24 "k8s.io/kubernetes/pkg/conversion" 25 "k8s.io/kubernetes/pkg/runtime" 26 "k8s.io/kubernetes/pkg/types" 27 28 "github.com/golang/glog" 29 ) 30 31 // Accessor takes an arbitrary object pointer and returns meta.Interface. 32 // obj must be a pointer to an API type. An error is returned if the minimum 33 // required fields are missing. Fields that are not required return the default 34 // value and are a no-op if set. 35 func Accessor(obj interface{}) (Object, error) { 36 if oi, ok := obj.(ObjectMetaAccessor); ok { 37 if om := oi.GetObjectMeta(); om != nil { 38 return om, nil 39 } 40 } 41 // we may get passed an object that is directly portable to Object 42 if oi, ok := obj.(Object); ok { 43 return oi, nil 44 } 45 46 glog.V(4).Infof("Calling Accessor on non-internal object: %v", reflect.TypeOf(obj)) 47 // legacy path for objects that do not implement Object and ObjectMetaAccessor via 48 // reflection - very slow code path. 49 v, err := conversion.EnforcePtr(obj) 50 if err != nil { 51 return nil, err 52 } 53 t := v.Type() 54 if v.Kind() != reflect.Struct { 55 return nil, fmt.Errorf("expected struct, but got %v: %v (%#v)", v.Kind(), t, v.Interface()) 56 } 57 58 typeMeta := v.FieldByName("TypeMeta") 59 if !typeMeta.IsValid() { 60 return nil, fmt.Errorf("struct %v lacks embedded TypeMeta type", t) 61 } 62 63 a := &genericAccessor{} 64 if err := extractFromTypeMeta(typeMeta, a); err != nil { 65 return nil, fmt.Errorf("unable to find type fields on %#v: %v", typeMeta, err) 66 } 67 68 objectMeta := v.FieldByName("ObjectMeta") 69 if objectMeta.IsValid() { 70 // look for the ObjectMeta fields 71 if err := extractFromObjectMeta(objectMeta, a); err != nil { 72 return nil, fmt.Errorf("unable to find object fields on %#v: %v", objectMeta, err) 73 } 74 } else { 75 listMeta := v.FieldByName("ListMeta") 76 if listMeta.IsValid() { 77 // look for the ListMeta fields 78 if err := extractFromListMeta(listMeta, a); err != nil { 79 return nil, fmt.Errorf("unable to find list fields on %#v: %v", listMeta, err) 80 } 81 } else { 82 // look for the older TypeMeta with all metadata 83 if err := extractFromObjectMeta(typeMeta, a); err != nil { 84 return nil, fmt.Errorf("unable to find object fields on %#v: %v", typeMeta, err) 85 } 86 } 87 } 88 89 return a, nil 90 } 91 92 // TypeAccessor returns an interface that allows retrieving and modifying the APIVersion 93 // and Kind of an in-memory internal object. 94 // TODO: this interface is used to test code that does not have ObjectMeta or ListMeta 95 // in round tripping (objects which can use apiVersion/kind, but do not fit the Kube 96 // api conventions). 97 func TypeAccessor(obj interface{}) (Type, error) { 98 if typed, ok := obj.(runtime.Object); ok { 99 return objectAccessor{typed}, nil 100 } 101 v, err := conversion.EnforcePtr(obj) 102 if err != nil { 103 return nil, err 104 } 105 t := v.Type() 106 if v.Kind() != reflect.Struct { 107 return nil, fmt.Errorf("expected struct, but got %v: %v (%#v)", v.Kind(), t, v.Interface()) 108 } 109 110 typeMeta := v.FieldByName("TypeMeta") 111 if !typeMeta.IsValid() { 112 return nil, fmt.Errorf("struct %v lacks embedded TypeMeta type", t) 113 } 114 a := &genericAccessor{} 115 if err := extractFromTypeMeta(typeMeta, a); err != nil { 116 return nil, fmt.Errorf("unable to find type fields on %#v: %v", typeMeta, err) 117 } 118 return a, nil 119 } 120 121 type objectAccessor struct { 122 runtime.Object 123 } 124 125 func (obj objectAccessor) GetKind() string { 126 return obj.GetObjectKind().GroupVersionKind().Kind 127 } 128 129 func (obj objectAccessor) SetKind(kind string) { 130 gvk := obj.GetObjectKind().GroupVersionKind() 131 gvk.Kind = kind 132 obj.GetObjectKind().SetGroupVersionKind(gvk) 133 } 134 135 func (obj objectAccessor) GetAPIVersion() string { 136 return obj.GetObjectKind().GroupVersionKind().GroupVersion().String() 137 } 138 139 func (obj objectAccessor) SetAPIVersion(version string) { 140 gvk := obj.GetObjectKind().GroupVersionKind() 141 gv, err := unversioned.ParseGroupVersion(version) 142 if err != nil { 143 gv = unversioned.GroupVersion{Version: version} 144 } 145 gvk.Group, gvk.Version = gv.Group, gv.Version 146 obj.GetObjectKind().SetGroupVersionKind(gvk) 147 } 148 149 // NewAccessor returns a MetadataAccessor that can retrieve 150 // or manipulate resource version on objects derived from core API 151 // metadata concepts. 152 func NewAccessor() MetadataAccessor { 153 return resourceAccessor{} 154 } 155 156 // resourceAccessor implements ResourceVersioner and SelfLinker. 157 type resourceAccessor struct{} 158 159 func (resourceAccessor) Kind(obj runtime.Object) (string, error) { 160 return objectAccessor{obj}.GetKind(), nil 161 } 162 163 func (resourceAccessor) SetKind(obj runtime.Object, kind string) error { 164 objectAccessor{obj}.SetKind(kind) 165 return nil 166 } 167 168 func (resourceAccessor) APIVersion(obj runtime.Object) (string, error) { 169 return objectAccessor{obj}.GetAPIVersion(), nil 170 } 171 172 func (resourceAccessor) SetAPIVersion(obj runtime.Object, version string) error { 173 objectAccessor{obj}.SetAPIVersion(version) 174 return nil 175 } 176 177 func (resourceAccessor) Namespace(obj runtime.Object) (string, error) { 178 accessor, err := Accessor(obj) 179 if err != nil { 180 return "", err 181 } 182 return accessor.GetNamespace(), nil 183 } 184 185 func (resourceAccessor) SetNamespace(obj runtime.Object, namespace string) error { 186 accessor, err := Accessor(obj) 187 if err != nil { 188 return err 189 } 190 accessor.SetNamespace(namespace) 191 return nil 192 } 193 194 func (resourceAccessor) Name(obj runtime.Object) (string, error) { 195 accessor, err := Accessor(obj) 196 if err != nil { 197 return "", err 198 } 199 return accessor.GetName(), nil 200 } 201 202 func (resourceAccessor) SetName(obj runtime.Object, name string) error { 203 accessor, err := Accessor(obj) 204 if err != nil { 205 return err 206 } 207 accessor.SetName(name) 208 return nil 209 } 210 211 func (resourceAccessor) GenerateName(obj runtime.Object) (string, error) { 212 accessor, err := Accessor(obj) 213 if err != nil { 214 return "", err 215 } 216 return accessor.GetGenerateName(), nil 217 } 218 219 func (resourceAccessor) SetGenerateName(obj runtime.Object, name string) error { 220 accessor, err := Accessor(obj) 221 if err != nil { 222 return err 223 } 224 accessor.SetGenerateName(name) 225 return nil 226 } 227 228 func (resourceAccessor) UID(obj runtime.Object) (types.UID, error) { 229 accessor, err := Accessor(obj) 230 if err != nil { 231 return "", err 232 } 233 return accessor.GetUID(), nil 234 } 235 236 func (resourceAccessor) SetUID(obj runtime.Object, uid types.UID) error { 237 accessor, err := Accessor(obj) 238 if err != nil { 239 return err 240 } 241 accessor.SetUID(uid) 242 return nil 243 } 244 245 func (resourceAccessor) SelfLink(obj runtime.Object) (string, error) { 246 accessor, err := Accessor(obj) 247 if err != nil { 248 return "", err 249 } 250 return accessor.GetSelfLink(), nil 251 } 252 253 func (resourceAccessor) SetSelfLink(obj runtime.Object, selfLink string) error { 254 accessor, err := Accessor(obj) 255 if err != nil { 256 return err 257 } 258 accessor.SetSelfLink(selfLink) 259 return nil 260 } 261 262 func (resourceAccessor) Labels(obj runtime.Object) (map[string]string, error) { 263 accessor, err := Accessor(obj) 264 if err != nil { 265 return nil, err 266 } 267 return accessor.GetLabels(), nil 268 } 269 270 func (resourceAccessor) SetLabels(obj runtime.Object, labels map[string]string) error { 271 accessor, err := Accessor(obj) 272 if err != nil { 273 return err 274 } 275 accessor.SetLabels(labels) 276 return nil 277 } 278 279 func (resourceAccessor) Annotations(obj runtime.Object) (map[string]string, error) { 280 accessor, err := Accessor(obj) 281 if err != nil { 282 return nil, err 283 } 284 return accessor.GetAnnotations(), nil 285 } 286 287 func (resourceAccessor) SetAnnotations(obj runtime.Object, annotations map[string]string) error { 288 accessor, err := Accessor(obj) 289 if err != nil { 290 return err 291 } 292 accessor.SetAnnotations(annotations) 293 return nil 294 } 295 296 func (resourceAccessor) ResourceVersion(obj runtime.Object) (string, error) { 297 accessor, err := Accessor(obj) 298 if err != nil { 299 return "", err 300 } 301 return accessor.GetResourceVersion(), nil 302 } 303 304 func (resourceAccessor) SetResourceVersion(obj runtime.Object, version string) error { 305 accessor, err := Accessor(obj) 306 if err != nil { 307 return err 308 } 309 accessor.SetResourceVersion(version) 310 return nil 311 } 312 313 // genericAccessor contains pointers to strings that can modify an arbitrary 314 // struct and implements the Accessor interface. 315 type genericAccessor struct { 316 namespace *string 317 name *string 318 generateName *string 319 uid *types.UID 320 apiVersion *string 321 kind *string 322 resourceVersion *string 323 selfLink *string 324 creationTimestamp *unversioned.Time 325 deletionTimestamp **unversioned.Time 326 labels *map[string]string 327 annotations *map[string]string 328 } 329 330 func (a genericAccessor) GetNamespace() string { 331 if a.namespace == nil { 332 return "" 333 } 334 return *a.namespace 335 } 336 337 func (a genericAccessor) SetNamespace(namespace string) { 338 if a.namespace == nil { 339 return 340 } 341 *a.namespace = namespace 342 } 343 344 func (a genericAccessor) GetName() string { 345 if a.name == nil { 346 return "" 347 } 348 return *a.name 349 } 350 351 func (a genericAccessor) SetName(name string) { 352 if a.name == nil { 353 return 354 } 355 *a.name = name 356 } 357 358 func (a genericAccessor) GetGenerateName() string { 359 if a.generateName == nil { 360 return "" 361 } 362 return *a.generateName 363 } 364 365 func (a genericAccessor) SetGenerateName(generateName string) { 366 if a.generateName == nil { 367 return 368 } 369 *a.generateName = generateName 370 } 371 372 func (a genericAccessor) GetUID() types.UID { 373 if a.uid == nil { 374 return "" 375 } 376 return *a.uid 377 } 378 379 func (a genericAccessor) SetUID(uid types.UID) { 380 if a.uid == nil { 381 return 382 } 383 *a.uid = uid 384 } 385 386 func (a genericAccessor) GetAPIVersion() string { 387 return *a.apiVersion 388 } 389 390 func (a genericAccessor) SetAPIVersion(version string) { 391 *a.apiVersion = version 392 } 393 394 func (a genericAccessor) GetKind() string { 395 return *a.kind 396 } 397 398 func (a genericAccessor) SetKind(kind string) { 399 *a.kind = kind 400 } 401 402 func (a genericAccessor) GetResourceVersion() string { 403 return *a.resourceVersion 404 } 405 406 func (a genericAccessor) SetResourceVersion(version string) { 407 *a.resourceVersion = version 408 } 409 410 func (a genericAccessor) GetSelfLink() string { 411 return *a.selfLink 412 } 413 414 func (a genericAccessor) SetSelfLink(selfLink string) { 415 *a.selfLink = selfLink 416 } 417 418 func (a genericAccessor) GetCreationTimestamp() unversioned.Time { 419 return *a.creationTimestamp 420 } 421 422 func (a genericAccessor) SetCreationTimestamp(timestamp unversioned.Time) { 423 *a.creationTimestamp = timestamp 424 } 425 426 func (a genericAccessor) GetDeletionTimestamp() *unversioned.Time { 427 return *a.deletionTimestamp 428 } 429 430 func (a genericAccessor) SetDeletionTimestamp(timestamp *unversioned.Time) { 431 *a.deletionTimestamp = timestamp 432 } 433 434 func (a genericAccessor) GetLabels() map[string]string { 435 if a.labels == nil { 436 return nil 437 } 438 return *a.labels 439 } 440 441 func (a genericAccessor) SetLabels(labels map[string]string) { 442 *a.labels = labels 443 } 444 445 func (a genericAccessor) GetAnnotations() map[string]string { 446 if a.annotations == nil { 447 return nil 448 } 449 return *a.annotations 450 } 451 452 func (a genericAccessor) SetAnnotations(annotations map[string]string) { 453 if a.annotations == nil { 454 emptyAnnotations := make(map[string]string) 455 a.annotations = &emptyAnnotations 456 } 457 *a.annotations = annotations 458 } 459 460 // extractFromTypeMeta extracts pointers to version and kind fields from an object 461 func extractFromTypeMeta(v reflect.Value, a *genericAccessor) error { 462 if err := runtime.FieldPtr(v, "APIVersion", &a.apiVersion); err != nil { 463 return err 464 } 465 if err := runtime.FieldPtr(v, "Kind", &a.kind); err != nil { 466 return err 467 } 468 return nil 469 } 470 471 // extractFromObjectMeta extracts pointers to metadata fields from an object 472 func extractFromObjectMeta(v reflect.Value, a *genericAccessor) error { 473 if err := runtime.FieldPtr(v, "Namespace", &a.namespace); err != nil { 474 return err 475 } 476 if err := runtime.FieldPtr(v, "Name", &a.name); err != nil { 477 return err 478 } 479 if err := runtime.FieldPtr(v, "GenerateName", &a.generateName); err != nil { 480 return err 481 } 482 if err := runtime.FieldPtr(v, "UID", &a.uid); err != nil { 483 return err 484 } 485 if err := runtime.FieldPtr(v, "ResourceVersion", &a.resourceVersion); err != nil { 486 return err 487 } 488 if err := runtime.FieldPtr(v, "SelfLink", &a.selfLink); err != nil { 489 return err 490 } 491 if err := runtime.FieldPtr(v, "Labels", &a.labels); err != nil { 492 return err 493 } 494 if err := runtime.FieldPtr(v, "Annotations", &a.annotations); err != nil { 495 return err 496 } 497 return nil 498 } 499 500 // extractFromObjectMeta extracts pointers to metadata fields from a list object 501 func extractFromListMeta(v reflect.Value, a *genericAccessor) error { 502 if err := runtime.FieldPtr(v, "ResourceVersion", &a.resourceVersion); err != nil { 503 return err 504 } 505 if err := runtime.FieldPtr(v, "SelfLink", &a.selfLink); err != nil { 506 return err 507 } 508 return nil 509 }