1
0

container_test.py 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. from __future__ import absolute_import
  2. from __future__ import unicode_literals
  3. import docker
  4. from .. import mock
  5. from .. import unittest
  6. from compose.const import LABEL_ONE_OFF
  7. from compose.const import LABEL_SLUG
  8. from compose.container import Container
  9. from compose.container import get_container_name
  10. class ContainerTest(unittest.TestCase):
  11. def setUp(self):
  12. self.container_id = "abcabcabcbabc12345"
  13. self.container_dict = {
  14. "Id": self.container_id,
  15. "Image": "busybox:latest",
  16. "Command": "top",
  17. "Created": 1387384730,
  18. "Status": "Up 8 seconds",
  19. "Ports": None,
  20. "SizeRw": 0,
  21. "SizeRootFs": 0,
  22. "Names": ["/composetest_db_1", "/composetest_web_1/db"],
  23. "NetworkSettings": {
  24. "Ports": {},
  25. },
  26. "Config": {
  27. "Labels": {
  28. "com.docker.compose.project": "composetest",
  29. "com.docker.compose.service": "web",
  30. "com.docker.compose.container-number": "7",
  31. },
  32. }
  33. }
  34. def test_from_ps(self):
  35. container = Container.from_ps(None,
  36. self.container_dict,
  37. has_been_inspected=True)
  38. assert container.dictionary == {
  39. "Id": self.container_id,
  40. "Image": "busybox:latest",
  41. "Name": "/composetest_db_1",
  42. }
  43. def test_from_ps_prefixed(self):
  44. self.container_dict['Names'] = [
  45. '/swarm-host-1' + n for n in self.container_dict['Names']
  46. ]
  47. container = Container.from_ps(
  48. None,
  49. self.container_dict,
  50. has_been_inspected=True)
  51. assert container.dictionary == {
  52. "Id": self.container_id,
  53. "Image": "busybox:latest",
  54. "Name": "/composetest_db_1",
  55. }
  56. def test_environment(self):
  57. container = Container(None, {
  58. 'Id': 'abc',
  59. 'Config': {
  60. 'Env': [
  61. 'FOO=BAR',
  62. 'BAZ=DOGE',
  63. ]
  64. }
  65. }, has_been_inspected=True)
  66. assert container.environment == {
  67. 'FOO': 'BAR',
  68. 'BAZ': 'DOGE',
  69. }
  70. def test_number(self):
  71. container = Container(None, self.container_dict, has_been_inspected=True)
  72. assert container.number == 7
  73. def test_name(self):
  74. container = Container.from_ps(None,
  75. self.container_dict,
  76. has_been_inspected=True)
  77. assert container.name == "composetest_db_1"
  78. def test_name_without_project(self):
  79. self.container_dict['Name'] = "/composetest_web_7"
  80. container = Container(None, self.container_dict, has_been_inspected=True)
  81. assert container.name_without_project == "web_7"
  82. def test_name_without_project_custom_container_name(self):
  83. self.container_dict['Name'] = "/custom_name_of_container"
  84. container = Container(None, self.container_dict, has_been_inspected=True)
  85. assert container.name_without_project == "custom_name_of_container"
  86. def test_name_without_project_one_off(self):
  87. self.container_dict['Name'] = "/composetest_web_092cd63296f"
  88. self.container_dict['Config']['Labels'][LABEL_SLUG] = (
  89. "092cd63296fdc446ad432d3905dd1fcbe12a2ba6b52"
  90. )
  91. self.container_dict['Config']['Labels'][LABEL_ONE_OFF] = 'True'
  92. container = Container(None, self.container_dict, has_been_inspected=True)
  93. assert container.name_without_project == 'web_092cd63296fd'
  94. def test_inspect_if_not_inspected(self):
  95. mock_client = mock.create_autospec(docker.APIClient)
  96. container = Container(mock_client, dict(Id="the_id"))
  97. container.inspect_if_not_inspected()
  98. mock_client.inspect_container.assert_called_once_with("the_id")
  99. assert container.dictionary == mock_client.inspect_container.return_value
  100. assert container.has_been_inspected
  101. container.inspect_if_not_inspected()
  102. assert mock_client.inspect_container.call_count == 1
  103. def test_human_readable_ports_none(self):
  104. container = Container(None, self.container_dict, has_been_inspected=True)
  105. assert container.human_readable_ports == ''
  106. def test_human_readable_ports_public_and_private(self):
  107. self.container_dict['NetworkSettings']['Ports'].update({
  108. "45454/tcp": [{"HostIp": "0.0.0.0", "HostPort": "49197"}],
  109. "45453/tcp": [],
  110. })
  111. container = Container(None, self.container_dict, has_been_inspected=True)
  112. expected = "45453/tcp, 0.0.0.0:49197->45454/tcp"
  113. assert container.human_readable_ports == expected
  114. def test_get_local_port(self):
  115. self.container_dict['NetworkSettings']['Ports'].update({
  116. "45454/tcp": [{"HostIp": "0.0.0.0", "HostPort": "49197"}],
  117. })
  118. container = Container(None, self.container_dict, has_been_inspected=True)
  119. assert container.get_local_port(45454, protocol='tcp') == '0.0.0.0:49197'
  120. def test_human_readable_states_no_health(self):
  121. container = Container(None, {
  122. "State": {
  123. "Status": "running",
  124. "Running": True,
  125. "Paused": False,
  126. "Restarting": False,
  127. "OOMKilled": False,
  128. "Dead": False,
  129. "Pid": 7623,
  130. "ExitCode": 0,
  131. "Error": "",
  132. "StartedAt": "2018-01-29T00:34:25.2052414Z",
  133. "FinishedAt": "0001-01-01T00:00:00Z"
  134. },
  135. }, has_been_inspected=True)
  136. expected = "Up"
  137. assert container.human_readable_state == expected
  138. def test_human_readable_states_starting(self):
  139. container = Container(None, {
  140. "State": {
  141. "Status": "running",
  142. "Running": True,
  143. "Paused": False,
  144. "Restarting": False,
  145. "OOMKilled": False,
  146. "Dead": False,
  147. "Pid": 11744,
  148. "ExitCode": 0,
  149. "Error": "",
  150. "StartedAt": "2018-02-03T07:56:20.3591233Z",
  151. "FinishedAt": "2018-01-31T08:56:11.0505228Z",
  152. "Health": {
  153. "Status": "starting",
  154. "FailingStreak": 0,
  155. "Log": []
  156. }
  157. }
  158. }, has_been_inspected=True)
  159. expected = "Up (health: starting)"
  160. assert container.human_readable_state == expected
  161. def test_human_readable_states_healthy(self):
  162. container = Container(None, {
  163. "State": {
  164. "Status": "running",
  165. "Running": True,
  166. "Paused": False,
  167. "Restarting": False,
  168. "OOMKilled": False,
  169. "Dead": False,
  170. "Pid": 5674,
  171. "ExitCode": 0,
  172. "Error": "",
  173. "StartedAt": "2018-02-03T08:32:05.3281831Z",
  174. "FinishedAt": "2018-02-03T08:11:35.7872706Z",
  175. "Health": {
  176. "Status": "healthy",
  177. "FailingStreak": 0,
  178. "Log": []
  179. }
  180. }
  181. }, has_been_inspected=True)
  182. expected = "Up (healthy)"
  183. assert container.human_readable_state == expected
  184. def test_get(self):
  185. container = Container(None, {
  186. "Status": "Up 8 seconds",
  187. "HostConfig": {
  188. "VolumesFrom": ["volume_id"]
  189. },
  190. }, has_been_inspected=True)
  191. assert container.get('Status') == "Up 8 seconds"
  192. assert container.get('HostConfig.VolumesFrom') == ["volume_id"]
  193. assert container.get('Foo.Bar.DoesNotExist') is None
  194. def test_short_id(self):
  195. container = Container(None, self.container_dict, has_been_inspected=True)
  196. assert container.short_id == self.container_id[:12]
  197. def test_has_api_logs(self):
  198. container_dict = {
  199. 'HostConfig': {
  200. 'LogConfig': {
  201. 'Type': 'json-file'
  202. }
  203. }
  204. }
  205. container = Container(None, container_dict, has_been_inspected=True)
  206. assert container.has_api_logs is True
  207. container_dict['HostConfig']['LogConfig']['Type'] = 'none'
  208. container = Container(None, container_dict, has_been_inspected=True)
  209. assert container.has_api_logs is False
  210. container_dict['HostConfig']['LogConfig']['Type'] = 'syslog'
  211. container = Container(None, container_dict, has_been_inspected=True)
  212. assert container.has_api_logs is False
  213. container_dict['HostConfig']['LogConfig']['Type'] = 'journald'
  214. container = Container(None, container_dict, has_been_inspected=True)
  215. assert container.has_api_logs is True
  216. container_dict['HostConfig']['LogConfig']['Type'] = 'foobar'
  217. container = Container(None, container_dict, has_been_inspected=True)
  218. assert container.has_api_logs is False
  219. class GetContainerNameTestCase(unittest.TestCase):
  220. def test_get_container_name(self):
  221. assert get_container_name({}) is None
  222. assert get_container_name({'Name': 'myproject_db_1'}) == 'myproject_db_1'
  223. assert get_container_name(
  224. {'Names': ['/myproject_db_1', '/myproject_web_1/db']}
  225. ) == 'myproject_db_1'
  226. assert get_container_name({
  227. 'Names': [
  228. '/swarm-host-1/myproject_db_1',
  229. '/swarm-host-1/myproject_web_1/db'
  230. ]
  231. }) == 'myproject_db_1'