1
0

container_test.py 9.6 KB

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