data.go 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
  1. /*
  2. Copyright 2018 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 etcd
  14. import (
  15. apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
  16. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  17. "k8s.io/apimachinery/pkg/runtime/schema"
  18. utilfeature "k8s.io/apiserver/pkg/util/feature"
  19. "k8s.io/kubernetes/pkg/features"
  20. "k8s.io/utils/pointer"
  21. )
  22. // GetEtcdStorageData returns etcd data for all persisted objects.
  23. // It is exported so that it can be reused across multiple tests.
  24. // It returns a new map on every invocation to prevent different tests from mutating shared state.
  25. func GetEtcdStorageData() map[schema.GroupVersionResource]StorageData {
  26. return GetEtcdStorageDataForNamespace("etcdstoragepathtestnamespace")
  27. }
  28. // GetEtcdStorageDataForNamespace returns etcd data for all persisted objects.
  29. // It is exported so that it can be reused across multiple tests.
  30. // It returns a new map on every invocation to prevent different tests from mutating shared state.
  31. // Namespaced objects keys are computed for the specified namespace.
  32. func GetEtcdStorageDataForNamespace(namespace string) map[schema.GroupVersionResource]StorageData {
  33. etcdStorageData := map[schema.GroupVersionResource]StorageData{
  34. // k8s.io/kubernetes/pkg/api/v1
  35. gvr("", "v1", "configmaps"): {
  36. Stub: `{"data": {"foo": "bar"}, "metadata": {"name": "cm1"}}`,
  37. ExpectedEtcdPath: "/registry/configmaps/" + namespace + "/cm1",
  38. },
  39. gvr("", "v1", "services"): {
  40. Stub: `{"metadata": {"name": "service1"}, "spec": {"externalName": "service1name", "ports": [{"port": 10000, "targetPort": 11000}], "selector": {"test": "data"}}}`,
  41. ExpectedEtcdPath: "/registry/services/specs/" + namespace + "/service1",
  42. },
  43. gvr("", "v1", "podtemplates"): {
  44. Stub: `{"metadata": {"name": "pt1name"}, "template": {"metadata": {"labels": {"pt": "01"}}, "spec": {"containers": [{"image": "fedora:latest", "name": "container9"}]}}}`,
  45. ExpectedEtcdPath: "/registry/podtemplates/" + namespace + "/pt1name",
  46. },
  47. gvr("", "v1", "pods"): {
  48. Stub: `{"metadata": {"name": "pod1"}, "spec": {"containers": [{"image": "fedora:latest", "name": "container7", "resources": {"limits": {"cpu": "1M"}, "requests": {"cpu": "1M"}}}]}}`,
  49. ExpectedEtcdPath: "/registry/pods/" + namespace + "/pod1",
  50. },
  51. gvr("", "v1", "endpoints"): {
  52. Stub: `{"metadata": {"name": "ep1name"}, "subsets": [{"addresses": [{"hostname": "bar-001", "ip": "192.168.3.1"}], "ports": [{"port": 8000}]}]}`,
  53. ExpectedEtcdPath: "/registry/services/endpoints/" + namespace + "/ep1name",
  54. },
  55. gvr("", "v1", "resourcequotas"): {
  56. Stub: `{"metadata": {"name": "rq1name"}, "spec": {"hard": {"cpu": "5M"}}}`,
  57. ExpectedEtcdPath: "/registry/resourcequotas/" + namespace + "/rq1name",
  58. },
  59. gvr("", "v1", "limitranges"): {
  60. Stub: `{"metadata": {"name": "lr1name"}, "spec": {"limits": [{"type": "Pod"}]}}`,
  61. ExpectedEtcdPath: "/registry/limitranges/" + namespace + "/lr1name",
  62. },
  63. gvr("", "v1", "namespaces"): {
  64. Stub: `{"metadata": {"name": "namespace1"}, "spec": {"finalizers": ["kubernetes"]}}`,
  65. ExpectedEtcdPath: "/registry/namespaces/namespace1",
  66. },
  67. gvr("", "v1", "nodes"): {
  68. Stub: `{"metadata": {"name": "node1"}, "spec": {"unschedulable": true}}`,
  69. ExpectedEtcdPath: "/registry/minions/node1",
  70. },
  71. gvr("", "v1", "persistentvolumes"): {
  72. Stub: `{"metadata": {"name": "pv1name"}, "spec": {"accessModes": ["ReadWriteOnce"], "capacity": {"storage": "3M"}, "hostPath": {"path": "/tmp/test/"}}}`,
  73. ExpectedEtcdPath: "/registry/persistentvolumes/pv1name",
  74. },
  75. gvr("", "v1", "events"): {
  76. Stub: `{"involvedObject": {"namespace": "` + namespace + `"}, "message": "some data here", "metadata": {"name": "event1"}}`,
  77. ExpectedEtcdPath: "/registry/events/" + namespace + "/event1",
  78. },
  79. gvr("", "v1", "persistentvolumeclaims"): {
  80. Stub: `{"metadata": {"name": "pvc1"}, "spec": {"accessModes": ["ReadWriteOnce"], "resources": {"limits": {"storage": "1M"}, "requests": {"storage": "2M"}}, "selector": {"matchLabels": {"pvc": "stuff"}}}}`,
  81. ExpectedEtcdPath: "/registry/persistentvolumeclaims/" + namespace + "/pvc1",
  82. },
  83. gvr("", "v1", "serviceaccounts"): {
  84. Stub: `{"metadata": {"name": "sa1name"}, "secrets": [{"name": "secret00"}]}`,
  85. ExpectedEtcdPath: "/registry/serviceaccounts/" + namespace + "/sa1name",
  86. },
  87. gvr("", "v1", "secrets"): {
  88. Stub: `{"data": {"key": "ZGF0YSBmaWxl"}, "metadata": {"name": "secret1"}}`,
  89. ExpectedEtcdPath: "/registry/secrets/" + namespace + "/secret1",
  90. },
  91. gvr("", "v1", "replicationcontrollers"): {
  92. Stub: `{"metadata": {"name": "rc1"}, "spec": {"selector": {"new": "stuff"}, "template": {"metadata": {"labels": {"new": "stuff"}}, "spec": {"containers": [{"image": "fedora:latest", "name": "container8"}]}}}}`,
  93. ExpectedEtcdPath: "/registry/controllers/" + namespace + "/rc1",
  94. },
  95. // --
  96. // k8s.io/kubernetes/pkg/apis/apps/v1beta1
  97. gvr("apps", "v1beta1", "statefulsets"): {
  98. Stub: `{"metadata": {"name": "ss1"}, "spec": {"selector": {"matchLabels": {"a": "b"}}, "template": {"metadata": {"labels": {"a": "b"}}}}}`,
  99. ExpectedEtcdPath: "/registry/statefulsets/" + namespace + "/ss1",
  100. ExpectedGVK: gvkP("apps", "v1", "StatefulSet"),
  101. },
  102. gvr("apps", "v1beta1", "deployments"): {
  103. Stub: `{"metadata": {"name": "deployment2"}, "spec": {"selector": {"matchLabels": {"f": "z"}}, "template": {"metadata": {"labels": {"f": "z"}}, "spec": {"containers": [{"image": "fedora:latest", "name": "container6"}]}}}}`,
  104. ExpectedEtcdPath: "/registry/deployments/" + namespace + "/deployment2",
  105. ExpectedGVK: gvkP("apps", "v1", "Deployment"),
  106. },
  107. gvr("apps", "v1beta1", "controllerrevisions"): {
  108. Stub: `{"metadata":{"name":"crs1"},"data":{"name":"abc","namespace":"default","creationTimestamp":null,"Spec":{"Replicas":0,"Selector":{"matchLabels":{"foo":"bar"}},"Template":{"creationTimestamp":null,"labels":{"foo":"bar"},"Spec":{"Volumes":null,"InitContainers":null,"Containers":null,"RestartPolicy":"Always","TerminationGracePeriodSeconds":null,"ActiveDeadlineSeconds":null,"DNSPolicy":"ClusterFirst","NodeSelector":null,"ServiceAccountName":"","AutomountServiceAccountToken":null,"NodeName":"","SecurityContext":null,"ImagePullSecrets":null,"Hostname":"","Subdomain":"","Affinity":null,"SchedulerName":"","Tolerations":null,"HostAliases":null}},"VolumeClaimTemplates":null,"ServiceName":""},"Status":{"ObservedGeneration":null,"Replicas":0}},"revision":0}`,
  109. ExpectedEtcdPath: "/registry/controllerrevisions/" + namespace + "/crs1",
  110. ExpectedGVK: gvkP("apps", "v1", "ControllerRevision"),
  111. },
  112. // --
  113. // k8s.io/kubernetes/pkg/apis/apps/v1beta2
  114. gvr("apps", "v1beta2", "statefulsets"): {
  115. Stub: `{"metadata": {"name": "ss2"}, "spec": {"selector": {"matchLabels": {"a": "b"}}, "template": {"metadata": {"labels": {"a": "b"}}}}}`,
  116. ExpectedEtcdPath: "/registry/statefulsets/" + namespace + "/ss2",
  117. ExpectedGVK: gvkP("apps", "v1", "StatefulSet"),
  118. },
  119. gvr("apps", "v1beta2", "deployments"): {
  120. Stub: `{"metadata": {"name": "deployment3"}, "spec": {"selector": {"matchLabels": {"f": "z"}}, "template": {"metadata": {"labels": {"f": "z"}}, "spec": {"containers": [{"image": "fedora:latest", "name": "container6"}]}}}}`,
  121. ExpectedEtcdPath: "/registry/deployments/" + namespace + "/deployment3",
  122. ExpectedGVK: gvkP("apps", "v1", "Deployment"),
  123. },
  124. gvr("apps", "v1beta2", "daemonsets"): {
  125. Stub: `{"metadata": {"name": "ds5"}, "spec": {"selector": {"matchLabels": {"a": "b"}}, "template": {"metadata": {"labels": {"a": "b"}}, "spec": {"containers": [{"image": "fedora:latest", "name": "container6"}]}}}}`,
  126. ExpectedEtcdPath: "/registry/daemonsets/" + namespace + "/ds5",
  127. ExpectedGVK: gvkP("apps", "v1", "DaemonSet"),
  128. },
  129. gvr("apps", "v1beta2", "replicasets"): {
  130. Stub: `{"metadata": {"name": "rs2"}, "spec": {"selector": {"matchLabels": {"g": "h"}}, "template": {"metadata": {"labels": {"g": "h"}}, "spec": {"containers": [{"image": "fedora:latest", "name": "container4"}]}}}}`,
  131. ExpectedEtcdPath: "/registry/replicasets/" + namespace + "/rs2",
  132. ExpectedGVK: gvkP("apps", "v1", "ReplicaSet"),
  133. },
  134. gvr("apps", "v1beta2", "controllerrevisions"): {
  135. Stub: `{"metadata":{"name":"crs2"},"data":{"name":"abc","namespace":"default","creationTimestamp":null,"Spec":{"Replicas":0,"Selector":{"matchLabels":{"foo":"bar"}},"Template":{"creationTimestamp":null,"labels":{"foo":"bar"},"Spec":{"Volumes":null,"InitContainers":null,"Containers":null,"RestartPolicy":"Always","TerminationGracePeriodSeconds":null,"ActiveDeadlineSeconds":null,"DNSPolicy":"ClusterFirst","NodeSelector":null,"ServiceAccountName":"","AutomountServiceAccountToken":null,"NodeName":"","SecurityContext":null,"ImagePullSecrets":null,"Hostname":"","Subdomain":"","Affinity":null,"SchedulerName":"","Tolerations":null,"HostAliases":null}},"VolumeClaimTemplates":null,"ServiceName":""},"Status":{"ObservedGeneration":null,"Replicas":0}},"revision":0}`,
  136. ExpectedEtcdPath: "/registry/controllerrevisions/" + namespace + "/crs2",
  137. ExpectedGVK: gvkP("apps", "v1", "ControllerRevision"),
  138. },
  139. // --
  140. // k8s.io/kubernetes/pkg/apis/apps/v1
  141. gvr("apps", "v1", "daemonsets"): {
  142. Stub: `{"metadata": {"name": "ds6"}, "spec": {"selector": {"matchLabels": {"a": "b"}}, "template": {"metadata": {"labels": {"a": "b"}}, "spec": {"containers": [{"image": "fedora:latest", "name": "container6"}]}}}}`,
  143. ExpectedEtcdPath: "/registry/daemonsets/" + namespace + "/ds6",
  144. },
  145. gvr("apps", "v1", "deployments"): {
  146. Stub: `{"metadata": {"name": "deployment4"}, "spec": {"selector": {"matchLabels": {"f": "z"}}, "template": {"metadata": {"labels": {"f": "z"}}, "spec": {"containers": [{"image": "fedora:latest", "name": "container6"}]}}}}`,
  147. ExpectedEtcdPath: "/registry/deployments/" + namespace + "/deployment4",
  148. },
  149. gvr("apps", "v1", "statefulsets"): {
  150. Stub: `{"metadata": {"name": "ss3"}, "spec": {"selector": {"matchLabels": {"a": "b"}}, "template": {"metadata": {"labels": {"a": "b"}}}}}`,
  151. ExpectedEtcdPath: "/registry/statefulsets/" + namespace + "/ss3",
  152. },
  153. gvr("apps", "v1", "replicasets"): {
  154. Stub: `{"metadata": {"name": "rs3"}, "spec": {"selector": {"matchLabels": {"g": "h"}}, "template": {"metadata": {"labels": {"g": "h"}}, "spec": {"containers": [{"image": "fedora:latest", "name": "container4"}]}}}}`,
  155. ExpectedEtcdPath: "/registry/replicasets/" + namespace + "/rs3",
  156. },
  157. gvr("apps", "v1", "controllerrevisions"): {
  158. Stub: `{"metadata":{"name":"crs3"},"data":{"name":"abc","namespace":"default","creationTimestamp":null,"Spec":{"Replicas":0,"Selector":{"matchLabels":{"foo":"bar"}},"Template":{"creationTimestamp":null,"labels":{"foo":"bar"},"Spec":{"Volumes":null,"InitContainers":null,"Containers":null,"RestartPolicy":"Always","TerminationGracePeriodSeconds":null,"ActiveDeadlineSeconds":null,"DNSPolicy":"ClusterFirst","NodeSelector":null,"ServiceAccountName":"","AutomountServiceAccountToken":null,"NodeName":"","SecurityContext":null,"ImagePullSecrets":null,"Hostname":"","Subdomain":"","Affinity":null,"SchedulerName":"","Tolerations":null,"HostAliases":null}},"VolumeClaimTemplates":null,"ServiceName":""},"Status":{"ObservedGeneration":null,"Replicas":0}},"revision":0}`,
  159. ExpectedEtcdPath: "/registry/controllerrevisions/" + namespace + "/crs3",
  160. },
  161. // --
  162. // k8s.io/kubernetes/pkg/apis/autoscaling/v1
  163. gvr("autoscaling", "v1", "horizontalpodautoscalers"): {
  164. Stub: `{"metadata": {"name": "hpa2"}, "spec": {"maxReplicas": 3, "scaleTargetRef": {"kind": "something", "name": "cross"}}}`,
  165. ExpectedEtcdPath: "/registry/horizontalpodautoscalers/" + namespace + "/hpa2",
  166. },
  167. // --
  168. // k8s.io/kubernetes/pkg/apis/autoscaling/v2beta1
  169. gvr("autoscaling", "v2beta1", "horizontalpodautoscalers"): {
  170. Stub: `{"metadata": {"name": "hpa1"}, "spec": {"maxReplicas": 3, "scaleTargetRef": {"kind": "something", "name": "cross"}}}`,
  171. ExpectedEtcdPath: "/registry/horizontalpodautoscalers/" + namespace + "/hpa1",
  172. ExpectedGVK: gvkP("autoscaling", "v1", "HorizontalPodAutoscaler"),
  173. },
  174. // --
  175. // k8s.io/kubernetes/pkg/apis/autoscaling/v2beta2
  176. gvr("autoscaling", "v2beta2", "horizontalpodautoscalers"): {
  177. Stub: `{"metadata": {"name": "hpa3"}, "spec": {"maxReplicas": 3, "scaleTargetRef": {"kind": "something", "name": "cross"}}}`,
  178. ExpectedEtcdPath: "/registry/horizontalpodautoscalers/" + namespace + "/hpa3",
  179. ExpectedGVK: gvkP("autoscaling", "v1", "HorizontalPodAutoscaler"),
  180. },
  181. // --
  182. // k8s.io/kubernetes/pkg/apis/batch/v1
  183. gvr("batch", "v1", "jobs"): {
  184. Stub: `{"metadata": {"name": "job1"}, "spec": {"manualSelector": true, "selector": {"matchLabels": {"controller-uid": "uid1"}}, "template": {"metadata": {"labels": {"controller-uid": "uid1"}}, "spec": {"containers": [{"image": "fedora:latest", "name": "container1"}], "dnsPolicy": "ClusterFirst", "restartPolicy": "Never"}}}}`,
  185. ExpectedEtcdPath: "/registry/jobs/" + namespace + "/job1",
  186. },
  187. // --
  188. // k8s.io/kubernetes/pkg/apis/batch/v1beta1
  189. gvr("batch", "v1beta1", "cronjobs"): {
  190. Stub: `{"metadata": {"name": "cjv1beta1"}, "spec": {"jobTemplate": {"spec": {"template": {"metadata": {"labels": {"controller-uid": "uid0"}}, "spec": {"containers": [{"image": "fedora:latest", "name": "container0"}], "dnsPolicy": "ClusterFirst", "restartPolicy": "Never"}}}}, "schedule": "* * * * *"}}`,
  191. ExpectedEtcdPath: "/registry/cronjobs/" + namespace + "/cjv1beta1",
  192. },
  193. // --
  194. // k8s.io/kubernetes/pkg/apis/batch/v2alpha1
  195. gvr("batch", "v2alpha1", "cronjobs"): {
  196. Stub: `{"metadata": {"name": "cjv2alpha1"}, "spec": {"jobTemplate": {"spec": {"template": {"metadata": {"labels": {"controller-uid": "uid0"}}, "spec": {"containers": [{"image": "fedora:latest", "name": "container0"}], "dnsPolicy": "ClusterFirst", "restartPolicy": "Never"}}}}, "schedule": "* * * * *"}}`,
  197. ExpectedEtcdPath: "/registry/cronjobs/" + namespace + "/cjv2alpha1",
  198. ExpectedGVK: gvkP("batch", "v1beta1", "CronJob"),
  199. },
  200. // --
  201. // k8s.io/kubernetes/pkg/apis/certificates/v1beta1
  202. gvr("certificates.k8s.io", "v1beta1", "certificatesigningrequests"): {
  203. Stub: `{"metadata": {"name": "csr1"}, "spec": {"request": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQnlqQ0NBVE1DQVFBd2dZa3hDekFKQmdOVkJBWVRBbFZUTVJNd0VRWURWUVFJRXdwRFlXeHBabTl5Ym1saApNUll3RkFZRFZRUUhFdzFOYjNWdWRHRnBiaUJXYVdWM01STXdFUVlEVlFRS0V3cEhiMjluYkdVZ1NXNWpNUjh3CkhRWURWUVFMRXhaSmJtWnZjbTFoZEdsdmJpQlVaV05vYm05c2IyZDVNUmN3RlFZRFZRUURFdzUzZDNjdVoyOXYKWjJ4bExtTnZiVENCbnpBTkJna3Foa2lHOXcwQkFRRUZBQU9CalFBd2dZa0NnWUVBcFp0WUpDSEo0VnBWWEhmVgpJbHN0UVRsTzRxQzAzaGpYK1prUHl2ZFlkMVE0K3FiQWVUd1htQ1VLWUhUaFZSZDVhWFNxbFB6eUlCd2llTVpyCldGbFJRZGRaMUl6WEFsVlJEV3dBbzYwS2VjcWVBWG5uVUsrNWZYb1RJL1VnV3NocmU4dEoreC9UTUhhUUtSL0oKY0lXUGhxYVFoc0p1elpidkFkR0E4MEJMeGRNQ0F3RUFBYUFBTUEwR0NTcUdTSWIzRFFFQkJRVUFBNEdCQUlobAo0UHZGcStlN2lwQVJnSTVaTStHWng2bXBDejQ0RFRvMEprd2ZSRGYrQnRyc2FDMHE2OGVUZjJYaFlPc3E0ZmtIClEwdUEwYVZvZzNmNWlKeENhM0hwNWd4YkpRNnpWNmtKMFRFc3VhYU9oRWtvOXNkcENvUE9uUkJtMmkvWFJEMkQKNmlOaDhmOHowU2hHc0ZxakRnRkh5RjNvK2xVeWorVUM2SDFRVzdibgotLS0tLUVORCBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0="}}`,
  204. ExpectedEtcdPath: "/registry/certificatesigningrequests/csr1",
  205. },
  206. // --
  207. // k8s.io/kubernetes/pkg/apis/coordination/v1
  208. gvr("coordination.k8s.io", "v1", "leases"): {
  209. Stub: `{"metadata": {"name": "leasev1"}, "spec": {"holderIdentity": "holder", "leaseDurationSeconds": 5}}`,
  210. ExpectedEtcdPath: "/registry/leases/" + namespace + "/leasev1",
  211. ExpectedGVK: gvkP("coordination.k8s.io", "v1beta1", "Lease"),
  212. },
  213. // --
  214. // k8s.io/kubernetes/pkg/apis/coordination/v1beta1
  215. gvr("coordination.k8s.io", "v1beta1", "leases"): {
  216. Stub: `{"metadata": {"name": "leasev1beta1"}, "spec": {"holderIdentity": "holder", "leaseDurationSeconds": 5}}`,
  217. ExpectedEtcdPath: "/registry/leases/" + namespace + "/leasev1beta1",
  218. },
  219. // --
  220. // k8s.io/kubernetes/pkg/apis/events/v1beta1
  221. gvr("events.k8s.io", "v1beta1", "events"): {
  222. Stub: `{"metadata": {"name": "event2"}, "regarding": {"namespace": "` + namespace + `"}, "note": "some data here", "eventTime": "2017-08-09T15:04:05.000000Z", "reportingInstance": "node-xyz", "reportingController": "k8s.io/my-controller", "action": "DidNothing", "reason": "Laziness"}`,
  223. ExpectedEtcdPath: "/registry/events/" + namespace + "/event2",
  224. ExpectedGVK: gvkP("", "v1", "Event"),
  225. },
  226. // --
  227. // k8s.io/kubernetes/pkg/apis/extensions/v1beta1
  228. gvr("extensions", "v1beta1", "daemonsets"): {
  229. Stub: `{"metadata": {"name": "ds1"}, "spec": {"selector": {"matchLabels": {"u": "t"}}, "template": {"metadata": {"labels": {"u": "t"}}, "spec": {"containers": [{"image": "fedora:latest", "name": "container5"}]}}}}`,
  230. ExpectedEtcdPath: "/registry/daemonsets/" + namespace + "/ds1",
  231. ExpectedGVK: gvkP("apps", "v1", "DaemonSet"),
  232. },
  233. gvr("extensions", "v1beta1", "podsecuritypolicies"): {
  234. Stub: `{"metadata": {"name": "psp1"}, "spec": {"fsGroup": {"rule": "RunAsAny"}, "privileged": true, "runAsUser": {"rule": "RunAsAny"}, "seLinux": {"rule": "MustRunAs"}, "supplementalGroups": {"rule": "RunAsAny"}}}`,
  235. ExpectedEtcdPath: "/registry/podsecuritypolicy/psp1",
  236. ExpectedGVK: gvkP("policy", "v1beta1", "PodSecurityPolicy"),
  237. },
  238. gvr("extensions", "v1beta1", "ingresses"): {
  239. Stub: `{"metadata": {"name": "ingress1"}, "spec": {"backend": {"serviceName": "service", "servicePort": 5000}}}`,
  240. ExpectedEtcdPath: "/registry/ingress/" + namespace + "/ingress1",
  241. ExpectedGVK: gvkP("networking.k8s.io", "v1beta1", "Ingress"),
  242. },
  243. gvr("extensions", "v1beta1", "networkpolicies"): {
  244. Stub: `{"metadata": {"name": "np1"}, "spec": {"podSelector": {"matchLabels": {"e": "f"}}}}`,
  245. ExpectedEtcdPath: "/registry/networkpolicies/" + namespace + "/np1",
  246. ExpectedGVK: gvkP("networking.k8s.io", "v1", "NetworkPolicy"),
  247. },
  248. gvr("extensions", "v1beta1", "deployments"): {
  249. Stub: `{"metadata": {"name": "deployment1"}, "spec": {"selector": {"matchLabels": {"f": "z"}}, "template": {"metadata": {"labels": {"f": "z"}}, "spec": {"containers": [{"image": "fedora:latest", "name": "container6"}]}}}}`,
  250. ExpectedEtcdPath: "/registry/deployments/" + namespace + "/deployment1",
  251. ExpectedGVK: gvkP("apps", "v1", "Deployment"),
  252. },
  253. gvr("extensions", "v1beta1", "replicasets"): {
  254. Stub: `{"metadata": {"name": "rs1"}, "spec": {"selector": {"matchLabels": {"g": "h"}}, "template": {"metadata": {"labels": {"g": "h"}}, "spec": {"containers": [{"image": "fedora:latest", "name": "container4"}]}}}}`,
  255. ExpectedEtcdPath: "/registry/replicasets/" + namespace + "/rs1",
  256. ExpectedGVK: gvkP("apps", "v1", "ReplicaSet"),
  257. },
  258. // --
  259. // k8s.io/kubernetes/pkg/apis/networking/v1beta1
  260. gvr("networking.k8s.io", "v1beta1", "ingresses"): {
  261. Stub: `{"metadata": {"name": "ingress2"}, "spec": {"backend": {"serviceName": "service", "servicePort": 5000}}}`,
  262. ExpectedEtcdPath: "/registry/ingress/" + namespace + "/ingress2",
  263. },
  264. // --
  265. // k8s.io/kubernetes/pkg/apis/networking/v1
  266. gvr("networking.k8s.io", "v1", "networkpolicies"): {
  267. Stub: `{"metadata": {"name": "np2"}, "spec": {"podSelector": {"matchLabels": {"e": "f"}}}}`,
  268. ExpectedEtcdPath: "/registry/networkpolicies/" + namespace + "/np2",
  269. },
  270. // --
  271. // k8s.io/kubernetes/pkg/apis/policy/v1beta1
  272. gvr("policy", "v1beta1", "poddisruptionbudgets"): {
  273. Stub: `{"metadata": {"name": "pdb1"}, "spec": {"selector": {"matchLabels": {"anokkey": "anokvalue"}}}}`,
  274. ExpectedEtcdPath: "/registry/poddisruptionbudgets/" + namespace + "/pdb1",
  275. },
  276. gvr("policy", "v1beta1", "podsecuritypolicies"): {
  277. Stub: `{"metadata": {"name": "psp2"}, "spec": {"fsGroup": {"rule": "RunAsAny"}, "privileged": true, "runAsUser": {"rule": "RunAsAny"}, "seLinux": {"rule": "MustRunAs"}, "supplementalGroups": {"rule": "RunAsAny"}}}`,
  278. ExpectedEtcdPath: "/registry/podsecuritypolicy/psp2",
  279. },
  280. // --
  281. // k8s.io/kubernetes/pkg/apis/storage/v1alpha1
  282. gvr("storage.k8s.io", "v1alpha1", "volumeattachments"): {
  283. Stub: `{"metadata": {"name": "va1"}, "spec": {"attacher": "gce", "nodeName": "localhost", "source": {"persistentVolumeName": "pv1"}}}`,
  284. ExpectedEtcdPath: "/registry/volumeattachments/va1",
  285. ExpectedGVK: gvkP("storage.k8s.io", "v1", "VolumeAttachment"),
  286. },
  287. // --
  288. // k8s.io/kubernetes/pkg/apis/storage/v1beta1
  289. gvr("storage.k8s.io", "v1beta1", "volumeattachments"): {
  290. Stub: `{"metadata": {"name": "va2"}, "spec": {"attacher": "gce", "nodeName": "localhost", "source": {"persistentVolumeName": "pv2"}}}`,
  291. ExpectedEtcdPath: "/registry/volumeattachments/va2",
  292. ExpectedGVK: gvkP("storage.k8s.io", "v1", "VolumeAttachment"),
  293. },
  294. // --
  295. // k8s.io/kubernetes/pkg/apis/storage/v1
  296. gvr("storage.k8s.io", "v1", "volumeattachments"): {
  297. Stub: `{"metadata": {"name": "va3"}, "spec": {"attacher": "gce", "nodeName": "localhost", "source": {"persistentVolumeName": "pv3"}}}`,
  298. ExpectedEtcdPath: "/registry/volumeattachments/va3",
  299. },
  300. // --
  301. // k8s.io/kubernetes/pkg/apis/storage/v1beta1
  302. gvr("storage.k8s.io", "v1beta1", "storageclasses"): {
  303. Stub: `{"metadata": {"name": "sc1"}, "provisioner": "aws"}`,
  304. ExpectedEtcdPath: "/registry/storageclasses/sc1",
  305. ExpectedGVK: gvkP("storage.k8s.io", "v1", "StorageClass"),
  306. },
  307. // --
  308. // k8s.io/kubernetes/pkg/apis/storage/v1
  309. gvr("storage.k8s.io", "v1", "storageclasses"): {
  310. Stub: `{"metadata": {"name": "sc2"}, "provisioner": "aws"}`,
  311. ExpectedEtcdPath: "/registry/storageclasses/sc2",
  312. },
  313. // --
  314. // k8s.io/kubernetes/pkg/apis/settings/v1alpha1
  315. gvr("settings.k8s.io", "v1alpha1", "podpresets"): {
  316. Stub: `{"metadata": {"name": "podpre1"}, "spec": {"env": [{"name": "FOO"}]}}`,
  317. ExpectedEtcdPath: "/registry/podpresets/" + namespace + "/podpre1",
  318. },
  319. // --
  320. // k8s.io/kubernetes/pkg/apis/rbac/v1alpha1
  321. gvr("rbac.authorization.k8s.io", "v1alpha1", "roles"): {
  322. Stub: `{"metadata": {"name": "role1"}, "rules": [{"apiGroups": ["v1"], "resources": ["events"], "verbs": ["watch"]}]}`,
  323. ExpectedEtcdPath: "/registry/roles/" + namespace + "/role1",
  324. ExpectedGVK: gvkP("rbac.authorization.k8s.io", "v1", "Role"),
  325. },
  326. gvr("rbac.authorization.k8s.io", "v1alpha1", "clusterroles"): {
  327. Stub: `{"metadata": {"name": "crole1"}, "rules": [{"nonResourceURLs": ["/version"], "verbs": ["get"]}]}`,
  328. ExpectedEtcdPath: "/registry/clusterroles/crole1",
  329. ExpectedGVK: gvkP("rbac.authorization.k8s.io", "v1", "ClusterRole"),
  330. },
  331. gvr("rbac.authorization.k8s.io", "v1alpha1", "rolebindings"): {
  332. Stub: `{"metadata": {"name": "roleb1"}, "roleRef": {"apiGroup": "rbac.authorization.k8s.io", "kind": "ClusterRole", "name": "somecr"}, "subjects": [{"apiVersion": "rbac.authorization.k8s.io/v1alpha1", "kind": "Group", "name": "system:authenticated"}]}`,
  333. ExpectedEtcdPath: "/registry/rolebindings/" + namespace + "/roleb1",
  334. ExpectedGVK: gvkP("rbac.authorization.k8s.io", "v1", "RoleBinding"),
  335. },
  336. gvr("rbac.authorization.k8s.io", "v1alpha1", "clusterrolebindings"): {
  337. Stub: `{"metadata": {"name": "croleb1"}, "roleRef": {"apiGroup": "rbac.authorization.k8s.io", "kind": "ClusterRole", "name": "somecr"}, "subjects": [{"apiVersion": "rbac.authorization.k8s.io/v1alpha1", "kind": "Group", "name": "system:authenticated"}]}`,
  338. ExpectedEtcdPath: "/registry/clusterrolebindings/croleb1",
  339. ExpectedGVK: gvkP("rbac.authorization.k8s.io", "v1", "ClusterRoleBinding"),
  340. },
  341. // --
  342. // k8s.io/kubernetes/pkg/apis/rbac/v1beta1
  343. gvr("rbac.authorization.k8s.io", "v1beta1", "roles"): {
  344. Stub: `{"metadata": {"name": "role2"}, "rules": [{"apiGroups": ["v1"], "resources": ["events"], "verbs": ["watch"]}]}`,
  345. ExpectedEtcdPath: "/registry/roles/" + namespace + "/role2",
  346. ExpectedGVK: gvkP("rbac.authorization.k8s.io", "v1", "Role"),
  347. },
  348. gvr("rbac.authorization.k8s.io", "v1beta1", "clusterroles"): {
  349. Stub: `{"metadata": {"name": "crole2"}, "rules": [{"nonResourceURLs": ["/version"], "verbs": ["get"]}]}`,
  350. ExpectedEtcdPath: "/registry/clusterroles/crole2",
  351. ExpectedGVK: gvkP("rbac.authorization.k8s.io", "v1", "ClusterRole"),
  352. },
  353. gvr("rbac.authorization.k8s.io", "v1beta1", "rolebindings"): {
  354. Stub: `{"metadata": {"name": "roleb2"}, "roleRef": {"apiGroup": "rbac.authorization.k8s.io", "kind": "ClusterRole", "name": "somecr"}, "subjects": [{"apiVersion": "rbac.authorization.k8s.io/v1alpha1", "kind": "Group", "name": "system:authenticated"}]}`,
  355. ExpectedEtcdPath: "/registry/rolebindings/" + namespace + "/roleb2",
  356. ExpectedGVK: gvkP("rbac.authorization.k8s.io", "v1", "RoleBinding"),
  357. },
  358. gvr("rbac.authorization.k8s.io", "v1beta1", "clusterrolebindings"): {
  359. Stub: `{"metadata": {"name": "croleb2"}, "roleRef": {"apiGroup": "rbac.authorization.k8s.io", "kind": "ClusterRole", "name": "somecr"}, "subjects": [{"apiVersion": "rbac.authorization.k8s.io/v1alpha1", "kind": "Group", "name": "system:authenticated"}]}`,
  360. ExpectedEtcdPath: "/registry/clusterrolebindings/croleb2",
  361. ExpectedGVK: gvkP("rbac.authorization.k8s.io", "v1", "ClusterRoleBinding"),
  362. },
  363. // --
  364. // k8s.io/kubernetes/pkg/apis/rbac/v1
  365. gvr("rbac.authorization.k8s.io", "v1", "roles"): {
  366. Stub: `{"metadata": {"name": "role3"}, "rules": [{"apiGroups": ["v1"], "resources": ["events"], "verbs": ["watch"]}]}`,
  367. ExpectedEtcdPath: "/registry/roles/" + namespace + "/role3",
  368. },
  369. gvr("rbac.authorization.k8s.io", "v1", "clusterroles"): {
  370. Stub: `{"metadata": {"name": "crole3"}, "rules": [{"nonResourceURLs": ["/version"], "verbs": ["get"]}]}`,
  371. ExpectedEtcdPath: "/registry/clusterroles/crole3",
  372. },
  373. gvr("rbac.authorization.k8s.io", "v1", "rolebindings"): {
  374. Stub: `{"metadata": {"name": "roleb3"}, "roleRef": {"apiGroup": "rbac.authorization.k8s.io", "kind": "ClusterRole", "name": "somecr"}, "subjects": [{"apiVersion": "rbac.authorization.k8s.io/v1alpha1", "kind": "Group", "name": "system:authenticated"}]}`,
  375. ExpectedEtcdPath: "/registry/rolebindings/" + namespace + "/roleb3",
  376. },
  377. gvr("rbac.authorization.k8s.io", "v1", "clusterrolebindings"): {
  378. Stub: `{"metadata": {"name": "croleb3"}, "roleRef": {"apiGroup": "rbac.authorization.k8s.io", "kind": "ClusterRole", "name": "somecr"}, "subjects": [{"apiVersion": "rbac.authorization.k8s.io/v1alpha1", "kind": "Group", "name": "system:authenticated"}]}`,
  379. ExpectedEtcdPath: "/registry/clusterrolebindings/croleb3",
  380. },
  381. // --
  382. // k8s.io/kubernetes/pkg/apis/admissionregistration/v1beta1
  383. gvr("admissionregistration.k8s.io", "v1beta1", "validatingwebhookconfigurations"): {
  384. Stub: `{"metadata":{"name":"hook1","creationTimestamp":null},"webhooks":[{"name":"externaladmissionhook.k8s.io","clientConfig":{"service":{"namespace":"ns","name":"n"},"caBundle":null},"rules":[{"operations":["CREATE"],"apiGroups":["group"],"apiVersions":["version"],"resources":["resource"]}],"failurePolicy":"Ignore"}]}`,
  385. ExpectedEtcdPath: "/registry/validatingwebhookconfigurations/hook1",
  386. },
  387. gvr("admissionregistration.k8s.io", "v1beta1", "mutatingwebhookconfigurations"): {
  388. Stub: `{"metadata":{"name":"hook1","creationTimestamp":null},"webhooks":[{"name":"externaladmissionhook.k8s.io","clientConfig":{"service":{"namespace":"ns","name":"n"},"caBundle":null},"rules":[{"operations":["CREATE"],"apiGroups":["group"],"apiVersions":["version"],"resources":["resource"]}],"failurePolicy":"Ignore"}]}`,
  389. ExpectedEtcdPath: "/registry/mutatingwebhookconfigurations/hook1",
  390. },
  391. // --
  392. // k8s.io/kubernetes/pkg/apis/scheduling/v1alpha1
  393. gvr("scheduling.k8s.io", "v1alpha1", "priorityclasses"): {
  394. Stub: `{"metadata":{"name":"pc1"},"Value":1000}`,
  395. ExpectedEtcdPath: "/registry/priorityclasses/pc1",
  396. ExpectedGVK: gvkP("scheduling.k8s.io", "v1", "PriorityClass"),
  397. },
  398. // --
  399. // k8s.io/kubernetes/pkg/apis/scheduling/v1beta1
  400. gvr("scheduling.k8s.io", "v1beta1", "priorityclasses"): {
  401. Stub: `{"metadata":{"name":"pc2"},"Value":1000}`,
  402. ExpectedEtcdPath: "/registry/priorityclasses/pc2",
  403. ExpectedGVK: gvkP("scheduling.k8s.io", "v1", "PriorityClass"),
  404. },
  405. // --
  406. // k8s.io/kubernetes/pkg/apis/scheduling/v1
  407. gvr("scheduling.k8s.io", "v1", "priorityclasses"): {
  408. Stub: `{"metadata":{"name":"pc3"},"Value":1000}`,
  409. ExpectedEtcdPath: "/registry/priorityclasses/pc3",
  410. },
  411. // --
  412. // k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1
  413. // depends on aggregator using the same ungrouped RESTOptionsGetter as the kube apiserver, not SimpleRestOptionsFactory in aggregator.go
  414. gvr("apiregistration.k8s.io", "v1beta1", "apiservices"): {
  415. Stub: `{"metadata": {"name": "as1.foo.com"}, "spec": {"group": "foo.com", "version": "as1", "groupPriorityMinimum":100, "versionPriority":10}}`,
  416. ExpectedEtcdPath: "/registry/apiregistration.k8s.io/apiservices/as1.foo.com",
  417. },
  418. // --
  419. // k8s.io/kube-aggregator/pkg/apis/apiregistration/v1
  420. // depends on aggregator using the same ungrouped RESTOptionsGetter as the kube apiserver, not SimpleRestOptionsFactory in aggregator.go
  421. gvr("apiregistration.k8s.io", "v1", "apiservices"): {
  422. Stub: `{"metadata": {"name": "as2.foo.com"}, "spec": {"group": "foo.com", "version": "as2", "groupPriorityMinimum":100, "versionPriority":10}}`,
  423. ExpectedEtcdPath: "/registry/apiregistration.k8s.io/apiservices/as2.foo.com",
  424. ExpectedGVK: gvkP("apiregistration.k8s.io", "v1beta1", "APIService"),
  425. },
  426. // --
  427. // k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1
  428. gvr("apiextensions.k8s.io", "v1beta1", "customresourcedefinitions"): {
  429. Stub: `{"metadata": {"name": "openshiftwebconsoleconfigs.webconsole.operator.openshift.io"},"spec": {"scope": "Cluster","group": "webconsole.operator.openshift.io","version": "v1alpha1","names": {"kind": "OpenShiftWebConsoleConfig","plural": "openshiftwebconsoleconfigs","singular": "openshiftwebconsoleconfig"}}}`,
  430. ExpectedEtcdPath: "/registry/apiextensions.k8s.io/customresourcedefinitions/openshiftwebconsoleconfigs.webconsole.operator.openshift.io",
  431. },
  432. gvr("cr.bar.com", "v1", "foos"): {
  433. Stub: `{"kind": "Foo", "apiVersion": "cr.bar.com/v1", "metadata": {"name": "cr1foo"}, "color": "blue"}`, // requires TypeMeta due to CRD scheme's UnstructuredObjectTyper
  434. ExpectedEtcdPath: "/registry/cr.bar.com/foos/" + namespace + "/cr1foo",
  435. },
  436. gvr("custom.fancy.com", "v2", "pants"): {
  437. Stub: `{"kind": "Pant", "apiVersion": "custom.fancy.com/v2", "metadata": {"name": "cr2pant"}, "isFancy": true}`, // requires TypeMeta due to CRD scheme's UnstructuredObjectTyper
  438. ExpectedEtcdPath: "/registry/custom.fancy.com/pants/cr2pant",
  439. },
  440. gvr("awesome.bears.com", "v1", "pandas"): {
  441. Stub: `{"kind": "Panda", "apiVersion": "awesome.bears.com/v1", "metadata": {"name": "cr3panda"}, "spec":{"replicas": 100}}`, // requires TypeMeta due to CRD scheme's UnstructuredObjectTyper
  442. ExpectedEtcdPath: "/registry/awesome.bears.com/pandas/cr3panda",
  443. },
  444. gvr("awesome.bears.com", "v3", "pandas"): {
  445. Stub: `{"kind": "Panda", "apiVersion": "awesome.bears.com/v3", "metadata": {"name": "cr4panda"}, "spec":{"replicas": 300}}`, // requires TypeMeta due to CRD scheme's UnstructuredObjectTyper
  446. ExpectedEtcdPath: "/registry/awesome.bears.com/pandas/cr4panda",
  447. ExpectedGVK: gvkP("awesome.bears.com", "v1", "Panda"),
  448. },
  449. gvr("random.numbers.com", "v1", "integers"): {
  450. Stub: `{"kind": "Integer", "apiVersion": "random.numbers.com/v1", "metadata": {"name": "fortytwo"}, "value": 42, "garbage": "oiujnasdf"}`, // requires TypeMeta due to CRD scheme's UnstructuredObjectTyper
  451. ExpectedEtcdPath: "/registry/random.numbers.com/integers/fortytwo",
  452. },
  453. // --
  454. // k8s.io/kubernetes/pkg/apis/auditregistration/v1alpha1
  455. gvr("auditregistration.k8s.io", "v1alpha1", "auditsinks"): {
  456. Stub: `{"metadata":{"name":"sink1"},"spec":{"policy":{"level":"Metadata","stages":["ResponseStarted"]},"webhook":{"clientConfig":{"url":"http://localhost:4444","service":null,"caBundle":null}}}}`,
  457. ExpectedEtcdPath: "/registry/auditsinks/sink1",
  458. },
  459. // --
  460. // k8s.io/kubernetes/pkg/apis/node/v1alpha1
  461. gvr("node.k8s.io", "v1alpha1", "runtimeclasses"): {
  462. Stub: `{"metadata": {"name": "rc1"}, "spec": {"runtimeHandler": "h1"}}`,
  463. ExpectedEtcdPath: "/registry/runtimeclasses/rc1",
  464. ExpectedGVK: gvkP("node.k8s.io", "v1beta1", "RuntimeClass"),
  465. },
  466. // --
  467. // k8s.io/kubernetes/pkg/apis/node/v1beta1
  468. gvr("node.k8s.io", "v1beta1", "runtimeclasses"): {
  469. Stub: `{"metadata": {"name": "rc2"}, "handler": "h2"}`,
  470. ExpectedEtcdPath: "/registry/runtimeclasses/rc2",
  471. },
  472. // --
  473. }
  474. // k8s.io/kubernetes/pkg/apis/storage/v1beta1
  475. // add csinodes if CSINodeInfo feature gate is enabled
  476. if utilfeature.DefaultFeatureGate.Enabled(features.CSINodeInfo) {
  477. etcdStorageData[gvr("storage.k8s.io", "v1beta1", "csinodes")] = StorageData{
  478. Stub: `{"metadata": {"name": "csini1"}, "spec": {"drivers": [{"name": "test-driver", "nodeID": "localhost", "topologyKeys": ["company.com/zone1", "company.com/zone2"]}]}}`,
  479. ExpectedEtcdPath: "/registry/csinodes/csini1",
  480. }
  481. }
  482. // k8s.io/kubernetes/pkg/apis/storage/v1beta1
  483. // add csidrivers if CSIDriverRegistry feature gate is enabled
  484. if utilfeature.DefaultFeatureGate.Enabled(features.CSIDriverRegistry) {
  485. etcdStorageData[gvr("storage.k8s.io", "v1beta1", "csidrivers")] = StorageData{
  486. Stub: `{"metadata": {"name": "csid1"}, "spec": {"attachRequired": true, "podInfoOnMount": true}}`,
  487. ExpectedEtcdPath: "/registry/csidrivers/csid1",
  488. }
  489. }
  490. return etcdStorageData
  491. }
  492. // StorageData contains information required to create an object and verify its storage in etcd
  493. // It must be paired with a specific resource
  494. type StorageData struct {
  495. Stub string // Valid JSON stub to use during create
  496. Prerequisites []Prerequisite // Optional, ordered list of JSON objects to create before stub
  497. ExpectedEtcdPath string // Expected location of object in etcd, do not use any variables, constants, etc to derive this value - always supply the full raw string
  498. ExpectedGVK *schema.GroupVersionKind // The GVK that we expect this object to be stored as - leave this nil to use the default
  499. }
  500. // Prerequisite contains information required to create a resource (but not verify it)
  501. type Prerequisite struct {
  502. GvrData schema.GroupVersionResource
  503. Stub string
  504. }
  505. // GetCustomResourceDefinitionData returns the resource definitions that back the custom resources
  506. // included in GetEtcdStorageData. They should be created using CreateTestCRDs before running any tests.
  507. func GetCustomResourceDefinitionData() []*apiextensionsv1beta1.CustomResourceDefinition {
  508. return []*apiextensionsv1beta1.CustomResourceDefinition{
  509. // namespaced with legacy version field
  510. {
  511. ObjectMeta: metav1.ObjectMeta{
  512. Name: "foos.cr.bar.com",
  513. },
  514. Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
  515. Group: "cr.bar.com",
  516. Version: "v1",
  517. Scope: apiextensionsv1beta1.NamespaceScoped,
  518. Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
  519. Plural: "foos",
  520. Kind: "Foo",
  521. },
  522. },
  523. },
  524. // cluster scoped with legacy version field
  525. {
  526. ObjectMeta: metav1.ObjectMeta{
  527. Name: "pants.custom.fancy.com",
  528. },
  529. Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
  530. Group: "custom.fancy.com",
  531. Version: "v2",
  532. Scope: apiextensionsv1beta1.ClusterScoped,
  533. Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
  534. Plural: "pants",
  535. Kind: "Pant",
  536. },
  537. },
  538. },
  539. // cluster scoped with legacy version field and pruning.
  540. {
  541. ObjectMeta: metav1.ObjectMeta{
  542. Name: "integers.random.numbers.com",
  543. },
  544. Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
  545. Group: "random.numbers.com",
  546. Version: "v1",
  547. Scope: apiextensionsv1beta1.ClusterScoped,
  548. Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
  549. Plural: "integers",
  550. Kind: "Integer",
  551. },
  552. Validation: &apiextensionsv1beta1.CustomResourceValidation{
  553. OpenAPIV3Schema: &apiextensionsv1beta1.JSONSchemaProps{
  554. Type: "object",
  555. Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{
  556. "value": {
  557. Type: "number",
  558. },
  559. },
  560. },
  561. },
  562. PreserveUnknownFields: pointer.BoolPtr(false),
  563. },
  564. },
  565. // cluster scoped with versions field
  566. {
  567. ObjectMeta: metav1.ObjectMeta{
  568. Name: "pandas.awesome.bears.com",
  569. },
  570. Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
  571. Group: "awesome.bears.com",
  572. Versions: []apiextensionsv1beta1.CustomResourceDefinitionVersion{
  573. {
  574. Name: "v1",
  575. Served: true,
  576. Storage: true,
  577. },
  578. {
  579. Name: "v2",
  580. Served: false,
  581. Storage: false,
  582. },
  583. {
  584. Name: "v3",
  585. Served: true,
  586. Storage: false,
  587. },
  588. },
  589. Scope: apiextensionsv1beta1.ClusterScoped,
  590. Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
  591. Plural: "pandas",
  592. Kind: "Panda",
  593. },
  594. Subresources: &apiextensionsv1beta1.CustomResourceSubresources{
  595. Status: &apiextensionsv1beta1.CustomResourceSubresourceStatus{},
  596. Scale: &apiextensionsv1beta1.CustomResourceSubresourceScale{
  597. SpecReplicasPath: ".spec.replicas",
  598. StatusReplicasPath: ".status.replicas",
  599. LabelSelectorPath: func() *string { path := ".status.selector"; return &path }(),
  600. },
  601. },
  602. },
  603. },
  604. }
  605. }
  606. func gvr(g, v, r string) schema.GroupVersionResource {
  607. return schema.GroupVersionResource{Group: g, Version: v, Resource: r}
  608. }
  609. func gvkP(g, v, k string) *schema.GroupVersionKind {
  610. return &schema.GroupVersionKind{Group: g, Version: v, Kind: k}
  611. }