container_test.py 9.1 KB

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