main_test.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. from __future__ import absolute_import
  2. from __future__ import unicode_literals
  3. import logging
  4. import docker
  5. import pytest
  6. from compose import container
  7. from compose.cli.errors import UserError
  8. from compose.cli.formatter import ConsoleWarningFormatter
  9. from compose.cli.main import call_docker
  10. from compose.cli.main import convergence_strategy_from_opts
  11. from compose.cli.main import filter_containers_to_service_names
  12. from compose.cli.main import setup_console_handler
  13. from compose.cli.main import warn_for_swarm_mode
  14. from compose.service import ConvergenceStrategy
  15. from tests import mock
  16. def mock_container(service, number):
  17. return mock.create_autospec(
  18. container.Container,
  19. service=service,
  20. number=number,
  21. name_without_project='{0}_{1}'.format(service, number))
  22. @pytest.fixture
  23. def logging_handler():
  24. stream = mock.Mock()
  25. stream.isatty.return_value = True
  26. return logging.StreamHandler(stream=stream)
  27. class TestCLIMainTestCase(object):
  28. def test_filter_containers_to_service_names(self):
  29. containers = [
  30. mock_container('web', 1),
  31. mock_container('web', 2),
  32. mock_container('db', 1),
  33. mock_container('other', 1),
  34. mock_container('another', 1),
  35. ]
  36. service_names = ['web', 'db']
  37. actual = filter_containers_to_service_names(containers, service_names)
  38. assert actual == containers[:3]
  39. def test_filter_containers_to_service_names_all(self):
  40. containers = [
  41. mock_container('web', 1),
  42. mock_container('db', 1),
  43. mock_container('other', 1),
  44. ]
  45. service_names = []
  46. actual = filter_containers_to_service_names(containers, service_names)
  47. assert actual == containers
  48. def test_warning_in_swarm_mode(self):
  49. mock_client = mock.create_autospec(docker.APIClient)
  50. mock_client.info.return_value = {'Swarm': {'LocalNodeState': 'active'}}
  51. with mock.patch('compose.cli.main.log') as fake_log:
  52. warn_for_swarm_mode(mock_client)
  53. assert fake_log.warn.call_count == 1
  54. class TestSetupConsoleHandlerTestCase(object):
  55. def test_with_tty_verbose(self, logging_handler):
  56. setup_console_handler(logging_handler, True)
  57. assert type(logging_handler.formatter) == ConsoleWarningFormatter
  58. assert '%(name)s' in logging_handler.formatter._fmt
  59. assert '%(funcName)s' in logging_handler.formatter._fmt
  60. def test_with_tty_not_verbose(self, logging_handler):
  61. setup_console_handler(logging_handler, False)
  62. assert type(logging_handler.formatter) == ConsoleWarningFormatter
  63. assert '%(name)s' not in logging_handler.formatter._fmt
  64. assert '%(funcName)s' not in logging_handler.formatter._fmt
  65. def test_with_not_a_tty(self, logging_handler):
  66. logging_handler.stream.isatty.return_value = False
  67. setup_console_handler(logging_handler, False)
  68. assert type(logging_handler.formatter) == logging.Formatter
  69. class TestConvergeStrategyFromOptsTestCase(object):
  70. def test_invalid_opts(self):
  71. options = {'--force-recreate': True, '--no-recreate': True}
  72. with pytest.raises(UserError):
  73. convergence_strategy_from_opts(options)
  74. def test_always(self):
  75. options = {'--force-recreate': True, '--no-recreate': False}
  76. assert (
  77. convergence_strategy_from_opts(options) ==
  78. ConvergenceStrategy.always
  79. )
  80. def test_never(self):
  81. options = {'--force-recreate': False, '--no-recreate': True}
  82. assert (
  83. convergence_strategy_from_opts(options) ==
  84. ConvergenceStrategy.never
  85. )
  86. def test_changed(self):
  87. options = {'--force-recreate': False, '--no-recreate': False}
  88. assert (
  89. convergence_strategy_from_opts(options) ==
  90. ConvergenceStrategy.changed
  91. )
  92. def mock_find_executable(exe):
  93. return exe
  94. @mock.patch('compose.cli.main.find_executable', mock_find_executable)
  95. class TestCallDocker(object):
  96. def test_simple_no_options(self):
  97. with mock.patch('subprocess.call') as fake_call:
  98. call_docker(['ps'], {})
  99. assert fake_call.call_args[0][0] == ['docker', 'ps']
  100. def test_simple_tls_option(self):
  101. with mock.patch('subprocess.call') as fake_call:
  102. call_docker(['ps'], {'--tls': True})
  103. assert fake_call.call_args[0][0] == ['docker', '--tls', 'ps']
  104. def test_advanced_tls_options(self):
  105. with mock.patch('subprocess.call') as fake_call:
  106. call_docker(['ps'], {
  107. '--tls': True,
  108. '--tlscacert': './ca.pem',
  109. '--tlscert': './cert.pem',
  110. '--tlskey': './key.pem',
  111. })
  112. assert fake_call.call_args[0][0] == [
  113. 'docker', '--tls', '--tlscacert', './ca.pem', '--tlscert',
  114. './cert.pem', '--tlskey', './key.pem', 'ps'
  115. ]
  116. def test_with_host_option(self):
  117. with mock.patch('subprocess.call') as fake_call:
  118. call_docker(['ps'], {'--host': 'tcp://mydocker.net:2333'})
  119. assert fake_call.call_args[0][0] == [
  120. 'docker', '--host', 'tcp://mydocker.net:2333', 'ps'
  121. ]
  122. def test_with_http_host(self):
  123. with mock.patch('subprocess.call') as fake_call:
  124. call_docker(['ps'], {'--host': 'http://mydocker.net:2333'})
  125. assert fake_call.call_args[0][0] == [
  126. 'docker', '--host', 'tcp://mydocker.net:2333', 'ps',
  127. ]
  128. def test_with_host_option_shorthand_equal(self):
  129. with mock.patch('subprocess.call') as fake_call:
  130. call_docker(['ps'], {'--host': '=tcp://mydocker.net:2333'})
  131. assert fake_call.call_args[0][0] == [
  132. 'docker', '--host', 'tcp://mydocker.net:2333', 'ps'
  133. ]