node_info_test.go 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934
  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 nodeinfo
  14. import (
  15. "fmt"
  16. "reflect"
  17. "strings"
  18. "testing"
  19. "k8s.io/api/core/v1"
  20. "k8s.io/apimachinery/pkg/api/resource"
  21. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  22. "k8s.io/apimachinery/pkg/types"
  23. )
  24. func TestNewResource(t *testing.T) {
  25. tests := []struct {
  26. resourceList v1.ResourceList
  27. expected *Resource
  28. }{
  29. {
  30. resourceList: map[v1.ResourceName]resource.Quantity{},
  31. expected: &Resource{},
  32. },
  33. {
  34. resourceList: map[v1.ResourceName]resource.Quantity{
  35. v1.ResourceCPU: *resource.NewScaledQuantity(4, -3),
  36. v1.ResourceMemory: *resource.NewQuantity(2000, resource.BinarySI),
  37. v1.ResourcePods: *resource.NewQuantity(80, resource.BinarySI),
  38. v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI),
  39. "scalar.test/" + "scalar1": *resource.NewQuantity(1, resource.DecimalSI),
  40. v1.ResourceHugePagesPrefix + "test": *resource.NewQuantity(2, resource.BinarySI),
  41. },
  42. expected: &Resource{
  43. MilliCPU: 4,
  44. Memory: 2000,
  45. EphemeralStorage: 5000,
  46. AllowedPodNumber: 80,
  47. ScalarResources: map[v1.ResourceName]int64{"scalar.test/scalar1": 1, "hugepages-test": 2},
  48. },
  49. },
  50. }
  51. for _, test := range tests {
  52. r := NewResource(test.resourceList)
  53. if !reflect.DeepEqual(test.expected, r) {
  54. t.Errorf("expected: %#v, got: %#v", test.expected, r)
  55. }
  56. }
  57. }
  58. func TestResourceList(t *testing.T) {
  59. tests := []struct {
  60. resource *Resource
  61. expected v1.ResourceList
  62. }{
  63. {
  64. resource: &Resource{},
  65. expected: map[v1.ResourceName]resource.Quantity{
  66. v1.ResourceCPU: *resource.NewScaledQuantity(0, -3),
  67. v1.ResourceMemory: *resource.NewQuantity(0, resource.BinarySI),
  68. v1.ResourcePods: *resource.NewQuantity(0, resource.BinarySI),
  69. v1.ResourceEphemeralStorage: *resource.NewQuantity(0, resource.BinarySI),
  70. },
  71. },
  72. {
  73. resource: &Resource{
  74. MilliCPU: 4,
  75. Memory: 2000,
  76. EphemeralStorage: 5000,
  77. AllowedPodNumber: 80,
  78. ScalarResources: map[v1.ResourceName]int64{
  79. "scalar.test/scalar1": 1,
  80. "hugepages-test": 2,
  81. "attachable-volumes-aws-ebs": 39,
  82. },
  83. },
  84. expected: map[v1.ResourceName]resource.Quantity{
  85. v1.ResourceCPU: *resource.NewScaledQuantity(4, -3),
  86. v1.ResourceMemory: *resource.NewQuantity(2000, resource.BinarySI),
  87. v1.ResourcePods: *resource.NewQuantity(80, resource.BinarySI),
  88. v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI),
  89. "scalar.test/" + "scalar1": *resource.NewQuantity(1, resource.DecimalSI),
  90. "attachable-volumes-aws-ebs": *resource.NewQuantity(39, resource.DecimalSI),
  91. v1.ResourceHugePagesPrefix + "test": *resource.NewQuantity(2, resource.BinarySI),
  92. },
  93. },
  94. }
  95. for _, test := range tests {
  96. rl := test.resource.ResourceList()
  97. if !reflect.DeepEqual(test.expected, rl) {
  98. t.Errorf("expected: %#v, got: %#v", test.expected, rl)
  99. }
  100. }
  101. }
  102. func TestResourceClone(t *testing.T) {
  103. tests := []struct {
  104. resource *Resource
  105. expected *Resource
  106. }{
  107. {
  108. resource: &Resource{},
  109. expected: &Resource{},
  110. },
  111. {
  112. resource: &Resource{
  113. MilliCPU: 4,
  114. Memory: 2000,
  115. EphemeralStorage: 5000,
  116. AllowedPodNumber: 80,
  117. ScalarResources: map[v1.ResourceName]int64{"scalar.test/scalar1": 1, "hugepages-test": 2},
  118. },
  119. expected: &Resource{
  120. MilliCPU: 4,
  121. Memory: 2000,
  122. EphemeralStorage: 5000,
  123. AllowedPodNumber: 80,
  124. ScalarResources: map[v1.ResourceName]int64{"scalar.test/scalar1": 1, "hugepages-test": 2},
  125. },
  126. },
  127. }
  128. for _, test := range tests {
  129. r := test.resource.Clone()
  130. // Modify the field to check if the result is a clone of the origin one.
  131. test.resource.MilliCPU += 1000
  132. if !reflect.DeepEqual(test.expected, r) {
  133. t.Errorf("expected: %#v, got: %#v", test.expected, r)
  134. }
  135. }
  136. }
  137. func TestResourceAddScalar(t *testing.T) {
  138. tests := []struct {
  139. resource *Resource
  140. scalarName v1.ResourceName
  141. scalarQuantity int64
  142. expected *Resource
  143. }{
  144. {
  145. resource: &Resource{},
  146. scalarName: "scalar1",
  147. scalarQuantity: 100,
  148. expected: &Resource{
  149. ScalarResources: map[v1.ResourceName]int64{"scalar1": 100},
  150. },
  151. },
  152. {
  153. resource: &Resource{
  154. MilliCPU: 4,
  155. Memory: 2000,
  156. EphemeralStorage: 5000,
  157. AllowedPodNumber: 80,
  158. ScalarResources: map[v1.ResourceName]int64{"hugepages-test": 2},
  159. },
  160. scalarName: "scalar2",
  161. scalarQuantity: 200,
  162. expected: &Resource{
  163. MilliCPU: 4,
  164. Memory: 2000,
  165. EphemeralStorage: 5000,
  166. AllowedPodNumber: 80,
  167. ScalarResources: map[v1.ResourceName]int64{"hugepages-test": 2, "scalar2": 200},
  168. },
  169. },
  170. }
  171. for _, test := range tests {
  172. test.resource.AddScalar(test.scalarName, test.scalarQuantity)
  173. if !reflect.DeepEqual(test.expected, test.resource) {
  174. t.Errorf("expected: %#v, got: %#v", test.expected, test.resource)
  175. }
  176. }
  177. }
  178. func TestSetMaxResource(t *testing.T) {
  179. tests := []struct {
  180. resource *Resource
  181. resourceList v1.ResourceList
  182. expected *Resource
  183. }{
  184. {
  185. resource: &Resource{},
  186. resourceList: map[v1.ResourceName]resource.Quantity{
  187. v1.ResourceCPU: *resource.NewScaledQuantity(4, -3),
  188. v1.ResourceMemory: *resource.NewQuantity(2000, resource.BinarySI),
  189. v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI),
  190. },
  191. expected: &Resource{
  192. MilliCPU: 4,
  193. Memory: 2000,
  194. EphemeralStorage: 5000,
  195. },
  196. },
  197. {
  198. resource: &Resource{
  199. MilliCPU: 4,
  200. Memory: 4000,
  201. EphemeralStorage: 5000,
  202. ScalarResources: map[v1.ResourceName]int64{"scalar.test/scalar1": 1, "hugepages-test": 2},
  203. },
  204. resourceList: map[v1.ResourceName]resource.Quantity{
  205. v1.ResourceCPU: *resource.NewScaledQuantity(4, -3),
  206. v1.ResourceMemory: *resource.NewQuantity(2000, resource.BinarySI),
  207. v1.ResourceEphemeralStorage: *resource.NewQuantity(7000, resource.BinarySI),
  208. "scalar.test/scalar1": *resource.NewQuantity(4, resource.DecimalSI),
  209. v1.ResourceHugePagesPrefix + "test": *resource.NewQuantity(5, resource.BinarySI),
  210. },
  211. expected: &Resource{
  212. MilliCPU: 4,
  213. Memory: 4000,
  214. EphemeralStorage: 7000,
  215. ScalarResources: map[v1.ResourceName]int64{"scalar.test/scalar1": 4, "hugepages-test": 5},
  216. },
  217. },
  218. }
  219. for _, test := range tests {
  220. test.resource.SetMaxResource(test.resourceList)
  221. if !reflect.DeepEqual(test.expected, test.resource) {
  222. t.Errorf("expected: %#v, got: %#v", test.expected, test.resource)
  223. }
  224. }
  225. }
  226. type testingMode interface {
  227. Fatalf(format string, args ...interface{})
  228. }
  229. func makeBasePod(t testingMode, nodeName, objName, cpu, mem, extended string, ports []v1.ContainerPort) *v1.Pod {
  230. req := v1.ResourceList{}
  231. if cpu != "" {
  232. req = v1.ResourceList{
  233. v1.ResourceCPU: resource.MustParse(cpu),
  234. v1.ResourceMemory: resource.MustParse(mem),
  235. }
  236. if extended != "" {
  237. parts := strings.Split(extended, ":")
  238. if len(parts) != 2 {
  239. t.Fatalf("Invalid extended resource string: \"%s\"", extended)
  240. }
  241. req[v1.ResourceName(parts[0])] = resource.MustParse(parts[1])
  242. }
  243. }
  244. return &v1.Pod{
  245. ObjectMeta: metav1.ObjectMeta{
  246. UID: types.UID(objName),
  247. Namespace: "node_info_cache_test",
  248. Name: objName,
  249. },
  250. Spec: v1.PodSpec{
  251. Containers: []v1.Container{{
  252. Resources: v1.ResourceRequirements{
  253. Requests: req,
  254. },
  255. Ports: ports,
  256. }},
  257. NodeName: nodeName,
  258. },
  259. }
  260. }
  261. func TestNewNodeInfo(t *testing.T) {
  262. nodeName := "test-node"
  263. pods := []*v1.Pod{
  264. makeBasePod(t, nodeName, "test-1", "100m", "500", "", []v1.ContainerPort{{HostIP: "127.0.0.1", HostPort: 80, Protocol: "TCP"}}),
  265. makeBasePod(t, nodeName, "test-2", "200m", "1Ki", "", []v1.ContainerPort{{HostIP: "127.0.0.1", HostPort: 8080, Protocol: "TCP"}}),
  266. }
  267. expected := &NodeInfo{
  268. requestedResource: &Resource{
  269. MilliCPU: 300,
  270. Memory: 1524,
  271. EphemeralStorage: 0,
  272. AllowedPodNumber: 0,
  273. ScalarResources: map[v1.ResourceName]int64(nil),
  274. },
  275. nonzeroRequest: &Resource{
  276. MilliCPU: 300,
  277. Memory: 1524,
  278. EphemeralStorage: 0,
  279. AllowedPodNumber: 0,
  280. ScalarResources: map[v1.ResourceName]int64(nil),
  281. },
  282. TransientInfo: NewTransientSchedulerInfo(),
  283. allocatableResource: &Resource{},
  284. generation: 2,
  285. usedPorts: HostPortInfo{
  286. "127.0.0.1": map[ProtocolPort]struct{}{
  287. {Protocol: "TCP", Port: 80}: {},
  288. {Protocol: "TCP", Port: 8080}: {},
  289. },
  290. },
  291. imageStates: map[string]*ImageStateSummary{},
  292. pods: []*v1.Pod{
  293. {
  294. ObjectMeta: metav1.ObjectMeta{
  295. Namespace: "node_info_cache_test",
  296. Name: "test-1",
  297. UID: types.UID("test-1"),
  298. },
  299. Spec: v1.PodSpec{
  300. Containers: []v1.Container{
  301. {
  302. Resources: v1.ResourceRequirements{
  303. Requests: v1.ResourceList{
  304. v1.ResourceCPU: resource.MustParse("100m"),
  305. v1.ResourceMemory: resource.MustParse("500"),
  306. },
  307. },
  308. Ports: []v1.ContainerPort{
  309. {
  310. HostIP: "127.0.0.1",
  311. HostPort: 80,
  312. Protocol: "TCP",
  313. },
  314. },
  315. },
  316. },
  317. NodeName: nodeName,
  318. },
  319. },
  320. {
  321. ObjectMeta: metav1.ObjectMeta{
  322. Namespace: "node_info_cache_test",
  323. Name: "test-2",
  324. UID: types.UID("test-2"),
  325. },
  326. Spec: v1.PodSpec{
  327. Containers: []v1.Container{
  328. {
  329. Resources: v1.ResourceRequirements{
  330. Requests: v1.ResourceList{
  331. v1.ResourceCPU: resource.MustParse("200m"),
  332. v1.ResourceMemory: resource.MustParse("1Ki"),
  333. },
  334. },
  335. Ports: []v1.ContainerPort{
  336. {
  337. HostIP: "127.0.0.1",
  338. HostPort: 8080,
  339. Protocol: "TCP",
  340. },
  341. },
  342. },
  343. },
  344. NodeName: nodeName,
  345. },
  346. },
  347. },
  348. }
  349. gen := generation
  350. ni := NewNodeInfo(pods...)
  351. if ni.generation <= gen {
  352. t.Errorf("generation is not incremented. previous: %v, current: %v", gen, ni.generation)
  353. }
  354. expected.generation = ni.generation
  355. if !reflect.DeepEqual(expected, ni) {
  356. t.Errorf("expected: %#v, got: %#v", expected, ni)
  357. }
  358. }
  359. func TestNodeInfoClone(t *testing.T) {
  360. nodeName := "test-node"
  361. tests := []struct {
  362. nodeInfo *NodeInfo
  363. expected *NodeInfo
  364. }{
  365. {
  366. nodeInfo: &NodeInfo{
  367. requestedResource: &Resource{},
  368. nonzeroRequest: &Resource{},
  369. TransientInfo: NewTransientSchedulerInfo(),
  370. allocatableResource: &Resource{},
  371. generation: 2,
  372. usedPorts: HostPortInfo{
  373. "127.0.0.1": map[ProtocolPort]struct{}{
  374. {Protocol: "TCP", Port: 80}: {},
  375. {Protocol: "TCP", Port: 8080}: {},
  376. },
  377. },
  378. imageStates: map[string]*ImageStateSummary{},
  379. pods: []*v1.Pod{
  380. {
  381. ObjectMeta: metav1.ObjectMeta{
  382. Namespace: "node_info_cache_test",
  383. Name: "test-1",
  384. UID: types.UID("test-1"),
  385. },
  386. Spec: v1.PodSpec{
  387. Containers: []v1.Container{
  388. {
  389. Resources: v1.ResourceRequirements{
  390. Requests: v1.ResourceList{
  391. v1.ResourceCPU: resource.MustParse("100m"),
  392. v1.ResourceMemory: resource.MustParse("500"),
  393. },
  394. },
  395. Ports: []v1.ContainerPort{
  396. {
  397. HostIP: "127.0.0.1",
  398. HostPort: 80,
  399. Protocol: "TCP",
  400. },
  401. },
  402. },
  403. },
  404. NodeName: nodeName,
  405. },
  406. },
  407. {
  408. ObjectMeta: metav1.ObjectMeta{
  409. Namespace: "node_info_cache_test",
  410. Name: "test-2",
  411. UID: types.UID("test-2"),
  412. },
  413. Spec: v1.PodSpec{
  414. Containers: []v1.Container{
  415. {
  416. Resources: v1.ResourceRequirements{
  417. Requests: v1.ResourceList{
  418. v1.ResourceCPU: resource.MustParse("200m"),
  419. v1.ResourceMemory: resource.MustParse("1Ki"),
  420. },
  421. },
  422. Ports: []v1.ContainerPort{
  423. {
  424. HostIP: "127.0.0.1",
  425. HostPort: 8080,
  426. Protocol: "TCP",
  427. },
  428. },
  429. },
  430. },
  431. NodeName: nodeName,
  432. },
  433. },
  434. },
  435. },
  436. expected: &NodeInfo{
  437. requestedResource: &Resource{},
  438. nonzeroRequest: &Resource{},
  439. TransientInfo: NewTransientSchedulerInfo(),
  440. allocatableResource: &Resource{},
  441. generation: 2,
  442. usedPorts: HostPortInfo{
  443. "127.0.0.1": map[ProtocolPort]struct{}{
  444. {Protocol: "TCP", Port: 80}: {},
  445. {Protocol: "TCP", Port: 8080}: {},
  446. },
  447. },
  448. imageStates: map[string]*ImageStateSummary{},
  449. pods: []*v1.Pod{
  450. {
  451. ObjectMeta: metav1.ObjectMeta{
  452. Namespace: "node_info_cache_test",
  453. Name: "test-1",
  454. UID: types.UID("test-1"),
  455. },
  456. Spec: v1.PodSpec{
  457. Containers: []v1.Container{
  458. {
  459. Resources: v1.ResourceRequirements{
  460. Requests: v1.ResourceList{
  461. v1.ResourceCPU: resource.MustParse("100m"),
  462. v1.ResourceMemory: resource.MustParse("500"),
  463. },
  464. },
  465. Ports: []v1.ContainerPort{
  466. {
  467. HostIP: "127.0.0.1",
  468. HostPort: 80,
  469. Protocol: "TCP",
  470. },
  471. },
  472. },
  473. },
  474. NodeName: nodeName,
  475. },
  476. },
  477. {
  478. ObjectMeta: metav1.ObjectMeta{
  479. Namespace: "node_info_cache_test",
  480. Name: "test-2",
  481. UID: types.UID("test-2"),
  482. },
  483. Spec: v1.PodSpec{
  484. Containers: []v1.Container{
  485. {
  486. Resources: v1.ResourceRequirements{
  487. Requests: v1.ResourceList{
  488. v1.ResourceCPU: resource.MustParse("200m"),
  489. v1.ResourceMemory: resource.MustParse("1Ki"),
  490. },
  491. },
  492. Ports: []v1.ContainerPort{
  493. {
  494. HostIP: "127.0.0.1",
  495. HostPort: 8080,
  496. Protocol: "TCP",
  497. },
  498. },
  499. },
  500. },
  501. NodeName: nodeName,
  502. },
  503. },
  504. },
  505. },
  506. },
  507. }
  508. for _, test := range tests {
  509. ni := test.nodeInfo.Clone()
  510. // Modify the field to check if the result is a clone of the origin one.
  511. test.nodeInfo.generation += 10
  512. test.nodeInfo.usedPorts.Remove("127.0.0.1", "TCP", 80)
  513. if !reflect.DeepEqual(test.expected, ni) {
  514. t.Errorf("expected: %#v, got: %#v", test.expected, ni)
  515. }
  516. }
  517. }
  518. func TestNodeInfoAddPod(t *testing.T) {
  519. nodeName := "test-node"
  520. pods := []*v1.Pod{
  521. {
  522. ObjectMeta: metav1.ObjectMeta{
  523. Namespace: "node_info_cache_test",
  524. Name: "test-1",
  525. UID: types.UID("test-1"),
  526. },
  527. Spec: v1.PodSpec{
  528. Containers: []v1.Container{
  529. {
  530. Resources: v1.ResourceRequirements{
  531. Requests: v1.ResourceList{
  532. v1.ResourceCPU: resource.MustParse("100m"),
  533. v1.ResourceMemory: resource.MustParse("500"),
  534. },
  535. },
  536. Ports: []v1.ContainerPort{
  537. {
  538. HostIP: "127.0.0.1",
  539. HostPort: 80,
  540. Protocol: "TCP",
  541. },
  542. },
  543. },
  544. },
  545. NodeName: nodeName,
  546. },
  547. },
  548. {
  549. ObjectMeta: metav1.ObjectMeta{
  550. Namespace: "node_info_cache_test",
  551. Name: "test-2",
  552. UID: types.UID("test-2"),
  553. },
  554. Spec: v1.PodSpec{
  555. Containers: []v1.Container{
  556. {
  557. Resources: v1.ResourceRequirements{
  558. Requests: v1.ResourceList{
  559. v1.ResourceCPU: resource.MustParse("200m"),
  560. v1.ResourceMemory: resource.MustParse("1Ki"),
  561. },
  562. },
  563. Ports: []v1.ContainerPort{
  564. {
  565. HostIP: "127.0.0.1",
  566. HostPort: 8080,
  567. Protocol: "TCP",
  568. },
  569. },
  570. },
  571. },
  572. NodeName: nodeName,
  573. },
  574. },
  575. }
  576. expected := &NodeInfo{
  577. node: &v1.Node{
  578. ObjectMeta: metav1.ObjectMeta{
  579. Name: "test-node",
  580. },
  581. },
  582. requestedResource: &Resource{
  583. MilliCPU: 300,
  584. Memory: 1524,
  585. EphemeralStorage: 0,
  586. AllowedPodNumber: 0,
  587. ScalarResources: map[v1.ResourceName]int64(nil),
  588. },
  589. nonzeroRequest: &Resource{
  590. MilliCPU: 300,
  591. Memory: 1524,
  592. EphemeralStorage: 0,
  593. AllowedPodNumber: 0,
  594. ScalarResources: map[v1.ResourceName]int64(nil),
  595. },
  596. TransientInfo: NewTransientSchedulerInfo(),
  597. allocatableResource: &Resource{},
  598. generation: 2,
  599. usedPorts: HostPortInfo{
  600. "127.0.0.1": map[ProtocolPort]struct{}{
  601. {Protocol: "TCP", Port: 80}: {},
  602. {Protocol: "TCP", Port: 8080}: {},
  603. },
  604. },
  605. imageStates: map[string]*ImageStateSummary{},
  606. pods: []*v1.Pod{
  607. {
  608. ObjectMeta: metav1.ObjectMeta{
  609. Namespace: "node_info_cache_test",
  610. Name: "test-1",
  611. UID: types.UID("test-1"),
  612. },
  613. Spec: v1.PodSpec{
  614. Containers: []v1.Container{
  615. {
  616. Resources: v1.ResourceRequirements{
  617. Requests: v1.ResourceList{
  618. v1.ResourceCPU: resource.MustParse("100m"),
  619. v1.ResourceMemory: resource.MustParse("500"),
  620. },
  621. },
  622. Ports: []v1.ContainerPort{
  623. {
  624. HostIP: "127.0.0.1",
  625. HostPort: 80,
  626. Protocol: "TCP",
  627. },
  628. },
  629. },
  630. },
  631. NodeName: nodeName,
  632. },
  633. },
  634. {
  635. ObjectMeta: metav1.ObjectMeta{
  636. Namespace: "node_info_cache_test",
  637. Name: "test-2",
  638. UID: types.UID("test-2"),
  639. },
  640. Spec: v1.PodSpec{
  641. Containers: []v1.Container{
  642. {
  643. Resources: v1.ResourceRequirements{
  644. Requests: v1.ResourceList{
  645. v1.ResourceCPU: resource.MustParse("200m"),
  646. v1.ResourceMemory: resource.MustParse("1Ki"),
  647. },
  648. },
  649. Ports: []v1.ContainerPort{
  650. {
  651. HostIP: "127.0.0.1",
  652. HostPort: 8080,
  653. Protocol: "TCP",
  654. },
  655. },
  656. },
  657. },
  658. NodeName: nodeName,
  659. },
  660. },
  661. },
  662. }
  663. ni := fakeNodeInfo()
  664. gen := ni.generation
  665. for _, pod := range pods {
  666. ni.AddPod(pod)
  667. if ni.generation <= gen {
  668. t.Errorf("generation is not incremented. Prev: %v, current: %v", gen, ni.generation)
  669. }
  670. gen = ni.generation
  671. }
  672. expected.generation = ni.generation
  673. if !reflect.DeepEqual(expected, ni) {
  674. t.Errorf("expected: %#v, got: %#v", expected, ni)
  675. }
  676. }
  677. func TestNodeInfoRemovePod(t *testing.T) {
  678. nodeName := "test-node"
  679. pods := []*v1.Pod{
  680. makeBasePod(t, nodeName, "test-1", "100m", "500", "", []v1.ContainerPort{{HostIP: "127.0.0.1", HostPort: 80, Protocol: "TCP"}}),
  681. makeBasePod(t, nodeName, "test-2", "200m", "1Ki", "", []v1.ContainerPort{{HostIP: "127.0.0.1", HostPort: 8080, Protocol: "TCP"}}),
  682. }
  683. tests := []struct {
  684. pod *v1.Pod
  685. errExpected bool
  686. expectedNodeInfo *NodeInfo
  687. }{
  688. {
  689. pod: makeBasePod(t, nodeName, "non-exist", "0", "0", "", []v1.ContainerPort{{}}),
  690. errExpected: true,
  691. expectedNodeInfo: &NodeInfo{
  692. node: &v1.Node{
  693. ObjectMeta: metav1.ObjectMeta{
  694. Name: "test-node",
  695. },
  696. },
  697. requestedResource: &Resource{
  698. MilliCPU: 300,
  699. Memory: 1524,
  700. EphemeralStorage: 0,
  701. AllowedPodNumber: 0,
  702. ScalarResources: map[v1.ResourceName]int64(nil),
  703. },
  704. nonzeroRequest: &Resource{
  705. MilliCPU: 300,
  706. Memory: 1524,
  707. EphemeralStorage: 0,
  708. AllowedPodNumber: 0,
  709. ScalarResources: map[v1.ResourceName]int64(nil),
  710. },
  711. TransientInfo: NewTransientSchedulerInfo(),
  712. allocatableResource: &Resource{},
  713. generation: 2,
  714. usedPorts: HostPortInfo{
  715. "127.0.0.1": map[ProtocolPort]struct{}{
  716. {Protocol: "TCP", Port: 80}: {},
  717. {Protocol: "TCP", Port: 8080}: {},
  718. },
  719. },
  720. imageStates: map[string]*ImageStateSummary{},
  721. pods: []*v1.Pod{
  722. {
  723. ObjectMeta: metav1.ObjectMeta{
  724. Namespace: "node_info_cache_test",
  725. Name: "test-1",
  726. UID: types.UID("test-1"),
  727. },
  728. Spec: v1.PodSpec{
  729. Containers: []v1.Container{
  730. {
  731. Resources: v1.ResourceRequirements{
  732. Requests: v1.ResourceList{
  733. v1.ResourceCPU: resource.MustParse("100m"),
  734. v1.ResourceMemory: resource.MustParse("500"),
  735. },
  736. },
  737. Ports: []v1.ContainerPort{
  738. {
  739. HostIP: "127.0.0.1",
  740. HostPort: 80,
  741. Protocol: "TCP",
  742. },
  743. },
  744. },
  745. },
  746. NodeName: nodeName,
  747. },
  748. },
  749. {
  750. ObjectMeta: metav1.ObjectMeta{
  751. Namespace: "node_info_cache_test",
  752. Name: "test-2",
  753. UID: types.UID("test-2"),
  754. },
  755. Spec: v1.PodSpec{
  756. Containers: []v1.Container{
  757. {
  758. Resources: v1.ResourceRequirements{
  759. Requests: v1.ResourceList{
  760. v1.ResourceCPU: resource.MustParse("200m"),
  761. v1.ResourceMemory: resource.MustParse("1Ki"),
  762. },
  763. },
  764. Ports: []v1.ContainerPort{
  765. {
  766. HostIP: "127.0.0.1",
  767. HostPort: 8080,
  768. Protocol: "TCP",
  769. },
  770. },
  771. },
  772. },
  773. NodeName: nodeName,
  774. },
  775. },
  776. },
  777. },
  778. },
  779. {
  780. pod: &v1.Pod{
  781. ObjectMeta: metav1.ObjectMeta{
  782. Namespace: "node_info_cache_test",
  783. Name: "test-1",
  784. UID: types.UID("test-1"),
  785. },
  786. Spec: v1.PodSpec{
  787. Containers: []v1.Container{
  788. {
  789. Resources: v1.ResourceRequirements{
  790. Requests: v1.ResourceList{
  791. v1.ResourceCPU: resource.MustParse("100m"),
  792. v1.ResourceMemory: resource.MustParse("500"),
  793. },
  794. },
  795. Ports: []v1.ContainerPort{
  796. {
  797. HostIP: "127.0.0.1",
  798. HostPort: 80,
  799. Protocol: "TCP",
  800. },
  801. },
  802. },
  803. },
  804. NodeName: nodeName,
  805. },
  806. },
  807. errExpected: false,
  808. expectedNodeInfo: &NodeInfo{
  809. node: &v1.Node{
  810. ObjectMeta: metav1.ObjectMeta{
  811. Name: "test-node",
  812. },
  813. },
  814. requestedResource: &Resource{
  815. MilliCPU: 200,
  816. Memory: 1024,
  817. EphemeralStorage: 0,
  818. AllowedPodNumber: 0,
  819. ScalarResources: map[v1.ResourceName]int64(nil),
  820. },
  821. nonzeroRequest: &Resource{
  822. MilliCPU: 200,
  823. Memory: 1024,
  824. EphemeralStorage: 0,
  825. AllowedPodNumber: 0,
  826. ScalarResources: map[v1.ResourceName]int64(nil),
  827. },
  828. TransientInfo: NewTransientSchedulerInfo(),
  829. allocatableResource: &Resource{},
  830. generation: 3,
  831. usedPorts: HostPortInfo{
  832. "127.0.0.1": map[ProtocolPort]struct{}{
  833. {Protocol: "TCP", Port: 8080}: {},
  834. },
  835. },
  836. imageStates: map[string]*ImageStateSummary{},
  837. pods: []*v1.Pod{
  838. {
  839. ObjectMeta: metav1.ObjectMeta{
  840. Namespace: "node_info_cache_test",
  841. Name: "test-2",
  842. UID: types.UID("test-2"),
  843. },
  844. Spec: v1.PodSpec{
  845. Containers: []v1.Container{
  846. {
  847. Resources: v1.ResourceRequirements{
  848. Requests: v1.ResourceList{
  849. v1.ResourceCPU: resource.MustParse("200m"),
  850. v1.ResourceMemory: resource.MustParse("1Ki"),
  851. },
  852. },
  853. Ports: []v1.ContainerPort{
  854. {
  855. HostIP: "127.0.0.1",
  856. HostPort: 8080,
  857. Protocol: "TCP",
  858. },
  859. },
  860. },
  861. },
  862. NodeName: nodeName,
  863. },
  864. },
  865. },
  866. },
  867. },
  868. }
  869. for _, test := range tests {
  870. ni := fakeNodeInfo(pods...)
  871. gen := ni.generation
  872. err := ni.RemovePod(test.pod)
  873. if err != nil {
  874. if test.errExpected {
  875. expectedErrorMsg := fmt.Errorf("no corresponding pod %s in pods of node %s", test.pod.Name, ni.Node().Name)
  876. if expectedErrorMsg == err {
  877. t.Errorf("expected error: %v, got: %v", expectedErrorMsg, err)
  878. }
  879. } else {
  880. t.Errorf("expected no error, got: %v", err)
  881. }
  882. } else {
  883. if ni.generation <= gen {
  884. t.Errorf("generation is not incremented. Prev: %v, current: %v", gen, ni.generation)
  885. }
  886. }
  887. test.expectedNodeInfo.generation = ni.generation
  888. if !reflect.DeepEqual(test.expectedNodeInfo, ni) {
  889. t.Errorf("expected: %#v, got: %#v", test.expectedNodeInfo, ni)
  890. }
  891. }
  892. }
  893. func fakeNodeInfo(pods ...*v1.Pod) *NodeInfo {
  894. ni := NewNodeInfo(pods...)
  895. ni.SetNode(&v1.Node{
  896. ObjectMeta: metav1.ObjectMeta{
  897. Name: "test-node",
  898. },
  899. })
  900. return ni
  901. }