meta.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  1. /*
  2. Copyright 2014 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package meta
  14. import (
  15. "fmt"
  16. "reflect"
  17. "k8s.io/kubernetes/pkg/api/meta/metatypes"
  18. "k8s.io/kubernetes/pkg/api/unversioned"
  19. "k8s.io/kubernetes/pkg/conversion"
  20. "k8s.io/kubernetes/pkg/runtime"
  21. "k8s.io/kubernetes/pkg/types"
  22. "github.com/golang/glog"
  23. )
  24. // errNotList is returned when an object implements the Object style interfaces but not the List style
  25. // interfaces.
  26. var errNotList = fmt.Errorf("object does not implement the List interfaces")
  27. // ListAccessor returns a List interface for the provided object or an error if the object does
  28. // not provide List.
  29. // IMPORTANT: Objects are a superset of lists, so all Objects return List metadata. Do not use this
  30. // check to determine whether an object *is* a List.
  31. // TODO: return bool instead of error
  32. func ListAccessor(obj interface{}) (List, error) {
  33. switch t := obj.(type) {
  34. case List:
  35. return t, nil
  36. case unversioned.List:
  37. return t, nil
  38. case ListMetaAccessor:
  39. if m := t.GetListMeta(); m != nil {
  40. return m, nil
  41. }
  42. return nil, errNotList
  43. case unversioned.ListMetaAccessor:
  44. if m := t.GetListMeta(); m != nil {
  45. return m, nil
  46. }
  47. return nil, errNotList
  48. case Object:
  49. return t, nil
  50. case ObjectMetaAccessor:
  51. if m := t.GetObjectMeta(); m != nil {
  52. return m, nil
  53. }
  54. return nil, errNotList
  55. default:
  56. return nil, errNotList
  57. }
  58. }
  59. // errNotObject is returned when an object implements the List style interfaces but not the Object style
  60. // interfaces.
  61. var errNotObject = fmt.Errorf("object does not implement the Object interfaces")
  62. // Accessor takes an arbitrary object pointer and returns meta.Interface.
  63. // obj must be a pointer to an API type. An error is returned if the minimum
  64. // required fields are missing. Fields that are not required return the default
  65. // value and are a no-op if set.
  66. // TODO: return bool instead of error
  67. func Accessor(obj interface{}) (Object, error) {
  68. switch t := obj.(type) {
  69. case Object:
  70. return t, nil
  71. case ObjectMetaAccessor:
  72. if m := t.GetObjectMeta(); m != nil {
  73. return m, nil
  74. }
  75. return nil, errNotObject
  76. case List, unversioned.List, ListMetaAccessor, unversioned.ListMetaAccessor:
  77. return nil, errNotObject
  78. default:
  79. return nil, errNotObject
  80. }
  81. }
  82. // TypeAccessor returns an interface that allows retrieving and modifying the APIVersion
  83. // and Kind of an in-memory internal object.
  84. // TODO: this interface is used to test code that does not have ObjectMeta or ListMeta
  85. // in round tripping (objects which can use apiVersion/kind, but do not fit the Kube
  86. // api conventions).
  87. func TypeAccessor(obj interface{}) (Type, error) {
  88. if typed, ok := obj.(runtime.Object); ok {
  89. return objectAccessor{typed}, nil
  90. }
  91. v, err := conversion.EnforcePtr(obj)
  92. if err != nil {
  93. return nil, err
  94. }
  95. t := v.Type()
  96. if v.Kind() != reflect.Struct {
  97. return nil, fmt.Errorf("expected struct, but got %v: %v (%#v)", v.Kind(), t, v.Interface())
  98. }
  99. typeMeta := v.FieldByName("TypeMeta")
  100. if !typeMeta.IsValid() {
  101. return nil, fmt.Errorf("struct %v lacks embedded TypeMeta type", t)
  102. }
  103. a := &genericAccessor{}
  104. if err := extractFromTypeMeta(typeMeta, a); err != nil {
  105. return nil, fmt.Errorf("unable to find type fields on %#v: %v", typeMeta, err)
  106. }
  107. return a, nil
  108. }
  109. type objectAccessor struct {
  110. runtime.Object
  111. }
  112. func (obj objectAccessor) GetKind() string {
  113. return obj.GetObjectKind().GroupVersionKind().Kind
  114. }
  115. func (obj objectAccessor) SetKind(kind string) {
  116. gvk := obj.GetObjectKind().GroupVersionKind()
  117. gvk.Kind = kind
  118. obj.GetObjectKind().SetGroupVersionKind(gvk)
  119. }
  120. func (obj objectAccessor) GetAPIVersion() string {
  121. return obj.GetObjectKind().GroupVersionKind().GroupVersion().String()
  122. }
  123. func (obj objectAccessor) SetAPIVersion(version string) {
  124. gvk := obj.GetObjectKind().GroupVersionKind()
  125. gv, err := unversioned.ParseGroupVersion(version)
  126. if err != nil {
  127. gv = unversioned.GroupVersion{Version: version}
  128. }
  129. gvk.Group, gvk.Version = gv.Group, gv.Version
  130. obj.GetObjectKind().SetGroupVersionKind(gvk)
  131. }
  132. // NewAccessor returns a MetadataAccessor that can retrieve
  133. // or manipulate resource version on objects derived from core API
  134. // metadata concepts.
  135. func NewAccessor() MetadataAccessor {
  136. return resourceAccessor{}
  137. }
  138. // resourceAccessor implements ResourceVersioner and SelfLinker.
  139. type resourceAccessor struct{}
  140. func (resourceAccessor) Kind(obj runtime.Object) (string, error) {
  141. return objectAccessor{obj}.GetKind(), nil
  142. }
  143. func (resourceAccessor) SetKind(obj runtime.Object, kind string) error {
  144. objectAccessor{obj}.SetKind(kind)
  145. return nil
  146. }
  147. func (resourceAccessor) APIVersion(obj runtime.Object) (string, error) {
  148. return objectAccessor{obj}.GetAPIVersion(), nil
  149. }
  150. func (resourceAccessor) SetAPIVersion(obj runtime.Object, version string) error {
  151. objectAccessor{obj}.SetAPIVersion(version)
  152. return nil
  153. }
  154. func (resourceAccessor) Namespace(obj runtime.Object) (string, error) {
  155. accessor, err := Accessor(obj)
  156. if err != nil {
  157. return "", err
  158. }
  159. return accessor.GetNamespace(), nil
  160. }
  161. func (resourceAccessor) SetNamespace(obj runtime.Object, namespace string) error {
  162. accessor, err := Accessor(obj)
  163. if err != nil {
  164. return err
  165. }
  166. accessor.SetNamespace(namespace)
  167. return nil
  168. }
  169. func (resourceAccessor) Name(obj runtime.Object) (string, error) {
  170. accessor, err := Accessor(obj)
  171. if err != nil {
  172. return "", err
  173. }
  174. return accessor.GetName(), nil
  175. }
  176. func (resourceAccessor) SetName(obj runtime.Object, name string) error {
  177. accessor, err := Accessor(obj)
  178. if err != nil {
  179. return err
  180. }
  181. accessor.SetName(name)
  182. return nil
  183. }
  184. func (resourceAccessor) GenerateName(obj runtime.Object) (string, error) {
  185. accessor, err := Accessor(obj)
  186. if err != nil {
  187. return "", err
  188. }
  189. return accessor.GetGenerateName(), nil
  190. }
  191. func (resourceAccessor) SetGenerateName(obj runtime.Object, name string) error {
  192. accessor, err := Accessor(obj)
  193. if err != nil {
  194. return err
  195. }
  196. accessor.SetGenerateName(name)
  197. return nil
  198. }
  199. func (resourceAccessor) UID(obj runtime.Object) (types.UID, error) {
  200. accessor, err := Accessor(obj)
  201. if err != nil {
  202. return "", err
  203. }
  204. return accessor.GetUID(), nil
  205. }
  206. func (resourceAccessor) SetUID(obj runtime.Object, uid types.UID) error {
  207. accessor, err := Accessor(obj)
  208. if err != nil {
  209. return err
  210. }
  211. accessor.SetUID(uid)
  212. return nil
  213. }
  214. func (resourceAccessor) SelfLink(obj runtime.Object) (string, error) {
  215. accessor, err := ListAccessor(obj)
  216. if err != nil {
  217. return "", err
  218. }
  219. return accessor.GetSelfLink(), nil
  220. }
  221. func (resourceAccessor) SetSelfLink(obj runtime.Object, selfLink string) error {
  222. accessor, err := ListAccessor(obj)
  223. if err != nil {
  224. return err
  225. }
  226. accessor.SetSelfLink(selfLink)
  227. return nil
  228. }
  229. func (resourceAccessor) Labels(obj runtime.Object) (map[string]string, error) {
  230. accessor, err := Accessor(obj)
  231. if err != nil {
  232. return nil, err
  233. }
  234. return accessor.GetLabels(), nil
  235. }
  236. func (resourceAccessor) SetLabels(obj runtime.Object, labels map[string]string) error {
  237. accessor, err := Accessor(obj)
  238. if err != nil {
  239. return err
  240. }
  241. accessor.SetLabels(labels)
  242. return nil
  243. }
  244. func (resourceAccessor) Annotations(obj runtime.Object) (map[string]string, error) {
  245. accessor, err := Accessor(obj)
  246. if err != nil {
  247. return nil, err
  248. }
  249. return accessor.GetAnnotations(), nil
  250. }
  251. func (resourceAccessor) SetAnnotations(obj runtime.Object, annotations map[string]string) error {
  252. accessor, err := Accessor(obj)
  253. if err != nil {
  254. return err
  255. }
  256. accessor.SetAnnotations(annotations)
  257. return nil
  258. }
  259. func (resourceAccessor) ResourceVersion(obj runtime.Object) (string, error) {
  260. accessor, err := ListAccessor(obj)
  261. if err != nil {
  262. return "", err
  263. }
  264. return accessor.GetResourceVersion(), nil
  265. }
  266. func (resourceAccessor) SetResourceVersion(obj runtime.Object, version string) error {
  267. accessor, err := ListAccessor(obj)
  268. if err != nil {
  269. return err
  270. }
  271. accessor.SetResourceVersion(version)
  272. return nil
  273. }
  274. // extractFromOwnerReference extracts v to o. v is the OwnerReferences field of an object.
  275. func extractFromOwnerReference(v reflect.Value, o *metatypes.OwnerReference) error {
  276. if err := runtime.Field(v, "APIVersion", &o.APIVersion); err != nil {
  277. return err
  278. }
  279. if err := runtime.Field(v, "Kind", &o.Kind); err != nil {
  280. return err
  281. }
  282. if err := runtime.Field(v, "Name", &o.Name); err != nil {
  283. return err
  284. }
  285. if err := runtime.Field(v, "UID", &o.UID); err != nil {
  286. return err
  287. }
  288. var controllerPtr *bool
  289. if err := runtime.Field(v, "Controller", &controllerPtr); err != nil {
  290. return err
  291. }
  292. if controllerPtr != nil {
  293. controller := *controllerPtr
  294. o.Controller = &controller
  295. }
  296. return nil
  297. }
  298. // setOwnerReference sets v to o. v is the OwnerReferences field of an object.
  299. func setOwnerReference(v reflect.Value, o *metatypes.OwnerReference) error {
  300. if err := runtime.SetField(o.APIVersion, v, "APIVersion"); err != nil {
  301. return err
  302. }
  303. if err := runtime.SetField(o.Kind, v, "Kind"); err != nil {
  304. return err
  305. }
  306. if err := runtime.SetField(o.Name, v, "Name"); err != nil {
  307. return err
  308. }
  309. if err := runtime.SetField(o.UID, v, "UID"); err != nil {
  310. return err
  311. }
  312. if o.Controller != nil {
  313. controller := *(o.Controller)
  314. if err := runtime.SetField(&controller, v, "Controller"); err != nil {
  315. return err
  316. }
  317. }
  318. return nil
  319. }
  320. // genericAccessor contains pointers to strings that can modify an arbitrary
  321. // struct and implements the Accessor interface.
  322. type genericAccessor struct {
  323. namespace *string
  324. name *string
  325. generateName *string
  326. uid *types.UID
  327. apiVersion *string
  328. kind *string
  329. resourceVersion *string
  330. selfLink *string
  331. creationTimestamp *unversioned.Time
  332. deletionTimestamp **unversioned.Time
  333. labels *map[string]string
  334. annotations *map[string]string
  335. ownerReferences reflect.Value
  336. finalizers *[]string
  337. }
  338. func (a genericAccessor) GetNamespace() string {
  339. if a.namespace == nil {
  340. return ""
  341. }
  342. return *a.namespace
  343. }
  344. func (a genericAccessor) SetNamespace(namespace string) {
  345. if a.namespace == nil {
  346. return
  347. }
  348. *a.namespace = namespace
  349. }
  350. func (a genericAccessor) GetName() string {
  351. if a.name == nil {
  352. return ""
  353. }
  354. return *a.name
  355. }
  356. func (a genericAccessor) SetName(name string) {
  357. if a.name == nil {
  358. return
  359. }
  360. *a.name = name
  361. }
  362. func (a genericAccessor) GetGenerateName() string {
  363. if a.generateName == nil {
  364. return ""
  365. }
  366. return *a.generateName
  367. }
  368. func (a genericAccessor) SetGenerateName(generateName string) {
  369. if a.generateName == nil {
  370. return
  371. }
  372. *a.generateName = generateName
  373. }
  374. func (a genericAccessor) GetUID() types.UID {
  375. if a.uid == nil {
  376. return ""
  377. }
  378. return *a.uid
  379. }
  380. func (a genericAccessor) SetUID(uid types.UID) {
  381. if a.uid == nil {
  382. return
  383. }
  384. *a.uid = uid
  385. }
  386. func (a genericAccessor) GetAPIVersion() string {
  387. return *a.apiVersion
  388. }
  389. func (a genericAccessor) SetAPIVersion(version string) {
  390. *a.apiVersion = version
  391. }
  392. func (a genericAccessor) GetKind() string {
  393. return *a.kind
  394. }
  395. func (a genericAccessor) SetKind(kind string) {
  396. *a.kind = kind
  397. }
  398. func (a genericAccessor) GetResourceVersion() string {
  399. return *a.resourceVersion
  400. }
  401. func (a genericAccessor) SetResourceVersion(version string) {
  402. *a.resourceVersion = version
  403. }
  404. func (a genericAccessor) GetSelfLink() string {
  405. return *a.selfLink
  406. }
  407. func (a genericAccessor) SetSelfLink(selfLink string) {
  408. *a.selfLink = selfLink
  409. }
  410. func (a genericAccessor) GetCreationTimestamp() unversioned.Time {
  411. return *a.creationTimestamp
  412. }
  413. func (a genericAccessor) SetCreationTimestamp(timestamp unversioned.Time) {
  414. *a.creationTimestamp = timestamp
  415. }
  416. func (a genericAccessor) GetDeletionTimestamp() *unversioned.Time {
  417. return *a.deletionTimestamp
  418. }
  419. func (a genericAccessor) SetDeletionTimestamp(timestamp *unversioned.Time) {
  420. *a.deletionTimestamp = timestamp
  421. }
  422. func (a genericAccessor) GetLabels() map[string]string {
  423. if a.labels == nil {
  424. return nil
  425. }
  426. return *a.labels
  427. }
  428. func (a genericAccessor) SetLabels(labels map[string]string) {
  429. *a.labels = labels
  430. }
  431. func (a genericAccessor) GetAnnotations() map[string]string {
  432. if a.annotations == nil {
  433. return nil
  434. }
  435. return *a.annotations
  436. }
  437. func (a genericAccessor) SetAnnotations(annotations map[string]string) {
  438. if a.annotations == nil {
  439. emptyAnnotations := make(map[string]string)
  440. a.annotations = &emptyAnnotations
  441. }
  442. *a.annotations = annotations
  443. }
  444. func (a genericAccessor) GetFinalizers() []string {
  445. if a.finalizers == nil {
  446. return nil
  447. }
  448. return *a.finalizers
  449. }
  450. func (a genericAccessor) SetFinalizers(finalizers []string) {
  451. *a.finalizers = finalizers
  452. }
  453. func (a genericAccessor) GetOwnerReferences() []metatypes.OwnerReference {
  454. var ret []metatypes.OwnerReference
  455. s := a.ownerReferences
  456. if s.Kind() != reflect.Ptr || s.Elem().Kind() != reflect.Slice {
  457. glog.Errorf("expect %v to be a pointer to slice", s)
  458. return ret
  459. }
  460. s = s.Elem()
  461. // Set the capacity to one element greater to avoid copy if the caller later append an element.
  462. ret = make([]metatypes.OwnerReference, s.Len(), s.Len()+1)
  463. for i := 0; i < s.Len(); i++ {
  464. if err := extractFromOwnerReference(s.Index(i), &ret[i]); err != nil {
  465. glog.Errorf("extractFromOwnerReference failed: %v", err)
  466. return ret
  467. }
  468. }
  469. return ret
  470. }
  471. func (a genericAccessor) SetOwnerReferences(references []metatypes.OwnerReference) {
  472. s := a.ownerReferences
  473. if s.Kind() != reflect.Ptr || s.Elem().Kind() != reflect.Slice {
  474. glog.Errorf("expect %v to be a pointer to slice", s)
  475. }
  476. s = s.Elem()
  477. newReferences := reflect.MakeSlice(s.Type(), len(references), len(references))
  478. for i := 0; i < len(references); i++ {
  479. if err := setOwnerReference(newReferences.Index(i), &references[i]); err != nil {
  480. glog.Errorf("setOwnerReference failed: %v", err)
  481. return
  482. }
  483. }
  484. s.Set(newReferences)
  485. }
  486. // extractFromTypeMeta extracts pointers to version and kind fields from an object
  487. func extractFromTypeMeta(v reflect.Value, a *genericAccessor) error {
  488. if err := runtime.FieldPtr(v, "APIVersion", &a.apiVersion); err != nil {
  489. return err
  490. }
  491. if err := runtime.FieldPtr(v, "Kind", &a.kind); err != nil {
  492. return err
  493. }
  494. return nil
  495. }