cli_test.py 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. from __future__ import unicode_literals
  2. from __future__ import absolute_import
  3. import logging
  4. import os
  5. import tempfile
  6. import shutil
  7. from .. import unittest
  8. import docker
  9. import mock
  10. from compose.cli import main
  11. from compose.cli.main import TopLevelCommand
  12. from compose.cli.docopt_command import NoSuchCommand
  13. from compose.cli.errors import ComposeFileNotFound
  14. from compose.service import Service
  15. class CLITestCase(unittest.TestCase):
  16. def test_default_project_name(self):
  17. cwd = os.getcwd()
  18. try:
  19. os.chdir('tests/fixtures/simple-composefile')
  20. command = TopLevelCommand()
  21. project_name = command.get_project_name(command.get_config_path())
  22. self.assertEquals('simplecomposefile', project_name)
  23. finally:
  24. os.chdir(cwd)
  25. def test_project_name_with_explicit_base_dir(self):
  26. command = TopLevelCommand()
  27. command.base_dir = 'tests/fixtures/simple-composefile'
  28. project_name = command.get_project_name(command.get_config_path())
  29. self.assertEquals('simplecomposefile', project_name)
  30. def test_project_name_with_explicit_uppercase_base_dir(self):
  31. command = TopLevelCommand()
  32. command.base_dir = 'tests/fixtures/UpperCaseDir'
  33. project_name = command.get_project_name(command.get_config_path())
  34. self.assertEquals('uppercasedir', project_name)
  35. def test_project_name_with_explicit_project_name(self):
  36. command = TopLevelCommand()
  37. name = 'explicit-project-name'
  38. project_name = command.get_project_name(None, project_name=name)
  39. self.assertEquals('explicitprojectname', project_name)
  40. def test_project_name_from_environment_old_var(self):
  41. command = TopLevelCommand()
  42. name = 'namefromenv'
  43. with mock.patch.dict(os.environ):
  44. os.environ['FIG_PROJECT_NAME'] = name
  45. project_name = command.get_project_name(None)
  46. self.assertEquals(project_name, name)
  47. def test_project_name_from_environment_new_var(self):
  48. command = TopLevelCommand()
  49. name = 'namefromenv'
  50. with mock.patch.dict(os.environ):
  51. os.environ['COMPOSE_PROJECT_NAME'] = name
  52. project_name = command.get_project_name(None)
  53. self.assertEquals(project_name, name)
  54. def test_filename_check(self):
  55. files = [
  56. 'docker-compose.yml',
  57. 'docker-compose.yaml',
  58. 'fig.yml',
  59. 'fig.yaml',
  60. ]
  61. """Test with files placed in the basedir"""
  62. self.assertEqual('docker-compose.yml', get_config_filename_for_files(files[0:]))
  63. self.assertEqual('docker-compose.yaml', get_config_filename_for_files(files[1:]))
  64. self.assertEqual('fig.yml', get_config_filename_for_files(files[2:]))
  65. self.assertEqual('fig.yaml', get_config_filename_for_files(files[3:]))
  66. self.assertRaises(ComposeFileNotFound, lambda: get_config_filename_for_files([]))
  67. """Test with files placed in the subdir"""
  68. def get_config_filename_for_files_in_subdir(files):
  69. return get_config_filename_for_files(files, subdir=True)
  70. self.assertEqual('docker-compose.yml', get_config_filename_for_files_in_subdir(files[0:]))
  71. self.assertEqual('docker-compose.yaml', get_config_filename_for_files_in_subdir(files[1:]))
  72. self.assertEqual('fig.yml', get_config_filename_for_files_in_subdir(files[2:]))
  73. self.assertEqual('fig.yaml', get_config_filename_for_files_in_subdir(files[3:]))
  74. self.assertRaises(ComposeFileNotFound, lambda: get_config_filename_for_files_in_subdir([]))
  75. def test_get_project(self):
  76. command = TopLevelCommand()
  77. command.base_dir = 'tests/fixtures/longer-filename-composefile'
  78. project = command.get_project(command.get_config_path())
  79. self.assertEqual(project.name, 'longerfilenamecomposefile')
  80. self.assertTrue(project.client)
  81. self.assertTrue(project.services)
  82. def test_help(self):
  83. command = TopLevelCommand()
  84. with self.assertRaises(SystemExit):
  85. command.dispatch(['-h'], None)
  86. def test_command_help(self):
  87. with self.assertRaises(SystemExit) as ctx:
  88. TopLevelCommand().dispatch(['help', 'up'], None)
  89. self.assertIn('Usage: up', str(ctx.exception))
  90. def test_command_help_dashes(self):
  91. with self.assertRaises(SystemExit) as ctx:
  92. TopLevelCommand().dispatch(['help', 'migrate-to-labels'], None)
  93. self.assertIn('Usage: migrate-to-labels', str(ctx.exception))
  94. def test_command_help_nonexistent(self):
  95. with self.assertRaises(NoSuchCommand):
  96. TopLevelCommand().dispatch(['help', 'nonexistent'], None)
  97. def test_setup_logging(self):
  98. main.setup_logging()
  99. self.assertEqual(logging.getLogger().level, logging.DEBUG)
  100. self.assertEqual(logging.getLogger('requests').propagate, False)
  101. @mock.patch('compose.cli.main.dockerpty', autospec=True)
  102. def test_run_with_environment_merged_with_options_list(self, mock_dockerpty):
  103. command = TopLevelCommand()
  104. mock_client = mock.create_autospec(docker.Client)
  105. mock_project = mock.Mock()
  106. mock_project.get_service.return_value = Service(
  107. 'service',
  108. client=mock_client,
  109. environment=['FOO=ONE', 'BAR=TWO'],
  110. image='someimage')
  111. command.run(mock_project, {
  112. 'SERVICE': 'service',
  113. 'COMMAND': None,
  114. '-e': ['BAR=NEW', 'OTHER=THREE'],
  115. '--user': None,
  116. '--no-deps': None,
  117. '--allow-insecure-ssl': None,
  118. '-d': True,
  119. '-T': None,
  120. '--entrypoint': None,
  121. '--service-ports': None,
  122. '--rm': None,
  123. })
  124. _, _, call_kwargs = mock_client.create_container.mock_calls[0]
  125. self.assertEqual(
  126. call_kwargs['environment'],
  127. {'FOO': 'ONE', 'BAR': 'NEW', 'OTHER': 'THREE'})
  128. def test_run_service_with_restart_always(self):
  129. command = TopLevelCommand()
  130. mock_client = mock.create_autospec(docker.Client)
  131. mock_project = mock.Mock()
  132. mock_project.get_service.return_value = Service(
  133. 'service',
  134. client=mock_client,
  135. restart='always',
  136. image='someimage')
  137. command.run(mock_project, {
  138. 'SERVICE': 'service',
  139. 'COMMAND': None,
  140. '-e': [],
  141. '--user': None,
  142. '--no-deps': None,
  143. '--allow-insecure-ssl': None,
  144. '-d': True,
  145. '-T': None,
  146. '--entrypoint': None,
  147. '--service-ports': None,
  148. '--rm': None,
  149. })
  150. _, _, call_kwargs = mock_client.create_container.mock_calls[0]
  151. self.assertEquals(call_kwargs['host_config']['RestartPolicy']['Name'], 'always')
  152. command = TopLevelCommand()
  153. mock_client = mock.create_autospec(docker.Client)
  154. mock_project = mock.Mock()
  155. mock_project.get_service.return_value = Service(
  156. 'service',
  157. client=mock_client,
  158. restart='always',
  159. image='someimage')
  160. command.run(mock_project, {
  161. 'SERVICE': 'service',
  162. 'COMMAND': None,
  163. '-e': [],
  164. '--user': None,
  165. '--no-deps': None,
  166. '--allow-insecure-ssl': None,
  167. '-d': True,
  168. '-T': None,
  169. '--entrypoint': None,
  170. '--service-ports': None,
  171. '--rm': True,
  172. })
  173. _, _, call_kwargs = mock_client.create_container.mock_calls[0]
  174. self.assertFalse('RestartPolicy' in call_kwargs['host_config'])
  175. def get_config_filename_for_files(filenames, subdir=None):
  176. project_dir = tempfile.mkdtemp()
  177. try:
  178. make_files(project_dir, filenames)
  179. command = TopLevelCommand()
  180. if subdir:
  181. command.base_dir = tempfile.mkdtemp(dir=project_dir)
  182. else:
  183. command.base_dir = project_dir
  184. return os.path.basename(command.get_config_path())
  185. finally:
  186. shutil.rmtree(project_dir)
  187. def make_files(dirname, filenames):
  188. for fname in filenames:
  189. with open(os.path.join(dirname, fname), 'w') as f:
  190. f.write('')