admission_test.go 68 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477
  1. /*
  2. Copyright 2017 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 noderestriction
  14. import (
  15. "context"
  16. "fmt"
  17. "reflect"
  18. "strings"
  19. "testing"
  20. "time"
  21. corev1 "k8s.io/api/core/v1"
  22. v1 "k8s.io/api/core/v1"
  23. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  24. "k8s.io/apimachinery/pkg/runtime/schema"
  25. "k8s.io/apimachinery/pkg/types"
  26. utilruntime "k8s.io/apimachinery/pkg/util/runtime"
  27. "k8s.io/apimachinery/pkg/util/sets"
  28. "k8s.io/apiserver/pkg/admission"
  29. "k8s.io/apiserver/pkg/authentication/user"
  30. corev1lister "k8s.io/client-go/listers/core/v1"
  31. "k8s.io/client-go/tools/cache"
  32. "k8s.io/component-base/featuregate"
  33. authenticationapi "k8s.io/kubernetes/pkg/apis/authentication"
  34. "k8s.io/kubernetes/pkg/apis/coordination"
  35. api "k8s.io/kubernetes/pkg/apis/core"
  36. "k8s.io/kubernetes/pkg/apis/policy"
  37. storage "k8s.io/kubernetes/pkg/apis/storage"
  38. "k8s.io/kubernetes/pkg/auth/nodeidentifier"
  39. "k8s.io/kubernetes/pkg/features"
  40. kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
  41. "k8s.io/utils/pointer"
  42. )
  43. var (
  44. trEnabledFeature = featuregate.NewFeatureGate()
  45. csiNodeInfoEnabledFeature = featuregate.NewFeatureGate()
  46. csiNodeInfoDisabledFeature = featuregate.NewFeatureGate()
  47. )
  48. func init() {
  49. // all features need to be set on all featuregates for the tests. We set everything and then then the if's below override it.
  50. relevantFeatures := map[featuregate.Feature]featuregate.FeatureSpec{
  51. features.TokenRequest: {Default: false},
  52. features.CSINodeInfo: {Default: false},
  53. features.ExpandPersistentVolumes: {Default: false},
  54. }
  55. utilruntime.Must(trEnabledFeature.Add(relevantFeatures))
  56. utilruntime.Must(csiNodeInfoEnabledFeature.Add(relevantFeatures))
  57. utilruntime.Must(csiNodeInfoDisabledFeature.Add(relevantFeatures))
  58. utilruntime.Must(trEnabledFeature.SetFromMap(map[string]bool{string(features.TokenRequest): true}))
  59. utilruntime.Must(csiNodeInfoEnabledFeature.SetFromMap(map[string]bool{string(features.CSINodeInfo): true}))
  60. }
  61. func makeTestPod(namespace, name, node string, mirror bool) (*api.Pod, *corev1.Pod) {
  62. corePod := &api.Pod{}
  63. corePod.Namespace = namespace
  64. corePod.UID = types.UID("pod-uid")
  65. corePod.Name = name
  66. corePod.Spec.NodeName = node
  67. v1Pod := &corev1.Pod{}
  68. v1Pod.Namespace = namespace
  69. v1Pod.UID = types.UID("pod-uid")
  70. v1Pod.Name = name
  71. v1Pod.Spec.NodeName = node
  72. if mirror {
  73. corePod.Annotations = map[string]string{api.MirrorPodAnnotationKey: "true"}
  74. v1Pod.Annotations = map[string]string{api.MirrorPodAnnotationKey: "true"}
  75. // Insert a valid owner reference by default.
  76. controller := true
  77. owner := metav1.OwnerReference{
  78. APIVersion: "v1",
  79. Kind: "Node",
  80. Name: node,
  81. UID: types.UID(node + "-uid"),
  82. Controller: &controller,
  83. }
  84. corePod.OwnerReferences = []metav1.OwnerReference{owner}
  85. v1Pod.OwnerReferences = []metav1.OwnerReference{owner}
  86. }
  87. return corePod, v1Pod
  88. }
  89. func withLabels(pod *api.Pod, labels map[string]string) *api.Pod {
  90. labeledPod := pod.DeepCopy()
  91. if labels == nil {
  92. labeledPod.Labels = nil
  93. return labeledPod
  94. }
  95. // Clone.
  96. labeledPod.Labels = map[string]string{}
  97. for key, value := range labels {
  98. labeledPod.Labels[key] = value
  99. }
  100. return labeledPod
  101. }
  102. func makeTestPodEviction(name string) *policy.Eviction {
  103. eviction := &policy.Eviction{}
  104. eviction.Name = name
  105. eviction.Namespace = "ns"
  106. return eviction
  107. }
  108. func makeTokenRequest(podname string, poduid types.UID) *authenticationapi.TokenRequest {
  109. tr := &authenticationapi.TokenRequest{
  110. Spec: authenticationapi.TokenRequestSpec{
  111. Audiences: []string{"foo"},
  112. },
  113. }
  114. if podname != "" {
  115. tr.Spec.BoundObjectRef = &authenticationapi.BoundObjectReference{
  116. Kind: "Pod",
  117. APIVersion: "v1",
  118. Name: podname,
  119. UID: poduid,
  120. }
  121. }
  122. return tr
  123. }
  124. func setAllLabels(node *api.Node, value string) *api.Node {
  125. node = setAllowedCreateLabels(node, value)
  126. node = setAllowedUpdateLabels(node, value)
  127. node = setForbiddenCreateLabels(node, value)
  128. node = setForbiddenUpdateLabels(node, value)
  129. return node
  130. }
  131. func setAllowedCreateLabels(node *api.Node, value string) *api.Node {
  132. node = setAllowedUpdateLabels(node, value)
  133. // also allow other kubernetes labels on create until 1.17 (TODO: remove this in 1.17)
  134. node.Labels["other.kubernetes.io/foo"] = value
  135. node.Labels["other.k8s.io/foo"] = value
  136. return node
  137. }
  138. func setAllowedUpdateLabels(node *api.Node, value string) *api.Node {
  139. node = node.DeepCopy()
  140. if node.Labels == nil {
  141. node.Labels = map[string]string{}
  142. }
  143. if value == "" {
  144. value = "value"
  145. }
  146. // non-kube labels
  147. node.Labels["foo"] = value
  148. node.Labels["example.com/foo"] = value
  149. // kubelet labels
  150. node.Labels["kubernetes.io/hostname"] = value
  151. node.Labels["failure-domain.beta.kubernetes.io/zone"] = value
  152. node.Labels["failure-domain.beta.kubernetes.io/region"] = value
  153. node.Labels["topology.kubernetes.io/zone"] = value
  154. node.Labels["topology.kubernetes.io/region"] = value
  155. node.Labels["beta.kubernetes.io/instance-type"] = value
  156. node.Labels["node.kubernetes.io/instance-type"] = value
  157. node.Labels["beta.kubernetes.io/os"] = value
  158. node.Labels["beta.kubernetes.io/arch"] = value
  159. node.Labels["kubernetes.io/os"] = value
  160. node.Labels["kubernetes.io/arch"] = value
  161. // kubelet label prefixes
  162. node.Labels["kubelet.kubernetes.io/foo"] = value
  163. node.Labels["foo.kubelet.kubernetes.io/foo"] = value
  164. node.Labels["node.kubernetes.io/foo"] = value
  165. node.Labels["foo.node.kubernetes.io/foo"] = value
  166. // test all explicitly allowed labels and prefixes
  167. for _, key := range kubeletapis.KubeletLabels() {
  168. node.Labels[key] = value
  169. }
  170. for _, namespace := range kubeletapis.KubeletLabelNamespaces() {
  171. node.Labels[namespace+"/foo"] = value
  172. node.Labels["foo."+namespace+"/foo"] = value
  173. }
  174. return node
  175. }
  176. func setForbiddenCreateLabels(node *api.Node, value string) *api.Node {
  177. node = node.DeepCopy()
  178. if node.Labels == nil {
  179. node.Labels = map[string]string{}
  180. }
  181. if value == "" {
  182. value = "value"
  183. }
  184. // node restriction labels are forbidden
  185. node.Labels["node-restriction.kubernetes.io/foo"] = value
  186. node.Labels["foo.node-restriction.kubernetes.io/foo"] = value
  187. // TODO: in 1.17, forbid arbitrary kubernetes labels on create
  188. // node.Labels["other.kubernetes.io/foo"] = value
  189. // node.Labels["other.k8s.io/foo"] = value
  190. return node
  191. }
  192. func setForbiddenUpdateLabels(node *api.Node, value string) *api.Node {
  193. node = node.DeepCopy()
  194. if node.Labels == nil {
  195. node.Labels = map[string]string{}
  196. }
  197. if value == "" {
  198. value = "value"
  199. }
  200. // node restriction labels are forbidden
  201. node.Labels["node-restriction.kubernetes.io/foo"] = value
  202. node.Labels["foo.node-restriction.kubernetes.io/foo"] = value
  203. // arbitrary kubernetes labels are forbidden on update
  204. node.Labels["other.kubernetes.io/foo"] = value
  205. node.Labels["other.k8s.io/foo"] = value
  206. return node
  207. }
  208. type admitTestCase struct {
  209. name string
  210. podsGetter corev1lister.PodLister
  211. nodesGetter corev1lister.NodeLister
  212. attributes admission.Attributes
  213. features featuregate.FeatureGate
  214. err string
  215. }
  216. func (a *admitTestCase) run(t *testing.T) {
  217. t.Run(a.name, func(t *testing.T) {
  218. c := NewPlugin(nodeidentifier.NewDefaultNodeIdentifier())
  219. if a.features != nil {
  220. c.InspectFeatureGates(a.features)
  221. }
  222. c.podsGetter = a.podsGetter
  223. c.nodesGetter = a.nodesGetter
  224. err := c.Admit(context.TODO(), a.attributes, nil)
  225. if (err == nil) != (len(a.err) == 0) {
  226. t.Errorf("nodePlugin.Admit() error = %v, expected %v", err, a.err)
  227. return
  228. }
  229. if len(a.err) > 0 && !strings.Contains(err.Error(), a.err) {
  230. t.Errorf("nodePlugin.Admit() error = %v, expected %v", err, a.err)
  231. }
  232. })
  233. }
  234. func Test_nodePlugin_Admit(t *testing.T) {
  235. var (
  236. mynode = &user.DefaultInfo{Name: "system:node:mynode", Groups: []string{"system:nodes"}}
  237. bob = &user.DefaultInfo{Name: "bob"}
  238. mynodeObjMeta = metav1.ObjectMeta{Name: "mynode", UID: "mynode-uid"}
  239. mynodeObj = &api.Node{ObjectMeta: mynodeObjMeta}
  240. mynodeObjConfigA = &api.Node{ObjectMeta: mynodeObjMeta, Spec: api.NodeSpec{ConfigSource: &api.NodeConfigSource{
  241. ConfigMap: &api.ConfigMapNodeConfigSource{
  242. Name: "foo",
  243. Namespace: "bar",
  244. UID: "fooUID",
  245. KubeletConfigKey: "kubelet",
  246. }}}}
  247. mynodeObjConfigB = &api.Node{ObjectMeta: mynodeObjMeta, Spec: api.NodeSpec{ConfigSource: &api.NodeConfigSource{
  248. ConfigMap: &api.ConfigMapNodeConfigSource{
  249. Name: "qux",
  250. Namespace: "bar",
  251. UID: "quxUID",
  252. KubeletConfigKey: "kubelet",
  253. }}}}
  254. mynodeObjTaintA = &api.Node{ObjectMeta: mynodeObjMeta, Spec: api.NodeSpec{Taints: []api.Taint{{Key: "mykey", Value: "A"}}}}
  255. mynodeObjTaintB = &api.Node{ObjectMeta: mynodeObjMeta, Spec: api.NodeSpec{Taints: []api.Taint{{Key: "mykey", Value: "B"}}}}
  256. othernodeObj = &api.Node{ObjectMeta: metav1.ObjectMeta{Name: "othernode"}}
  257. coremymirrorpod, v1mymirrorpod = makeTestPod("ns", "mymirrorpod", "mynode", true)
  258. coreothermirrorpod, v1othermirrorpod = makeTestPod("ns", "othermirrorpod", "othernode", true)
  259. coreunboundmirrorpod, v1unboundmirrorpod = makeTestPod("ns", "unboundmirrorpod", "", true)
  260. coremypod, v1mypod = makeTestPod("ns", "mypod", "mynode", false)
  261. coreotherpod, v1otherpod = makeTestPod("ns", "otherpod", "othernode", false)
  262. coreunboundpod, v1unboundpod = makeTestPod("ns", "unboundpod", "", false)
  263. coreunnamedpod, _ = makeTestPod("ns", "", "mynode", false)
  264. mymirrorpodEviction = makeTestPodEviction("mymirrorpod")
  265. othermirrorpodEviction = makeTestPodEviction("othermirrorpod")
  266. unboundmirrorpodEviction = makeTestPodEviction("unboundmirrorpod")
  267. mypodEviction = makeTestPodEviction("mypod")
  268. otherpodEviction = makeTestPodEviction("otherpod")
  269. unboundpodEviction = makeTestPodEviction("unboundpod")
  270. unnamedEviction = makeTestPodEviction("")
  271. configmapResource = api.Resource("configmap").WithVersion("v1")
  272. configmapKind = api.Kind("ConfigMap").WithVersion("v1")
  273. podResource = api.Resource("pods").WithVersion("v1")
  274. podKind = api.Kind("Pod").WithVersion("v1")
  275. evictionKind = policy.Kind("Eviction").WithVersion("v1beta1")
  276. nodeResource = api.Resource("nodes").WithVersion("v1")
  277. nodeKind = api.Kind("Node").WithVersion("v1")
  278. svcacctResource = api.Resource("serviceaccounts").WithVersion("v1")
  279. tokenrequestKind = api.Kind("TokenRequest").WithVersion("v1")
  280. leaseResource = coordination.Resource("leases").WithVersion("v1beta1")
  281. leaseKind = coordination.Kind("Lease").WithVersion("v1beta1")
  282. lease = &coordination.Lease{
  283. ObjectMeta: metav1.ObjectMeta{
  284. Name: "mynode",
  285. Namespace: api.NamespaceNodeLease,
  286. },
  287. Spec: coordination.LeaseSpec{
  288. HolderIdentity: pointer.StringPtr("mynode"),
  289. LeaseDurationSeconds: pointer.Int32Ptr(40),
  290. RenewTime: &metav1.MicroTime{Time: time.Now()},
  291. },
  292. }
  293. leaseWrongNS = &coordination.Lease{
  294. ObjectMeta: metav1.ObjectMeta{
  295. Name: "mynode",
  296. Namespace: "foo",
  297. },
  298. Spec: coordination.LeaseSpec{
  299. HolderIdentity: pointer.StringPtr("mynode"),
  300. LeaseDurationSeconds: pointer.Int32Ptr(40),
  301. RenewTime: &metav1.MicroTime{Time: time.Now()},
  302. },
  303. }
  304. leaseWrongName = &coordination.Lease{
  305. ObjectMeta: metav1.ObjectMeta{
  306. Name: "foo",
  307. Namespace: api.NamespaceNodeLease,
  308. },
  309. Spec: coordination.LeaseSpec{
  310. HolderIdentity: pointer.StringPtr("mynode"),
  311. LeaseDurationSeconds: pointer.Int32Ptr(40),
  312. RenewTime: &metav1.MicroTime{Time: time.Now()},
  313. },
  314. }
  315. csiNodeResource = storage.Resource("csinodes").WithVersion("v1")
  316. csiNodeKind = schema.GroupVersionKind{Group: "storage.k8s.io", Version: "v1", Kind: "CSINode"}
  317. nodeInfo = &storage.CSINode{
  318. ObjectMeta: metav1.ObjectMeta{
  319. Name: "mynode",
  320. },
  321. Spec: storage.CSINodeSpec{
  322. Drivers: []storage.CSINodeDriver{
  323. {
  324. Name: "com.example.csi/mydriver",
  325. NodeID: "com.example.csi/mynode",
  326. TopologyKeys: []string{"com.example.csi/zone"},
  327. },
  328. },
  329. },
  330. }
  331. nodeInfoWrongName = &storage.CSINode{
  332. ObjectMeta: metav1.ObjectMeta{
  333. Name: "foo",
  334. },
  335. Spec: storage.CSINodeSpec{
  336. Drivers: []storage.CSINodeDriver{
  337. {
  338. Name: "com.example.csi/mydriver",
  339. NodeID: "com.example.csi/foo",
  340. TopologyKeys: []string{"com.example.csi/zone"},
  341. },
  342. },
  343. },
  344. }
  345. existingNodesIndex = cache.NewIndexer(cache.MetaNamespaceKeyFunc, nil)
  346. existingNodes = corev1lister.NewNodeLister(existingNodesIndex)
  347. noExistingPodsIndex = cache.NewIndexer(cache.MetaNamespaceKeyFunc, nil)
  348. noExistingPods = corev1lister.NewPodLister(noExistingPodsIndex)
  349. existingPodsIndex = cache.NewIndexer(cache.MetaNamespaceKeyFunc, nil)
  350. existingPods = corev1lister.NewPodLister(existingPodsIndex)
  351. labelsA = map[string]string{
  352. "label-a": "value-a",
  353. }
  354. labelsAB = map[string]string{
  355. "label-a": "value-a",
  356. "label-b": "value-b",
  357. }
  358. aLabeledPod = withLabels(coremypod, labelsA)
  359. abLabeledPod = withLabels(coremypod, labelsAB)
  360. )
  361. existingPodsIndex.Add(v1mymirrorpod)
  362. existingPodsIndex.Add(v1othermirrorpod)
  363. existingPodsIndex.Add(v1unboundmirrorpod)
  364. existingPodsIndex.Add(v1mypod)
  365. existingPodsIndex.Add(v1otherpod)
  366. existingPodsIndex.Add(v1unboundpod)
  367. existingNodesIndex.Add(&v1.Node{ObjectMeta: mynodeObjMeta})
  368. sapod, _ := makeTestPod("ns", "mysapod", "mynode", true)
  369. sapod.Spec.ServiceAccountName = "foo"
  370. secretpod, _ := makeTestPod("ns", "mysecretpod", "mynode", true)
  371. secretpod.Spec.Volumes = []api.Volume{{VolumeSource: api.VolumeSource{Secret: &api.SecretVolumeSource{SecretName: "foo"}}}}
  372. configmappod, _ := makeTestPod("ns", "myconfigmappod", "mynode", true)
  373. configmappod.Spec.Volumes = []api.Volume{{VolumeSource: api.VolumeSource{ConfigMap: &api.ConfigMapVolumeSource{LocalObjectReference: api.LocalObjectReference{Name: "foo"}}}}}
  374. pvcpod, _ := makeTestPod("ns", "mypvcpod", "mynode", true)
  375. pvcpod.Spec.Volumes = []api.Volume{{VolumeSource: api.VolumeSource{PersistentVolumeClaim: &api.PersistentVolumeClaimVolumeSource{ClaimName: "foo"}}}}
  376. tests := []admitTestCase{
  377. // Mirror pods bound to us
  378. {
  379. name: "allow creating a mirror pod bound to self",
  380. podsGetter: noExistingPods,
  381. attributes: admission.NewAttributesRecord(coremymirrorpod, nil, podKind, coremymirrorpod.Namespace, coremymirrorpod.Name, podResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode),
  382. err: "",
  383. },
  384. {
  385. name: "forbid update of mirror pod bound to self",
  386. podsGetter: existingPods,
  387. attributes: admission.NewAttributesRecord(coremymirrorpod, coremymirrorpod, podKind, coremymirrorpod.Namespace, coremymirrorpod.Name, podResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  388. err: "forbidden: unexpected operation",
  389. },
  390. {
  391. name: "allow delete of mirror pod bound to self",
  392. podsGetter: existingPods,
  393. attributes: admission.NewAttributesRecord(nil, nil, podKind, coremymirrorpod.Namespace, coremymirrorpod.Name, podResource, "", admission.Delete, &metav1.DeleteOptions{}, false, mynode),
  394. err: "",
  395. },
  396. {
  397. name: "forbid create of mirror pod status bound to self",
  398. podsGetter: noExistingPods,
  399. attributes: admission.NewAttributesRecord(coremymirrorpod, nil, podKind, coremymirrorpod.Namespace, coremymirrorpod.Name, podResource, "status", admission.Create, &metav1.CreateOptions{}, false, mynode),
  400. err: "forbidden: unexpected operation",
  401. },
  402. {
  403. name: "allow update of mirror pod status bound to self",
  404. podsGetter: existingPods,
  405. attributes: admission.NewAttributesRecord(coremymirrorpod, coremymirrorpod, podKind, coremymirrorpod.Namespace, coremymirrorpod.Name, podResource, "status", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  406. err: "",
  407. },
  408. {
  409. name: "forbid delete of mirror pod status bound to self",
  410. podsGetter: existingPods,
  411. attributes: admission.NewAttributesRecord(nil, nil, podKind, coremymirrorpod.Namespace, coremymirrorpod.Name, podResource, "status", admission.Delete, &metav1.DeleteOptions{}, false, mynode),
  412. err: "forbidden: unexpected operation",
  413. },
  414. {
  415. name: "allow create of eviction for mirror pod bound to self",
  416. podsGetter: existingPods,
  417. attributes: admission.NewAttributesRecord(mymirrorpodEviction, nil, evictionKind, coremymirrorpod.Namespace, coremymirrorpod.Name, podResource, "eviction", admission.Create, &metav1.CreateOptions{}, false, mynode),
  418. err: "",
  419. },
  420. {
  421. name: "forbid update of eviction for mirror pod bound to self",
  422. podsGetter: existingPods,
  423. attributes: admission.NewAttributesRecord(mymirrorpodEviction, nil, evictionKind, coremymirrorpod.Namespace, coremymirrorpod.Name, podResource, "eviction", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  424. err: "forbidden: unexpected operation",
  425. },
  426. {
  427. name: "forbid delete of eviction for mirror pod bound to self",
  428. podsGetter: existingPods,
  429. attributes: admission.NewAttributesRecord(mymirrorpodEviction, nil, evictionKind, coremymirrorpod.Namespace, coremymirrorpod.Name, podResource, "eviction", admission.Delete, &metav1.DeleteOptions{}, false, mynode),
  430. err: "forbidden: unexpected operation",
  431. },
  432. {
  433. name: "allow create of unnamed eviction for mirror pod bound to self",
  434. podsGetter: existingPods,
  435. attributes: admission.NewAttributesRecord(unnamedEviction, nil, evictionKind, coremymirrorpod.Namespace, coremymirrorpod.Name, podResource, "eviction", admission.Create, &metav1.CreateOptions{}, false, mynode),
  436. err: "",
  437. },
  438. // Mirror pods bound to another node
  439. {
  440. name: "forbid creating a mirror pod bound to another",
  441. podsGetter: noExistingPods,
  442. attributes: admission.NewAttributesRecord(coreothermirrorpod, nil, podKind, coreothermirrorpod.Namespace, coreothermirrorpod.Name, podResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode),
  443. err: "spec.nodeName set to itself",
  444. },
  445. {
  446. name: "forbid update of mirror pod bound to another",
  447. podsGetter: existingPods,
  448. attributes: admission.NewAttributesRecord(coreothermirrorpod, coreothermirrorpod, podKind, coreothermirrorpod.Namespace, coreothermirrorpod.Name, podResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  449. err: "forbidden: unexpected operation",
  450. },
  451. {
  452. name: "forbid delete of mirror pod bound to another",
  453. podsGetter: existingPods,
  454. attributes: admission.NewAttributesRecord(nil, nil, podKind, coreothermirrorpod.Namespace, coreothermirrorpod.Name, podResource, "", admission.Delete, &metav1.DeleteOptions{}, false, mynode),
  455. err: "spec.nodeName set to itself",
  456. },
  457. {
  458. name: "forbid create of mirror pod status bound to another",
  459. podsGetter: noExistingPods,
  460. attributes: admission.NewAttributesRecord(coreothermirrorpod, nil, podKind, coreothermirrorpod.Namespace, coreothermirrorpod.Name, podResource, "status", admission.Create, &metav1.CreateOptions{}, false, mynode),
  461. err: "forbidden: unexpected operation",
  462. },
  463. {
  464. name: "forbid update of mirror pod status bound to another",
  465. podsGetter: existingPods,
  466. attributes: admission.NewAttributesRecord(coreothermirrorpod, coreothermirrorpod, podKind, coreothermirrorpod.Namespace, coreothermirrorpod.Name, podResource, "status", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  467. err: "spec.nodeName set to itself",
  468. },
  469. {
  470. name: "forbid delete of mirror pod status bound to another",
  471. podsGetter: existingPods,
  472. attributes: admission.NewAttributesRecord(nil, nil, podKind, coreothermirrorpod.Namespace, coreothermirrorpod.Name, podResource, "status", admission.Delete, &metav1.DeleteOptions{}, false, mynode),
  473. err: "forbidden: unexpected operation",
  474. },
  475. {
  476. name: "forbid create of eviction for mirror pod bound to another",
  477. podsGetter: existingPods,
  478. attributes: admission.NewAttributesRecord(othermirrorpodEviction, nil, evictionKind, coreothermirrorpod.Namespace, coreothermirrorpod.Name, podResource, "eviction", admission.Create, &metav1.CreateOptions{}, false, mynode),
  479. err: "spec.nodeName set to itself",
  480. },
  481. {
  482. name: "forbid update of eviction for mirror pod bound to another",
  483. podsGetter: existingPods,
  484. attributes: admission.NewAttributesRecord(othermirrorpodEviction, nil, evictionKind, coreothermirrorpod.Namespace, coreothermirrorpod.Name, podResource, "eviction", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  485. err: "forbidden: unexpected operation",
  486. },
  487. {
  488. name: "forbid delete of eviction for mirror pod bound to another",
  489. podsGetter: existingPods,
  490. attributes: admission.NewAttributesRecord(othermirrorpodEviction, nil, evictionKind, coreothermirrorpod.Namespace, coreothermirrorpod.Name, podResource, "eviction", admission.Delete, &metav1.DeleteOptions{}, false, mynode),
  491. err: "forbidden: unexpected operation",
  492. },
  493. {
  494. name: "forbid create of unnamed eviction for mirror pod to another",
  495. podsGetter: existingPods,
  496. attributes: admission.NewAttributesRecord(unnamedEviction, nil, evictionKind, coreothermirrorpod.Namespace, coreothermirrorpod.Name, podResource, "eviction", admission.Create, &metav1.CreateOptions{}, false, mynode),
  497. err: "spec.nodeName set to itself",
  498. },
  499. // Mirror pods not bound to any node
  500. {
  501. name: "forbid creating a mirror pod unbound",
  502. podsGetter: noExistingPods,
  503. attributes: admission.NewAttributesRecord(coreunboundmirrorpod, nil, podKind, coreunboundmirrorpod.Namespace, coreunboundmirrorpod.Name, podResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode),
  504. err: "spec.nodeName set to itself",
  505. },
  506. {
  507. name: "forbid update of mirror pod unbound",
  508. podsGetter: existingPods,
  509. attributes: admission.NewAttributesRecord(coreunboundmirrorpod, coreunboundmirrorpod, podKind, coreunboundmirrorpod.Namespace, coreunboundmirrorpod.Name, podResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  510. err: "forbidden: unexpected operation",
  511. },
  512. {
  513. name: "forbid delete of mirror pod unbound",
  514. podsGetter: existingPods,
  515. attributes: admission.NewAttributesRecord(nil, nil, podKind, coreunboundmirrorpod.Namespace, coreunboundmirrorpod.Name, podResource, "", admission.Delete, &metav1.DeleteOptions{}, false, mynode),
  516. err: "spec.nodeName set to itself",
  517. },
  518. {
  519. name: "forbid create of mirror pod status unbound",
  520. podsGetter: noExistingPods,
  521. attributes: admission.NewAttributesRecord(coreunboundmirrorpod, nil, podKind, coreunboundmirrorpod.Namespace, coreunboundmirrorpod.Name, podResource, "status", admission.Create, &metav1.CreateOptions{}, false, mynode),
  522. err: "forbidden: unexpected operation",
  523. },
  524. {
  525. name: "forbid update of mirror pod status unbound",
  526. podsGetter: existingPods,
  527. attributes: admission.NewAttributesRecord(coreunboundmirrorpod, coreunboundmirrorpod, podKind, coreunboundmirrorpod.Namespace, coreunboundmirrorpod.Name, podResource, "status", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  528. err: "spec.nodeName set to itself",
  529. },
  530. {
  531. name: "forbid delete of mirror pod status unbound",
  532. podsGetter: existingPods,
  533. attributes: admission.NewAttributesRecord(nil, nil, podKind, coreunboundmirrorpod.Namespace, coreunboundmirrorpod.Name, podResource, "status", admission.Delete, &metav1.DeleteOptions{}, false, mynode),
  534. err: "forbidden: unexpected operation",
  535. },
  536. {
  537. name: "forbid create of eviction for mirror pod unbound",
  538. podsGetter: existingPods,
  539. attributes: admission.NewAttributesRecord(unboundmirrorpodEviction, nil, evictionKind, coreunboundmirrorpod.Namespace, coreunboundmirrorpod.Name, podResource, "eviction", admission.Create, &metav1.CreateOptions{}, false, mynode),
  540. err: "spec.nodeName set to itself",
  541. },
  542. {
  543. name: "forbid update of eviction for mirror pod unbound",
  544. podsGetter: existingPods,
  545. attributes: admission.NewAttributesRecord(unboundmirrorpodEviction, nil, evictionKind, coreunboundmirrorpod.Namespace, coreunboundmirrorpod.Name, podResource, "eviction", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  546. err: "forbidden: unexpected operation",
  547. },
  548. {
  549. name: "forbid delete of eviction for mirror pod unbound",
  550. podsGetter: existingPods,
  551. attributes: admission.NewAttributesRecord(unboundmirrorpodEviction, nil, evictionKind, coreunboundmirrorpod.Namespace, coreunboundmirrorpod.Name, podResource, "eviction", admission.Delete, &metav1.DeleteOptions{}, false, mynode),
  552. err: "forbidden: unexpected operation",
  553. },
  554. {
  555. name: "forbid create of unnamed eviction for mirror pod unbound",
  556. podsGetter: existingPods,
  557. attributes: admission.NewAttributesRecord(unnamedEviction, nil, evictionKind, coreunboundmirrorpod.Namespace, coreunboundmirrorpod.Name, podResource, "eviction", admission.Create, &metav1.CreateOptions{}, false, mynode),
  558. err: "spec.nodeName set to itself",
  559. },
  560. // Normal pods bound to us
  561. {
  562. name: "forbid creating a normal pod bound to self",
  563. podsGetter: noExistingPods,
  564. attributes: admission.NewAttributesRecord(coremypod, nil, podKind, coremypod.Namespace, coremypod.Name, podResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode),
  565. err: "can only create mirror pods",
  566. },
  567. {
  568. name: "forbid update of normal pod bound to self",
  569. podsGetter: existingPods,
  570. attributes: admission.NewAttributesRecord(coremypod, coremypod, podKind, coremypod.Namespace, coremypod.Name, podResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  571. err: "forbidden: unexpected operation",
  572. },
  573. {
  574. name: "allow delete of normal pod bound to self",
  575. podsGetter: existingPods,
  576. attributes: admission.NewAttributesRecord(nil, nil, podKind, coremypod.Namespace, coremypod.Name, podResource, "", admission.Delete, &metav1.DeleteOptions{}, false, mynode),
  577. err: "",
  578. },
  579. {
  580. name: "forbid create of normal pod status bound to self",
  581. podsGetter: noExistingPods,
  582. attributes: admission.NewAttributesRecord(coremypod, nil, podKind, coremypod.Namespace, coremypod.Name, podResource, "status", admission.Create, &metav1.CreateOptions{}, false, mynode),
  583. err: "forbidden: unexpected operation",
  584. },
  585. {
  586. name: "allow update of normal pod status bound to self",
  587. podsGetter: existingPods,
  588. attributes: admission.NewAttributesRecord(coremypod, coremypod, podKind, coremypod.Namespace, coremypod.Name, podResource, "status", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  589. err: "",
  590. },
  591. {
  592. name: "forbid delete of normal pod status bound to self",
  593. podsGetter: existingPods,
  594. attributes: admission.NewAttributesRecord(nil, nil, podKind, coremypod.Namespace, coremypod.Name, podResource, "status", admission.Delete, &metav1.DeleteOptions{}, false, mynode),
  595. err: "forbidden: unexpected operation",
  596. },
  597. {
  598. name: "forbid addition of pod status preexisting labels",
  599. podsGetter: noExistingPods,
  600. attributes: admission.NewAttributesRecord(abLabeledPod, aLabeledPod, podKind, coremypod.Namespace, coremypod.Name, podResource, "status", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  601. err: "cannot update labels through pod status",
  602. },
  603. {
  604. name: "forbid deletion of pod status preexisting labels",
  605. podsGetter: noExistingPods,
  606. attributes: admission.NewAttributesRecord(aLabeledPod, abLabeledPod, podKind, coremypod.Namespace, coremypod.Name, podResource, "status", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  607. err: "cannot update labels through pod status",
  608. },
  609. {
  610. name: "forbid deletion of all pod status preexisting labels",
  611. podsGetter: noExistingPods,
  612. attributes: admission.NewAttributesRecord(aLabeledPod, coremypod, podKind, coremypod.Namespace, coremypod.Name, podResource, "status", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  613. err: "cannot update labels through pod status",
  614. },
  615. {
  616. name: "forbid addition of pod status labels",
  617. podsGetter: noExistingPods,
  618. attributes: admission.NewAttributesRecord(coremypod, aLabeledPod, podKind, coremypod.Namespace, coremypod.Name, podResource, "status", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  619. err: "cannot update labels through pod status",
  620. },
  621. {
  622. name: "forbid update of eviction for normal pod bound to self",
  623. podsGetter: existingPods,
  624. attributes: admission.NewAttributesRecord(mypodEviction, nil, evictionKind, coremypod.Namespace, coremypod.Name, podResource, "eviction", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  625. err: "forbidden: unexpected operation",
  626. },
  627. {
  628. name: "forbid delete of eviction for normal pod bound to self",
  629. podsGetter: existingPods,
  630. attributes: admission.NewAttributesRecord(mypodEviction, nil, evictionKind, coremypod.Namespace, coremypod.Name, podResource, "eviction", admission.Delete, &metav1.DeleteOptions{}, false, mynode),
  631. err: "forbidden: unexpected operation",
  632. },
  633. {
  634. name: "allow create of unnamed eviction for normal pod bound to self",
  635. podsGetter: existingPods,
  636. attributes: admission.NewAttributesRecord(unnamedEviction, nil, evictionKind, coremypod.Namespace, coremypod.Name, podResource, "eviction", admission.Create, &metav1.CreateOptions{}, false, mynode),
  637. err: "",
  638. },
  639. // Normal pods bound to another
  640. {
  641. name: "forbid creating a normal pod bound to another",
  642. podsGetter: noExistingPods,
  643. attributes: admission.NewAttributesRecord(coreotherpod, nil, podKind, coreotherpod.Namespace, coreotherpod.Name, podResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode),
  644. err: "can only create mirror pods",
  645. },
  646. {
  647. name: "forbid update of normal pod bound to another",
  648. podsGetter: existingPods,
  649. attributes: admission.NewAttributesRecord(coreotherpod, coreotherpod, podKind, coreotherpod.Namespace, coreotherpod.Name, podResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  650. err: "forbidden: unexpected operation",
  651. },
  652. {
  653. name: "forbid delete of normal pod bound to another",
  654. podsGetter: existingPods,
  655. attributes: admission.NewAttributesRecord(nil, nil, podKind, coreotherpod.Namespace, coreotherpod.Name, podResource, "", admission.Delete, &metav1.UpdateOptions{}, false, mynode),
  656. err: "spec.nodeName set to itself",
  657. },
  658. {
  659. name: "forbid create of normal pod status bound to another",
  660. podsGetter: noExistingPods,
  661. attributes: admission.NewAttributesRecord(coreotherpod, nil, podKind, coreotherpod.Namespace, coreotherpod.Name, podResource, "status", admission.Create, &metav1.CreateOptions{}, false, mynode),
  662. err: "forbidden: unexpected operation",
  663. },
  664. {
  665. name: "forbid update of normal pod status bound to another",
  666. podsGetter: existingPods,
  667. attributes: admission.NewAttributesRecord(coreotherpod, coreotherpod, podKind, coreotherpod.Namespace, coreotherpod.Name, podResource, "status", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  668. err: "spec.nodeName set to itself",
  669. },
  670. {
  671. name: "forbid delete of normal pod status bound to another",
  672. podsGetter: existingPods,
  673. attributes: admission.NewAttributesRecord(nil, nil, podKind, coreotherpod.Namespace, coreotherpod.Name, podResource, "status", admission.Delete, &metav1.DeleteOptions{}, false, mynode),
  674. err: "forbidden: unexpected operation",
  675. },
  676. {
  677. name: "forbid create of eviction for normal pod bound to another",
  678. podsGetter: existingPods,
  679. attributes: admission.NewAttributesRecord(otherpodEviction, nil, evictionKind, otherpodEviction.Namespace, otherpodEviction.Name, podResource, "eviction", admission.Create, &metav1.CreateOptions{}, false, mynode),
  680. err: "spec.nodeName set to itself",
  681. },
  682. {
  683. name: "forbid update of eviction for normal pod bound to another",
  684. podsGetter: existingPods,
  685. attributes: admission.NewAttributesRecord(otherpodEviction, nil, evictionKind, otherpodEviction.Namespace, otherpodEviction.Name, podResource, "eviction", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  686. err: "forbidden: unexpected operation",
  687. },
  688. {
  689. name: "forbid delete of eviction for normal pod bound to another",
  690. podsGetter: existingPods,
  691. attributes: admission.NewAttributesRecord(otherpodEviction, nil, evictionKind, otherpodEviction.Namespace, otherpodEviction.Name, podResource, "eviction", admission.Delete, &metav1.UpdateOptions{}, false, mynode),
  692. err: "forbidden: unexpected operation",
  693. },
  694. {
  695. name: "forbid create of unnamed eviction for normal pod bound to another",
  696. podsGetter: existingPods,
  697. attributes: admission.NewAttributesRecord(unnamedEviction, nil, evictionKind, coreotherpod.Namespace, coreotherpod.Name, podResource, "eviction", admission.Create, &metav1.CreateOptions{}, false, mynode),
  698. err: "spec.nodeName set to itself",
  699. },
  700. // Normal pods not bound to any node
  701. {
  702. name: "forbid creating a normal pod unbound",
  703. podsGetter: noExistingPods,
  704. attributes: admission.NewAttributesRecord(coreunboundpod, nil, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode),
  705. err: "can only create mirror pods",
  706. },
  707. {
  708. name: "forbid update of normal pod unbound",
  709. podsGetter: existingPods,
  710. attributes: admission.NewAttributesRecord(coreunboundpod, coreunboundpod, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  711. err: "forbidden: unexpected operation",
  712. },
  713. {
  714. name: "forbid delete of normal pod unbound",
  715. podsGetter: existingPods,
  716. attributes: admission.NewAttributesRecord(nil, nil, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "", admission.Delete, &metav1.DeleteOptions{}, false, mynode),
  717. err: "spec.nodeName set to itself",
  718. },
  719. {
  720. name: "forbid create of normal pod status unbound",
  721. podsGetter: noExistingPods,
  722. attributes: admission.NewAttributesRecord(coreunboundpod, nil, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "status", admission.Create, &metav1.CreateOptions{}, false, mynode),
  723. err: "forbidden: unexpected operation",
  724. },
  725. {
  726. name: "forbid update of normal pod status unbound",
  727. podsGetter: existingPods,
  728. attributes: admission.NewAttributesRecord(coreunboundpod, coreunboundpod, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "status", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  729. err: "spec.nodeName set to itself",
  730. },
  731. {
  732. name: "forbid delete of normal pod status unbound",
  733. podsGetter: existingPods,
  734. attributes: admission.NewAttributesRecord(nil, nil, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "status", admission.Delete, &metav1.DeleteOptions{}, false, mynode),
  735. err: "forbidden: unexpected operation",
  736. },
  737. {
  738. name: "forbid create of eviction for normal pod unbound",
  739. podsGetter: existingPods,
  740. attributes: admission.NewAttributesRecord(unboundpodEviction, nil, evictionKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "eviction", admission.Create, &metav1.CreateOptions{}, false, mynode),
  741. err: "spec.nodeName set to itself",
  742. },
  743. {
  744. name: "forbid update of eviction for normal pod unbound",
  745. podsGetter: existingPods,
  746. attributes: admission.NewAttributesRecord(unboundpodEviction, nil, evictionKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "eviction", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  747. err: "forbidden: unexpected operation",
  748. },
  749. {
  750. name: "forbid delete of eviction for normal pod unbound",
  751. podsGetter: existingPods,
  752. attributes: admission.NewAttributesRecord(unboundpodEviction, nil, evictionKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "eviction", admission.Delete, &metav1.DeleteOptions{}, false, mynode),
  753. err: "forbidden: unexpected operation",
  754. },
  755. {
  756. name: "forbid create of unnamed eviction for normal unbound",
  757. podsGetter: existingPods,
  758. attributes: admission.NewAttributesRecord(unnamedEviction, nil, evictionKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "eviction", admission.Create, &metav1.CreateOptions{}, false, mynode),
  759. err: "spec.nodeName set to itself",
  760. },
  761. // Missing pod
  762. {
  763. name: "forbid delete of unknown pod",
  764. podsGetter: noExistingPods,
  765. attributes: admission.NewAttributesRecord(nil, nil, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "", admission.Delete, &metav1.DeleteOptions{}, false, mynode),
  766. err: "not found",
  767. },
  768. {
  769. name: "forbid create of eviction for unknown pod",
  770. podsGetter: noExistingPods,
  771. attributes: admission.NewAttributesRecord(mypodEviction, nil, evictionKind, coremypod.Namespace, coremypod.Name, podResource, "eviction", admission.Create, &metav1.CreateOptions{}, false, mynode),
  772. err: "not found",
  773. },
  774. {
  775. name: "forbid update of eviction for unknown pod",
  776. podsGetter: noExistingPods,
  777. attributes: admission.NewAttributesRecord(mypodEviction, nil, evictionKind, coremypod.Namespace, coremypod.Name, podResource, "eviction", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  778. err: "forbidden: unexpected operation",
  779. },
  780. {
  781. name: "forbid delete of eviction for unknown pod",
  782. podsGetter: noExistingPods,
  783. attributes: admission.NewAttributesRecord(mypodEviction, nil, evictionKind, coremypod.Namespace, coremypod.Name, podResource, "eviction", admission.Delete, &metav1.DeleteOptions{}, false, mynode),
  784. err: "forbidden: unexpected operation",
  785. },
  786. {
  787. name: "forbid create of unnamed eviction for unknown pod",
  788. podsGetter: noExistingPods,
  789. attributes: admission.NewAttributesRecord(unnamedEviction, nil, evictionKind, coremypod.Namespace, coremypod.Name, podResource, "eviction", admission.Create, &metav1.CreateOptions{}, false, mynode),
  790. err: "not found",
  791. },
  792. // Eviction for unnamed pod
  793. {
  794. name: "allow create of eviction for unnamed pod",
  795. podsGetter: existingPods,
  796. attributes: admission.NewAttributesRecord(mypodEviction, nil, evictionKind, coreunnamedpod.Namespace, coreunnamedpod.Name, podResource, "eviction", admission.Create, &metav1.CreateOptions{}, false, mynode),
  797. // use the submitted eviction resource name as the pod name
  798. err: "",
  799. },
  800. {
  801. name: "forbid update of eviction for unnamed pod",
  802. podsGetter: existingPods,
  803. attributes: admission.NewAttributesRecord(mypodEviction, nil, evictionKind, coreunnamedpod.Namespace, coreunnamedpod.Name, podResource, "eviction", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  804. err: "forbidden: unexpected operation",
  805. },
  806. {
  807. name: "forbid delete of eviction for unnamed pod",
  808. podsGetter: existingPods,
  809. attributes: admission.NewAttributesRecord(mypodEviction, nil, evictionKind, coreunnamedpod.Namespace, coreunnamedpod.Name, podResource, "eviction", admission.Delete, &metav1.DeleteOptions{}, false, mynode),
  810. err: "forbidden: unexpected operation",
  811. },
  812. {
  813. name: "forbid create of unnamed eviction for unnamed pod",
  814. podsGetter: existingPods,
  815. attributes: admission.NewAttributesRecord(unnamedEviction, nil, evictionKind, coreunnamedpod.Namespace, coreunnamedpod.Name, podResource, "eviction", admission.Create, &metav1.CreateOptions{}, false, mynode),
  816. err: "could not determine pod from request data",
  817. },
  818. // Resource pods
  819. {
  820. name: "forbid create of pod referencing service account",
  821. podsGetter: noExistingPods,
  822. attributes: admission.NewAttributesRecord(sapod, nil, podKind, sapod.Namespace, sapod.Name, podResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode),
  823. err: "reference a service account",
  824. },
  825. {
  826. name: "forbid create of pod referencing secret",
  827. podsGetter: noExistingPods,
  828. attributes: admission.NewAttributesRecord(secretpod, nil, podKind, secretpod.Namespace, secretpod.Name, podResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode),
  829. err: "reference secrets",
  830. },
  831. {
  832. name: "forbid create of pod referencing configmap",
  833. podsGetter: noExistingPods,
  834. attributes: admission.NewAttributesRecord(configmappod, nil, podKind, configmappod.Namespace, configmappod.Name, podResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode),
  835. err: "reference configmaps",
  836. },
  837. {
  838. name: "forbid create of pod referencing persistentvolumeclaim",
  839. podsGetter: noExistingPods,
  840. attributes: admission.NewAttributesRecord(pvcpod, nil, podKind, pvcpod.Namespace, pvcpod.Name, podResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode),
  841. err: "reference persistentvolumeclaims",
  842. },
  843. // My node object
  844. {
  845. name: "allow create of my node",
  846. podsGetter: noExistingPods,
  847. attributes: admission.NewAttributesRecord(mynodeObj, nil, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode),
  848. err: "",
  849. },
  850. {
  851. name: "allow create of my node pulling name from object",
  852. podsGetter: noExistingPods,
  853. attributes: admission.NewAttributesRecord(mynodeObj, nil, nodeKind, mynodeObj.Namespace, "mynode", nodeResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode),
  854. err: "",
  855. },
  856. {
  857. name: "allow create of my node with taints",
  858. podsGetter: noExistingPods,
  859. attributes: admission.NewAttributesRecord(mynodeObjTaintA, nil, nodeKind, mynodeObj.Namespace, "mynode", nodeResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode),
  860. err: "",
  861. },
  862. {
  863. name: "allow create of my node with labels",
  864. podsGetter: noExistingPods,
  865. attributes: admission.NewAttributesRecord(setAllowedCreateLabels(mynodeObj, ""), nil, nodeKind, mynodeObj.Namespace, "mynode", nodeResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode),
  866. err: "",
  867. },
  868. {
  869. name: "forbid create of my node with forbidden labels",
  870. podsGetter: noExistingPods,
  871. attributes: admission.NewAttributesRecord(setForbiddenCreateLabels(mynodeObj, ""), nil, nodeKind, mynodeObj.Namespace, "", nodeResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode),
  872. err: `is not allowed to set the following labels: foo.node-restriction.kubernetes.io/foo, node-restriction.kubernetes.io/foo`,
  873. },
  874. {
  875. name: "allow update of my node",
  876. podsGetter: existingPods,
  877. attributes: admission.NewAttributesRecord(mynodeObj, mynodeObj, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  878. err: "",
  879. },
  880. {
  881. name: "allow delete of my node",
  882. podsGetter: existingPods,
  883. attributes: admission.NewAttributesRecord(nil, nil, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Delete, &metav1.DeleteOptions{}, false, mynode),
  884. err: "",
  885. },
  886. {
  887. name: "allow update of my node status",
  888. podsGetter: existingPods,
  889. attributes: admission.NewAttributesRecord(mynodeObj, mynodeObj, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "status", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  890. err: "",
  891. },
  892. {
  893. name: "forbid create of my node with non-nil configSource",
  894. podsGetter: noExistingPods,
  895. attributes: admission.NewAttributesRecord(mynodeObjConfigA, nil, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode),
  896. err: "is not allowed to create pods with a non-nil configSource",
  897. },
  898. {
  899. name: "forbid update of my node: nil configSource to new non-nil configSource",
  900. podsGetter: existingPods,
  901. attributes: admission.NewAttributesRecord(mynodeObjConfigA, mynodeObj, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  902. err: "update configSource to a new non-nil configSource",
  903. },
  904. {
  905. name: "forbid update of my node: non-nil configSource to new non-nil configSource",
  906. podsGetter: existingPods,
  907. attributes: admission.NewAttributesRecord(mynodeObjConfigB, mynodeObjConfigA, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  908. err: "update configSource to a new non-nil configSource",
  909. },
  910. {
  911. name: "allow update of my node: non-nil configSource unchanged",
  912. podsGetter: existingPods,
  913. attributes: admission.NewAttributesRecord(mynodeObjConfigA, mynodeObjConfigA, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  914. err: "",
  915. },
  916. {
  917. name: "allow update of my node: non-nil configSource to nil configSource",
  918. podsGetter: existingPods,
  919. attributes: admission.NewAttributesRecord(mynodeObj, mynodeObjConfigA, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  920. err: "",
  921. },
  922. {
  923. name: "allow update of my node: no change to taints",
  924. podsGetter: existingPods,
  925. attributes: admission.NewAttributesRecord(mynodeObjTaintA, mynodeObjTaintA, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  926. err: "",
  927. },
  928. {
  929. name: "allow update of my node: add allowed labels",
  930. podsGetter: existingPods,
  931. attributes: admission.NewAttributesRecord(setAllowedUpdateLabels(mynodeObj, ""), mynodeObj, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  932. err: "",
  933. },
  934. {
  935. name: "allow update of my node: remove allowed labels",
  936. podsGetter: existingPods,
  937. attributes: admission.NewAttributesRecord(mynodeObj, setAllowedUpdateLabels(mynodeObj, ""), nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  938. err: "",
  939. },
  940. {
  941. name: "allow update of my node: modify allowed labels",
  942. podsGetter: existingPods,
  943. attributes: admission.NewAttributesRecord(setAllowedUpdateLabels(mynodeObj, "b"), setAllowedUpdateLabels(mynodeObj, "a"), nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  944. err: "",
  945. },
  946. {
  947. name: "allow update of my node: no change to labels",
  948. podsGetter: existingPods,
  949. attributes: admission.NewAttributesRecord(setAllLabels(mynodeObj, ""), setAllLabels(mynodeObj, ""), nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  950. err: "",
  951. },
  952. {
  953. name: "allow update of my node: add allowed labels while forbidden labels exist unmodified",
  954. podsGetter: existingPods,
  955. attributes: admission.NewAttributesRecord(setAllLabels(mynodeObj, ""), setForbiddenUpdateLabels(mynodeObj, ""), nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  956. err: "",
  957. },
  958. {
  959. name: "allow update of my node: remove allowed labels while forbidden labels exist unmodified",
  960. podsGetter: existingPods,
  961. attributes: admission.NewAttributesRecord(setForbiddenUpdateLabels(mynodeObj, ""), setAllLabels(mynodeObj, ""), nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  962. err: "",
  963. },
  964. {
  965. name: "forbid update of my node: add taints",
  966. podsGetter: existingPods,
  967. attributes: admission.NewAttributesRecord(mynodeObjTaintA, mynodeObj, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  968. err: "is not allowed to modify taints",
  969. },
  970. {
  971. name: "forbid update of my node: remove taints",
  972. podsGetter: existingPods,
  973. attributes: admission.NewAttributesRecord(mynodeObj, mynodeObjTaintA, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  974. err: "is not allowed to modify taints",
  975. },
  976. {
  977. name: "forbid update of my node: change taints",
  978. podsGetter: existingPods,
  979. attributes: admission.NewAttributesRecord(mynodeObjTaintA, mynodeObjTaintB, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  980. err: "is not allowed to modify taints",
  981. },
  982. {
  983. name: "forbid update of my node: add labels",
  984. podsGetter: existingPods,
  985. attributes: admission.NewAttributesRecord(setForbiddenUpdateLabels(mynodeObj, ""), mynodeObj, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  986. err: `is not allowed to modify labels: foo.node-restriction.kubernetes.io/foo, node-restriction.kubernetes.io/foo, other.k8s.io/foo, other.kubernetes.io/foo`,
  987. },
  988. {
  989. name: "forbid update of my node: remove labels",
  990. podsGetter: existingPods,
  991. attributes: admission.NewAttributesRecord(mynodeObj, setForbiddenUpdateLabels(mynodeObj, ""), nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  992. err: `is not allowed to modify labels: foo.node-restriction.kubernetes.io/foo, node-restriction.kubernetes.io/foo, other.k8s.io/foo, other.kubernetes.io/foo`,
  993. },
  994. {
  995. name: "forbid update of my node: change labels",
  996. podsGetter: existingPods,
  997. attributes: admission.NewAttributesRecord(setForbiddenUpdateLabels(mynodeObj, "new"), setForbiddenUpdateLabels(mynodeObj, "old"), nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  998. err: `is not allowed to modify labels: foo.node-restriction.kubernetes.io/foo, node-restriction.kubernetes.io/foo, other.k8s.io/foo, other.kubernetes.io/foo`,
  999. },
  1000. // Other node object
  1001. {
  1002. name: "forbid create of other node",
  1003. podsGetter: noExistingPods,
  1004. attributes: admission.NewAttributesRecord(othernodeObj, nil, nodeKind, othernodeObj.Namespace, othernodeObj.Name, nodeResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode),
  1005. err: "is not allowed to modify node",
  1006. },
  1007. {
  1008. name: "forbid create of other node pulling name from object",
  1009. podsGetter: noExistingPods,
  1010. attributes: admission.NewAttributesRecord(othernodeObj, nil, nodeKind, othernodeObj.Namespace, "", nodeResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode),
  1011. err: "is not allowed to modify node",
  1012. },
  1013. {
  1014. name: "forbid update of other node",
  1015. podsGetter: existingPods,
  1016. attributes: admission.NewAttributesRecord(othernodeObj, othernodeObj, nodeKind, othernodeObj.Namespace, othernodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  1017. err: "is not allowed to modify node",
  1018. },
  1019. {
  1020. name: "forbid delete of other node",
  1021. podsGetter: existingPods,
  1022. attributes: admission.NewAttributesRecord(nil, nil, nodeKind, othernodeObj.Namespace, othernodeObj.Name, nodeResource, "", admission.Delete, &metav1.DeleteOptions{}, false, mynode),
  1023. err: "is not allowed to modify node",
  1024. },
  1025. {
  1026. name: "forbid update of other node status",
  1027. podsGetter: existingPods,
  1028. attributes: admission.NewAttributesRecord(othernodeObj, othernodeObj, nodeKind, othernodeObj.Namespace, othernodeObj.Name, nodeResource, "status", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  1029. err: "is not allowed to modify node",
  1030. },
  1031. // Service accounts
  1032. {
  1033. name: "forbid create of unbound token",
  1034. podsGetter: noExistingPods,
  1035. features: trEnabledFeature,
  1036. attributes: admission.NewAttributesRecord(makeTokenRequest("", ""), nil, tokenrequestKind, "ns", "mysa", svcacctResource, "token", admission.Create, &metav1.CreateOptions{}, false, mynode),
  1037. err: "not bound to a pod",
  1038. },
  1039. {
  1040. name: "forbid create of token bound to nonexistant pod",
  1041. podsGetter: noExistingPods,
  1042. features: trEnabledFeature,
  1043. attributes: admission.NewAttributesRecord(makeTokenRequest("nopod", "someuid"), nil, tokenrequestKind, "ns", "mysa", svcacctResource, "token", admission.Create, &metav1.CreateOptions{}, false, mynode),
  1044. err: "not found",
  1045. },
  1046. {
  1047. name: "forbid create of token bound to pod without uid",
  1048. podsGetter: existingPods,
  1049. features: trEnabledFeature,
  1050. attributes: admission.NewAttributesRecord(makeTokenRequest(coremypod.Name, ""), nil, tokenrequestKind, "ns", "mysa", svcacctResource, "token", admission.Create, &metav1.CreateOptions{}, false, mynode),
  1051. err: "pod binding without a uid",
  1052. },
  1053. {
  1054. name: "forbid create of token bound to pod scheduled on another node",
  1055. podsGetter: existingPods,
  1056. features: trEnabledFeature,
  1057. attributes: admission.NewAttributesRecord(makeTokenRequest(coreotherpod.Name, coreotherpod.UID), nil, tokenrequestKind, coreotherpod.Namespace, "mysa", svcacctResource, "token", admission.Create, &metav1.CreateOptions{}, false, mynode),
  1058. err: "pod scheduled on a different node",
  1059. },
  1060. {
  1061. name: "allow create of token bound to pod scheduled this node",
  1062. podsGetter: existingPods,
  1063. features: trEnabledFeature,
  1064. attributes: admission.NewAttributesRecord(makeTokenRequest(coremypod.Name, coremypod.UID), nil, tokenrequestKind, coremypod.Namespace, "mysa", svcacctResource, "token", admission.Create, &metav1.CreateOptions{}, false, mynode),
  1065. },
  1066. // Unrelated objects
  1067. {
  1068. name: "allow create of unrelated object",
  1069. podsGetter: existingPods,
  1070. attributes: admission.NewAttributesRecord(&api.ConfigMap{}, nil, configmapKind, "myns", "mycm", configmapResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode),
  1071. err: "",
  1072. },
  1073. {
  1074. name: "allow update of unrelated object",
  1075. podsGetter: existingPods,
  1076. attributes: admission.NewAttributesRecord(&api.ConfigMap{}, &api.ConfigMap{}, configmapKind, "myns", "mycm", configmapResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  1077. err: "",
  1078. },
  1079. {
  1080. name: "allow delete of unrelated object",
  1081. podsGetter: existingPods,
  1082. attributes: admission.NewAttributesRecord(nil, nil, configmapKind, "myns", "mycm", configmapResource, "", admission.Delete, &metav1.DeleteOptions{}, false, mynode),
  1083. err: "",
  1084. },
  1085. // Unrelated user
  1086. {
  1087. name: "allow unrelated user creating a normal pod unbound",
  1088. podsGetter: noExistingPods,
  1089. attributes: admission.NewAttributesRecord(coreunboundpod, nil, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "", admission.Create, &metav1.CreateOptions{}, false, bob),
  1090. err: "",
  1091. },
  1092. {
  1093. name: "allow unrelated user update of normal pod unbound",
  1094. podsGetter: existingPods,
  1095. attributes: admission.NewAttributesRecord(coreunboundpod, coreunboundpod, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "", admission.Update, &metav1.UpdateOptions{}, false, bob),
  1096. err: "",
  1097. },
  1098. {
  1099. name: "allow unrelated user delete of normal pod unbound",
  1100. podsGetter: existingPods,
  1101. attributes: admission.NewAttributesRecord(nil, nil, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "", admission.Delete, &metav1.DeleteOptions{}, false, bob),
  1102. err: "",
  1103. },
  1104. {
  1105. name: "allow unrelated user create of normal pod status unbound",
  1106. podsGetter: noExistingPods,
  1107. attributes: admission.NewAttributesRecord(coreunboundpod, nil, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "status", admission.Create, &metav1.CreateOptions{}, false, bob),
  1108. err: "",
  1109. },
  1110. {
  1111. name: "allow unrelated user update of normal pod status unbound",
  1112. podsGetter: existingPods,
  1113. attributes: admission.NewAttributesRecord(coreunboundpod, coreunboundpod, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "status", admission.Update, &metav1.UpdateOptions{}, false, bob),
  1114. err: "",
  1115. },
  1116. {
  1117. name: "allow unrelated user delete of normal pod status unbound",
  1118. podsGetter: existingPods,
  1119. attributes: admission.NewAttributesRecord(nil, nil, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "status", admission.Delete, &metav1.DeleteOptions{}, false, bob),
  1120. err: "",
  1121. },
  1122. // Node leases
  1123. {
  1124. name: "disallowed create lease in namespace other than kube-node-lease - feature enabled",
  1125. attributes: admission.NewAttributesRecord(leaseWrongNS, nil, leaseKind, leaseWrongNS.Namespace, leaseWrongNS.Name, leaseResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode),
  1126. err: "forbidden: ",
  1127. },
  1128. {
  1129. name: "disallowed update lease in namespace other than kube-node-lease - feature enabled",
  1130. attributes: admission.NewAttributesRecord(leaseWrongNS, leaseWrongNS, leaseKind, leaseWrongNS.Namespace, leaseWrongNS.Name, leaseResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  1131. err: "forbidden: ",
  1132. },
  1133. {
  1134. name: "disallowed delete lease in namespace other than kube-node-lease - feature enabled",
  1135. attributes: admission.NewAttributesRecord(nil, nil, leaseKind, leaseWrongNS.Namespace, leaseWrongNS.Name, leaseResource, "", admission.Delete, &metav1.DeleteOptions{}, false, mynode),
  1136. err: "forbidden: ",
  1137. },
  1138. {
  1139. name: "disallowed create another node's lease - feature enabled",
  1140. attributes: admission.NewAttributesRecord(leaseWrongName, nil, leaseKind, leaseWrongName.Namespace, leaseWrongName.Name, leaseResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode),
  1141. err: "forbidden: ",
  1142. },
  1143. {
  1144. name: "disallowed update another node's lease - feature enabled",
  1145. attributes: admission.NewAttributesRecord(leaseWrongName, leaseWrongName, leaseKind, leaseWrongName.Namespace, leaseWrongName.Name, leaseResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  1146. err: "forbidden: ",
  1147. },
  1148. {
  1149. name: "disallowed delete another node's lease - feature enabled",
  1150. attributes: admission.NewAttributesRecord(nil, nil, leaseKind, leaseWrongName.Namespace, leaseWrongName.Name, leaseResource, "", admission.Delete, &metav1.DeleteOptions{}, false, mynode),
  1151. err: "forbidden: ",
  1152. },
  1153. {
  1154. name: "allowed create node lease - feature enabled",
  1155. attributes: admission.NewAttributesRecord(lease, nil, leaseKind, lease.Namespace, lease.Name, leaseResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode),
  1156. err: "",
  1157. },
  1158. {
  1159. name: "allowed update node lease - feature enabled",
  1160. attributes: admission.NewAttributesRecord(lease, lease, leaseKind, lease.Namespace, lease.Name, leaseResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  1161. err: "",
  1162. },
  1163. {
  1164. name: "allowed delete node lease - feature enabled",
  1165. attributes: admission.NewAttributesRecord(nil, nil, leaseKind, lease.Namespace, lease.Name, leaseResource, "", admission.Delete, &metav1.DeleteOptions{}, false, mynode),
  1166. err: "",
  1167. },
  1168. // CSINode
  1169. {
  1170. name: "disallowed create CSINode - feature disabled",
  1171. attributes: admission.NewAttributesRecord(nodeInfo, nil, csiNodeKind, nodeInfo.Namespace, nodeInfo.Name, csiNodeResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode),
  1172. features: csiNodeInfoDisabledFeature,
  1173. err: fmt.Sprintf("forbidden: disabled by feature gates %s", features.CSINodeInfo),
  1174. },
  1175. {
  1176. name: "disallowed create another node's CSINode - feature enabled",
  1177. attributes: admission.NewAttributesRecord(nodeInfoWrongName, nil, csiNodeKind, nodeInfoWrongName.Namespace, nodeInfoWrongName.Name, csiNodeResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode),
  1178. features: csiNodeInfoEnabledFeature,
  1179. err: "forbidden: ",
  1180. },
  1181. {
  1182. name: "disallowed update another node's CSINode - feature enabled",
  1183. attributes: admission.NewAttributesRecord(nodeInfoWrongName, nodeInfoWrongName, csiNodeKind, nodeInfoWrongName.Namespace, nodeInfoWrongName.Name, csiNodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  1184. features: csiNodeInfoEnabledFeature,
  1185. err: "forbidden: ",
  1186. },
  1187. {
  1188. name: "disallowed delete another node's CSINode - feature enabled",
  1189. attributes: admission.NewAttributesRecord(nil, nil, csiNodeKind, nodeInfoWrongName.Namespace, nodeInfoWrongName.Name, csiNodeResource, "", admission.Delete, &metav1.DeleteOptions{}, false, mynode),
  1190. features: csiNodeInfoEnabledFeature,
  1191. err: "forbidden: ",
  1192. },
  1193. {
  1194. name: "allowed create node CSINode - feature enabled",
  1195. attributes: admission.NewAttributesRecord(nodeInfo, nil, csiNodeKind, nodeInfo.Namespace, nodeInfo.Name, csiNodeResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode),
  1196. features: csiNodeInfoEnabledFeature,
  1197. err: "",
  1198. },
  1199. {
  1200. name: "allowed update node CSINode - feature enabled",
  1201. attributes: admission.NewAttributesRecord(nodeInfo, nodeInfo, csiNodeKind, nodeInfo.Namespace, nodeInfo.Name, csiNodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode),
  1202. features: csiNodeInfoEnabledFeature,
  1203. err: "",
  1204. },
  1205. {
  1206. name: "allowed delete node CSINode - feature enabled",
  1207. attributes: admission.NewAttributesRecord(nil, nil, csiNodeKind, nodeInfo.Namespace, nodeInfo.Name, csiNodeResource, "", admission.Delete, &metav1.UpdateOptions{}, false, mynode),
  1208. features: csiNodeInfoEnabledFeature,
  1209. err: "",
  1210. },
  1211. }
  1212. for _, tt := range tests {
  1213. tt.nodesGetter = existingNodes
  1214. tt.run(t)
  1215. }
  1216. }
  1217. func Test_nodePlugin_Admit_OwnerReference(t *testing.T) {
  1218. expectedNodeIndex := cache.NewIndexer(cache.MetaNamespaceKeyFunc, nil)
  1219. expectedNodeIndex.Add(&v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "mynode", UID: "mynode-uid"}})
  1220. expectedNode := corev1lister.NewNodeLister(expectedNodeIndex)
  1221. unexpectedNodeIndex := cache.NewIndexer(cache.MetaNamespaceKeyFunc, nil)
  1222. unexpectedNodeIndex.Add(&v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "mynode", UID: "mynode-unexpected-uid"}})
  1223. unexpectedNode := corev1lister.NewNodeLister(unexpectedNodeIndex)
  1224. noNodesIndex := cache.NewIndexer(cache.MetaNamespaceKeyFunc, nil)
  1225. noNodes := corev1lister.NewNodeLister(noNodesIndex)
  1226. noExistingPodsIndex := cache.NewIndexer(cache.MetaNamespaceKeyFunc, nil)
  1227. noExistingPods := corev1lister.NewPodLister(noExistingPodsIndex)
  1228. mynode := &user.DefaultInfo{Name: "system:node:mynode", Groups: []string{"system:nodes"}}
  1229. validOwner := metav1.OwnerReference{
  1230. APIVersion: "v1",
  1231. Kind: "Node",
  1232. Name: "mynode",
  1233. UID: "mynode-uid",
  1234. Controller: pointer.BoolPtr(true),
  1235. }
  1236. invalidName := validOwner
  1237. invalidName.Name = "other"
  1238. invalidKind := validOwner
  1239. invalidKind.Kind = "Pod"
  1240. invalidAPI := validOwner
  1241. invalidAPI.APIVersion = "v2"
  1242. invalidControllerNil := validOwner
  1243. invalidControllerNil.Controller = nil
  1244. invalidControllerFalse := validOwner
  1245. invalidControllerFalse.Controller = pointer.BoolPtr(false)
  1246. invalidBlockDeletion := validOwner
  1247. invalidBlockDeletion.BlockOwnerDeletion = pointer.BoolPtr(true)
  1248. tests := []struct {
  1249. name string
  1250. owners []metav1.OwnerReference
  1251. nodesGetter corev1lister.NodeLister
  1252. expectErr string
  1253. }{
  1254. {
  1255. name: "no owner",
  1256. owners: nil,
  1257. },
  1258. {
  1259. name: "valid owner",
  1260. owners: []metav1.OwnerReference{validOwner},
  1261. },
  1262. {
  1263. name: "duplicate owner",
  1264. owners: []metav1.OwnerReference{validOwner, validOwner},
  1265. expectErr: "can only create pods with a single owner reference set to itself",
  1266. },
  1267. {
  1268. name: "invalid name",
  1269. owners: []metav1.OwnerReference{invalidName},
  1270. expectErr: "can only create pods with an owner reference set to itself",
  1271. },
  1272. {
  1273. name: "invalid UID",
  1274. owners: []metav1.OwnerReference{validOwner},
  1275. nodesGetter: unexpectedNode,
  1276. expectErr: "UID mismatch",
  1277. },
  1278. {
  1279. name: "node not found",
  1280. owners: []metav1.OwnerReference{validOwner},
  1281. nodesGetter: noNodes,
  1282. expectErr: "not found",
  1283. },
  1284. {
  1285. name: "invalid API version",
  1286. owners: []metav1.OwnerReference{invalidAPI},
  1287. expectErr: "can only create pods with an owner reference set to itself",
  1288. },
  1289. {
  1290. name: "invalid kind",
  1291. owners: []metav1.OwnerReference{invalidKind},
  1292. expectErr: "can only create pods with an owner reference set to itself",
  1293. },
  1294. {
  1295. name: "nil controller",
  1296. owners: []metav1.OwnerReference{invalidControllerNil},
  1297. expectErr: "can only create pods with a controller owner reference set to itself",
  1298. },
  1299. {
  1300. name: "false controller",
  1301. owners: []metav1.OwnerReference{invalidControllerFalse},
  1302. expectErr: "can only create pods with a controller owner reference set to itself",
  1303. },
  1304. {
  1305. name: "invalid blockOwnerDeletion",
  1306. owners: []metav1.OwnerReference{invalidBlockDeletion},
  1307. expectErr: "must not set blockOwnerDeletion on an owner reference",
  1308. },
  1309. }
  1310. for _, test := range tests {
  1311. if test.nodesGetter == nil {
  1312. test.nodesGetter = expectedNode
  1313. }
  1314. pod, _ := makeTestPod("ns", "test", "mynode", true)
  1315. pod.OwnerReferences = test.owners
  1316. a := &admitTestCase{
  1317. name: test.name,
  1318. podsGetter: noExistingPods,
  1319. nodesGetter: test.nodesGetter,
  1320. attributes: createPodAttributes(pod, mynode),
  1321. err: test.expectErr,
  1322. }
  1323. a.run(t)
  1324. }
  1325. }
  1326. func Test_getModifiedLabels(t *testing.T) {
  1327. tests := []struct {
  1328. name string
  1329. a map[string]string
  1330. b map[string]string
  1331. want sets.String
  1332. }{
  1333. {
  1334. name: "empty",
  1335. a: nil,
  1336. b: nil,
  1337. want: sets.NewString(),
  1338. },
  1339. {
  1340. name: "no change",
  1341. a: map[string]string{"x": "1", "y": "2", "z": "3"},
  1342. b: map[string]string{"x": "1", "y": "2", "z": "3"},
  1343. want: sets.NewString(),
  1344. },
  1345. {
  1346. name: "added",
  1347. a: map[string]string{},
  1348. b: map[string]string{"a": "0"},
  1349. want: sets.NewString("a"),
  1350. },
  1351. {
  1352. name: "removed",
  1353. a: map[string]string{"z": "3"},
  1354. b: map[string]string{},
  1355. want: sets.NewString("z"),
  1356. },
  1357. {
  1358. name: "changed",
  1359. a: map[string]string{"z": "3"},
  1360. b: map[string]string{"z": "4"},
  1361. want: sets.NewString("z"),
  1362. },
  1363. {
  1364. name: "added empty",
  1365. a: map[string]string{},
  1366. b: map[string]string{"a": ""},
  1367. want: sets.NewString("a"),
  1368. },
  1369. {
  1370. name: "removed empty",
  1371. a: map[string]string{"z": ""},
  1372. b: map[string]string{},
  1373. want: sets.NewString("z"),
  1374. },
  1375. {
  1376. name: "changed to empty",
  1377. a: map[string]string{"z": "3"},
  1378. b: map[string]string{"z": ""},
  1379. want: sets.NewString("z"),
  1380. },
  1381. {
  1382. name: "changed from empty",
  1383. a: map[string]string{"z": ""},
  1384. b: map[string]string{"z": "3"},
  1385. want: sets.NewString("z"),
  1386. },
  1387. {
  1388. name: "added, removed, and changed",
  1389. a: map[string]string{"a": "1", "b": "2"},
  1390. b: map[string]string{"a": "2", "c": "3"},
  1391. want: sets.NewString("a", "b", "c"),
  1392. },
  1393. }
  1394. for _, tt := range tests {
  1395. t.Run(tt.name, func(t *testing.T) {
  1396. if got := getModifiedLabels(tt.a, tt.b); !reflect.DeepEqual(got, tt.want) {
  1397. t.Errorf("getModifiedLabels() = %v, want %v", got, tt.want)
  1398. }
  1399. })
  1400. }
  1401. }
  1402. func createPodAttributes(pod *api.Pod, user user.Info) admission.Attributes {
  1403. podResource := api.Resource("pods").WithVersion("v1")
  1404. podKind := api.Kind("Pod").WithVersion("v1")
  1405. return admission.NewAttributesRecord(pod, nil, podKind, pod.Namespace, pod.Name, podResource, "", admission.Create, &metav1.CreateOptions{}, false, user)
  1406. }