util_test.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885
  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 util
  14. import (
  15. "io/ioutil"
  16. "os"
  17. "runtime"
  18. "testing"
  19. v1 "k8s.io/api/core/v1"
  20. "k8s.io/apimachinery/pkg/util/sets"
  21. utilfeature "k8s.io/apiserver/pkg/util/feature"
  22. featuregatetesting "k8s.io/component-base/featuregate/testing"
  23. _ "k8s.io/kubernetes/pkg/apis/core/install"
  24. "k8s.io/kubernetes/pkg/features"
  25. "reflect"
  26. "strings"
  27. "k8s.io/apimachinery/pkg/api/resource"
  28. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  29. "k8s.io/kubernetes/pkg/util/slice"
  30. "k8s.io/kubernetes/pkg/volume"
  31. )
  32. var nodeLabels = map[string]string{
  33. "test-key1": "test-value1",
  34. "test-key2": "test-value2",
  35. }
  36. func TestCheckVolumeNodeAffinity(t *testing.T) {
  37. type affinityTest struct {
  38. name string
  39. expectSuccess bool
  40. pv *v1.PersistentVolume
  41. }
  42. cases := []affinityTest{
  43. {
  44. name: "valid-nil",
  45. expectSuccess: true,
  46. pv: testVolumeWithNodeAffinity(t, nil),
  47. },
  48. {
  49. name: "valid-no-constraints",
  50. expectSuccess: true,
  51. pv: testVolumeWithNodeAffinity(t, &v1.VolumeNodeAffinity{}),
  52. },
  53. {
  54. name: "select-nothing",
  55. expectSuccess: false,
  56. pv: testVolumeWithNodeAffinity(t, &v1.VolumeNodeAffinity{Required: &v1.NodeSelector{}}),
  57. },
  58. {
  59. name: "select-nothing-empty-terms",
  60. expectSuccess: false,
  61. pv: testVolumeWithNodeAffinity(t, &v1.VolumeNodeAffinity{
  62. Required: &v1.NodeSelector{
  63. NodeSelectorTerms: []v1.NodeSelectorTerm{
  64. {
  65. MatchExpressions: []v1.NodeSelectorRequirement{},
  66. },
  67. },
  68. },
  69. }),
  70. },
  71. {
  72. name: "valid-multiple-terms",
  73. expectSuccess: true,
  74. pv: testVolumeWithNodeAffinity(t, &v1.VolumeNodeAffinity{
  75. Required: &v1.NodeSelector{
  76. NodeSelectorTerms: []v1.NodeSelectorTerm{
  77. {
  78. MatchExpressions: []v1.NodeSelectorRequirement{
  79. {
  80. Key: "test-key3",
  81. Operator: v1.NodeSelectorOpIn,
  82. Values: []string{"test-value1", "test-value3"},
  83. },
  84. },
  85. },
  86. {
  87. MatchExpressions: []v1.NodeSelectorRequirement{
  88. {
  89. Key: "test-key2",
  90. Operator: v1.NodeSelectorOpIn,
  91. Values: []string{"test-value0", "test-value2"},
  92. },
  93. },
  94. },
  95. },
  96. },
  97. }),
  98. },
  99. {
  100. name: "valid-multiple-match-expressions",
  101. expectSuccess: true,
  102. pv: testVolumeWithNodeAffinity(t, &v1.VolumeNodeAffinity{
  103. Required: &v1.NodeSelector{
  104. NodeSelectorTerms: []v1.NodeSelectorTerm{
  105. {
  106. MatchExpressions: []v1.NodeSelectorRequirement{
  107. {
  108. Key: "test-key1",
  109. Operator: v1.NodeSelectorOpIn,
  110. Values: []string{"test-value1", "test-value3"},
  111. },
  112. {
  113. Key: "test-key2",
  114. Operator: v1.NodeSelectorOpIn,
  115. Values: []string{"test-value0", "test-value2"},
  116. },
  117. },
  118. },
  119. },
  120. },
  121. }),
  122. },
  123. {
  124. name: "invalid-multiple-match-expressions-key",
  125. expectSuccess: false,
  126. pv: testVolumeWithNodeAffinity(t, &v1.VolumeNodeAffinity{
  127. Required: &v1.NodeSelector{
  128. NodeSelectorTerms: []v1.NodeSelectorTerm{
  129. {
  130. MatchExpressions: []v1.NodeSelectorRequirement{
  131. {
  132. Key: "test-key1",
  133. Operator: v1.NodeSelectorOpIn,
  134. Values: []string{"test-value1", "test-value3"},
  135. },
  136. {
  137. Key: "test-key3",
  138. Operator: v1.NodeSelectorOpIn,
  139. Values: []string{"test-value0", "test-value2"},
  140. },
  141. },
  142. },
  143. },
  144. },
  145. }),
  146. },
  147. {
  148. name: "invalid-multiple-match-expressions-values",
  149. expectSuccess: false,
  150. pv: testVolumeWithNodeAffinity(t, &v1.VolumeNodeAffinity{
  151. Required: &v1.NodeSelector{
  152. NodeSelectorTerms: []v1.NodeSelectorTerm{
  153. {
  154. MatchExpressions: []v1.NodeSelectorRequirement{
  155. {
  156. Key: "test-key1",
  157. Operator: v1.NodeSelectorOpIn,
  158. Values: []string{"test-value3", "test-value4"},
  159. },
  160. {
  161. Key: "test-key2",
  162. Operator: v1.NodeSelectorOpIn,
  163. Values: []string{"test-value0", "test-value2"},
  164. },
  165. },
  166. },
  167. },
  168. },
  169. }),
  170. },
  171. {
  172. name: "invalid-multiple-terms",
  173. expectSuccess: false,
  174. pv: testVolumeWithNodeAffinity(t, &v1.VolumeNodeAffinity{
  175. Required: &v1.NodeSelector{
  176. NodeSelectorTerms: []v1.NodeSelectorTerm{
  177. {
  178. MatchExpressions: []v1.NodeSelectorRequirement{
  179. {
  180. Key: "test-key3",
  181. Operator: v1.NodeSelectorOpIn,
  182. Values: []string{"test-value1", "test-value3"},
  183. },
  184. },
  185. },
  186. {
  187. MatchExpressions: []v1.NodeSelectorRequirement{
  188. {
  189. Key: "test-key2",
  190. Operator: v1.NodeSelectorOpIn,
  191. Values: []string{"test-value0", "test-value1"},
  192. },
  193. },
  194. },
  195. },
  196. },
  197. }),
  198. },
  199. }
  200. for _, c := range cases {
  201. err := CheckNodeAffinity(c.pv, nodeLabels)
  202. if err != nil && c.expectSuccess {
  203. t.Errorf("CheckTopology %v returned error: %v", c.name, err)
  204. }
  205. if err == nil && !c.expectSuccess {
  206. t.Errorf("CheckTopology %v returned success, expected error", c.name)
  207. }
  208. }
  209. }
  210. func testVolumeWithNodeAffinity(t *testing.T, affinity *v1.VolumeNodeAffinity) *v1.PersistentVolume {
  211. objMeta := metav1.ObjectMeta{Name: "test-constraints"}
  212. return &v1.PersistentVolume{
  213. ObjectMeta: objMeta,
  214. Spec: v1.PersistentVolumeSpec{
  215. NodeAffinity: affinity,
  216. },
  217. }
  218. }
  219. func TestLoadPodFromFile(t *testing.T) {
  220. tests := []struct {
  221. name string
  222. content string
  223. expectError bool
  224. }{
  225. {
  226. "yaml",
  227. `
  228. apiVersion: v1
  229. kind: Pod
  230. metadata:
  231. name: testpod
  232. spec:
  233. containers:
  234. - image: k8s.gcr.io/busybox
  235. `,
  236. false,
  237. },
  238. {
  239. "json",
  240. `
  241. {
  242. "apiVersion": "v1",
  243. "kind": "Pod",
  244. "metadata": {
  245. "name": "testpod"
  246. },
  247. "spec": {
  248. "containers": [
  249. {
  250. "image": "k8s.gcr.io/busybox"
  251. }
  252. ]
  253. }
  254. }`,
  255. false,
  256. },
  257. {
  258. "invalid pod",
  259. `
  260. apiVersion: v1
  261. kind: Pod
  262. metadata:
  263. name: testpod
  264. spec:
  265. - image: k8s.gcr.io/busybox
  266. `,
  267. true,
  268. },
  269. }
  270. for _, test := range tests {
  271. tempFile, err := ioutil.TempFile("", "podfile")
  272. defer os.Remove(tempFile.Name())
  273. if err != nil {
  274. t.Fatalf("cannot create temporary file: %v", err)
  275. }
  276. if _, err = tempFile.Write([]byte(test.content)); err != nil {
  277. t.Fatalf("cannot save temporary file: %v", err)
  278. }
  279. if err = tempFile.Close(); err != nil {
  280. t.Fatalf("cannot close temporary file: %v", err)
  281. }
  282. pod, err := LoadPodFromFile(tempFile.Name())
  283. if test.expectError {
  284. if err == nil {
  285. t.Errorf("test %q expected error, got nil", test.name)
  286. }
  287. } else {
  288. // no error expected
  289. if err != nil {
  290. t.Errorf("error loading pod %q: %v", test.name, err)
  291. }
  292. if pod == nil {
  293. t.Errorf("test %q expected pod, got nil", test.name)
  294. }
  295. }
  296. }
  297. }
  298. func TestCalculateTimeoutForVolume(t *testing.T) {
  299. pv := &v1.PersistentVolume{
  300. Spec: v1.PersistentVolumeSpec{
  301. Capacity: v1.ResourceList{
  302. v1.ResourceName(v1.ResourceStorage): resource.MustParse("500M"),
  303. },
  304. },
  305. }
  306. timeout := CalculateTimeoutForVolume(50, 30, pv)
  307. if timeout != 50 {
  308. t.Errorf("Expected 50 for timeout but got %v", timeout)
  309. }
  310. pv.Spec.Capacity[v1.ResourceStorage] = resource.MustParse("2Gi")
  311. timeout = CalculateTimeoutForVolume(50, 30, pv)
  312. if timeout != 60 {
  313. t.Errorf("Expected 60 for timeout but got %v", timeout)
  314. }
  315. pv.Spec.Capacity[v1.ResourceStorage] = resource.MustParse("150Gi")
  316. timeout = CalculateTimeoutForVolume(50, 30, pv)
  317. if timeout != 4500 {
  318. t.Errorf("Expected 4500 for timeout but got %v", timeout)
  319. }
  320. }
  321. func TestGenerateVolumeName(t *testing.T) {
  322. // Normal operation, no truncate
  323. v1 := GenerateVolumeName("kubernetes", "pv-cinder-abcde", 255)
  324. if v1 != "kubernetes-dynamic-pv-cinder-abcde" {
  325. t.Errorf("Expected kubernetes-dynamic-pv-cinder-abcde, got %s", v1)
  326. }
  327. // Truncate trailing "6789-dynamic"
  328. prefix := strings.Repeat("0123456789", 9) // 90 characters prefix + 8 chars. of "-dynamic"
  329. v2 := GenerateVolumeName(prefix, "pv-cinder-abcde", 100)
  330. expect := prefix[:84] + "-pv-cinder-abcde"
  331. if v2 != expect {
  332. t.Errorf("Expected %s, got %s", expect, v2)
  333. }
  334. // Truncate really long cluster name
  335. prefix = strings.Repeat("0123456789", 1000) // 10000 characters prefix
  336. v3 := GenerateVolumeName(prefix, "pv-cinder-abcde", 100)
  337. if v3 != expect {
  338. t.Errorf("Expected %s, got %s", expect, v3)
  339. }
  340. }
  341. func TestMountOptionFromSpec(t *testing.T) {
  342. scenarios := map[string]struct {
  343. volume *volume.Spec
  344. expectedMountList []string
  345. systemOptions []string
  346. }{
  347. "volume-with-mount-options": {
  348. volume: createVolumeSpecWithMountOption("good-mount-opts", "ro,nfsvers=3", v1.PersistentVolumeSpec{
  349. PersistentVolumeSource: v1.PersistentVolumeSource{
  350. NFS: &v1.NFSVolumeSource{Server: "localhost", Path: "/srv", ReadOnly: false},
  351. },
  352. }),
  353. expectedMountList: []string{"ro", "nfsvers=3"},
  354. systemOptions: nil,
  355. },
  356. "volume-with-bad-mount-options": {
  357. volume: createVolumeSpecWithMountOption("good-mount-opts", "", v1.PersistentVolumeSpec{
  358. PersistentVolumeSource: v1.PersistentVolumeSource{
  359. NFS: &v1.NFSVolumeSource{Server: "localhost", Path: "/srv", ReadOnly: false},
  360. },
  361. }),
  362. expectedMountList: []string{},
  363. systemOptions: nil,
  364. },
  365. "vol-with-sys-opts": {
  366. volume: createVolumeSpecWithMountOption("good-mount-opts", "ro,nfsvers=3", v1.PersistentVolumeSpec{
  367. PersistentVolumeSource: v1.PersistentVolumeSource{
  368. NFS: &v1.NFSVolumeSource{Server: "localhost", Path: "/srv", ReadOnly: false},
  369. },
  370. }),
  371. expectedMountList: []string{"ro", "nfsvers=3", "fsid=100", "hard"},
  372. systemOptions: []string{"fsid=100", "hard"},
  373. },
  374. "vol-with-sys-opts-with-dup": {
  375. volume: createVolumeSpecWithMountOption("good-mount-opts", "ro,nfsvers=3", v1.PersistentVolumeSpec{
  376. PersistentVolumeSource: v1.PersistentVolumeSource{
  377. NFS: &v1.NFSVolumeSource{Server: "localhost", Path: "/srv", ReadOnly: false},
  378. },
  379. }),
  380. expectedMountList: []string{"ro", "nfsvers=3", "fsid=100"},
  381. systemOptions: []string{"fsid=100", "ro"},
  382. },
  383. }
  384. for name, scenario := range scenarios {
  385. mountOptions := MountOptionFromSpec(scenario.volume, scenario.systemOptions...)
  386. if !reflect.DeepEqual(slice.SortStrings(mountOptions), slice.SortStrings(scenario.expectedMountList)) {
  387. t.Errorf("for %s expected mount options : %v got %v", name, scenario.expectedMountList, mountOptions)
  388. }
  389. }
  390. }
  391. func createVolumeSpecWithMountOption(name string, mountOptions string, spec v1.PersistentVolumeSpec) *volume.Spec {
  392. annotations := map[string]string{
  393. v1.MountOptionAnnotation: mountOptions,
  394. }
  395. objMeta := metav1.ObjectMeta{
  396. Name: name,
  397. Annotations: annotations,
  398. }
  399. pv := &v1.PersistentVolume{
  400. ObjectMeta: objMeta,
  401. Spec: spec,
  402. }
  403. return &volume.Spec{PersistentVolume: pv}
  404. }
  405. func TestGetWindowsPath(t *testing.T) {
  406. tests := []struct {
  407. path string
  408. expectedPath string
  409. }{
  410. {
  411. path: `/var/lib/kubelet/pods/146f8428-83e7-11e7-8dd4-000d3a31dac4/volumes/kubernetes.io~disk`,
  412. expectedPath: `c:\var\lib\kubelet\pods\146f8428-83e7-11e7-8dd4-000d3a31dac4\volumes\kubernetes.io~disk`,
  413. },
  414. {
  415. path: `\var/lib/kubelet/pods/146f8428-83e7-11e7-8dd4-000d3a31dac4\volumes\kubernetes.io~disk`,
  416. expectedPath: `c:\var\lib\kubelet\pods\146f8428-83e7-11e7-8dd4-000d3a31dac4\volumes\kubernetes.io~disk`,
  417. },
  418. {
  419. path: `/`,
  420. expectedPath: `c:\`,
  421. },
  422. {
  423. path: ``,
  424. expectedPath: ``,
  425. },
  426. }
  427. for _, test := range tests {
  428. result := GetWindowsPath(test.path)
  429. if result != test.expectedPath {
  430. t.Errorf("GetWindowsPath(%v) returned (%v), want (%v)", test.path, result, test.expectedPath)
  431. }
  432. }
  433. }
  434. func TestIsWindowsUNCPath(t *testing.T) {
  435. tests := []struct {
  436. goos string
  437. path string
  438. isUNCPath bool
  439. }{
  440. {
  441. goos: "linux",
  442. path: `/usr/bin`,
  443. isUNCPath: false,
  444. },
  445. {
  446. goos: "linux",
  447. path: `\\.\pipe\foo`,
  448. isUNCPath: false,
  449. },
  450. {
  451. goos: "windows",
  452. path: `C:\foo`,
  453. isUNCPath: false,
  454. },
  455. {
  456. goos: "windows",
  457. path: `\\server\share\foo`,
  458. isUNCPath: true,
  459. },
  460. {
  461. goos: "windows",
  462. path: `\\?\server\share`,
  463. isUNCPath: true,
  464. },
  465. {
  466. goos: "windows",
  467. path: `\\?\c:\`,
  468. isUNCPath: true,
  469. },
  470. {
  471. goos: "windows",
  472. path: `\\.\pipe\valid_pipe`,
  473. isUNCPath: true,
  474. },
  475. }
  476. for _, test := range tests {
  477. result := IsWindowsUNCPath(test.goos, test.path)
  478. if result != test.isUNCPath {
  479. t.Errorf("IsWindowsUNCPath(%v) returned (%v), expected (%v)", test.path, result, test.isUNCPath)
  480. }
  481. }
  482. }
  483. func TestIsWindowsLocalPath(t *testing.T) {
  484. tests := []struct {
  485. goos string
  486. path string
  487. isWindowsLocalPath bool
  488. }{
  489. {
  490. goos: "linux",
  491. path: `/usr/bin`,
  492. isWindowsLocalPath: false,
  493. },
  494. {
  495. goos: "linux",
  496. path: `\\.\pipe\foo`,
  497. isWindowsLocalPath: false,
  498. },
  499. {
  500. goos: "windows",
  501. path: `C:\foo`,
  502. isWindowsLocalPath: false,
  503. },
  504. {
  505. goos: "windows",
  506. path: `:\foo`,
  507. isWindowsLocalPath: false,
  508. },
  509. {
  510. goos: "windows",
  511. path: `X:\foo`,
  512. isWindowsLocalPath: false,
  513. },
  514. {
  515. goos: "windows",
  516. path: `\\server\share\foo`,
  517. isWindowsLocalPath: false,
  518. },
  519. {
  520. goos: "windows",
  521. path: `\\?\server\share`,
  522. isWindowsLocalPath: false,
  523. },
  524. {
  525. goos: "windows",
  526. path: `\\?\c:\`,
  527. isWindowsLocalPath: false,
  528. },
  529. {
  530. goos: "windows",
  531. path: `\\.\pipe\valid_pipe`,
  532. isWindowsLocalPath: false,
  533. },
  534. {
  535. goos: "windows",
  536. path: `foo`,
  537. isWindowsLocalPath: false,
  538. },
  539. {
  540. goos: "windows",
  541. path: `:foo`,
  542. isWindowsLocalPath: false,
  543. },
  544. {
  545. goos: "windows",
  546. path: `\foo`,
  547. isWindowsLocalPath: true,
  548. },
  549. {
  550. goos: "windows",
  551. path: `\foo\bar`,
  552. isWindowsLocalPath: true,
  553. },
  554. {
  555. goos: "windows",
  556. path: `/foo`,
  557. isWindowsLocalPath: true,
  558. },
  559. {
  560. goos: "windows",
  561. path: `/foo/bar`,
  562. isWindowsLocalPath: true,
  563. },
  564. }
  565. for _, test := range tests {
  566. result := IsWindowsLocalPath(test.goos, test.path)
  567. if result != test.isWindowsLocalPath {
  568. t.Errorf("isWindowsLocalPath(%v) returned (%v), expected (%v)", test.path, result, test.isWindowsLocalPath)
  569. }
  570. }
  571. }
  572. func TestMakeAbsolutePath(t *testing.T) {
  573. tests := []struct {
  574. goos string
  575. path string
  576. expectedPath string
  577. name string
  578. }{
  579. {
  580. goos: "linux",
  581. path: "non-absolute/path",
  582. expectedPath: "/non-absolute/path",
  583. name: "linux non-absolute path",
  584. },
  585. {
  586. goos: "linux",
  587. path: "/absolute/path",
  588. expectedPath: "/absolute/path",
  589. name: "linux absolute path",
  590. },
  591. {
  592. goos: "windows",
  593. path: "some\\path",
  594. expectedPath: "c:\\some\\path",
  595. name: "basic windows",
  596. },
  597. {
  598. goos: "windows",
  599. path: "/some/path",
  600. expectedPath: "c:/some/path",
  601. name: "linux path on windows",
  602. },
  603. {
  604. goos: "windows",
  605. path: "\\some\\path",
  606. expectedPath: "c:\\some\\path",
  607. name: "windows path no drive",
  608. },
  609. {
  610. goos: "windows",
  611. path: "\\:\\some\\path",
  612. expectedPath: "\\:\\some\\path",
  613. name: "windows path with colon",
  614. },
  615. }
  616. for _, test := range tests {
  617. if runtime.GOOS == test.goos {
  618. path := MakeAbsolutePath(test.goos, test.path)
  619. if path != test.expectedPath {
  620. t.Errorf("[%s] Expected %s saw %s", test.name, test.expectedPath, path)
  621. }
  622. }
  623. }
  624. }
  625. func TestGetPodVolumeNames(t *testing.T) {
  626. defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EphemeralContainers, true)()
  627. tests := []struct {
  628. name string
  629. pod *v1.Pod
  630. expectedMounts sets.String
  631. expectedDevices sets.String
  632. }{
  633. {
  634. name: "empty pod",
  635. pod: &v1.Pod{
  636. Spec: v1.PodSpec{},
  637. },
  638. expectedMounts: sets.NewString(),
  639. expectedDevices: sets.NewString(),
  640. },
  641. {
  642. name: "pod with volumes",
  643. pod: &v1.Pod{
  644. Spec: v1.PodSpec{
  645. Containers: []v1.Container{
  646. {
  647. Name: "container",
  648. VolumeMounts: []v1.VolumeMount{
  649. {
  650. Name: "vol1",
  651. },
  652. {
  653. Name: "vol2",
  654. },
  655. },
  656. VolumeDevices: []v1.VolumeDevice{
  657. {
  658. Name: "vol3",
  659. },
  660. {
  661. Name: "vol4",
  662. },
  663. },
  664. },
  665. },
  666. Volumes: []v1.Volume{
  667. {
  668. Name: "vol1",
  669. },
  670. {
  671. Name: "vol2",
  672. },
  673. {
  674. Name: "vol3",
  675. },
  676. {
  677. Name: "vol4",
  678. },
  679. },
  680. },
  681. },
  682. expectedMounts: sets.NewString("vol1", "vol2"),
  683. expectedDevices: sets.NewString("vol3", "vol4"),
  684. },
  685. {
  686. name: "pod with init containers",
  687. pod: &v1.Pod{
  688. Spec: v1.PodSpec{
  689. InitContainers: []v1.Container{
  690. {
  691. Name: "initContainer",
  692. VolumeMounts: []v1.VolumeMount{
  693. {
  694. Name: "vol1",
  695. },
  696. {
  697. Name: "vol2",
  698. },
  699. },
  700. VolumeDevices: []v1.VolumeDevice{
  701. {
  702. Name: "vol3",
  703. },
  704. {
  705. Name: "vol4",
  706. },
  707. },
  708. },
  709. },
  710. Volumes: []v1.Volume{
  711. {
  712. Name: "vol1",
  713. },
  714. {
  715. Name: "vol2",
  716. },
  717. {
  718. Name: "vol3",
  719. },
  720. {
  721. Name: "vol4",
  722. },
  723. },
  724. },
  725. },
  726. expectedMounts: sets.NewString("vol1", "vol2"),
  727. expectedDevices: sets.NewString("vol3", "vol4"),
  728. },
  729. {
  730. name: "pod with multiple containers",
  731. pod: &v1.Pod{
  732. Spec: v1.PodSpec{
  733. InitContainers: []v1.Container{
  734. {
  735. Name: "initContainer1",
  736. VolumeMounts: []v1.VolumeMount{
  737. {
  738. Name: "vol1",
  739. },
  740. },
  741. },
  742. {
  743. Name: "initContainer2",
  744. VolumeDevices: []v1.VolumeDevice{
  745. {
  746. Name: "vol2",
  747. },
  748. },
  749. },
  750. },
  751. Containers: []v1.Container{
  752. {
  753. Name: "container1",
  754. VolumeMounts: []v1.VolumeMount{
  755. {
  756. Name: "vol3",
  757. },
  758. },
  759. },
  760. {
  761. Name: "container2",
  762. VolumeDevices: []v1.VolumeDevice{
  763. {
  764. Name: "vol4",
  765. },
  766. },
  767. },
  768. },
  769. Volumes: []v1.Volume{
  770. {
  771. Name: "vol1",
  772. },
  773. {
  774. Name: "vol2",
  775. },
  776. {
  777. Name: "vol3",
  778. },
  779. {
  780. Name: "vol4",
  781. },
  782. },
  783. },
  784. },
  785. expectedMounts: sets.NewString("vol1", "vol3"),
  786. expectedDevices: sets.NewString("vol2", "vol4"),
  787. },
  788. {
  789. name: "pod with ephemeral containers",
  790. pod: &v1.Pod{
  791. Spec: v1.PodSpec{
  792. Containers: []v1.Container{
  793. {
  794. Name: "container1",
  795. VolumeMounts: []v1.VolumeMount{
  796. {
  797. Name: "vol1",
  798. },
  799. },
  800. },
  801. },
  802. EphemeralContainers: []v1.EphemeralContainer{
  803. {
  804. EphemeralContainerCommon: v1.EphemeralContainerCommon{
  805. Name: "debugger",
  806. VolumeMounts: []v1.VolumeMount{
  807. {
  808. Name: "vol1",
  809. },
  810. {
  811. Name: "vol2",
  812. },
  813. },
  814. },
  815. },
  816. },
  817. Volumes: []v1.Volume{
  818. {
  819. Name: "vol1",
  820. },
  821. {
  822. Name: "vol2",
  823. },
  824. },
  825. },
  826. },
  827. expectedMounts: sets.NewString("vol1", "vol2"),
  828. expectedDevices: sets.NewString(),
  829. },
  830. }
  831. for _, test := range tests {
  832. t.Run(test.name, func(t *testing.T) {
  833. mounts, devices := GetPodVolumeNames(test.pod)
  834. if !mounts.Equal(test.expectedMounts) {
  835. t.Errorf("Expected mounts: %q, got %q", mounts.List(), test.expectedMounts.List())
  836. }
  837. if !devices.Equal(test.expectedDevices) {
  838. t.Errorf("Expected devices: %q, got %q", devices.List(), test.expectedDevices.List())
  839. }
  840. })
  841. }
  842. }