mirror of https://github.com/docker/compose.git
commit
adb8de367e
|
@ -20,14 +20,16 @@ def docker_client(version=None):
|
||||||
according to the same logic as the official Docker client.
|
according to the same logic as the official Docker client.
|
||||||
"""
|
"""
|
||||||
if 'DOCKER_CLIENT_TIMEOUT' in os.environ:
|
if 'DOCKER_CLIENT_TIMEOUT' in os.environ:
|
||||||
log.warn('The DOCKER_CLIENT_TIMEOUT environment variable is deprecated. Please use COMPOSE_HTTP_TIMEOUT instead.')
|
log.warn("The DOCKER_CLIENT_TIMEOUT environment variable is deprecated. "
|
||||||
|
"Please use COMPOSE_HTTP_TIMEOUT instead.")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
kwargs = kwargs_from_env(assert_hostname=False)
|
kwargs = kwargs_from_env(assert_hostname=False)
|
||||||
except TLSParameterError:
|
except TLSParameterError:
|
||||||
raise UserError(
|
raise UserError(
|
||||||
'TLS configuration is invalid - make sure your DOCKER_TLS_VERIFY and DOCKER_CERT_PATH are set correctly.\n'
|
"TLS configuration is invalid - make sure your DOCKER_TLS_VERIFY "
|
||||||
'You might need to run `eval "$(docker-machine env default)"`')
|
"and DOCKER_CERT_PATH are set correctly.\n"
|
||||||
|
"You might need to run `eval \"$(docker-machine env default)\"`")
|
||||||
|
|
||||||
if version:
|
if version:
|
||||||
kwargs['version'] = version
|
kwargs['version'] = version
|
||||||
|
|
|
@ -78,9 +78,11 @@ def main():
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
except ReadTimeout as e:
|
except ReadTimeout as e:
|
||||||
log.error(
|
log.error(
|
||||||
"An HTTP request took too long to complete. Retry with --verbose to obtain debug information.\n"
|
"An HTTP request took too long to complete. Retry with --verbose to "
|
||||||
"If you encounter this issue regularly because of slow network conditions, consider setting "
|
"obtain debug information.\n"
|
||||||
"COMPOSE_HTTP_TIMEOUT to a higher value (current value: %s)." % HTTP_TIMEOUT
|
"If you encounter this issue regularly because of slow network "
|
||||||
|
"conditions, consider setting COMPOSE_HTTP_TIMEOUT to a higher "
|
||||||
|
"value (current value: %s)." % HTTP_TIMEOUT
|
||||||
)
|
)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,8 @@ class CircularReference(ConfigurationError):
|
||||||
class ComposeFileNotFound(ConfigurationError):
|
class ComposeFileNotFound(ConfigurationError):
|
||||||
def __init__(self, supported_filenames):
|
def __init__(self, supported_filenames):
|
||||||
super(ComposeFileNotFound, self).__init__("""
|
super(ComposeFileNotFound, self).__init__("""
|
||||||
Can't find a suitable configuration file in this directory or any parent. Are you in the right directory?
|
Can't find a suitable configuration file in this directory or any
|
||||||
|
parent. Are you in the right directory?
|
||||||
|
|
||||||
Supported filenames: %s
|
Supported filenames: %s
|
||||||
""" % ", ".join(supported_filenames))
|
""" % ", ".join(supported_filenames))
|
||||||
|
|
|
@ -196,7 +196,9 @@ class Service(object):
|
||||||
|
|
||||||
if num_running != len(all_containers):
|
if num_running != len(all_containers):
|
||||||
# we have some stopped containers, let's start them up again
|
# we have some stopped containers, let's start them up again
|
||||||
stopped_containers = sorted([c for c in all_containers if not c.is_running], key=attrgetter('number'))
|
stopped_containers = sorted(
|
||||||
|
(c for c in all_containers if not c.is_running),
|
||||||
|
key=attrgetter('number'))
|
||||||
|
|
||||||
num_stopped = len(stopped_containers)
|
num_stopped = len(stopped_containers)
|
||||||
|
|
||||||
|
|
|
@ -930,7 +930,12 @@ class CLITestCase(DockerClientTestCase):
|
||||||
def test_run_service_with_explicitly_maped_ip_ports(self):
|
def test_run_service_with_explicitly_maped_ip_ports(self):
|
||||||
# create one off container
|
# create one off container
|
||||||
self.base_dir = 'tests/fixtures/ports-composefile'
|
self.base_dir = 'tests/fixtures/ports-composefile'
|
||||||
self.dispatch(['run', '-d', '-p', '127.0.0.1:30000:3000', '--publish', '127.0.0.1:30001:3001', 'simple'], None)
|
self.dispatch([
|
||||||
|
'run', '-d',
|
||||||
|
'-p', '127.0.0.1:30000:3000',
|
||||||
|
'--publish', '127.0.0.1:30001:3001',
|
||||||
|
'simple'
|
||||||
|
])
|
||||||
container = self.project.get_service('simple').containers(one_off=True)[0]
|
container = self.project.get_service('simple').containers(one_off=True)[0]
|
||||||
|
|
||||||
# get port information
|
# get port information
|
||||||
|
|
|
@ -242,19 +242,24 @@ class ProjectTest(DockerClientTestCase):
|
||||||
db_container = db.create_container()
|
db_container = db.create_container()
|
||||||
|
|
||||||
project.start(service_names=['web'])
|
project.start(service_names=['web'])
|
||||||
self.assertEqual(set(c.name for c in project.containers()), set([web_container_1.name, web_container_2.name]))
|
self.assertEqual(
|
||||||
|
set(c.name for c in project.containers()),
|
||||||
|
set([web_container_1.name, web_container_2.name]))
|
||||||
|
|
||||||
project.start()
|
project.start()
|
||||||
self.assertEqual(set(c.name for c in project.containers()),
|
self.assertEqual(
|
||||||
set([web_container_1.name, web_container_2.name, db_container.name]))
|
set(c.name for c in project.containers()),
|
||||||
|
set([web_container_1.name, web_container_2.name, db_container.name]))
|
||||||
|
|
||||||
project.pause(service_names=['web'])
|
project.pause(service_names=['web'])
|
||||||
self.assertEqual(set([c.name for c in project.containers() if c.is_paused]),
|
self.assertEqual(
|
||||||
set([web_container_1.name, web_container_2.name]))
|
set([c.name for c in project.containers() if c.is_paused]),
|
||||||
|
set([web_container_1.name, web_container_2.name]))
|
||||||
|
|
||||||
project.pause()
|
project.pause()
|
||||||
self.assertEqual(set([c.name for c in project.containers() if c.is_paused]),
|
self.assertEqual(
|
||||||
set([web_container_1.name, web_container_2.name, db_container.name]))
|
set([c.name for c in project.containers() if c.is_paused]),
|
||||||
|
set([web_container_1.name, web_container_2.name, db_container.name]))
|
||||||
|
|
||||||
project.unpause(service_names=['db'])
|
project.unpause(service_names=['db'])
|
||||||
self.assertEqual(len([c.name for c in project.containers() if c.is_paused]), 2)
|
self.assertEqual(len([c.name for c in project.containers() if c.is_paused]), 2)
|
||||||
|
|
|
@ -135,7 +135,7 @@ class ServiceTest(DockerClientTestCase):
|
||||||
service = self.create_service('db', read_only=read_only)
|
service = self.create_service('db', read_only=read_only)
|
||||||
container = service.create_container()
|
container = service.create_container()
|
||||||
service.start_container(container)
|
service.start_container(container)
|
||||||
self.assertEqual(container.get('HostConfig.ReadonlyRootfs'), read_only, container.get('HostConfig'))
|
assert container.get('HostConfig.ReadonlyRootfs') == read_only
|
||||||
|
|
||||||
def test_create_container_with_security_opt(self):
|
def test_create_container_with_security_opt(self):
|
||||||
security_opt = ['label:disable']
|
security_opt = ['label:disable']
|
||||||
|
@ -409,7 +409,9 @@ class ServiceTest(DockerClientTestCase):
|
||||||
self.assertEqual(len(service.containers()), 0)
|
self.assertEqual(len(service.containers()), 0)
|
||||||
self.assertEqual(len(service.containers(stopped=True)), 1)
|
self.assertEqual(len(service.containers(stopped=True)), 1)
|
||||||
|
|
||||||
containers = service.execute_convergence_plan(ConvergencePlan('recreate', containers), start=False)
|
containers = service.execute_convergence_plan(
|
||||||
|
ConvergencePlan('recreate', containers),
|
||||||
|
start=False)
|
||||||
self.assertEqual(len(service.containers()), 0)
|
self.assertEqual(len(service.containers()), 0)
|
||||||
self.assertEqual(len(service.containers(stopped=True)), 1)
|
self.assertEqual(len(service.containers(stopped=True)), 1)
|
||||||
|
|
||||||
|
@ -800,7 +802,9 @@ class ServiceTest(DockerClientTestCase):
|
||||||
containers = service.containers()
|
containers = service.containers()
|
||||||
self.assertEqual(len(containers), 2)
|
self.assertEqual(len(containers), 2)
|
||||||
for container in containers:
|
for container in containers:
|
||||||
self.assertEqual(list(container.inspect()['HostConfig']['PortBindings'].keys()), ['8000/tcp'])
|
self.assertEqual(
|
||||||
|
list(container.get('HostConfig.PortBindings')),
|
||||||
|
['8000/tcp'])
|
||||||
|
|
||||||
def test_scale_with_immediate_exit(self):
|
def test_scale_with_immediate_exit(self):
|
||||||
service = self.create_service('web', image='busybox', command='true')
|
service = self.create_service('web', image='busybox', command='true')
|
||||||
|
@ -877,7 +881,9 @@ class ServiceTest(DockerClientTestCase):
|
||||||
self.assertEqual(container.get('Config.WorkingDir'), '/working/dir/sample')
|
self.assertEqual(container.get('Config.WorkingDir'), '/working/dir/sample')
|
||||||
|
|
||||||
def test_split_env(self):
|
def test_split_env(self):
|
||||||
service = self.create_service('web', environment=['NORMAL=F1', 'CONTAINS_EQUALS=F=2', 'TRAILING_EQUALS='])
|
service = self.create_service(
|
||||||
|
'web',
|
||||||
|
environment=['NORMAL=F1', 'CONTAINS_EQUALS=F=2', 'TRAILING_EQUALS='])
|
||||||
env = create_and_start_container(service).environment
|
env = create_and_start_container(service).environment
|
||||||
for k, v in {'NORMAL': 'F1', 'CONTAINS_EQUALS': 'F=2', 'TRAILING_EQUALS': ''}.items():
|
for k, v in {'NORMAL': 'F1', 'CONTAINS_EQUALS': 'F=2', 'TRAILING_EQUALS': ''}.items():
|
||||||
self.assertEqual(env[k], v)
|
self.assertEqual(env[k], v)
|
||||||
|
|
|
@ -1649,24 +1649,42 @@ class VolumeConfigTest(unittest.TestCase):
|
||||||
|
|
||||||
@pytest.mark.skipif(IS_WINDOWS_PLATFORM, reason='posix paths')
|
@pytest.mark.skipif(IS_WINDOWS_PLATFORM, reason='posix paths')
|
||||||
def test_relative_path_does_expand_posix(self):
|
def test_relative_path_does_expand_posix(self):
|
||||||
d = make_service_dict('foo', {'build': '.', 'volumes': ['./data:/data']}, working_dir='/home/me/myproject')
|
d = make_service_dict(
|
||||||
|
'foo',
|
||||||
|
{'build': '.', 'volumes': ['./data:/data']},
|
||||||
|
working_dir='/home/me/myproject')
|
||||||
self.assertEqual(d['volumes'], ['/home/me/myproject/data:/data'])
|
self.assertEqual(d['volumes'], ['/home/me/myproject/data:/data'])
|
||||||
|
|
||||||
d = make_service_dict('foo', {'build': '.', 'volumes': ['.:/data']}, working_dir='/home/me/myproject')
|
d = make_service_dict(
|
||||||
|
'foo',
|
||||||
|
{'build': '.', 'volumes': ['.:/data']},
|
||||||
|
working_dir='/home/me/myproject')
|
||||||
self.assertEqual(d['volumes'], ['/home/me/myproject:/data'])
|
self.assertEqual(d['volumes'], ['/home/me/myproject:/data'])
|
||||||
|
|
||||||
d = make_service_dict('foo', {'build': '.', 'volumes': ['../otherproject:/data']}, working_dir='/home/me/myproject')
|
d = make_service_dict(
|
||||||
|
'foo',
|
||||||
|
{'build': '.', 'volumes': ['../otherproject:/data']},
|
||||||
|
working_dir='/home/me/myproject')
|
||||||
self.assertEqual(d['volumes'], ['/home/me/otherproject:/data'])
|
self.assertEqual(d['volumes'], ['/home/me/otherproject:/data'])
|
||||||
|
|
||||||
@pytest.mark.skipif(not IS_WINDOWS_PLATFORM, reason='windows paths')
|
@pytest.mark.skipif(not IS_WINDOWS_PLATFORM, reason='windows paths')
|
||||||
def test_relative_path_does_expand_windows(self):
|
def test_relative_path_does_expand_windows(self):
|
||||||
d = make_service_dict('foo', {'build': '.', 'volumes': ['./data:/data']}, working_dir='c:\\Users\\me\\myproject')
|
d = make_service_dict(
|
||||||
|
'foo',
|
||||||
|
{'build': '.', 'volumes': ['./data:/data']},
|
||||||
|
working_dir='c:\\Users\\me\\myproject')
|
||||||
self.assertEqual(d['volumes'], ['c:\\Users\\me\\myproject\\data:/data'])
|
self.assertEqual(d['volumes'], ['c:\\Users\\me\\myproject\\data:/data'])
|
||||||
|
|
||||||
d = make_service_dict('foo', {'build': '.', 'volumes': ['.:/data']}, working_dir='c:\\Users\\me\\myproject')
|
d = make_service_dict(
|
||||||
|
'foo',
|
||||||
|
{'build': '.', 'volumes': ['.:/data']},
|
||||||
|
working_dir='c:\\Users\\me\\myproject')
|
||||||
self.assertEqual(d['volumes'], ['c:\\Users\\me\\myproject:/data'])
|
self.assertEqual(d['volumes'], ['c:\\Users\\me\\myproject:/data'])
|
||||||
|
|
||||||
d = make_service_dict('foo', {'build': '.', 'volumes': ['../otherproject:/data']}, working_dir='c:\\Users\\me\\myproject')
|
d = make_service_dict(
|
||||||
|
'foo',
|
||||||
|
{'build': '.', 'volumes': ['../otherproject:/data']},
|
||||||
|
working_dir='c:\\Users\\me\\myproject')
|
||||||
self.assertEqual(d['volumes'], ['c:\\Users\\me\\otherproject:/data'])
|
self.assertEqual(d['volumes'], ['c:\\Users\\me\\otherproject:/data'])
|
||||||
|
|
||||||
@mock.patch.dict(os.environ)
|
@mock.patch.dict(os.environ)
|
||||||
|
@ -2550,14 +2568,11 @@ class VolumePathTest(unittest.TestCase):
|
||||||
|
|
||||||
@pytest.mark.xfail((not IS_WINDOWS_PLATFORM), reason='does not have a drive')
|
@pytest.mark.xfail((not IS_WINDOWS_PLATFORM), reason='does not have a drive')
|
||||||
def test_split_path_mapping_with_windows_path(self):
|
def test_split_path_mapping_with_windows_path(self):
|
||||||
windows_volume_path = "c:\\Users\\msamblanet\\Documents\\anvil\\connect\\config:/opt/connect/config:ro"
|
host_path = "c:\\Users\\msamblanet\\Documents\\anvil\\connect\\config"
|
||||||
expected_mapping = (
|
windows_volume_path = host_path + ":/opt/connect/config:ro"
|
||||||
"/opt/connect/config:ro",
|
expected_mapping = ("/opt/connect/config:ro", host_path)
|
||||||
"c:\\Users\\msamblanet\\Documents\\anvil\\connect\\config"
|
|
||||||
)
|
|
||||||
|
|
||||||
mapping = config.split_path_mapping(windows_volume_path)
|
mapping = config.split_path_mapping(windows_volume_path)
|
||||||
|
|
||||||
self.assertEqual(mapping, expected_mapping)
|
self.assertEqual(mapping, expected_mapping)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -156,7 +156,9 @@ class GetContainerNameTestCase(unittest.TestCase):
|
||||||
def test_get_container_name(self):
|
def test_get_container_name(self):
|
||||||
self.assertIsNone(get_container_name({}))
|
self.assertIsNone(get_container_name({}))
|
||||||
self.assertEqual(get_container_name({'Name': 'myproject_db_1'}), 'myproject_db_1')
|
self.assertEqual(get_container_name({'Name': 'myproject_db_1'}), 'myproject_db_1')
|
||||||
self.assertEqual(get_container_name({'Names': ['/myproject_db_1', '/myproject_web_1/db']}), 'myproject_db_1')
|
self.assertEqual(
|
||||||
|
get_container_name({'Names': ['/myproject_db_1', '/myproject_web_1/db']}),
|
||||||
|
'myproject_db_1')
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
get_container_name({
|
get_container_name({
|
||||||
'Names': [
|
'Names': [
|
||||||
|
|
|
@ -146,7 +146,13 @@ class ServiceTest(unittest.TestCase):
|
||||||
def test_memory_swap_limit(self):
|
def test_memory_swap_limit(self):
|
||||||
self.mock_client.create_host_config.return_value = {}
|
self.mock_client.create_host_config.return_value = {}
|
||||||
|
|
||||||
service = Service(name='foo', image='foo', hostname='name', client=self.mock_client, mem_limit=1000000000, memswap_limit=2000000000)
|
service = Service(
|
||||||
|
name='foo',
|
||||||
|
image='foo',
|
||||||
|
hostname='name',
|
||||||
|
client=self.mock_client,
|
||||||
|
mem_limit=1000000000,
|
||||||
|
memswap_limit=2000000000)
|
||||||
service._get_container_create_options({'some': 'overrides'}, 1)
|
service._get_container_create_options({'some': 'overrides'}, 1)
|
||||||
|
|
||||||
self.assertTrue(self.mock_client.create_host_config.called)
|
self.assertTrue(self.mock_client.create_host_config.called)
|
||||||
|
@ -162,7 +168,12 @@ class ServiceTest(unittest.TestCase):
|
||||||
def test_cgroup_parent(self):
|
def test_cgroup_parent(self):
|
||||||
self.mock_client.create_host_config.return_value = {}
|
self.mock_client.create_host_config.return_value = {}
|
||||||
|
|
||||||
service = Service(name='foo', image='foo', hostname='name', client=self.mock_client, cgroup_parent='test')
|
service = Service(
|
||||||
|
name='foo',
|
||||||
|
image='foo',
|
||||||
|
hostname='name',
|
||||||
|
client=self.mock_client,
|
||||||
|
cgroup_parent='test')
|
||||||
service._get_container_create_options({'some': 'overrides'}, 1)
|
service._get_container_create_options({'some': 'overrides'}, 1)
|
||||||
|
|
||||||
self.assertTrue(self.mock_client.create_host_config.called)
|
self.assertTrue(self.mock_client.create_host_config.called)
|
||||||
|
@ -176,7 +187,13 @@ class ServiceTest(unittest.TestCase):
|
||||||
|
|
||||||
log_opt = {'syslog-address': 'tcp://192.168.0.42:123'}
|
log_opt = {'syslog-address': 'tcp://192.168.0.42:123'}
|
||||||
logging = {'driver': 'syslog', 'options': log_opt}
|
logging = {'driver': 'syslog', 'options': log_opt}
|
||||||
service = Service(name='foo', image='foo', hostname='name', client=self.mock_client, logging=logging)
|
service = Service(
|
||||||
|
name='foo',
|
||||||
|
image='foo',
|
||||||
|
hostname='name',
|
||||||
|
client=self.mock_client,
|
||||||
|
log_driver='syslog',
|
||||||
|
logging=logging)
|
||||||
service._get_container_create_options({'some': 'overrides'}, 1)
|
service._get_container_create_options({'some': 'overrides'}, 1)
|
||||||
|
|
||||||
self.assertTrue(self.mock_client.create_host_config.called)
|
self.assertTrue(self.mock_client.create_host_config.called)
|
||||||
|
@ -387,11 +404,18 @@ class ServiceTest(unittest.TestCase):
|
||||||
self.assertEqual(parse_repository_tag("user/repo"), ("user/repo", "", ":"))
|
self.assertEqual(parse_repository_tag("user/repo"), ("user/repo", "", ":"))
|
||||||
self.assertEqual(parse_repository_tag("user/repo:tag"), ("user/repo", "tag", ":"))
|
self.assertEqual(parse_repository_tag("user/repo:tag"), ("user/repo", "tag", ":"))
|
||||||
self.assertEqual(parse_repository_tag("url:5000/repo"), ("url:5000/repo", "", ":"))
|
self.assertEqual(parse_repository_tag("url:5000/repo"), ("url:5000/repo", "", ":"))
|
||||||
self.assertEqual(parse_repository_tag("url:5000/repo:tag"), ("url:5000/repo", "tag", ":"))
|
self.assertEqual(
|
||||||
|
parse_repository_tag("url:5000/repo:tag"),
|
||||||
self.assertEqual(parse_repository_tag("root@sha256:digest"), ("root", "sha256:digest", "@"))
|
("url:5000/repo", "tag", ":"))
|
||||||
self.assertEqual(parse_repository_tag("user/repo@sha256:digest"), ("user/repo", "sha256:digest", "@"))
|
self.assertEqual(
|
||||||
self.assertEqual(parse_repository_tag("url:5000/repo@sha256:digest"), ("url:5000/repo", "sha256:digest", "@"))
|
parse_repository_tag("root@sha256:digest"),
|
||||||
|
("root", "sha256:digest", "@"))
|
||||||
|
self.assertEqual(
|
||||||
|
parse_repository_tag("user/repo@sha256:digest"),
|
||||||
|
("user/repo", "sha256:digest", "@"))
|
||||||
|
self.assertEqual(
|
||||||
|
parse_repository_tag("url:5000/repo@sha256:digest"),
|
||||||
|
("url:5000/repo", "sha256:digest", "@"))
|
||||||
|
|
||||||
def test_create_container_with_build(self):
|
def test_create_container_with_build(self):
|
||||||
service = Service('foo', client=self.mock_client, build={'context': '.'})
|
service = Service('foo', client=self.mock_client, build={'context': '.'})
|
||||||
|
|
3
tox.ini
3
tox.ini
|
@ -42,8 +42,7 @@ directory = coverage-html
|
||||||
# end coverage configuration
|
# end coverage configuration
|
||||||
|
|
||||||
[flake8]
|
[flake8]
|
||||||
# Allow really long lines for now
|
max-line-length = 105
|
||||||
max-line-length = 140
|
|
||||||
# Set this high for now
|
# Set this high for now
|
||||||
max-complexity = 11
|
max-complexity = 11
|
||||||
exclude = compose/packages
|
exclude = compose/packages
|
||||||
|
|
Loading…
Reference in New Issue