2014-04-25 23:58:21 +02:00
|
|
|
from __future__ import unicode_literals
|
|
|
|
from __future__ import absolute_import
|
2014-08-26 04:16:37 +02:00
|
|
|
|
2014-04-25 23:58:21 +02:00
|
|
|
from .. import unittest
|
2014-08-26 04:16:37 +02:00
|
|
|
import mock
|
|
|
|
|
2014-07-30 22:11:11 +02:00
|
|
|
import docker
|
2015-07-07 13:40:16 +02:00
|
|
|
from docker.utils import LogConfig
|
2014-08-08 18:41:52 +02:00
|
|
|
|
2015-04-26 23:09:20 +02:00
|
|
|
from compose.service import Service
|
2015-01-12 15:59:05 +01:00
|
|
|
from compose.container import Container
|
2015-04-26 23:09:20 +02:00
|
|
|
from compose.const import LABEL_SERVICE, LABEL_PROJECT, LABEL_ONE_OFF
|
2015-01-12 15:59:05 +01:00
|
|
|
from compose.service import (
|
2014-08-26 04:16:37 +02:00
|
|
|
ConfigError,
|
2015-05-12 12:11:36 +02:00
|
|
|
NeedsBuildError,
|
2015-07-06 16:30:27 +02:00
|
|
|
NoSuchImageError,
|
2014-08-26 04:16:37 +02:00
|
|
|
build_volume_binding,
|
2015-05-10 01:38:53 +02:00
|
|
|
get_container_data_volumes,
|
|
|
|
merge_volume_bindings,
|
2014-12-09 01:03:42 +01:00
|
|
|
parse_repository_tag,
|
2015-02-14 20:09:55 +01:00
|
|
|
parse_volume_spec,
|
2014-08-26 04:16:37 +02:00
|
|
|
)
|
|
|
|
|
2014-04-25 23:58:21 +02:00
|
|
|
|
|
|
|
class ServiceTest(unittest.TestCase):
|
2014-08-24 20:55:38 +02:00
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
self.mock_client = mock.create_autospec(docker.Client)
|
|
|
|
|
2014-04-25 23:58:21 +02:00
|
|
|
def test_project_validation(self):
|
2015-07-01 18:56:39 +02:00
|
|
|
self.assertRaises(ConfigError, lambda: Service(name='foo', project='>', image='foo'))
|
|
|
|
|
|
|
|
Service(name='foo', project='bar.bar__', image='foo')
|
2014-04-25 23:58:21 +02:00
|
|
|
|
2015-01-16 14:12:29 +01:00
|
|
|
def test_containers(self):
|
2015-04-26 23:09:20 +02:00
|
|
|
service = Service('db', self.mock_client, 'myproject', image='foo')
|
2015-01-16 14:12:29 +01:00
|
|
|
self.mock_client.containers.return_value = []
|
|
|
|
self.assertEqual(service.containers(), [])
|
|
|
|
|
2015-04-26 23:09:20 +02:00
|
|
|
def test_containers_with_containers(self):
|
2015-01-16 14:12:29 +01:00
|
|
|
self.mock_client.containers.return_value = [
|
2015-04-26 23:09:20 +02:00
|
|
|
dict(Name=str(i), Image='foo', Id=i) for i in range(3)
|
2015-01-16 14:12:29 +01:00
|
|
|
]
|
2015-04-26 23:09:20 +02:00
|
|
|
service = Service('db', self.mock_client, 'myproject', image='foo')
|
|
|
|
self.assertEqual([c.id for c in service.containers()], range(3))
|
2015-01-16 17:43:59 +01:00
|
|
|
|
2015-04-26 23:09:20 +02:00
|
|
|
expected_labels = [
|
|
|
|
'{0}=myproject'.format(LABEL_PROJECT),
|
|
|
|
'{0}=db'.format(LABEL_SERVICE),
|
|
|
|
'{0}=False'.format(LABEL_ONE_OFF),
|
2015-01-16 17:43:59 +01:00
|
|
|
]
|
2015-04-26 23:09:20 +02:00
|
|
|
|
|
|
|
self.mock_client.containers.assert_called_once_with(
|
|
|
|
all=False,
|
|
|
|
filters={'label': expected_labels})
|
2015-01-16 17:43:59 +01:00
|
|
|
|
2015-08-10 17:00:45 +02:00
|
|
|
def test_container_without_name(self):
|
|
|
|
self.mock_client.containers.return_value = [
|
|
|
|
{'Image': 'foo', 'Id': '1', 'Name': '1'},
|
|
|
|
{'Image': 'foo', 'Id': '2', 'Name': None},
|
|
|
|
{'Image': 'foo', 'Id': '3'},
|
|
|
|
]
|
|
|
|
service = Service('db', self.mock_client, 'myproject', image='foo')
|
|
|
|
|
|
|
|
self.assertEqual([c.id for c in service.containers()], ['1'])
|
|
|
|
self.assertEqual(service._next_container_number(), 2)
|
|
|
|
self.assertEqual(service.get_container(1).id, '1')
|
|
|
|
|
2014-08-30 17:33:25 +02:00
|
|
|
def test_get_volumes_from_container(self):
|
|
|
|
container_id = 'aabbccddee'
|
|
|
|
service = Service(
|
|
|
|
'test',
|
2015-04-15 04:03:02 +02:00
|
|
|
image='foo',
|
2014-08-30 17:33:25 +02:00
|
|
|
volumes_from=[mock.Mock(id=container_id, spec=Container)])
|
|
|
|
|
|
|
|
self.assertEqual(service._get_volumes_from(), [container_id])
|
|
|
|
|
|
|
|
def test_get_volumes_from_service_container_exists(self):
|
|
|
|
container_ids = ['aabbccddee', '12345']
|
|
|
|
from_service = mock.create_autospec(Service)
|
|
|
|
from_service.containers.return_value = [
|
|
|
|
mock.Mock(id=container_id, spec=Container)
|
|
|
|
for container_id in container_ids
|
|
|
|
]
|
2015-04-15 04:03:02 +02:00
|
|
|
service = Service('test', volumes_from=[from_service], image='foo')
|
2014-08-30 17:33:25 +02:00
|
|
|
|
|
|
|
self.assertEqual(service._get_volumes_from(), container_ids)
|
|
|
|
|
|
|
|
def test_get_volumes_from_service_no_container(self):
|
|
|
|
container_id = 'abababab'
|
|
|
|
from_service = mock.create_autospec(Service)
|
|
|
|
from_service.containers.return_value = []
|
|
|
|
from_service.create_container.return_value = mock.Mock(
|
|
|
|
id=container_id,
|
|
|
|
spec=Container)
|
2015-04-15 04:03:02 +02:00
|
|
|
service = Service('test', image='foo', volumes_from=[from_service])
|
2014-08-30 17:33:25 +02:00
|
|
|
|
|
|
|
self.assertEqual(service._get_volumes_from(), [container_id])
|
|
|
|
from_service.create_container.assert_called_once_with()
|
|
|
|
|
2014-07-11 00:56:38 +02:00
|
|
|
def test_split_domainname_none(self):
|
2015-04-15 04:03:02 +02:00
|
|
|
service = Service('foo', image='foo', hostname='name', client=self.mock_client)
|
2014-08-24 20:55:38 +02:00
|
|
|
self.mock_client.containers.return_value = []
|
2015-04-26 23:09:20 +02:00
|
|
|
opts = service._get_container_create_options({'image': 'foo'}, 1)
|
2014-07-11 00:56:38 +02:00
|
|
|
self.assertEqual(opts['hostname'], 'name', 'hostname')
|
|
|
|
self.assertFalse('domainname' in opts, 'domainname')
|
2014-06-25 12:49:54 +02:00
|
|
|
|
2015-07-06 18:07:31 +02:00
|
|
|
def test_memory_swap_limit(self):
|
|
|
|
service = Service(name='foo', image='foo', hostname='name', client=self.mock_client, mem_limit=1000000000, memswap_limit=2000000000)
|
|
|
|
self.mock_client.containers.return_value = []
|
|
|
|
opts = service._get_container_create_options({'some': 'overrides'}, 1)
|
2015-08-11 15:17:30 +02:00
|
|
|
self.assertEqual(opts['host_config']['MemorySwap'], 2000000000)
|
|
|
|
self.assertEqual(opts['host_config']['Memory'], 1000000000)
|
2015-07-06 18:07:31 +02:00
|
|
|
|
2015-07-07 13:40:16 +02:00
|
|
|
def test_log_opt(self):
|
|
|
|
log_opt = {'address': 'tcp://192.168.0.42:123'}
|
|
|
|
service = Service(name='foo', image='foo', hostname='name', client=self.mock_client, log_driver='syslog', log_opt=log_opt)
|
|
|
|
self.mock_client.containers.return_value = []
|
|
|
|
opts = service._get_container_create_options({'some': 'overrides'}, 1)
|
|
|
|
|
|
|
|
self.assertIsInstance(opts['host_config']['LogConfig'], LogConfig)
|
|
|
|
self.assertEqual(opts['host_config']['LogConfig'].type, 'syslog')
|
|
|
|
self.assertEqual(opts['host_config']['LogConfig'].config, log_opt)
|
|
|
|
|
2014-07-11 00:56:38 +02:00
|
|
|
def test_split_domainname_fqdn(self):
|
2015-03-26 04:13:01 +01:00
|
|
|
service = Service(
|
|
|
|
'foo',
|
|
|
|
hostname='name.domain.tld',
|
2015-04-15 04:03:02 +02:00
|
|
|
image='foo',
|
2015-03-26 04:13:01 +01:00
|
|
|
client=self.mock_client)
|
2014-08-24 20:55:38 +02:00
|
|
|
self.mock_client.containers.return_value = []
|
2015-04-26 23:09:20 +02:00
|
|
|
opts = service._get_container_create_options({'image': 'foo'}, 1)
|
2014-07-11 00:56:38 +02:00
|
|
|
self.assertEqual(opts['hostname'], 'name', 'hostname')
|
|
|
|
self.assertEqual(opts['domainname'], 'domain.tld', 'domainname')
|
|
|
|
|
|
|
|
def test_split_domainname_both(self):
|
2015-03-26 04:13:01 +01:00
|
|
|
service = Service(
|
|
|
|
'foo',
|
|
|
|
hostname='name',
|
2015-04-15 04:03:02 +02:00
|
|
|
image='foo',
|
2015-03-26 04:13:01 +01:00
|
|
|
domainname='domain.tld',
|
|
|
|
client=self.mock_client)
|
2014-08-24 20:55:38 +02:00
|
|
|
self.mock_client.containers.return_value = []
|
2015-04-26 23:09:20 +02:00
|
|
|
opts = service._get_container_create_options({'image': 'foo'}, 1)
|
2014-07-11 00:56:38 +02:00
|
|
|
self.assertEqual(opts['hostname'], 'name', 'hostname')
|
|
|
|
self.assertEqual(opts['domainname'], 'domain.tld', 'domainname')
|
|
|
|
|
|
|
|
def test_split_domainname_weird(self):
|
2015-03-26 04:13:01 +01:00
|
|
|
service = Service(
|
|
|
|
'foo',
|
|
|
|
hostname='name.sub',
|
|
|
|
domainname='domain.tld',
|
2015-04-15 04:03:02 +02:00
|
|
|
image='foo',
|
2015-03-26 04:13:01 +01:00
|
|
|
client=self.mock_client)
|
2014-08-24 20:55:38 +02:00
|
|
|
self.mock_client.containers.return_value = []
|
2015-04-26 23:09:20 +02:00
|
|
|
opts = service._get_container_create_options({'image': 'foo'}, 1)
|
2014-07-11 00:56:38 +02:00
|
|
|
self.assertEqual(opts['hostname'], 'name.sub', 'hostname')
|
|
|
|
self.assertEqual(opts['domainname'], 'domain.tld', 'domainname')
|
2014-08-26 04:16:37 +02:00
|
|
|
|
2014-08-08 18:41:52 +02:00
|
|
|
def test_get_container_not_found(self):
|
2014-12-11 19:08:39 +01:00
|
|
|
self.mock_client.containers.return_value = []
|
2015-04-15 04:03:02 +02:00
|
|
|
service = Service('foo', client=self.mock_client, image='foo')
|
2014-08-08 18:41:52 +02:00
|
|
|
|
|
|
|
self.assertRaises(ValueError, service.get_container)
|
|
|
|
|
2015-01-12 15:59:05 +01:00
|
|
|
@mock.patch('compose.service.Container', autospec=True)
|
2014-08-08 18:41:52 +02:00
|
|
|
def test_get_container(self, mock_container_class):
|
|
|
|
container_dict = dict(Name='default_foo_2')
|
2014-12-11 19:08:39 +01:00
|
|
|
self.mock_client.containers.return_value = [container_dict]
|
2015-04-15 04:03:02 +02:00
|
|
|
service = Service('foo', image='foo', client=self.mock_client)
|
2014-08-08 18:41:52 +02:00
|
|
|
|
|
|
|
container = service.get_container(number=2)
|
|
|
|
self.assertEqual(container, mock_container_class.from_ps.return_value)
|
|
|
|
mock_container_class.from_ps.assert_called_once_with(
|
2014-12-11 19:08:39 +01:00
|
|
|
self.mock_client, container_dict)
|
2014-08-08 18:41:52 +02:00
|
|
|
|
2015-01-12 15:59:05 +01:00
|
|
|
@mock.patch('compose.service.log', autospec=True)
|
2014-10-01 17:09:19 +02:00
|
|
|
def test_pull_image(self, mock_log):
|
|
|
|
service = Service('foo', client=self.mock_client, image='someimage:sometag')
|
2015-07-20 18:13:09 +02:00
|
|
|
service.pull()
|
2015-04-24 17:11:01 +02:00
|
|
|
self.mock_client.pull.assert_called_once_with(
|
|
|
|
'someimage',
|
|
|
|
tag='sometag',
|
|
|
|
stream=True)
|
2014-10-01 17:09:19 +02:00
|
|
|
mock_log.info.assert_called_once_with('Pulling foo (someimage:sometag)...')
|
|
|
|
|
2015-04-24 17:11:01 +02:00
|
|
|
def test_pull_image_no_tag(self):
|
|
|
|
service = Service('foo', client=self.mock_client, image='ababab')
|
|
|
|
service.pull()
|
|
|
|
self.mock_client.pull.assert_called_once_with(
|
|
|
|
'ababab',
|
|
|
|
tag='latest',
|
|
|
|
stream=True)
|
|
|
|
|
2015-08-18 22:46:05 +02:00
|
|
|
@mock.patch('compose.service.log', autospec=True)
|
|
|
|
def test_pull_image_digest(self, mock_log):
|
|
|
|
service = Service('foo', client=self.mock_client, image='someimage@sha256:1234')
|
|
|
|
service.pull()
|
|
|
|
self.mock_client.pull.assert_called_once_with(
|
|
|
|
'someimage',
|
|
|
|
tag='sha256:1234',
|
|
|
|
stream=True)
|
|
|
|
mock_log.info.assert_called_once_with('Pulling foo (someimage@sha256:1234)...')
|
|
|
|
|
2015-04-24 20:05:17 +02:00
|
|
|
@mock.patch('compose.service.Container', autospec=True)
|
|
|
|
def test_recreate_container(self, _):
|
|
|
|
mock_container = mock.create_autospec(Container)
|
|
|
|
service = Service('foo', client=self.mock_client, image='someimage')
|
2015-05-12 12:11:36 +02:00
|
|
|
service.image = lambda: {'Id': 'abc123'}
|
2015-04-24 20:05:17 +02:00
|
|
|
new_container = service.recreate_container(mock_container)
|
|
|
|
|
2015-06-14 23:11:29 +02:00
|
|
|
mock_container.stop.assert_called_once_with(timeout=10)
|
2015-04-24 20:05:17 +02:00
|
|
|
self.mock_client.rename.assert_called_once_with(
|
|
|
|
mock_container.id,
|
|
|
|
'%s_%s' % (mock_container.short_id, mock_container.name))
|
|
|
|
|
|
|
|
new_container.start.assert_called_once_with()
|
|
|
|
mock_container.remove.assert_called_once_with()
|
|
|
|
|
2015-05-28 15:28:02 +02:00
|
|
|
@mock.patch('compose.service.Container', autospec=True)
|
|
|
|
def test_recreate_container_with_timeout(self, _):
|
|
|
|
mock_container = mock.create_autospec(Container)
|
|
|
|
self.mock_client.inspect_image.return_value = {'Id': 'abc123'}
|
|
|
|
service = Service('foo', client=self.mock_client, image='someimage')
|
|
|
|
service.recreate_container(mock_container, timeout=1)
|
|
|
|
|
|
|
|
mock_container.stop.assert_called_once_with(timeout=1)
|
|
|
|
|
2014-12-09 01:03:42 +01:00
|
|
|
def test_parse_repository_tag(self):
|
2015-08-18 22:46:05 +02:00
|
|
|
self.assertEqual(parse_repository_tag("root"), ("root", "", ":"))
|
|
|
|
self.assertEqual(parse_repository_tag("root:tag"), ("root", "tag", ":"))
|
|
|
|
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("url:5000/repo"), ("url:5000/repo", "", ":"))
|
|
|
|
self.assertEqual(parse_repository_tag("url:5000/repo:tag"), ("url:5000/repo", "tag", ":"))
|
|
|
|
|
|
|
|
self.assertEqual(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", "@"))
|
2014-12-09 01:03:42 +01:00
|
|
|
|
2015-04-24 17:11:01 +02:00
|
|
|
@mock.patch('compose.service.Container', autospec=True)
|
|
|
|
def test_create_container_latest_is_used_when_no_tag_specified(self, mock_container):
|
2014-12-09 01:03:42 +01:00
|
|
|
service = Service('foo', client=self.mock_client, image='someimage')
|
2015-05-12 12:11:36 +02:00
|
|
|
images = []
|
|
|
|
|
|
|
|
def pull(repo, tag=None, **kwargs):
|
|
|
|
self.assertEqual('someimage', repo)
|
|
|
|
self.assertEqual('latest', tag)
|
|
|
|
images.append({'Id': 'abc123'})
|
|
|
|
return []
|
|
|
|
|
2015-07-06 16:30:27 +02:00
|
|
|
service.image = lambda *args, **kwargs: mock_get_image(images)
|
2015-05-12 12:11:36 +02:00
|
|
|
self.mock_client.pull = pull
|
|
|
|
|
|
|
|
service.create_container()
|
|
|
|
self.assertEqual(1, len(images))
|
2014-12-09 01:03:42 +01:00
|
|
|
|
2014-10-26 18:23:15 +01:00
|
|
|
def test_create_container_with_build(self):
|
|
|
|
service = Service('foo', client=self.mock_client, build='.')
|
|
|
|
|
2015-05-12 12:11:36 +02:00
|
|
|
images = []
|
2015-07-06 16:30:27 +02:00
|
|
|
service.image = lambda *args, **kwargs: mock_get_image(images)
|
2015-05-12 12:11:36 +02:00
|
|
|
service.build = lambda: images.append({'Id': 'abc123'})
|
|
|
|
|
|
|
|
service.create_container(do_build=True)
|
|
|
|
self.assertEqual(1, len(images))
|
2014-10-26 18:23:15 +01:00
|
|
|
|
|
|
|
def test_create_container_no_build(self):
|
|
|
|
service = Service('foo', client=self.mock_client, build='.')
|
2015-05-12 12:11:36 +02:00
|
|
|
service.image = lambda: {'Id': 'abc123'}
|
2014-10-26 18:23:15 +01:00
|
|
|
|
2015-05-12 12:11:36 +02:00
|
|
|
service.create_container(do_build=False)
|
2014-10-26 18:23:15 +01:00
|
|
|
self.assertFalse(self.mock_client.build.called)
|
|
|
|
|
2015-05-12 12:11:36 +02:00
|
|
|
def test_create_container_no_build_but_needs_build(self):
|
|
|
|
service = Service('foo', client=self.mock_client, build='.')
|
2015-07-06 16:30:27 +02:00
|
|
|
service.image = lambda *args, **kwargs: mock_get_image([])
|
2015-05-12 12:11:36 +02:00
|
|
|
|
|
|
|
with self.assertRaises(NeedsBuildError):
|
|
|
|
service.create_container(do_build=False)
|
|
|
|
|
2015-06-19 02:43:16 +02:00
|
|
|
def test_build_does_not_pull(self):
|
|
|
|
self.mock_client.build.return_value = [
|
|
|
|
'{"stream": "Successfully built 12345"}',
|
|
|
|
]
|
|
|
|
|
|
|
|
service = Service('foo', client=self.mock_client, build='.')
|
|
|
|
service.build()
|
|
|
|
|
|
|
|
self.assertEqual(self.mock_client.build.call_count, 1)
|
|
|
|
self.assertFalse(self.mock_client.build.call_args[1]['pull'])
|
|
|
|
|
2014-08-26 04:16:37 +02:00
|
|
|
|
2015-07-06 16:30:27 +02:00
|
|
|
def mock_get_image(images):
|
|
|
|
if images:
|
|
|
|
return images[0]
|
|
|
|
else:
|
|
|
|
raise NoSuchImageError()
|
|
|
|
|
|
|
|
|
2014-08-26 04:16:37 +02:00
|
|
|
class ServiceVolumesTest(unittest.TestCase):
|
|
|
|
|
2015-05-10 01:38:53 +02:00
|
|
|
def setUp(self):
|
|
|
|
self.mock_client = mock.create_autospec(docker.Client)
|
|
|
|
|
2014-08-26 04:16:37 +02:00
|
|
|
def test_parse_volume_spec_only_one_path(self):
|
|
|
|
spec = parse_volume_spec('/the/volume')
|
|
|
|
self.assertEqual(spec, (None, '/the/volume', 'rw'))
|
|
|
|
|
|
|
|
def test_parse_volume_spec_internal_and_external(self):
|
|
|
|
spec = parse_volume_spec('external:interval')
|
|
|
|
self.assertEqual(spec, ('external', 'interval', 'rw'))
|
|
|
|
|
|
|
|
def test_parse_volume_spec_with_mode(self):
|
|
|
|
spec = parse_volume_spec('external:interval:ro')
|
|
|
|
self.assertEqual(spec, ('external', 'interval', 'ro'))
|
|
|
|
|
2015-06-05 10:57:00 +02:00
|
|
|
spec = parse_volume_spec('external:interval:z')
|
|
|
|
self.assertEqual(spec, ('external', 'interval', 'z'))
|
|
|
|
|
2014-08-26 04:16:37 +02:00
|
|
|
def test_parse_volume_spec_too_many_parts(self):
|
|
|
|
with self.assertRaises(ConfigError):
|
|
|
|
parse_volume_spec('one:two:three:four')
|
|
|
|
|
|
|
|
def test_build_volume_binding(self):
|
|
|
|
binding = build_volume_binding(parse_volume_spec('/outside:/inside'))
|
2015-06-12 19:51:55 +02:00
|
|
|
self.assertEqual(binding, ('/inside', '/outside:/inside:rw'))
|
2015-05-10 01:38:53 +02:00
|
|
|
|
|
|
|
def test_get_container_data_volumes(self):
|
|
|
|
options = [
|
|
|
|
'/host/volume:/host/volume:ro',
|
|
|
|
'/new/volume',
|
|
|
|
'/existing/volume',
|
|
|
|
]
|
|
|
|
|
|
|
|
self.mock_client.inspect_image.return_value = {
|
|
|
|
'ContainerConfig': {
|
|
|
|
'Volumes': {
|
|
|
|
'/mnt/image/data': {},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
container = Container(self.mock_client, {
|
|
|
|
'Image': 'ababab',
|
|
|
|
'Volumes': {
|
|
|
|
'/host/volume': '/host/volume',
|
|
|
|
'/existing/volume': '/var/lib/docker/aaaaaaaa',
|
|
|
|
'/removed/volume': '/var/lib/docker/bbbbbbbb',
|
|
|
|
'/mnt/image/data': '/var/lib/docker/cccccccc',
|
|
|
|
},
|
|
|
|
}, has_been_inspected=True)
|
|
|
|
|
|
|
|
expected = {
|
2015-06-12 19:51:55 +02:00
|
|
|
'/existing/volume': '/var/lib/docker/aaaaaaaa:/existing/volume:rw',
|
|
|
|
'/mnt/image/data': '/var/lib/docker/cccccccc:/mnt/image/data:rw',
|
2015-05-10 01:38:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
binds = get_container_data_volumes(container, options)
|
|
|
|
self.assertEqual(binds, expected)
|
|
|
|
|
|
|
|
def test_merge_volume_bindings(self):
|
|
|
|
options = [
|
|
|
|
'/host/volume:/host/volume:ro',
|
|
|
|
'/host/rw/volume:/host/rw/volume',
|
|
|
|
'/new/volume',
|
|
|
|
'/existing/volume',
|
|
|
|
]
|
|
|
|
|
|
|
|
self.mock_client.inspect_image.return_value = {
|
|
|
|
'ContainerConfig': {'Volumes': {}}
|
|
|
|
}
|
|
|
|
|
|
|
|
intermediate_container = Container(self.mock_client, {
|
|
|
|
'Image': 'ababab',
|
|
|
|
'Volumes': {'/existing/volume': '/var/lib/docker/aaaaaaaa'},
|
|
|
|
}, has_been_inspected=True)
|
|
|
|
|
2015-06-12 19:51:55 +02:00
|
|
|
expected = [
|
|
|
|
'/host/volume:/host/volume:ro',
|
|
|
|
'/host/rw/volume:/host/rw/volume:rw',
|
|
|
|
'/var/lib/docker/aaaaaaaa:/existing/volume:rw',
|
|
|
|
]
|
2015-05-10 01:38:53 +02:00
|
|
|
|
|
|
|
binds = merge_volume_bindings(options, intermediate_container)
|
2015-06-12 19:51:55 +02:00
|
|
|
self.assertEqual(set(binds), set(expected))
|
|
|
|
|
|
|
|
def test_mount_same_host_path_to_two_volumes(self):
|
|
|
|
service = Service(
|
|
|
|
'web',
|
|
|
|
image='busybox',
|
|
|
|
volumes=[
|
|
|
|
'/host/path:/data1',
|
|
|
|
'/host/path:/data2',
|
|
|
|
],
|
|
|
|
client=self.mock_client,
|
|
|
|
)
|
|
|
|
|
|
|
|
self.mock_client.inspect_image.return_value = {
|
|
|
|
'Id': 'ababab',
|
|
|
|
'ContainerConfig': {
|
|
|
|
'Volumes': {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
create_options = service._get_container_create_options(
|
|
|
|
override_options={},
|
|
|
|
number=1,
|
|
|
|
)
|
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
set(create_options['host_config']['Binds']),
|
|
|
|
set([
|
|
|
|
'/host/path:/data1:rw',
|
|
|
|
'/host/path:/data2:rw',
|
|
|
|
]),
|
|
|
|
)
|
|
|
|
|
|
|
|
def test_different_host_path_in_container_json(self):
|
|
|
|
service = Service(
|
|
|
|
'web',
|
|
|
|
image='busybox',
|
|
|
|
volumes=['/host/path:/data'],
|
|
|
|
client=self.mock_client,
|
|
|
|
)
|
|
|
|
|
|
|
|
self.mock_client.inspect_image.return_value = {
|
|
|
|
'Id': 'ababab',
|
|
|
|
'ContainerConfig': {
|
|
|
|
'Volumes': {
|
|
|
|
'/data': {},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
self.mock_client.inspect_container.return_value = {
|
|
|
|
'Id': '123123123',
|
|
|
|
'Image': 'ababab',
|
|
|
|
'Volumes': {
|
|
|
|
'/data': '/mnt/sda1/host/path',
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
create_options = service._get_container_create_options(
|
|
|
|
override_options={},
|
|
|
|
number=1,
|
|
|
|
previous_container=Container(self.mock_client, {'Id': '123123123'}),
|
|
|
|
)
|
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
create_options['host_config']['Binds'],
|
|
|
|
['/mnt/sda1/host/path:/data:rw'],
|
|
|
|
)
|
2015-06-05 10:57:00 +02:00
|
|
|
|
|
|
|
def test_create_with_special_volume_mode(self):
|
|
|
|
self.mock_client.inspect_image.return_value = {'Id': 'imageid'}
|
|
|
|
|
|
|
|
create_calls = []
|
|
|
|
|
|
|
|
def create_container(*args, **kwargs):
|
|
|
|
create_calls.append((args, kwargs))
|
|
|
|
return {'Id': 'containerid'}
|
|
|
|
|
|
|
|
self.mock_client.create_container = create_container
|
|
|
|
|
|
|
|
volumes = ['/tmp:/foo:z']
|
|
|
|
|
|
|
|
Service(
|
|
|
|
'web',
|
|
|
|
client=self.mock_client,
|
|
|
|
image='busybox',
|
|
|
|
volumes=volumes,
|
|
|
|
).create_container()
|
|
|
|
|
|
|
|
self.assertEqual(len(create_calls), 1)
|
|
|
|
self.assertEqual(create_calls[0][1]['host_config']['Binds'], volumes)
|