test_volumes.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746
  1. import pytest
  2. from render import Render
  3. from formatter import get_hashed_name_for_volume
  4. @pytest.fixture
  5. def mock_values():
  6. return {
  7. "images": {
  8. "test_image": {
  9. "repository": "nginx",
  10. "tag": "latest",
  11. }
  12. },
  13. }
  14. def test_add_volume_invalid_type(mock_values):
  15. render = Render(mock_values)
  16. c1 = render.add_container("test_container", "test_image")
  17. c1.healthcheck.disable()
  18. with pytest.raises(Exception):
  19. c1.add_storage("/some/path", {"type": "invalid_type"})
  20. def test_add_volume_empty_mount_path(mock_values):
  21. render = Render(mock_values)
  22. c1 = render.add_container("test_container", "test_image")
  23. c1.healthcheck.disable()
  24. with pytest.raises(Exception):
  25. c1.add_storage("", {"type": "tmpfs"})
  26. def test_add_volume_duplicate_mount_path(mock_values):
  27. render = Render(mock_values)
  28. c1 = render.add_container("test_container", "test_image")
  29. c1.healthcheck.disable()
  30. c1.add_storage("/some/path", {"type": "tmpfs"})
  31. with pytest.raises(Exception):
  32. c1.add_storage("/some/path", {"type": "tmpfs"})
  33. def test_add_volume_host_path_invalid_propagation(mock_values):
  34. render = Render(mock_values)
  35. c1 = render.add_container("test_container", "test_image")
  36. c1.healthcheck.disable()
  37. host_path_config = {
  38. "type": "host_path",
  39. "host_path_config": {"path": "/mnt/test", "propagation": "invalid_propagation"},
  40. }
  41. with pytest.raises(Exception):
  42. c1.add_storage("/some/path", host_path_config)
  43. def test_add_host_path_volume_no_host_path_config(mock_values):
  44. render = Render(mock_values)
  45. c1 = render.add_container("test_container", "test_image")
  46. c1.healthcheck.disable()
  47. host_path_config = {"type": "host_path"}
  48. with pytest.raises(Exception):
  49. c1.add_storage("/some/path", host_path_config)
  50. def test_add_host_path_volume_no_path(mock_values):
  51. render = Render(mock_values)
  52. c1 = render.add_container("test_container", "test_image")
  53. c1.healthcheck.disable()
  54. host_path_config = {"type": "host_path", "host_path_config": {"path": ""}}
  55. with pytest.raises(Exception):
  56. c1.add_storage("/some/path", host_path_config)
  57. def test_add_host_path_with_acl_no_path(mock_values):
  58. render = Render(mock_values)
  59. c1 = render.add_container("test_container", "test_image")
  60. c1.healthcheck.disable()
  61. host_path_config = {"type": "host_path", "host_path_config": {"acl_enable": True, "acl": {"path": ""}}}
  62. with pytest.raises(Exception):
  63. c1.add_storage("/some/path", host_path_config)
  64. def test_add_host_path_volume_mount(mock_values):
  65. render = Render(mock_values)
  66. c1 = render.add_container("test_container", "test_image")
  67. c1.healthcheck.disable()
  68. host_path_config = {"type": "host_path", "host_path_config": {"path": "/mnt/test"}}
  69. c1.add_storage("/some/path", host_path_config)
  70. output = render.render()
  71. assert output["services"]["test_container"]["volumes"] == [
  72. {
  73. "type": "bind",
  74. "source": "/mnt/test",
  75. "target": "/some/path",
  76. "read_only": False,
  77. "bind": {"create_host_path": False, "propagation": "rprivate"},
  78. }
  79. ]
  80. def test_add_host_path_volume_mount_with_acl(mock_values):
  81. render = Render(mock_values)
  82. c1 = render.add_container("test_container", "test_image")
  83. c1.healthcheck.disable()
  84. host_path_config = {
  85. "type": "host_path",
  86. "host_path_config": {"path": "/mnt/test", "acl_enable": True, "acl": {"path": "/mnt/test/acl"}},
  87. }
  88. c1.add_storage("/some/path", host_path_config)
  89. output = render.render()
  90. assert output["services"]["test_container"]["volumes"] == [
  91. {
  92. "type": "bind",
  93. "source": "/mnt/test/acl",
  94. "target": "/some/path",
  95. "read_only": False,
  96. "bind": {"create_host_path": False, "propagation": "rprivate"},
  97. }
  98. ]
  99. def test_add_host_path_volume_mount_with_propagation(mock_values):
  100. render = Render(mock_values)
  101. c1 = render.add_container("test_container", "test_image")
  102. c1.healthcheck.disable()
  103. host_path_config = {"type": "host_path", "host_path_config": {"path": "/mnt/test", "propagation": "slave"}}
  104. c1.add_storage("/some/path", host_path_config)
  105. output = render.render()
  106. assert output["services"]["test_container"]["volumes"] == [
  107. {
  108. "type": "bind",
  109. "source": "/mnt/test",
  110. "target": "/some/path",
  111. "read_only": False,
  112. "bind": {"create_host_path": False, "propagation": "slave"},
  113. }
  114. ]
  115. def test_add_host_path_volume_mount_with_create_host_path(mock_values):
  116. render = Render(mock_values)
  117. c1 = render.add_container("test_container", "test_image")
  118. c1.healthcheck.disable()
  119. host_path_config = {"type": "host_path", "host_path_config": {"path": "/mnt/test", "create_host_path": True}}
  120. c1.add_storage("/some/path", host_path_config)
  121. output = render.render()
  122. assert output["services"]["test_container"]["volumes"] == [
  123. {
  124. "type": "bind",
  125. "source": "/mnt/test",
  126. "target": "/some/path",
  127. "read_only": False,
  128. "bind": {"create_host_path": True, "propagation": "rprivate"},
  129. }
  130. ]
  131. def test_add_host_path_volume_mount_with_read_only(mock_values):
  132. render = Render(mock_values)
  133. c1 = render.add_container("test_container", "test_image")
  134. c1.healthcheck.disable()
  135. host_path_config = {"type": "host_path", "read_only": True, "host_path_config": {"path": "/mnt/test"}}
  136. c1.add_storage("/some/path", host_path_config)
  137. output = render.render()
  138. assert output["services"]["test_container"]["volumes"] == [
  139. {
  140. "type": "bind",
  141. "source": "/mnt/test",
  142. "target": "/some/path",
  143. "read_only": True,
  144. "bind": {"create_host_path": False, "propagation": "rprivate"},
  145. }
  146. ]
  147. def test_add_ix_volume_invalid_dataset_name(mock_values):
  148. mock_values["ix_volumes"] = {"test_dataset": "/mnt/test"}
  149. render = Render(mock_values)
  150. c1 = render.add_container("test_container", "test_image")
  151. c1.healthcheck.disable()
  152. ix_volume_config = {"type": "ix_volume", "ix_volume_config": {"dataset_name": "invalid_dataset"}}
  153. with pytest.raises(Exception):
  154. c1.add_storage("/some/path", ix_volume_config)
  155. def test_add_ix_volume_no_ix_volume_config(mock_values):
  156. mock_values["ix_volumes"] = {"test_dataset": "/mnt/test"}
  157. render = Render(mock_values)
  158. c1 = render.add_container("test_container", "test_image")
  159. c1.healthcheck.disable()
  160. ix_volume_config = {"type": "ix_volume"}
  161. with pytest.raises(Exception):
  162. c1.add_storage("/some/path", ix_volume_config)
  163. def test_add_ix_volume_volume_mount(mock_values):
  164. mock_values["ix_volumes"] = {"test_dataset": "/mnt/test"}
  165. render = Render(mock_values)
  166. c1 = render.add_container("test_container", "test_image")
  167. c1.healthcheck.disable()
  168. ix_volume_config = {"type": "ix_volume", "ix_volume_config": {"dataset_name": "test_dataset"}}
  169. c1.add_storage("/some/path", ix_volume_config)
  170. output = render.render()
  171. assert output["services"]["test_container"]["volumes"] == [
  172. {
  173. "type": "bind",
  174. "source": "/mnt/test",
  175. "target": "/some/path",
  176. "read_only": False,
  177. "bind": {"create_host_path": False, "propagation": "rprivate"},
  178. }
  179. ]
  180. def test_add_ix_volume_volume_mount_with_options(mock_values):
  181. mock_values["ix_volumes"] = {"test_dataset": "/mnt/test"}
  182. render = Render(mock_values)
  183. c1 = render.add_container("test_container", "test_image")
  184. c1.healthcheck.disable()
  185. ix_volume_config = {
  186. "type": "ix_volume",
  187. "ix_volume_config": {"dataset_name": "test_dataset", "propagation": "rslave", "create_host_path": True},
  188. }
  189. c1.add_storage("/some/path", ix_volume_config)
  190. output = render.render()
  191. assert output["services"]["test_container"]["volumes"] == [
  192. {
  193. "type": "bind",
  194. "source": "/mnt/test",
  195. "target": "/some/path",
  196. "read_only": False,
  197. "bind": {"create_host_path": True, "propagation": "rslave"},
  198. }
  199. ]
  200. def test_cifs_volume_missing_server(mock_values):
  201. render = Render(mock_values)
  202. c1 = render.add_container("test_container", "test_image")
  203. c1.healthcheck.disable()
  204. cifs_config = {"type": "cifs", "cifs_config": {"path": "/path", "username": "user", "password": "password"}}
  205. with pytest.raises(Exception):
  206. c1.add_storage("/some/path", cifs_config)
  207. def test_cifs_volume_missing_path(mock_values):
  208. render = Render(mock_values)
  209. c1 = render.add_container("test_container", "test_image")
  210. c1.healthcheck.disable()
  211. cifs_config = {"type": "cifs", "cifs_config": {"server": "server", "username": "user", "password": "password"}}
  212. with pytest.raises(Exception):
  213. c1.add_storage("/some/path", cifs_config)
  214. def test_cifs_volume_missing_username(mock_values):
  215. render = Render(mock_values)
  216. c1 = render.add_container("test_container", "test_image")
  217. c1.healthcheck.disable()
  218. cifs_config = {"type": "cifs", "cifs_config": {"server": "server", "path": "/path", "password": "password"}}
  219. with pytest.raises(Exception):
  220. c1.add_storage("/some/path", cifs_config)
  221. def test_cifs_volume_missing_password(mock_values):
  222. render = Render(mock_values)
  223. c1 = render.add_container("test_container", "test_image")
  224. c1.healthcheck.disable()
  225. cifs_config = {"type": "cifs", "cifs_config": {"server": "server", "path": "/path", "username": "user"}}
  226. with pytest.raises(Exception):
  227. c1.add_storage("/some/path", cifs_config)
  228. def test_cifs_volume_without_cifs_config(mock_values):
  229. render = Render(mock_values)
  230. c1 = render.add_container("test_container", "test_image")
  231. c1.healthcheck.disable()
  232. cifs_config = {"type": "cifs"}
  233. with pytest.raises(Exception):
  234. c1.add_storage("/some/path", cifs_config)
  235. def test_cifs_volume_duplicate_option(mock_values):
  236. render = Render(mock_values)
  237. c1 = render.add_container("test_container", "test_image")
  238. c1.healthcheck.disable()
  239. cifs_config = {
  240. "type": "cifs",
  241. "cifs_config": {
  242. "server": "server",
  243. "path": "/path",
  244. "username": "user",
  245. "password": "pas$word",
  246. "options": ["verbose=true", "verbose=true"],
  247. },
  248. }
  249. with pytest.raises(Exception):
  250. c1.add_storage("/some/path", cifs_config)
  251. def test_cifs_volume_disallowed_option(mock_values):
  252. render = Render(mock_values)
  253. c1 = render.add_container("test_container", "test_image")
  254. c1.healthcheck.disable()
  255. cifs_config = {
  256. "type": "cifs",
  257. "cifs_config": {
  258. "server": "server",
  259. "path": "/path",
  260. "username": "user",
  261. "password": "pas$word",
  262. "options": ["user=username"],
  263. },
  264. }
  265. with pytest.raises(Exception):
  266. c1.add_storage("/some/path", cifs_config)
  267. def test_cifs_volume_invalid_options(mock_values):
  268. render = Render(mock_values)
  269. c1 = render.add_container("test_container", "test_image")
  270. c1.healthcheck.disable()
  271. cifs_config = {
  272. "type": "cifs",
  273. "cifs_config": {
  274. "server": "server",
  275. "path": "/path",
  276. "username": "user",
  277. "password": "pas$word",
  278. "options": {"verbose": True},
  279. },
  280. }
  281. with pytest.raises(Exception):
  282. c1.add_storage("/some/path", cifs_config)
  283. def test_cifs_volume_invalid_options2(mock_values):
  284. render = Render(mock_values)
  285. c1 = render.add_container("test_container", "test_image")
  286. c1.healthcheck.disable()
  287. cifs_config = {
  288. "type": "cifs",
  289. "cifs_config": {
  290. "server": "server",
  291. "path": "/path",
  292. "username": "user",
  293. "password": "pas$word",
  294. "options": [{"verbose": True}],
  295. },
  296. }
  297. with pytest.raises(Exception):
  298. c1.add_storage("/some/path", cifs_config)
  299. def test_add_cifs_volume(mock_values):
  300. render = Render(mock_values)
  301. c1 = render.add_container("test_container", "test_image")
  302. c1.healthcheck.disable()
  303. cifs_inner_config = {"server": "server", "path": "/path", "username": "user", "password": "pas$word"}
  304. cifs_config = {"type": "cifs", "cifs_config": cifs_inner_config}
  305. c1.add_storage("/some/path", cifs_config)
  306. output = render.render()
  307. vol_name = get_hashed_name_for_volume("cifs", cifs_inner_config)
  308. assert output["volumes"] == {
  309. vol_name: {
  310. "driver_opts": {"type": "cifs", "device": "//server/path", "o": "noperm,password=pas$$word,user=user"}
  311. }
  312. }
  313. assert output["services"]["test_container"]["volumes"] == [
  314. {"type": "volume", "source": vol_name, "target": "/some/path", "read_only": False, "volume": {"nocopy": False}}
  315. ]
  316. def test_cifs_volume_with_options(mock_values):
  317. render = Render(mock_values)
  318. c1 = render.add_container("test_container", "test_image")
  319. c1.healthcheck.disable()
  320. cifs_inner_config = {
  321. "server": "server",
  322. "path": "/path",
  323. "username": "user",
  324. "password": "pas$word",
  325. "options": ["vers=3.0", "verbose=true"],
  326. }
  327. cifs_config = {"type": "cifs", "cifs_config": cifs_inner_config}
  328. c1.add_storage("/some/path", cifs_config)
  329. output = render.render()
  330. vol_name = get_hashed_name_for_volume("cifs", cifs_inner_config)
  331. assert output["volumes"] == {
  332. vol_name: {
  333. "driver_opts": {
  334. "type": "cifs",
  335. "device": "//server/path",
  336. "o": "noperm,password=pas$$word,user=user,verbose=true,vers=3.0",
  337. }
  338. }
  339. }
  340. assert output["services"]["test_container"]["volumes"] == [
  341. {"type": "volume", "source": vol_name, "target": "/some/path", "read_only": False, "volume": {"nocopy": False}}
  342. ]
  343. def test_nfs_volume_missing_server(mock_values):
  344. render = Render(mock_values)
  345. c1 = render.add_container("test_container", "test_image")
  346. c1.healthcheck.disable()
  347. nfs_config = {"type": "nfs", "nfs_config": {"path": "/path"}}
  348. with pytest.raises(Exception):
  349. c1.add_storage("/some/path", nfs_config)
  350. def test_nfs_volume_missing_path(mock_values):
  351. render = Render(mock_values)
  352. c1 = render.add_container("test_container", "test_image")
  353. c1.healthcheck.disable()
  354. nfs_config = {"type": "nfs", "nfs_config": {"server": "server"}}
  355. with pytest.raises(Exception):
  356. c1.add_storage("/some/path", nfs_config)
  357. def test_nfs_volume_without_nfs_config(mock_values):
  358. render = Render(mock_values)
  359. c1 = render.add_container("test_container", "test_image")
  360. c1.healthcheck.disable()
  361. nfs_config = {"type": "nfs"}
  362. with pytest.raises(Exception):
  363. c1.add_storage("/some/path", nfs_config)
  364. def test_nfs_volume_duplicate_option(mock_values):
  365. render = Render(mock_values)
  366. c1 = render.add_container("test_container", "test_image")
  367. c1.healthcheck.disable()
  368. nfs_config = {
  369. "type": "nfs",
  370. "nfs_config": {"server": "server", "path": "/path", "options": ["verbose=true", "verbose=true"]},
  371. }
  372. with pytest.raises(Exception):
  373. c1.add_storage("/some/path", nfs_config)
  374. def test_nfs_volume_disallowed_option(mock_values):
  375. render = Render(mock_values)
  376. c1 = render.add_container("test_container", "test_image")
  377. c1.healthcheck.disable()
  378. nfs_config = {"type": "nfs", "nfs_config": {"server": "server", "path": "/path", "options": ["addr=server"]}}
  379. with pytest.raises(Exception):
  380. c1.add_storage("/some/path", nfs_config)
  381. def test_nfs_volume_invalid_options(mock_values):
  382. render = Render(mock_values)
  383. c1 = render.add_container("test_container", "test_image")
  384. c1.healthcheck.disable()
  385. nfs_config = {"type": "nfs", "nfs_config": {"server": "server", "path": "/path", "options": {"verbose": True}}}
  386. with pytest.raises(Exception):
  387. c1.add_storage("/some/path", nfs_config)
  388. def test_nfs_volume_invalid_options2(mock_values):
  389. render = Render(mock_values)
  390. c1 = render.add_container("test_container", "test_image")
  391. c1.healthcheck.disable()
  392. nfs_config = {"type": "nfs", "nfs_config": {"server": "server", "path": "/path", "options": [{"verbose": True}]}}
  393. with pytest.raises(Exception):
  394. c1.add_storage("/some/path", nfs_config)
  395. def test_add_nfs_volume(mock_values):
  396. render = Render(mock_values)
  397. c1 = render.add_container("test_container", "test_image")
  398. c1.healthcheck.disable()
  399. nfs_inner_config = {"server": "server", "path": "/path"}
  400. nfs_config = {"type": "nfs", "nfs_config": nfs_inner_config}
  401. c1.add_storage("/some/path", nfs_config)
  402. output = render.render()
  403. vol_name = get_hashed_name_for_volume("nfs", nfs_inner_config)
  404. assert output["volumes"] == {vol_name: {"driver_opts": {"type": "nfs", "device": ":/path", "o": "addr=server"}}}
  405. assert output["services"]["test_container"]["volumes"] == [
  406. {"type": "volume", "source": vol_name, "target": "/some/path", "read_only": False, "volume": {"nocopy": False}}
  407. ]
  408. def test_nfs_volume_with_options(mock_values):
  409. render = Render(mock_values)
  410. c1 = render.add_container("test_container", "test_image")
  411. c1.healthcheck.disable()
  412. nfs_inner_config = {"server": "server", "path": "/path", "options": ["vers=3.0", "verbose=true"]}
  413. nfs_config = {"type": "nfs", "nfs_config": nfs_inner_config}
  414. c1.add_storage("/some/path", nfs_config)
  415. output = render.render()
  416. vol_name = get_hashed_name_for_volume("nfs", nfs_inner_config)
  417. assert output["volumes"] == {
  418. vol_name: {
  419. "driver_opts": {
  420. "type": "nfs",
  421. "device": ":/path",
  422. "o": "addr=server,verbose=true,vers=3.0",
  423. }
  424. }
  425. }
  426. assert output["services"]["test_container"]["volumes"] == [
  427. {"type": "volume", "source": vol_name, "target": "/some/path", "read_only": False, "volume": {"nocopy": False}}
  428. ]
  429. def test_tmpfs_invalid_size(mock_values):
  430. render = Render(mock_values)
  431. c1 = render.add_container("test_container", "test_image")
  432. c1.healthcheck.disable()
  433. vol_config = {"type": "tmpfs", "tmpfs_config": {"size": "2"}}
  434. with pytest.raises(Exception):
  435. c1.add_storage("/some/path", vol_config)
  436. def test_tmpfs_zero_size(mock_values):
  437. render = Render(mock_values)
  438. c1 = render.add_container("test_container", "test_image")
  439. c1.healthcheck.disable()
  440. vol_config = {"type": "tmpfs", "tmpfs_config": {"size": 0}}
  441. with pytest.raises(Exception):
  442. c1.add_storage("/some/path", vol_config)
  443. def test_tmpfs_invalid_mode(mock_values):
  444. render = Render(mock_values)
  445. c1 = render.add_container("test_container", "test_image")
  446. c1.healthcheck.disable()
  447. vol_config = {"type": "tmpfs", "tmpfs_config": {"mode": "invalid"}}
  448. with pytest.raises(Exception):
  449. c1.add_storage("/some/path", vol_config)
  450. def test_tmpfs_volume(mock_values):
  451. render = Render(mock_values)
  452. c1 = render.add_container("test_container", "test_image")
  453. c1.healthcheck.disable()
  454. c1.add_storage("/some/path", {"type": "tmpfs"})
  455. c1.add_storage("/some/other/path", {"type": "tmpfs", "tmpfs_config": {"size": 100}})
  456. c1.add_storage(
  457. "/some/other/path2", {"type": "tmpfs", "tmpfs_config": {"size": 100, "mode": "0777", "uid": 1000, "gid": 1000}}
  458. )
  459. output = render.render()
  460. assert output["services"]["test_container"]["tmpfs"] == [
  461. "/some/other/path2:gid=1000,mode=0777,size=104857600,uid=1000",
  462. "/some/other/path:size=104857600",
  463. "/some/path",
  464. ]
  465. def test_add_tmpfs_with_existing_volume(mock_values):
  466. render = Render(mock_values)
  467. c1 = render.add_container("test_container", "test_image")
  468. c1.healthcheck.disable()
  469. c1.add_storage("/some/path", {"type": "volume", "volume_config": {"volume_name": "test_volume"}})
  470. with pytest.raises(Exception):
  471. c1.add_storage("/some/path", {"type": "tmpfs", "tmpfs_config": {"size": 100}})
  472. def test_add_volume_with_existing_tmpfs(mock_values):
  473. render = Render(mock_values)
  474. c1 = render.add_container("test_container", "test_image")
  475. c1.healthcheck.disable()
  476. c1.add_storage("/some/path", {"type": "tmpfs", "tmpfs_config": {"size": 100}})
  477. with pytest.raises(Exception):
  478. c1.add_storage("/some/path", {"type": "volume", "volume_config": {"volume_name": "test_volume"}})
  479. def test_temporary_volume(mock_values):
  480. render = Render(mock_values)
  481. c1 = render.add_container("test_container", "test_image")
  482. c1.healthcheck.disable()
  483. vol_config = {"type": "temporary", "volume_config": {"volume_name": "test_temp_volume"}}
  484. c1.add_storage("/some/path", vol_config)
  485. output = render.render()
  486. assert output["services"]["test_container"]["volumes"] == [
  487. {
  488. "source": "test_temp_volume",
  489. "type": "volume",
  490. "target": "/some/path",
  491. "read_only": False,
  492. "volume": {"nocopy": False},
  493. }
  494. ]
  495. def test_docker_volume_missing_config(mock_values):
  496. render = Render(mock_values)
  497. c1 = render.add_container("test_container", "test_image")
  498. c1.healthcheck.disable()
  499. vol_config = {"type": "volume", "volume_config": {}}
  500. with pytest.raises(Exception):
  501. c1.add_storage("/some/path", vol_config)
  502. def test_docker_volume_missing_volume_name(mock_values):
  503. render = Render(mock_values)
  504. c1 = render.add_container("test_container", "test_image")
  505. c1.healthcheck.disable()
  506. vol_config = {"type": "volume", "volume_config": {"volume_name": ""}}
  507. with pytest.raises(Exception):
  508. c1.add_storage("/some/path", vol_config)
  509. def test_docker_volume(mock_values):
  510. render = Render(mock_values)
  511. c1 = render.add_container("test_container", "test_image")
  512. c1.healthcheck.disable()
  513. vol_config = {"type": "volume", "volume_config": {"volume_name": "test_volume"}}
  514. c1.add_storage("/some/path", vol_config)
  515. output = render.render()
  516. assert output["services"]["test_container"]["volumes"] == [
  517. {
  518. "type": "volume",
  519. "source": "test_volume",
  520. "target": "/some/path",
  521. "read_only": False,
  522. "volume": {"nocopy": False},
  523. }
  524. ]
  525. assert output["volumes"] == {"test_volume": {}}
  526. def test_anonymous_volume(mock_values):
  527. render = Render(mock_values)
  528. c1 = render.add_container("test_container", "test_image")
  529. c1.healthcheck.disable()
  530. vol_config = {"type": "anonymous", "volume_config": {"nocopy": True}}
  531. c1.add_storage("/some/path", vol_config)
  532. output = render.render()
  533. assert output["services"]["test_container"]["volumes"] == [
  534. {"type": "volume", "target": "/some/path", "read_only": False, "volume": {"nocopy": True}}
  535. ]
  536. assert "volumes" not in output
  537. def test_add_udev(mock_values):
  538. render = Render(mock_values)
  539. c1 = render.add_container("test_container", "test_image")
  540. c1.healthcheck.disable()
  541. c1.add_udev()
  542. output = render.render()
  543. assert output["services"]["test_container"]["volumes"] == [
  544. {
  545. "type": "bind",
  546. "source": "/run/udev",
  547. "target": "/run/udev",
  548. "read_only": True,
  549. "bind": {"create_host_path": False, "propagation": "rprivate"},
  550. }
  551. ]
  552. def test_add_udev_not_read_only(mock_values):
  553. render = Render(mock_values)
  554. c1 = render.add_container("test_container", "test_image")
  555. c1.healthcheck.disable()
  556. c1.add_udev(read_only=False)
  557. output = render.render()
  558. assert output["services"]["test_container"]["volumes"] == [
  559. {
  560. "type": "bind",
  561. "source": "/run/udev",
  562. "target": "/run/udev",
  563. "read_only": False,
  564. "bind": {"create_host_path": False, "propagation": "rprivate"},
  565. }
  566. ]
  567. def test_add_docker_socket(mock_values):
  568. render = Render(mock_values)
  569. c1 = render.add_container("test_container", "test_image")
  570. c1.healthcheck.disable()
  571. c1.storage._add_docker_socket(mount_path="/var/run/docker.sock")
  572. output = render.render()
  573. assert output["services"]["test_container"]["volumes"] == [
  574. {
  575. "type": "bind",
  576. "source": "/var/run/docker.sock",
  577. "target": "/var/run/docker.sock",
  578. "read_only": True,
  579. "bind": {"create_host_path": False, "propagation": "rprivate"},
  580. }
  581. ]
  582. def test_add_docker_socket_not_read_only(mock_values):
  583. render = Render(mock_values)
  584. c1 = render.add_container("test_container", "test_image")
  585. c1.healthcheck.disable()
  586. c1.storage._add_docker_socket(read_only=False, mount_path="/var/run/docker.sock")
  587. output = render.render()
  588. assert output["services"]["test_container"]["volumes"] == [
  589. {
  590. "type": "bind",
  591. "source": "/var/run/docker.sock",
  592. "target": "/var/run/docker.sock",
  593. "read_only": False,
  594. "bind": {"create_host_path": False, "propagation": "rprivate"},
  595. }
  596. ]
  597. def test_add_docker_socket_mount_path(mock_values):
  598. render = Render(mock_values)
  599. c1 = render.add_container("test_container", "test_image")
  600. c1.healthcheck.disable()
  601. c1.storage._add_docker_socket(mount_path="/some/path")
  602. output = render.render()
  603. assert output["services"]["test_container"]["volumes"] == [
  604. {
  605. "type": "bind",
  606. "source": "/var/run/docker.sock",
  607. "target": "/some/path",
  608. "read_only": True,
  609. "bind": {"create_host_path": False, "propagation": "rprivate"},
  610. }
  611. ]
  612. def test_host_path_with_disallowed_path(mock_values):
  613. render = Render(mock_values)
  614. c1 = render.add_container("test_container", "test_image")
  615. c1.healthcheck.disable()
  616. host_path_config = {"type": "host_path", "host_path_config": {"path": "/mnt"}}
  617. with pytest.raises(Exception):
  618. c1.add_storage("/some/path", host_path_config)
  619. def test_host_path_without_disallowed_path(mock_values):
  620. render = Render(mock_values)
  621. c1 = render.add_container("test_container", "test_image")
  622. c1.healthcheck.disable()
  623. host_path_config = {"type": "host_path", "host_path_config": {"path": "/mnt/test"}}
  624. c1.add_storage("/mnt", host_path_config)
  625. output = render.render()
  626. assert output["services"]["test_container"]["volumes"] == [
  627. {
  628. "type": "bind",
  629. "source": "/mnt/test",
  630. "target": "/mnt",
  631. "read_only": False,
  632. "bind": {"create_host_path": False, "propagation": "rprivate"},
  633. }
  634. ]