Use individual volumes for recreate instead of volumes_from

Signed-off-by: Daniel Nephin <dnephin@gmail.com>
This commit is contained in:
Daniel Nephin 2015-05-09 19:38:53 -04:00
commit 417d9c2d51
5 changed files with 152 additions and 40 deletions

View file

@ -107,7 +107,7 @@ class ServiceTest(DockerClientTestCase):
service = self.create_service('db', volumes=['/var/db'])
container = service.create_container()
service.start_container(container)
self.assertIn('/var/db', container.inspect()['Volumes'])
self.assertIn('/var/db', container.get('Volumes'))
def test_create_container_with_cpu_shares(self):
service = self.create_service('db', cpu_shares=73)
@ -239,24 +239,27 @@ class ServiceTest(DockerClientTestCase):
command=['300']
)
old_container = service.create_container()
self.assertEqual(old_container.dictionary['Config']['Entrypoint'], ['sleep'])
self.assertEqual(old_container.dictionary['Config']['Cmd'], ['300'])
self.assertIn('FOO=1', old_container.dictionary['Config']['Env'])
self.assertEqual(old_container.get('Config.Entrypoint'), ['sleep'])
self.assertEqual(old_container.get('Config.Cmd'), ['300'])
self.assertIn('FOO=1', old_container.get('Config.Env'))
self.assertEqual(old_container.name, 'composetest_db_1')
service.start_container(old_container)
volume_path = old_container.inspect()['Volumes']['/etc']
old_container.inspect() # reload volume data
volume_path = old_container.get('Volumes')['/etc']
num_containers_before = len(self.client.containers(all=True))
service.options['environment']['FOO'] = '2'
new_container, = service.recreate_containers()
self.assertEqual(new_container.dictionary['Config']['Entrypoint'], ['sleep'])
self.assertEqual(new_container.dictionary['Config']['Cmd'], ['300'])
self.assertIn('FOO=2', new_container.dictionary['Config']['Env'])
self.assertEqual(new_container.get('Config.Entrypoint'), ['sleep'])
self.assertEqual(new_container.get('Config.Cmd'), ['300'])
self.assertIn('FOO=2', new_container.get('Config.Env'))
self.assertEqual(new_container.name, 'composetest_db_1')
self.assertEqual(new_container.inspect()['Volumes']['/etc'], volume_path)
self.assertIn(old_container.id, new_container.dictionary['HostConfig']['VolumesFrom'])
self.assertEqual(new_container.get('Volumes')['/etc'], volume_path)
self.assertIn(
'affinity:container==%s' % old_container.id,
new_container.get('Config.Env'))
self.assertEqual(len(self.client.containers(all=True)), num_containers_before)
self.assertNotEqual(old_container.id, new_container.id)
@ -289,9 +292,7 @@ class ServiceTest(DockerClientTestCase):
self.assertEqual(old_container.get('Volumes').keys(), ['/data'])
volume_path = old_container.get('Volumes')['/data']
service.recreate_containers()
new_container = service.containers()[0]
service.start_container(new_container)
new_container = service.recreate_containers()[0]
self.assertEqual(new_container.get('Volumes').keys(), ['/data'])
self.assertEqual(new_container.get('Volumes')['/data'], volume_path)

View file

@ -14,7 +14,9 @@ from compose.service import (
ConfigError,
build_port_bindings,
build_volume_binding,
get_container_data_volumes,
get_container_name,
merge_volume_bindings,
parse_repository_tag,
parse_volume_spec,
split_port,
@ -86,13 +88,6 @@ class ServiceTest(unittest.TestCase):
self.assertEqual(service._get_volumes_from(), [container_id])
def test_get_volumes_from_previous_container(self):
container_id = 'aabbccddee'
service = Service('test', image='foo')
container = mock.Mock(id=container_id, spec=Container, image='foo')
self.assertEqual(service._get_volumes_from(container), [container_id])
def test_get_volumes_from_service_container_exists(self):
container_ids = ['aabbccddee', '12345']
from_service = mock.create_autospec(Service)
@ -320,6 +315,9 @@ class ServiceTest(unittest.TestCase):
class ServiceVolumesTest(unittest.TestCase):
def setUp(self):
self.mock_client = mock.create_autospec(docker.Client)
def test_parse_volume_spec_only_one_path(self):
spec = parse_volume_spec('/the/volume')
self.assertEqual(spec, (None, '/the/volume', 'rw'))
@ -345,3 +343,61 @@ class ServiceVolumesTest(unittest.TestCase):
self.assertEqual(
binding,
('/outside', dict(bind='/inside', ro=False)))
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 = {
'/var/lib/docker/aaaaaaaa': {'bind': '/existing/volume', 'ro': False},
'/var/lib/docker/cccccccc': {'bind': '/mnt/image/data', 'ro': False},
}
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)
expected = {
'/host/volume': {'bind': '/host/volume', 'ro': True},
'/host/rw/volume': {'bind': '/host/rw/volume', 'ro': False},
'/var/lib/docker/aaaaaaaa': {'bind': '/existing/volume', 'ro': False},
}
binds = merge_volume_bindings(options, intermediate_container)
self.assertEqual(binds, expected)