project_test.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. from __future__ import unicode_literals
  2. import docker
  3. from .. import mock
  4. from .. import unittest
  5. from compose.config.types import VolumeFromSpec
  6. from compose.const import LABEL_SERVICE
  7. from compose.container import Container
  8. from compose.project import Project
  9. from compose.service import ContainerNet
  10. from compose.service import Net
  11. from compose.service import Service
  12. class ProjectTest(unittest.TestCase):
  13. def setUp(self):
  14. self.mock_client = mock.create_autospec(docker.Client)
  15. def test_from_dict(self):
  16. project = Project.from_dicts('composetest', [
  17. {
  18. 'name': 'web',
  19. 'image': 'busybox:latest'
  20. },
  21. {
  22. 'name': 'db',
  23. 'image': 'busybox:latest'
  24. },
  25. ], None)
  26. self.assertEqual(len(project.services), 2)
  27. self.assertEqual(project.get_service('web').name, 'web')
  28. self.assertEqual(project.get_service('web').options['image'], 'busybox:latest')
  29. self.assertEqual(project.get_service('db').name, 'db')
  30. self.assertEqual(project.get_service('db').options['image'], 'busybox:latest')
  31. def test_from_dict_sorts_in_dependency_order(self):
  32. project = Project.from_dicts('composetest', [
  33. {
  34. 'name': 'web',
  35. 'image': 'busybox:latest',
  36. 'links': ['db'],
  37. },
  38. {
  39. 'name': 'db',
  40. 'image': 'busybox:latest',
  41. 'volumes_from': [VolumeFromSpec('volume', 'ro')]
  42. },
  43. {
  44. 'name': 'volume',
  45. 'image': 'busybox:latest',
  46. 'volumes': ['/tmp'],
  47. }
  48. ], None)
  49. self.assertEqual(project.services[0].name, 'volume')
  50. self.assertEqual(project.services[1].name, 'db')
  51. self.assertEqual(project.services[2].name, 'web')
  52. def test_from_config(self):
  53. dicts = [
  54. {
  55. 'name': 'web',
  56. 'image': 'busybox:latest',
  57. },
  58. {
  59. 'name': 'db',
  60. 'image': 'busybox:latest',
  61. },
  62. ]
  63. project = Project.from_dicts('composetest', dicts, None)
  64. self.assertEqual(len(project.services), 2)
  65. self.assertEqual(project.get_service('web').name, 'web')
  66. self.assertEqual(project.get_service('web').options['image'], 'busybox:latest')
  67. self.assertEqual(project.get_service('db').name, 'db')
  68. self.assertEqual(project.get_service('db').options['image'], 'busybox:latest')
  69. def test_get_service(self):
  70. web = Service(
  71. project='composetest',
  72. name='web',
  73. client=None,
  74. image="busybox:latest",
  75. )
  76. project = Project('test', [web], None)
  77. self.assertEqual(project.get_service('web'), web)
  78. def test_get_services_returns_all_services_without_args(self):
  79. web = Service(
  80. project='composetest',
  81. name='web',
  82. image='foo',
  83. )
  84. console = Service(
  85. project='composetest',
  86. name='console',
  87. image='foo',
  88. )
  89. project = Project('test', [web, console], None)
  90. self.assertEqual(project.get_services(), [web, console])
  91. def test_get_services_returns_listed_services_with_args(self):
  92. web = Service(
  93. project='composetest',
  94. name='web',
  95. image='foo',
  96. )
  97. console = Service(
  98. project='composetest',
  99. name='console',
  100. image='foo',
  101. )
  102. project = Project('test', [web, console], None)
  103. self.assertEqual(project.get_services(['console']), [console])
  104. def test_get_services_with_include_links(self):
  105. db = Service(
  106. project='composetest',
  107. name='db',
  108. image='foo',
  109. )
  110. web = Service(
  111. project='composetest',
  112. name='web',
  113. image='foo',
  114. links=[(db, 'database')]
  115. )
  116. cache = Service(
  117. project='composetest',
  118. name='cache',
  119. image='foo'
  120. )
  121. console = Service(
  122. project='composetest',
  123. name='console',
  124. image='foo',
  125. links=[(web, 'web')]
  126. )
  127. project = Project('test', [web, db, cache, console], None)
  128. self.assertEqual(
  129. project.get_services(['console'], include_deps=True),
  130. [db, web, console]
  131. )
  132. def test_get_services_removes_duplicates_following_links(self):
  133. db = Service(
  134. project='composetest',
  135. name='db',
  136. image='foo',
  137. )
  138. web = Service(
  139. project='composetest',
  140. name='web',
  141. image='foo',
  142. links=[(db, 'database')]
  143. )
  144. project = Project('test', [web, db], None)
  145. self.assertEqual(
  146. project.get_services(['web', 'db'], include_deps=True),
  147. [db, web]
  148. )
  149. def test_use_volumes_from_container(self):
  150. container_id = 'aabbccddee'
  151. container_dict = dict(Name='aaa', Id=container_id)
  152. self.mock_client.inspect_container.return_value = container_dict
  153. project = Project.from_dicts('test', [
  154. {
  155. 'name': 'test',
  156. 'image': 'busybox:latest',
  157. 'volumes_from': [VolumeFromSpec('aaa', 'rw')]
  158. }
  159. ], self.mock_client)
  160. self.assertEqual(project.get_service('test')._get_volumes_from(), [container_id + ":rw"])
  161. def test_use_volumes_from_service_no_container(self):
  162. container_name = 'test_vol_1'
  163. self.mock_client.containers.return_value = [
  164. {
  165. "Name": container_name,
  166. "Names": [container_name],
  167. "Id": container_name,
  168. "Image": 'busybox:latest'
  169. }
  170. ]
  171. project = Project.from_dicts('test', [
  172. {
  173. 'name': 'vol',
  174. 'image': 'busybox:latest'
  175. },
  176. {
  177. 'name': 'test',
  178. 'image': 'busybox:latest',
  179. 'volumes_from': [VolumeFromSpec('vol', 'rw')]
  180. }
  181. ], self.mock_client)
  182. self.assertEqual(project.get_service('test')._get_volumes_from(), [container_name + ":rw"])
  183. def test_use_volumes_from_service_container(self):
  184. container_ids = ['aabbccddee', '12345']
  185. project = Project.from_dicts('test', [
  186. {
  187. 'name': 'vol',
  188. 'image': 'busybox:latest'
  189. },
  190. {
  191. 'name': 'test',
  192. 'image': 'busybox:latest',
  193. 'volumes_from': [VolumeFromSpec('vol', 'rw')]
  194. }
  195. ], None)
  196. with mock.patch.object(Service, 'containers') as mock_return:
  197. mock_return.return_value = [
  198. mock.Mock(id=container_id, spec=Container)
  199. for container_id in container_ids]
  200. self.assertEqual(
  201. project.get_service('test')._get_volumes_from(),
  202. [container_ids[0] + ':rw'])
  203. def test_net_unset(self):
  204. project = Project.from_dicts('test', [
  205. {
  206. 'name': 'test',
  207. 'image': 'busybox:latest',
  208. }
  209. ], self.mock_client)
  210. service = project.get_service('test')
  211. self.assertEqual(service.net.id, None)
  212. self.assertNotIn('NetworkMode', service._get_container_host_config({}))
  213. def test_use_net_from_container(self):
  214. container_id = 'aabbccddee'
  215. container_dict = dict(Name='aaa', Id=container_id)
  216. self.mock_client.inspect_container.return_value = container_dict
  217. project = Project.from_dicts('test', [
  218. {
  219. 'name': 'test',
  220. 'image': 'busybox:latest',
  221. 'net': 'container:aaa'
  222. }
  223. ], self.mock_client)
  224. service = project.get_service('test')
  225. self.assertEqual(service.net.mode, 'container:' + container_id)
  226. def test_use_net_from_service(self):
  227. container_name = 'test_aaa_1'
  228. self.mock_client.containers.return_value = [
  229. {
  230. "Name": container_name,
  231. "Names": [container_name],
  232. "Id": container_name,
  233. "Image": 'busybox:latest'
  234. }
  235. ]
  236. project = Project.from_dicts('test', [
  237. {
  238. 'name': 'aaa',
  239. 'image': 'busybox:latest'
  240. },
  241. {
  242. 'name': 'test',
  243. 'image': 'busybox:latest',
  244. 'net': 'container:aaa'
  245. }
  246. ], self.mock_client)
  247. service = project.get_service('test')
  248. self.assertEqual(service.net.mode, 'container:' + container_name)
  249. def test_uses_default_network_true(self):
  250. web = Service('web', project='test', image="alpine", net=Net('test'))
  251. db = Service('web', project='test', image="alpine", net=Net('other'))
  252. project = Project('test', [web, db], None)
  253. assert project.uses_default_network()
  254. def test_uses_default_network_custom_name(self):
  255. web = Service('web', project='test', image="alpine", net=Net('other'))
  256. project = Project('test', [web], None)
  257. assert not project.uses_default_network()
  258. def test_uses_default_network_host(self):
  259. web = Service('web', project='test', image="alpine", net=Net('host'))
  260. project = Project('test', [web], None)
  261. assert not project.uses_default_network()
  262. def test_uses_default_network_container(self):
  263. container = mock.Mock(id='test')
  264. web = Service(
  265. 'web',
  266. project='test',
  267. image="alpine",
  268. net=ContainerNet(container))
  269. project = Project('test', [web], None)
  270. assert not project.uses_default_network()
  271. def test_container_without_name(self):
  272. self.mock_client.containers.return_value = [
  273. {'Image': 'busybox:latest', 'Id': '1', 'Name': '1'},
  274. {'Image': 'busybox:latest', 'Id': '2', 'Name': None},
  275. {'Image': 'busybox:latest', 'Id': '3'},
  276. ]
  277. self.mock_client.inspect_container.return_value = {
  278. 'Id': '1',
  279. 'Config': {
  280. 'Labels': {
  281. LABEL_SERVICE: 'web',
  282. },
  283. },
  284. }
  285. project = Project.from_dicts(
  286. 'test',
  287. [{
  288. 'name': 'web',
  289. 'image': 'busybox:latest',
  290. }],
  291. self.mock_client,
  292. )
  293. self.assertEqual([c.id for c in project.containers()], ['1'])