123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250 |
- import logging
- import docker
- import pytest
- from compose import container
- from compose.cli.errors import UserError
- from compose.cli.formatter import ConsoleWarningFormatter
- from compose.cli.main import build_one_off_container_options
- from compose.cli.main import call_docker
- from compose.cli.main import convergence_strategy_from_opts
- from compose.cli.main import filter_attached_containers
- from compose.cli.main import get_docker_start_call
- from compose.cli.main import setup_console_handler
- from compose.cli.main import warn_for_swarm_mode
- from compose.service import ConvergenceStrategy
- from tests import mock
- def mock_container(service, number):
- return mock.create_autospec(
- container.Container,
- service=service,
- number=number,
- name_without_project='{0}_{1}'.format(service, number))
- @pytest.fixture
- def logging_handler():
- stream = mock.Mock()
- stream.isatty.return_value = True
- return logging.StreamHandler(stream=stream)
- class TestCLIMainTestCase(object):
- def test_filter_attached_containers(self):
- containers = [
- mock_container('web', 1),
- mock_container('web', 2),
- mock_container('db', 1),
- mock_container('other', 1),
- mock_container('another', 1),
- ]
- service_names = ['web', 'db']
- actual = filter_attached_containers(containers, service_names)
- assert actual == containers[:3]
- def test_filter_attached_containers_with_dependencies(self):
- containers = [
- mock_container('web', 1),
- mock_container('web', 2),
- mock_container('db', 1),
- mock_container('other', 1),
- mock_container('another', 1),
- ]
- service_names = ['web', 'db']
- actual = filter_attached_containers(containers, service_names, attach_dependencies=True)
- assert actual == containers
- def test_filter_attached_containers_all(self):
- containers = [
- mock_container('web', 1),
- mock_container('db', 1),
- mock_container('other', 1),
- ]
- service_names = []
- actual = filter_attached_containers(containers, service_names)
- assert actual == containers
- def test_warning_in_swarm_mode(self):
- mock_client = mock.create_autospec(docker.APIClient)
- mock_client.info.return_value = {'Swarm': {'LocalNodeState': 'active'}}
- with mock.patch('compose.cli.main.log') as fake_log:
- warn_for_swarm_mode(mock_client)
- assert fake_log.warning.call_count == 1
- def test_build_one_off_container_options(self):
- command = 'build myservice'
- detach = False
- options = {
- '-e': ['MYVAR=MYVALUE'],
- '-T': True,
- '--label': ['MYLABEL'],
- '--entrypoint': 'bash',
- '--user': 'MYUSER',
- '--service-ports': [],
- '--publish': '',
- '--name': 'MYNAME',
- '--workdir': '.',
- '--volume': [],
- 'stdin_open': False,
- }
- expected_container_options = {
- 'command': command,
- 'tty': False,
- 'stdin_open': False,
- 'detach': detach,
- 'entrypoint': 'bash',
- 'environment': {'MYVAR': 'MYVALUE'},
- 'labels': {'MYLABEL': ''},
- 'name': 'MYNAME',
- 'ports': [],
- 'restart': None,
- 'user': 'MYUSER',
- 'working_dir': '.',
- }
- container_options = build_one_off_container_options(options, detach, command)
- assert container_options == expected_container_options
- def test_get_docker_start_call(self):
- container_id = 'my_container_id'
- mock_container_options = {'detach': False, 'stdin_open': True}
- expected_docker_start_call = ['start', '--attach', '--interactive', container_id]
- docker_start_call = get_docker_start_call(mock_container_options, container_id)
- assert expected_docker_start_call == docker_start_call
- mock_container_options = {'detach': False, 'stdin_open': False}
- expected_docker_start_call = ['start', '--attach', container_id]
- docker_start_call = get_docker_start_call(mock_container_options, container_id)
- assert expected_docker_start_call == docker_start_call
- mock_container_options = {'detach': True, 'stdin_open': True}
- expected_docker_start_call = ['start', '--interactive', container_id]
- docker_start_call = get_docker_start_call(mock_container_options, container_id)
- assert expected_docker_start_call == docker_start_call
- mock_container_options = {'detach': True, 'stdin_open': False}
- expected_docker_start_call = ['start', container_id]
- docker_start_call = get_docker_start_call(mock_container_options, container_id)
- assert expected_docker_start_call == docker_start_call
- class TestSetupConsoleHandlerTestCase(object):
- def test_with_tty_verbose(self, logging_handler):
- setup_console_handler(logging_handler, True)
- assert type(logging_handler.formatter) == ConsoleWarningFormatter
- assert '%(name)s' in logging_handler.formatter._fmt
- assert '%(funcName)s' in logging_handler.formatter._fmt
- def test_with_tty_not_verbose(self, logging_handler):
- setup_console_handler(logging_handler, False)
- assert type(logging_handler.formatter) == ConsoleWarningFormatter
- assert '%(name)s' not in logging_handler.formatter._fmt
- assert '%(funcName)s' not in logging_handler.formatter._fmt
- def test_with_not_a_tty(self, logging_handler):
- logging_handler.stream.isatty.return_value = False
- setup_console_handler(logging_handler, False)
- assert type(logging_handler.formatter) == logging.Formatter
- class TestConvergeStrategyFromOptsTestCase(object):
- def test_invalid_opts(self):
- options = {'--force-recreate': True, '--no-recreate': True}
- with pytest.raises(UserError):
- convergence_strategy_from_opts(options)
- def test_always(self):
- options = {'--force-recreate': True, '--no-recreate': False}
- assert (
- convergence_strategy_from_opts(options) ==
- ConvergenceStrategy.always
- )
- def test_never(self):
- options = {'--force-recreate': False, '--no-recreate': True}
- assert (
- convergence_strategy_from_opts(options) ==
- ConvergenceStrategy.never
- )
- def test_changed(self):
- options = {'--force-recreate': False, '--no-recreate': False}
- assert (
- convergence_strategy_from_opts(options) ==
- ConvergenceStrategy.changed
- )
- def mock_find_executable(exe):
- return exe
- @mock.patch('compose.cli.main.find_executable', mock_find_executable)
- class TestCallDocker(object):
- def test_simple_no_options(self):
- with mock.patch('subprocess.call') as fake_call:
- call_docker(['ps'], {}, {})
- assert fake_call.call_args[0][0] == ['docker', 'ps']
- def test_simple_tls_option(self):
- with mock.patch('subprocess.call') as fake_call:
- call_docker(['ps'], {'--tls': True}, {})
- assert fake_call.call_args[0][0] == ['docker', '--tls', 'ps']
- def test_advanced_tls_options(self):
- with mock.patch('subprocess.call') as fake_call:
- call_docker(['ps'], {
- '--tls': True,
- '--tlscacert': './ca.pem',
- '--tlscert': './cert.pem',
- '--tlskey': './key.pem',
- }, {})
- assert fake_call.call_args[0][0] == [
- 'docker', '--tls', '--tlscacert', './ca.pem', '--tlscert',
- './cert.pem', '--tlskey', './key.pem', 'ps'
- ]
- def test_with_host_option(self):
- with mock.patch('subprocess.call') as fake_call:
- call_docker(['ps'], {'--host': 'tcp://mydocker.net:2333'}, {})
- assert fake_call.call_args[0][0] == [
- 'docker', '--host', 'tcp://mydocker.net:2333', 'ps'
- ]
- def test_with_http_host(self):
- with mock.patch('subprocess.call') as fake_call:
- call_docker(['ps'], {'--host': 'http://mydocker.net:2333'}, {})
- assert fake_call.call_args[0][0] == [
- 'docker', '--host', 'tcp://mydocker.net:2333', 'ps',
- ]
- def test_with_host_option_shorthand_equal(self):
- with mock.patch('subprocess.call') as fake_call:
- call_docker(['ps'], {'--host': '=tcp://mydocker.net:2333'}, {})
- assert fake_call.call_args[0][0] == [
- 'docker', '--host', 'tcp://mydocker.net:2333', 'ps'
- ]
- def test_with_env(self):
- with mock.patch('subprocess.call') as fake_call:
- call_docker(['ps'], {}, {'DOCKER_HOST': 'tcp://mydocker.net:2333'})
- assert fake_call.call_args[0][0] == [
- 'docker', 'ps'
- ]
- assert fake_call.call_args[1]['env'] == {'DOCKER_HOST': 'tcp://mydocker.net:2333'}
|