cli_test.py 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. # encoding: utf-8
  2. from __future__ import absolute_import
  3. from __future__ import unicode_literals
  4. import os
  5. import shutil
  6. import tempfile
  7. import docker
  8. import py
  9. import pytest
  10. from .. import mock
  11. from .. import unittest
  12. from ..helpers import build_config
  13. from compose.cli.command import get_project
  14. from compose.cli.command import get_project_name
  15. from compose.cli.docopt_command import NoSuchCommand
  16. from compose.cli.errors import UserError
  17. from compose.cli.main import TopLevelCommand
  18. from compose.const import IS_WINDOWS_PLATFORM
  19. from compose.project import Project
  20. class CLITestCase(unittest.TestCase):
  21. def test_default_project_name(self):
  22. test_dir = py._path.local.LocalPath('tests/fixtures/simple-composefile')
  23. with test_dir.as_cwd():
  24. project_name = get_project_name('.')
  25. self.assertEquals('simplecomposefile', project_name)
  26. def test_project_name_with_explicit_base_dir(self):
  27. base_dir = 'tests/fixtures/simple-composefile'
  28. project_name = get_project_name(base_dir)
  29. self.assertEquals('simplecomposefile', project_name)
  30. def test_project_name_with_explicit_uppercase_base_dir(self):
  31. base_dir = 'tests/fixtures/UpperCaseDir'
  32. project_name = get_project_name(base_dir)
  33. self.assertEquals('uppercasedir', project_name)
  34. def test_project_name_with_explicit_project_name(self):
  35. name = 'explicit-project-name'
  36. project_name = get_project_name(None, project_name=name)
  37. self.assertEquals('explicitprojectname', project_name)
  38. @mock.patch.dict(os.environ)
  39. def test_project_name_from_environment_new_var(self):
  40. name = 'namefromenv'
  41. os.environ['COMPOSE_PROJECT_NAME'] = name
  42. project_name = get_project_name(None)
  43. self.assertEquals(project_name, name)
  44. def test_project_name_with_empty_environment_var(self):
  45. base_dir = 'tests/fixtures/simple-composefile'
  46. with mock.patch.dict(os.environ):
  47. os.environ['COMPOSE_PROJECT_NAME'] = ''
  48. project_name = get_project_name(base_dir)
  49. self.assertEquals('simplecomposefile', project_name)
  50. @mock.patch.dict(os.environ)
  51. def test_project_name_with_environment_file(self):
  52. base_dir = tempfile.mkdtemp()
  53. try:
  54. name = 'namefromenvfile'
  55. with open(os.path.join(base_dir, '.env'), 'w') as f:
  56. f.write('COMPOSE_PROJECT_NAME={}'.format(name))
  57. project_name = get_project_name(base_dir)
  58. assert project_name == name
  59. # Environment has priority over .env file
  60. os.environ['COMPOSE_PROJECT_NAME'] = 'namefromenv'
  61. assert get_project_name(base_dir) == os.environ['COMPOSE_PROJECT_NAME']
  62. finally:
  63. shutil.rmtree(base_dir)
  64. def test_get_project(self):
  65. base_dir = 'tests/fixtures/longer-filename-composefile'
  66. project = get_project(base_dir)
  67. self.assertEqual(project.name, 'longerfilenamecomposefile')
  68. self.assertTrue(project.client)
  69. self.assertTrue(project.services)
  70. def test_command_help(self):
  71. with pytest.raises(SystemExit) as exc:
  72. TopLevelCommand.help({'COMMAND': 'up'})
  73. assert 'Usage: up' in exc.exconly()
  74. def test_command_help_nonexistent(self):
  75. with pytest.raises(NoSuchCommand):
  76. TopLevelCommand.help({'COMMAND': 'nonexistent'})
  77. @pytest.mark.xfail(IS_WINDOWS_PLATFORM, reason="requires dockerpty")
  78. @mock.patch('compose.cli.main.RunOperation', autospec=True)
  79. @mock.patch('compose.cli.main.PseudoTerminal', autospec=True)
  80. def test_run_interactive_passes_logs_false(self, mock_pseudo_terminal, mock_run_operation):
  81. mock_client = mock.create_autospec(docker.Client)
  82. project = Project.from_config(
  83. name='composetest',
  84. client=mock_client,
  85. config_data=build_config({
  86. 'service': {'image': 'busybox'}
  87. }),
  88. )
  89. command = TopLevelCommand(project)
  90. with pytest.raises(SystemExit):
  91. command.run({
  92. 'SERVICE': 'service',
  93. 'COMMAND': None,
  94. '-e': [],
  95. '--user': None,
  96. '--no-deps': None,
  97. '-d': False,
  98. '-T': None,
  99. '--entrypoint': None,
  100. '--service-ports': None,
  101. '--publish': [],
  102. '--rm': None,
  103. '--name': None,
  104. '--workdir': None,
  105. })
  106. _, _, call_kwargs = mock_run_operation.mock_calls[0]
  107. assert call_kwargs['logs'] is False
  108. def test_run_service_with_restart_always(self):
  109. mock_client = mock.create_autospec(docker.Client)
  110. project = Project.from_config(
  111. name='composetest',
  112. client=mock_client,
  113. config_data=build_config({
  114. 'service': {
  115. 'image': 'busybox',
  116. 'restart': 'always',
  117. }
  118. }),
  119. )
  120. command = TopLevelCommand(project)
  121. command.run({
  122. 'SERVICE': 'service',
  123. 'COMMAND': None,
  124. '-e': [],
  125. '--user': None,
  126. '--no-deps': None,
  127. '-d': True,
  128. '-T': None,
  129. '--entrypoint': None,
  130. '--service-ports': None,
  131. '--publish': [],
  132. '--rm': None,
  133. '--name': None,
  134. '--workdir': None,
  135. })
  136. self.assertEquals(
  137. mock_client.create_host_config.call_args[1]['restart_policy']['Name'],
  138. 'always'
  139. )
  140. command = TopLevelCommand(project)
  141. command.run({
  142. 'SERVICE': 'service',
  143. 'COMMAND': None,
  144. '-e': [],
  145. '--user': None,
  146. '--no-deps': None,
  147. '-d': True,
  148. '-T': None,
  149. '--entrypoint': None,
  150. '--service-ports': None,
  151. '--publish': [],
  152. '--rm': True,
  153. '--name': None,
  154. '--workdir': None,
  155. })
  156. self.assertFalse(
  157. mock_client.create_host_config.call_args[1].get('restart_policy')
  158. )
  159. def test_command_manula_and_service_ports_together(self):
  160. project = Project.from_config(
  161. name='composetest',
  162. client=None,
  163. config_data=build_config({
  164. 'service': {'image': 'busybox'},
  165. }),
  166. )
  167. command = TopLevelCommand(project)
  168. with self.assertRaises(UserError):
  169. command.run({
  170. 'SERVICE': 'service',
  171. 'COMMAND': None,
  172. '-e': [],
  173. '--user': None,
  174. '--no-deps': None,
  175. '-d': True,
  176. '-T': None,
  177. '--entrypoint': None,
  178. '--service-ports': True,
  179. '--publish': ['80:80'],
  180. '--rm': None,
  181. '--name': None,
  182. })