framework_test.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806
  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 scheduler
  14. import (
  15. "fmt"
  16. "testing"
  17. "time"
  18. "k8s.io/api/core/v1"
  19. "k8s.io/apimachinery/pkg/runtime"
  20. "k8s.io/apimachinery/pkg/util/wait"
  21. schedulerconfig "k8s.io/kubernetes/pkg/scheduler/apis/config"
  22. framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
  23. )
  24. // TesterPlugin is common ancestor for a test plugin that allows injection of
  25. // failures and some other test functionalities.
  26. type TesterPlugin struct {
  27. numReserveCalled int
  28. numPrebindCalled int
  29. numPostbindCalled int
  30. numUnreserveCalled int
  31. failReserve bool
  32. failPrebind bool
  33. rejectPrebind bool
  34. numPermitCalled int
  35. failPermit bool
  36. rejectPermit bool
  37. timeoutPermit bool
  38. waitAndRejectPermit bool
  39. waitAndAllowPermit bool
  40. }
  41. type ReservePlugin struct {
  42. TesterPlugin
  43. }
  44. type PrebindPlugin struct {
  45. TesterPlugin
  46. }
  47. type PostbindPlugin struct {
  48. TesterPlugin
  49. }
  50. type UnreservePlugin struct {
  51. TesterPlugin
  52. }
  53. type PermitPlugin struct {
  54. TesterPlugin
  55. fh framework.FrameworkHandle
  56. }
  57. const (
  58. reservePluginName = "reserve-plugin"
  59. prebindPluginName = "prebind-plugin"
  60. unreservePluginName = "unreserve-plugin"
  61. postbindPluginName = "postbind-plugin"
  62. permitPluginName = "permit-plugin"
  63. )
  64. var _ = framework.ReservePlugin(&ReservePlugin{})
  65. var _ = framework.PrebindPlugin(&PrebindPlugin{})
  66. var _ = framework.PostbindPlugin(&PostbindPlugin{})
  67. var _ = framework.UnreservePlugin(&UnreservePlugin{})
  68. var _ = framework.PermitPlugin(&PermitPlugin{})
  69. // Name returns name of the plugin.
  70. func (rp *ReservePlugin) Name() string {
  71. return reservePluginName
  72. }
  73. var resPlugin = &ReservePlugin{}
  74. // Reserve is a test function that returns an error or nil, depending on the
  75. // value of "failReserve".
  76. func (rp *ReservePlugin) Reserve(pc *framework.PluginContext, pod *v1.Pod, nodeName string) *framework.Status {
  77. rp.numReserveCalled++
  78. if rp.failReserve {
  79. return framework.NewStatus(framework.Error, fmt.Sprintf("injecting failure for pod %v", pod.Name))
  80. }
  81. return nil
  82. }
  83. // NewReservePlugin is the factory for reserve plugin.
  84. func NewReservePlugin(_ *runtime.Unknown, _ framework.FrameworkHandle) (framework.Plugin, error) {
  85. return resPlugin, nil
  86. }
  87. var pbdPlugin = &PrebindPlugin{}
  88. // Name returns name of the plugin.
  89. func (pp *PrebindPlugin) Name() string {
  90. return prebindPluginName
  91. }
  92. // Prebind is a test function that returns (true, nil) or errors for testing.
  93. func (pp *PrebindPlugin) Prebind(pc *framework.PluginContext, pod *v1.Pod, nodeName string) *framework.Status {
  94. pp.numPrebindCalled++
  95. if pp.failPrebind {
  96. return framework.NewStatus(framework.Error, fmt.Sprintf("injecting failure for pod %v", pod.Name))
  97. }
  98. if pp.rejectPrebind {
  99. return framework.NewStatus(framework.Unschedulable, fmt.Sprintf("reject pod %v", pod.Name))
  100. }
  101. return nil
  102. }
  103. // reset used to reset numPrebindCalled.
  104. func (pp *PrebindPlugin) reset() {
  105. pp.numPrebindCalled = 0
  106. }
  107. // NewPrebindPlugin is the factory for prebind plugin.
  108. func NewPrebindPlugin(_ *runtime.Unknown, _ framework.FrameworkHandle) (framework.Plugin, error) {
  109. return pbdPlugin, nil
  110. }
  111. var ptbdPlugin = &PostbindPlugin{}
  112. // Name returns name of the plugin.
  113. func (pp *PostbindPlugin) Name() string {
  114. return postbindPluginName
  115. }
  116. // Postbind is a test function, which counts the number of times called.
  117. func (pp *PostbindPlugin) Postbind(pc *framework.PluginContext, pod *v1.Pod, nodeName string) {
  118. pp.numPostbindCalled++
  119. }
  120. // reset used to reset numPostbindCalled.
  121. func (pp *PostbindPlugin) reset() {
  122. pp.numPostbindCalled = 0
  123. }
  124. // NewPostbindPlugin is the factory for postbind plugin.
  125. func NewPostbindPlugin(_ *runtime.Unknown, _ framework.FrameworkHandle) (framework.Plugin, error) {
  126. return ptbdPlugin, nil
  127. }
  128. var unresPlugin = &UnreservePlugin{}
  129. // Name returns name of the plugin.
  130. func (up *UnreservePlugin) Name() string {
  131. return unreservePluginName
  132. }
  133. // Unreserve is a test function that returns an error or nil, depending on the
  134. // value of "failUnreserve".
  135. func (up *UnreservePlugin) Unreserve(pc *framework.PluginContext, pod *v1.Pod, nodeName string) {
  136. up.numUnreserveCalled++
  137. }
  138. // reset used to reset numUnreserveCalled.
  139. func (up *UnreservePlugin) reset() {
  140. up.numUnreserveCalled = 0
  141. }
  142. // NewUnreservePlugin is the factory for unreserve plugin.
  143. func NewUnreservePlugin(_ *runtime.Unknown, _ framework.FrameworkHandle) (framework.Plugin, error) {
  144. return unresPlugin, nil
  145. }
  146. var perPlugin = &PermitPlugin{}
  147. // Name returns name of the plugin.
  148. func (pp *PermitPlugin) Name() string {
  149. return permitPluginName
  150. }
  151. // Permit implements the permit test plugin.
  152. func (pp *PermitPlugin) Permit(pc *framework.PluginContext, pod *v1.Pod, nodeName string) (*framework.Status, time.Duration) {
  153. pp.numPermitCalled++
  154. if pp.failPermit {
  155. return framework.NewStatus(framework.Error, fmt.Sprintf("injecting failure for pod %v", pod.Name)), 0
  156. }
  157. if pp.rejectPermit {
  158. return framework.NewStatus(framework.Unschedulable, fmt.Sprintf("reject pod %v", pod.Name)), 0
  159. }
  160. if pp.timeoutPermit {
  161. return framework.NewStatus(framework.Wait, ""), 3 * time.Second
  162. }
  163. if pp.waitAndRejectPermit || pp.waitAndAllowPermit {
  164. if pod.Name == "waiting-pod" {
  165. return framework.NewStatus(framework.Wait, ""), 30 * time.Second
  166. }
  167. // This is the signalling pod, wait until the waiting-pod is actually waiting and then either reject or allow it.
  168. wait.Poll(10*time.Millisecond, 30*time.Second, func() (bool, error) {
  169. w := false
  170. pp.fh.IterateOverWaitingPods(func(wp framework.WaitingPod) { w = true })
  171. return w, nil
  172. })
  173. if pp.waitAndRejectPermit {
  174. pp.fh.IterateOverWaitingPods(func(wp framework.WaitingPod) {
  175. wp.Reject(fmt.Sprintf("reject pod %v", wp.GetPod().Name))
  176. })
  177. return framework.NewStatus(framework.Unschedulable, fmt.Sprintf("reject pod %v", pod.Name)), 0
  178. }
  179. if pp.waitAndAllowPermit {
  180. pp.fh.IterateOverWaitingPods(func(wp framework.WaitingPod) { wp.Allow() })
  181. return nil, 0
  182. }
  183. }
  184. return nil, 0
  185. }
  186. // NewPermitPlugin is the factory for permit plugin.
  187. func NewPermitPlugin(_ *runtime.Unknown, fh framework.FrameworkHandle) (framework.Plugin, error) {
  188. perPlugin.fh = fh
  189. return perPlugin, nil
  190. }
  191. // TestReservePlugin tests invocation of reserve plugins.
  192. func TestReservePlugin(t *testing.T) {
  193. // Create a plugin registry for testing. Register only a reserve plugin.
  194. registry := framework.Registry{reservePluginName: NewReservePlugin}
  195. // Setup initial reserve plugin for testing.
  196. reservePlugin := &schedulerconfig.Plugins{
  197. Reserve: &schedulerconfig.PluginSet{
  198. Enabled: []schedulerconfig.Plugin{
  199. {
  200. Name: reservePluginName,
  201. },
  202. },
  203. },
  204. }
  205. // Set empty plugin config for testing
  206. emptyPluginConfig := []schedulerconfig.PluginConfig{}
  207. // Create the master and the scheduler with the test plugin set.
  208. context := initTestSchedulerWithOptions(t,
  209. initTestMaster(t, "reserve-plugin", nil),
  210. false, nil, registry, reservePlugin, emptyPluginConfig, false, time.Second)
  211. defer cleanupTest(t, context)
  212. cs := context.clientSet
  213. // Add a few nodes.
  214. _, err := createNodes(cs, "test-node", nil, 2)
  215. if err != nil {
  216. t.Fatalf("Cannot create nodes: %v", err)
  217. }
  218. for _, fail := range []bool{false, true} {
  219. resPlugin.failReserve = fail
  220. // Create a best effort pod.
  221. pod, err := createPausePod(cs,
  222. initPausePod(cs, &pausePodConfig{Name: "test-pod", Namespace: context.ns.Name}))
  223. if err != nil {
  224. t.Errorf("Error while creating a test pod: %v", err)
  225. }
  226. if fail {
  227. if err = wait.Poll(10*time.Millisecond, 30*time.Second, podSchedulingError(cs, pod.Namespace, pod.Name)); err != nil {
  228. t.Errorf("Didn't expected the pod to be scheduled. error: %v", err)
  229. }
  230. } else {
  231. if err = waitForPodToSchedule(cs, pod); err != nil {
  232. t.Errorf("Expected the pod to be scheduled. error: %v", err)
  233. }
  234. }
  235. if resPlugin.numReserveCalled == 0 {
  236. t.Errorf("Expected the reserve plugin to be called.")
  237. }
  238. cleanupPods(cs, t, []*v1.Pod{pod})
  239. }
  240. }
  241. // TestPrebindPlugin tests invocation of prebind plugins.
  242. func TestPrebindPlugin(t *testing.T) {
  243. // Create a plugin registry for testing. Register only a prebind plugin.
  244. registry := framework.Registry{prebindPluginName: NewPrebindPlugin}
  245. // Setup initial prebind plugin for testing.
  246. preBindPlugin := &schedulerconfig.Plugins{
  247. PreBind: &schedulerconfig.PluginSet{
  248. Enabled: []schedulerconfig.Plugin{
  249. {
  250. Name: prebindPluginName,
  251. },
  252. },
  253. },
  254. }
  255. // Set reserve prebind config for testing
  256. preBindPluginConfig := []schedulerconfig.PluginConfig{
  257. {
  258. Name: prebindPluginName,
  259. Args: runtime.Unknown{},
  260. },
  261. }
  262. // Create the master and the scheduler with the test plugin set.
  263. context := initTestSchedulerWithOptions(t,
  264. initTestMaster(t, "prebind-plugin", nil),
  265. false, nil, registry, preBindPlugin, preBindPluginConfig, false, time.Second)
  266. defer cleanupTest(t, context)
  267. cs := context.clientSet
  268. // Add a few nodes.
  269. _, err := createNodes(cs, "test-node", nil, 2)
  270. if err != nil {
  271. t.Fatalf("Cannot create nodes: %v", err)
  272. }
  273. tests := []struct {
  274. fail bool
  275. reject bool
  276. }{
  277. {
  278. fail: false,
  279. reject: false,
  280. },
  281. {
  282. fail: true,
  283. reject: false,
  284. },
  285. {
  286. fail: false,
  287. reject: true,
  288. },
  289. {
  290. fail: true,
  291. reject: true,
  292. },
  293. }
  294. for i, test := range tests {
  295. pbdPlugin.failPrebind = test.fail
  296. pbdPlugin.rejectPrebind = test.reject
  297. // Create a best effort pod.
  298. pod, err := createPausePod(cs,
  299. initPausePod(cs, &pausePodConfig{Name: "test-pod", Namespace: context.ns.Name}))
  300. if err != nil {
  301. t.Errorf("Error while creating a test pod: %v", err)
  302. }
  303. if test.fail {
  304. if err = wait.Poll(10*time.Millisecond, 30*time.Second, podSchedulingError(cs, pod.Namespace, pod.Name)); err != nil {
  305. t.Errorf("test #%v: Expected a scheduling error, but didn't get it. error: %v", i, err)
  306. }
  307. } else {
  308. if test.reject {
  309. if err = waitForPodUnschedulable(cs, pod); err != nil {
  310. t.Errorf("test #%v: Didn't expected the pod to be scheduled. error: %v", i, err)
  311. }
  312. } else {
  313. if err = waitForPodToSchedule(cs, pod); err != nil {
  314. t.Errorf("test #%v: Expected the pod to be scheduled. error: %v", i, err)
  315. }
  316. }
  317. }
  318. if pbdPlugin.numPrebindCalled == 0 {
  319. t.Errorf("Expected the prebind plugin to be called.")
  320. }
  321. cleanupPods(cs, t, []*v1.Pod{pod})
  322. }
  323. }
  324. // TestUnreservePlugin tests invocation of un-reserve plugin
  325. func TestUnreservePlugin(t *testing.T) {
  326. // TODO: register more plugin which would trigger un-reserve plugin
  327. registry := framework.Registry{
  328. unreservePluginName: NewUnreservePlugin,
  329. prebindPluginName: NewPrebindPlugin,
  330. }
  331. // Setup initial unreserve and prebind plugin for testing.
  332. plugins := &schedulerconfig.Plugins{
  333. Unreserve: &schedulerconfig.PluginSet{
  334. Enabled: []schedulerconfig.Plugin{
  335. {
  336. Name: unreservePluginName,
  337. },
  338. },
  339. },
  340. PreBind: &schedulerconfig.PluginSet{
  341. Enabled: []schedulerconfig.Plugin{
  342. {
  343. Name: prebindPluginName,
  344. },
  345. },
  346. },
  347. }
  348. // Set unreserve and prebind plugin config for testing
  349. pluginConfig := []schedulerconfig.PluginConfig{
  350. {
  351. Name: unreservePluginName,
  352. Args: runtime.Unknown{},
  353. },
  354. {
  355. Name: prebindPluginName,
  356. Args: runtime.Unknown{},
  357. },
  358. }
  359. // Create the master and the scheduler with the test plugin set.
  360. context := initTestSchedulerWithOptions(t,
  361. initTestMaster(t, "unreserve-plugin", nil),
  362. false, nil, registry, plugins, pluginConfig, false, time.Second)
  363. defer cleanupTest(t, context)
  364. cs := context.clientSet
  365. // Add a few nodes.
  366. _, err := createNodes(cs, "test-node", nil, 2)
  367. if err != nil {
  368. t.Fatalf("Cannot create nodes: %v", err)
  369. }
  370. tests := []struct {
  371. prebindFail bool
  372. prebindReject bool
  373. }{
  374. {
  375. prebindFail: false,
  376. prebindReject: false,
  377. },
  378. {
  379. prebindFail: true,
  380. prebindReject: false,
  381. },
  382. {
  383. prebindFail: false,
  384. prebindReject: true,
  385. },
  386. {
  387. prebindFail: true,
  388. prebindReject: true,
  389. },
  390. }
  391. for i, test := range tests {
  392. pbdPlugin.failPrebind = test.prebindFail
  393. pbdPlugin.rejectPrebind = test.prebindReject
  394. // Create a best effort pod.
  395. pod, err := createPausePod(cs,
  396. initPausePod(cs, &pausePodConfig{Name: "test-pod", Namespace: context.ns.Name}))
  397. if err != nil {
  398. t.Errorf("Error while creating a test pod: %v", err)
  399. }
  400. if test.prebindFail {
  401. if err = wait.Poll(10*time.Millisecond, 30*time.Second, podSchedulingError(cs, pod.Namespace, pod.Name)); err != nil {
  402. t.Errorf("test #%v: Expected a scheduling error, but didn't get it. error: %v", i, err)
  403. }
  404. if unresPlugin.numUnreserveCalled == 0 || unresPlugin.numUnreserveCalled != pbdPlugin.numPrebindCalled {
  405. t.Errorf("test #%v: Expected the unreserve plugin to be called %d times, was called %d times.", i, pbdPlugin.numPrebindCalled, unresPlugin.numUnreserveCalled)
  406. }
  407. } else {
  408. if test.prebindReject {
  409. if err = waitForPodUnschedulable(cs, pod); err != nil {
  410. t.Errorf("test #%v: Didn't expected the pod to be scheduled. error: %v", i, err)
  411. }
  412. if unresPlugin.numUnreserveCalled == 0 || unresPlugin.numUnreserveCalled != pbdPlugin.numPrebindCalled {
  413. t.Errorf("test #%v: Expected the unreserve plugin to be called %d times, was called %d times.", i, pbdPlugin.numPrebindCalled, unresPlugin.numUnreserveCalled)
  414. }
  415. } else {
  416. if err = waitForPodToSchedule(cs, pod); err != nil {
  417. t.Errorf("test #%v: Expected the pod to be scheduled. error: %v", i, err)
  418. }
  419. if unresPlugin.numUnreserveCalled > 0 {
  420. t.Errorf("test #%v: Didn't expected the unreserve plugin to be called, was called %d times.", i, unresPlugin.numUnreserveCalled)
  421. }
  422. }
  423. }
  424. unresPlugin.reset()
  425. pbdPlugin.reset()
  426. cleanupPods(cs, t, []*v1.Pod{pod})
  427. }
  428. }
  429. // TestPostbindPlugin tests invocation of postbind plugins.
  430. func TestPostbindPlugin(t *testing.T) {
  431. // Create a plugin registry for testing. Register a prebind and a postbind plugin.
  432. registry := framework.Registry{
  433. prebindPluginName: NewPrebindPlugin,
  434. postbindPluginName: NewPostbindPlugin,
  435. }
  436. // Setup initial prebind and postbind plugin for testing.
  437. plugins := &schedulerconfig.Plugins{
  438. PreBind: &schedulerconfig.PluginSet{
  439. Enabled: []schedulerconfig.Plugin{
  440. {
  441. Name: prebindPluginName,
  442. },
  443. },
  444. },
  445. PostBind: &schedulerconfig.PluginSet{
  446. Enabled: []schedulerconfig.Plugin{
  447. {
  448. Name: postbindPluginName,
  449. },
  450. },
  451. },
  452. }
  453. // Set reserve prebind and postbind config for testing
  454. pluginConfig := []schedulerconfig.PluginConfig{
  455. {
  456. Name: prebindPluginName,
  457. Args: runtime.Unknown{},
  458. },
  459. {
  460. Name: postbindPluginName,
  461. Args: runtime.Unknown{},
  462. },
  463. }
  464. // Create the master and the scheduler with the test plugin set.
  465. context := initTestSchedulerWithOptions(t,
  466. initTestMaster(t, "postbind-plugin", nil),
  467. false, nil, registry, plugins, pluginConfig, false, time.Second)
  468. defer cleanupTest(t, context)
  469. cs := context.clientSet
  470. // Add a few nodes.
  471. _, err := createNodes(cs, "test-node", nil, 2)
  472. if err != nil {
  473. t.Fatalf("Cannot create nodes: %v", err)
  474. }
  475. tests := []struct {
  476. prebindFail bool
  477. prebindReject bool
  478. }{
  479. {
  480. prebindFail: false,
  481. prebindReject: false,
  482. },
  483. {
  484. prebindFail: true,
  485. prebindReject: false,
  486. },
  487. {
  488. prebindFail: false,
  489. prebindReject: true,
  490. },
  491. {
  492. prebindFail: true,
  493. prebindReject: true,
  494. },
  495. }
  496. for i, test := range tests {
  497. pbdPlugin.failPrebind = test.prebindFail
  498. pbdPlugin.rejectPrebind = test.prebindReject
  499. // Create a best effort pod.
  500. pod, err := createPausePod(cs,
  501. initPausePod(cs, &pausePodConfig{Name: "test-pod", Namespace: context.ns.Name}))
  502. if err != nil {
  503. t.Errorf("Error while creating a test pod: %v", err)
  504. }
  505. if test.prebindFail {
  506. if err = wait.Poll(10*time.Millisecond, 30*time.Second, podSchedulingError(cs, pod.Namespace, pod.Name)); err != nil {
  507. t.Errorf("test #%v: Expected a scheduling error, but didn't get it. error: %v", i, err)
  508. }
  509. if ptbdPlugin.numPostbindCalled > 0 {
  510. t.Errorf("test #%v: Didn't expected the postbind plugin to be called %d times.", i, ptbdPlugin.numPostbindCalled)
  511. }
  512. } else {
  513. if test.prebindReject {
  514. if err = waitForPodUnschedulable(cs, pod); err != nil {
  515. t.Errorf("test #%v: Didn't expected the pod to be scheduled. error: %v", i, err)
  516. }
  517. if ptbdPlugin.numPostbindCalled > 0 {
  518. t.Errorf("test #%v: Didn't expected the postbind plugin to be called %d times.", i, ptbdPlugin.numPostbindCalled)
  519. }
  520. } else {
  521. if err = waitForPodToSchedule(cs, pod); err != nil {
  522. t.Errorf("test #%v: Expected the pod to be scheduled. error: %v", i, err)
  523. }
  524. if ptbdPlugin.numPostbindCalled == 0 {
  525. t.Errorf("test #%v: Expected the postbind plugin to be called, was called %d times.", i, ptbdPlugin.numPostbindCalled)
  526. }
  527. }
  528. }
  529. ptbdPlugin.reset()
  530. pbdPlugin.reset()
  531. cleanupPods(cs, t, []*v1.Pod{pod})
  532. }
  533. }
  534. // TestPermitPlugin tests invocation of permit plugins.
  535. func TestPermitPlugin(t *testing.T) {
  536. // Create a plugin registry for testing. Register only a permit plugin.
  537. registry := framework.Registry{permitPluginName: NewPermitPlugin}
  538. // Setup initial permit plugin for testing.
  539. plugins := &schedulerconfig.Plugins{
  540. Permit: &schedulerconfig.PluginSet{
  541. Enabled: []schedulerconfig.Plugin{
  542. {
  543. Name: permitPluginName,
  544. },
  545. },
  546. },
  547. }
  548. // Set permit plugin config for testing
  549. pluginConfig := []schedulerconfig.PluginConfig{
  550. {
  551. Name: permitPluginName,
  552. Args: runtime.Unknown{},
  553. },
  554. }
  555. // Create the master and the scheduler with the test plugin set.
  556. context := initTestSchedulerWithOptions(t,
  557. initTestMaster(t, "permit-plugin", nil),
  558. false, nil, registry, plugins, pluginConfig, false, time.Second)
  559. defer cleanupTest(t, context)
  560. cs := context.clientSet
  561. // Add a few nodes.
  562. _, err := createNodes(cs, "test-node", nil, 2)
  563. if err != nil {
  564. t.Fatalf("Cannot create nodes: %v", err)
  565. }
  566. tests := []struct {
  567. fail bool
  568. reject bool
  569. timeout bool
  570. }{
  571. {
  572. fail: false,
  573. reject: false,
  574. timeout: false,
  575. },
  576. {
  577. fail: true,
  578. reject: false,
  579. timeout: false,
  580. },
  581. {
  582. fail: false,
  583. reject: true,
  584. timeout: false,
  585. },
  586. {
  587. fail: true,
  588. reject: true,
  589. timeout: false,
  590. },
  591. {
  592. fail: false,
  593. reject: false,
  594. timeout: true,
  595. },
  596. {
  597. fail: false,
  598. reject: false,
  599. timeout: true,
  600. },
  601. }
  602. for i, test := range tests {
  603. perPlugin.failPermit = test.fail
  604. perPlugin.rejectPermit = test.reject
  605. perPlugin.timeoutPermit = test.timeout
  606. perPlugin.waitAndRejectPermit = false
  607. perPlugin.waitAndAllowPermit = false
  608. // Create a best effort pod.
  609. pod, err := createPausePod(cs,
  610. initPausePod(cs, &pausePodConfig{Name: "test-pod", Namespace: context.ns.Name}))
  611. if err != nil {
  612. t.Errorf("Error while creating a test pod: %v", err)
  613. }
  614. if test.fail {
  615. if err = wait.Poll(10*time.Millisecond, 30*time.Second, podSchedulingError(cs, pod.Namespace, pod.Name)); err != nil {
  616. t.Errorf("test #%v: Expected a scheduling error, but didn't get it. error: %v", i, err)
  617. }
  618. } else {
  619. if test.reject || test.timeout {
  620. if err = waitForPodUnschedulable(cs, pod); err != nil {
  621. t.Errorf("test #%v: Didn't expect the pod to be scheduled. error: %v", i, err)
  622. }
  623. } else {
  624. if err = waitForPodToSchedule(cs, pod); err != nil {
  625. t.Errorf("test #%v: Expected the pod to be scheduled. error: %v", i, err)
  626. }
  627. }
  628. }
  629. if perPlugin.numPermitCalled == 0 {
  630. t.Errorf("Expected the permit plugin to be called.")
  631. }
  632. cleanupPods(cs, t, []*v1.Pod{pod})
  633. }
  634. }
  635. // TestCoSchedulingWithPermitPlugin tests invocation of permit plugins.
  636. func TestCoSchedulingWithPermitPlugin(t *testing.T) {
  637. // Create a plugin registry for testing. Register only a permit plugin.
  638. registry := framework.Registry{permitPluginName: NewPermitPlugin}
  639. // Setup initial permit plugin for testing.
  640. plugins := &schedulerconfig.Plugins{
  641. Permit: &schedulerconfig.PluginSet{
  642. Enabled: []schedulerconfig.Plugin{
  643. {
  644. Name: permitPluginName,
  645. },
  646. },
  647. },
  648. }
  649. // Set permit plugin config for testing
  650. pluginConfig := []schedulerconfig.PluginConfig{
  651. {
  652. Name: permitPluginName,
  653. Args: runtime.Unknown{},
  654. },
  655. }
  656. // Create the master and the scheduler with the test plugin set.
  657. context := initTestSchedulerWithOptions(t,
  658. initTestMaster(t, "permit-plugin", nil),
  659. false, nil, registry, plugins, pluginConfig, false, time.Second)
  660. defer cleanupTest(t, context)
  661. cs := context.clientSet
  662. // Add a few nodes.
  663. _, err := createNodes(cs, "test-node", nil, 2)
  664. if err != nil {
  665. t.Fatalf("Cannot create nodes: %v", err)
  666. }
  667. tests := []struct {
  668. waitReject bool
  669. waitAllow bool
  670. }{
  671. {
  672. waitReject: true,
  673. waitAllow: false,
  674. },
  675. {
  676. waitReject: false,
  677. waitAllow: true,
  678. },
  679. }
  680. for i, test := range tests {
  681. perPlugin.failPermit = false
  682. perPlugin.rejectPermit = false
  683. perPlugin.timeoutPermit = false
  684. perPlugin.waitAndRejectPermit = test.waitReject
  685. perPlugin.waitAndAllowPermit = test.waitAllow
  686. // Create two pods.
  687. waitingPod, err := createPausePod(cs,
  688. initPausePod(cs, &pausePodConfig{Name: "waiting-pod", Namespace: context.ns.Name}))
  689. if err != nil {
  690. t.Errorf("Error while creating the waiting pod: %v", err)
  691. }
  692. signallingPod, err := createPausePod(cs,
  693. initPausePod(cs, &pausePodConfig{Name: "signalling-pod", Namespace: context.ns.Name}))
  694. if err != nil {
  695. t.Errorf("Error while creating the signalling pod: %v", err)
  696. }
  697. if test.waitReject {
  698. if err = waitForPodUnschedulable(cs, waitingPod); err != nil {
  699. t.Errorf("test #%v: Didn't expect the waiting pod to be scheduled. error: %v", i, err)
  700. }
  701. if err = waitForPodUnschedulable(cs, signallingPod); err != nil {
  702. t.Errorf("test #%v: Didn't expect the signalling pod to be scheduled. error: %v", i, err)
  703. }
  704. } else {
  705. if err = waitForPodToSchedule(cs, waitingPod); err != nil {
  706. t.Errorf("test #%v: Expected the waiting pod to be scheduled. error: %v", i, err)
  707. }
  708. if err = waitForPodToSchedule(cs, signallingPod); err != nil {
  709. t.Errorf("test #%v: Expected the signalling pod to be scheduled. error: %v", i, err)
  710. }
  711. }
  712. if perPlugin.numPermitCalled == 0 {
  713. t.Errorf("Expected the permit plugin to be called.")
  714. }
  715. cleanupPods(cs, t, []*v1.Pod{waitingPod, signallingPod})
  716. }
  717. }