Merge pull request #2405 from dnephin/move_all_validation_to_config
Move all validation to config
This commit is contained in:
commit
cfb1b37da2
21 changed files with 477 additions and 497 deletions
|
|
@ -124,7 +124,7 @@ class CLITestCase(unittest.TestCase):
|
|||
mock_project.get_service.return_value = Service(
|
||||
'service',
|
||||
client=mock_client,
|
||||
restart='always',
|
||||
restart={'Name': 'always', 'MaximumRetryCount': 0},
|
||||
image='someimage')
|
||||
command.run(mock_project, {
|
||||
'SERVICE': 'service',
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import pytest
|
|||
|
||||
from compose.config import config
|
||||
from compose.config.errors import ConfigurationError
|
||||
from compose.config.types import VolumeSpec
|
||||
from compose.const import IS_WINDOWS_PLATFORM
|
||||
from tests import mock
|
||||
from tests import unittest
|
||||
|
|
@ -32,7 +33,7 @@ def service_sort(services):
|
|||
return sorted(services, key=itemgetter('name'))
|
||||
|
||||
|
||||
def build_config_details(contents, working_dir, filename):
|
||||
def build_config_details(contents, working_dir='working_dir', filename='filename.yml'):
|
||||
return config.ConfigDetails(
|
||||
working_dir,
|
||||
[config.ConfigFile(filename, contents)])
|
||||
|
|
@ -76,7 +77,7 @@ class ConfigTest(unittest.TestCase):
|
|||
)
|
||||
)
|
||||
|
||||
def test_config_invalid_service_names(self):
|
||||
def test_load_config_invalid_service_names(self):
|
||||
for invalid_name in ['?not?allowed', ' ', '', '!', '/', '\xe2']:
|
||||
with pytest.raises(ConfigurationError) as exc:
|
||||
config.load(build_config_details(
|
||||
|
|
@ -147,7 +148,7 @@ class ConfigTest(unittest.TestCase):
|
|||
'name': 'web',
|
||||
'build': '/',
|
||||
'links': ['db'],
|
||||
'volumes': ['/home/user/project:/code'],
|
||||
'volumes': [VolumeSpec.parse('/home/user/project:/code')],
|
||||
},
|
||||
{
|
||||
'name': 'db',
|
||||
|
|
@ -211,7 +212,7 @@ class ConfigTest(unittest.TestCase):
|
|||
{
|
||||
'name': 'web',
|
||||
'image': 'example/web',
|
||||
'volumes': ['/home/user/project:/code'],
|
||||
'volumes': [VolumeSpec.parse('/home/user/project:/code')],
|
||||
'labels': {'label': 'one'},
|
||||
},
|
||||
]
|
||||
|
|
@ -231,6 +232,27 @@ class ConfigTest(unittest.TestCase):
|
|||
assert "service 'bogus' doesn't have any configuration" in exc.exconly()
|
||||
assert "In file 'override.yaml'" in exc.exconly()
|
||||
|
||||
def test_load_sorts_in_dependency_order(self):
|
||||
config_details = build_config_details({
|
||||
'web': {
|
||||
'image': 'busybox:latest',
|
||||
'links': ['db'],
|
||||
},
|
||||
'db': {
|
||||
'image': 'busybox:latest',
|
||||
'volumes_from': ['volume:ro']
|
||||
},
|
||||
'volume': {
|
||||
'image': 'busybox:latest',
|
||||
'volumes': ['/tmp'],
|
||||
}
|
||||
})
|
||||
services = config.load(config_details)
|
||||
|
||||
assert services[0]['name'] == 'volume'
|
||||
assert services[1]['name'] == 'db'
|
||||
assert services[2]['name'] == 'web'
|
||||
|
||||
def test_config_valid_service_names(self):
|
||||
for valid_name in ['_', '-', '.__.', '_what-up.', 'what_.up----', 'whatup']:
|
||||
services = config.load(
|
||||
|
|
@ -512,6 +534,29 @@ class ConfigTest(unittest.TestCase):
|
|||
|
||||
assert 'line 3, column 32' in exc.exconly()
|
||||
|
||||
def test_validate_extra_hosts_invalid(self):
|
||||
with pytest.raises(ConfigurationError) as exc:
|
||||
config.load(build_config_details({
|
||||
'web': {
|
||||
'image': 'alpine',
|
||||
'extra_hosts': "www.example.com: 192.168.0.17",
|
||||
}
|
||||
}))
|
||||
assert "'extra_hosts' contains an invalid type" in exc.exconly()
|
||||
|
||||
def test_validate_extra_hosts_invalid_list(self):
|
||||
with pytest.raises(ConfigurationError) as exc:
|
||||
config.load(build_config_details({
|
||||
'web': {
|
||||
'image': 'alpine',
|
||||
'extra_hosts': [
|
||||
{'www.example.com': '192.168.0.17'},
|
||||
{'api.example.com': '192.168.0.18'}
|
||||
],
|
||||
}
|
||||
}))
|
||||
assert "which is an invalid type" in exc.exconly()
|
||||
|
||||
|
||||
class InterpolationTest(unittest.TestCase):
|
||||
@mock.patch.dict(os.environ)
|
||||
|
|
@ -603,14 +648,11 @@ class VolumeConfigTest(unittest.TestCase):
|
|||
@mock.patch.dict(os.environ)
|
||||
def test_volume_binding_with_environment_variable(self):
|
||||
os.environ['VOLUME_PATH'] = '/host/path'
|
||||
d = config.load(
|
||||
build_config_details(
|
||||
{'foo': {'build': '.', 'volumes': ['${VOLUME_PATH}:/container/path']}},
|
||||
'.',
|
||||
None,
|
||||
)
|
||||
)[0]
|
||||
self.assertEqual(d['volumes'], ['/host/path:/container/path'])
|
||||
d = config.load(build_config_details(
|
||||
{'foo': {'build': '.', 'volumes': ['${VOLUME_PATH}:/container/path']}},
|
||||
'.',
|
||||
))[0]
|
||||
self.assertEqual(d['volumes'], [VolumeSpec.parse('/host/path:/container/path')])
|
||||
|
||||
@pytest.mark.skipif(IS_WINDOWS_PLATFORM, reason='posix paths')
|
||||
@mock.patch.dict(os.environ)
|
||||
|
|
@ -1008,19 +1050,21 @@ class EnvTest(unittest.TestCase):
|
|||
build_config_details(
|
||||
{'foo': {'build': '.', 'volumes': ['$HOSTENV:$CONTAINERENV']}},
|
||||
"tests/fixtures/env",
|
||||
None,
|
||||
)
|
||||
)[0]
|
||||
self.assertEqual(set(service_dict['volumes']), set(['/tmp:/host/tmp']))
|
||||
self.assertEqual(
|
||||
set(service_dict['volumes']),
|
||||
set([VolumeSpec.parse('/tmp:/host/tmp')]))
|
||||
|
||||
service_dict = config.load(
|
||||
build_config_details(
|
||||
{'foo': {'build': '.', 'volumes': ['/opt${HOSTENV}:/opt${CONTAINERENV}']}},
|
||||
"tests/fixtures/env",
|
||||
None,
|
||||
)
|
||||
)[0]
|
||||
self.assertEqual(set(service_dict['volumes']), set(['/opt/tmp:/opt/host/tmp']))
|
||||
self.assertEqual(
|
||||
set(service_dict['volumes']),
|
||||
set([VolumeSpec.parse('/opt/tmp:/opt/host/tmp')]))
|
||||
|
||||
|
||||
def load_from_filename(filename):
|
||||
|
|
@ -1267,8 +1311,14 @@ class ExtendsTest(unittest.TestCase):
|
|||
dicts = load_from_filename('tests/fixtures/volume-path/docker-compose.yml')
|
||||
|
||||
paths = [
|
||||
'%s:/foo' % os.path.abspath('tests/fixtures/volume-path/common/foo'),
|
||||
'%s:/bar' % os.path.abspath('tests/fixtures/volume-path/bar'),
|
||||
VolumeSpec(
|
||||
os.path.abspath('tests/fixtures/volume-path/common/foo'),
|
||||
'/foo',
|
||||
'rw'),
|
||||
VolumeSpec(
|
||||
os.path.abspath('tests/fixtures/volume-path/bar'),
|
||||
'/bar',
|
||||
'rw')
|
||||
]
|
||||
|
||||
self.assertEqual(set(dicts[0]['volumes']), set(paths))
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
from .. import unittest
|
||||
from compose.project import DependencyError
|
||||
from compose.project import sort_service_dicts
|
||||
from compose.config.errors import DependencyError
|
||||
from compose.config.sort_services import sort_service_dicts
|
||||
from compose.config.types import VolumeFromSpec
|
||||
from tests import unittest
|
||||
|
||||
|
||||
class SortServiceTest(unittest.TestCase):
|
||||
|
|
@ -73,7 +74,7 @@ class SortServiceTest(unittest.TestCase):
|
|||
},
|
||||
{
|
||||
'name': 'parent',
|
||||
'volumes_from': ['child']
|
||||
'volumes_from': [VolumeFromSpec('child', 'rw')]
|
||||
},
|
||||
{
|
||||
'links': ['parent'],
|
||||
|
|
@ -116,7 +117,7 @@ class SortServiceTest(unittest.TestCase):
|
|||
},
|
||||
{
|
||||
'name': 'parent',
|
||||
'volumes_from': ['child']
|
||||
'volumes_from': [VolumeFromSpec('child', 'ro')]
|
||||
},
|
||||
{
|
||||
'name': 'child'
|
||||
|
|
@ -141,7 +142,7 @@ class SortServiceTest(unittest.TestCase):
|
|||
},
|
||||
{
|
||||
'name': 'two',
|
||||
'volumes_from': ['one']
|
||||
'volumes_from': [VolumeFromSpec('one', 'rw')]
|
||||
},
|
||||
{
|
||||
'name': 'one'
|
||||
66
tests/unit/config/types_test.py
Normal file
66
tests/unit/config/types_test.py
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
import pytest
|
||||
|
||||
from compose.config.errors import ConfigurationError
|
||||
from compose.config.types import parse_extra_hosts
|
||||
from compose.config.types import VolumeSpec
|
||||
from compose.const import IS_WINDOWS_PLATFORM
|
||||
|
||||
|
||||
def test_parse_extra_hosts_list():
|
||||
expected = {'www.example.com': '192.168.0.17'}
|
||||
assert parse_extra_hosts(["www.example.com:192.168.0.17"]) == expected
|
||||
|
||||
expected = {'www.example.com': '192.168.0.17'}
|
||||
assert parse_extra_hosts(["www.example.com: 192.168.0.17"]) == expected
|
||||
|
||||
assert parse_extra_hosts([
|
||||
"www.example.com: 192.168.0.17",
|
||||
"static.example.com:192.168.0.19",
|
||||
"api.example.com: 192.168.0.18"
|
||||
]) == {
|
||||
'www.example.com': '192.168.0.17',
|
||||
'static.example.com': '192.168.0.19',
|
||||
'api.example.com': '192.168.0.18'
|
||||
}
|
||||
|
||||
|
||||
def test_parse_extra_hosts_dict():
|
||||
assert parse_extra_hosts({
|
||||
'www.example.com': '192.168.0.17',
|
||||
'api.example.com': '192.168.0.18'
|
||||
}) == {
|
||||
'www.example.com': '192.168.0.17',
|
||||
'api.example.com': '192.168.0.18'
|
||||
}
|
||||
|
||||
|
||||
class TestVolumeSpec(object):
|
||||
|
||||
def test_parse_volume_spec_only_one_path(self):
|
||||
spec = VolumeSpec.parse('/the/volume')
|
||||
assert spec == (None, '/the/volume', 'rw')
|
||||
|
||||
def test_parse_volume_spec_internal_and_external(self):
|
||||
spec = VolumeSpec.parse('external:interval')
|
||||
assert spec == ('external', 'interval', 'rw')
|
||||
|
||||
def test_parse_volume_spec_with_mode(self):
|
||||
spec = VolumeSpec.parse('external:interval:ro')
|
||||
assert spec == ('external', 'interval', 'ro')
|
||||
|
||||
spec = VolumeSpec.parse('external:interval:z')
|
||||
assert spec == ('external', 'interval', 'z')
|
||||
|
||||
def test_parse_volume_spec_too_many_parts(self):
|
||||
with pytest.raises(ConfigurationError) as exc:
|
||||
VolumeSpec.parse('one:two:three:four')
|
||||
assert 'has incorrect format' in exc.exconly()
|
||||
|
||||
@pytest.mark.xfail((not IS_WINDOWS_PLATFORM), reason='does not have a drive')
|
||||
def test_parse_volume_windows_absolute_path(self):
|
||||
windows_path = "c:\\Users\\me\\Documents\\shiny\\config:\\opt\\shiny\\config:ro"
|
||||
assert VolumeSpec.parse(windows_path) == (
|
||||
"/c/Users/me/Documents/shiny/config",
|
||||
"/opt/shiny/config",
|
||||
"ro"
|
||||
)
|
||||
|
|
@ -4,6 +4,7 @@ import docker
|
|||
|
||||
from .. import mock
|
||||
from .. import unittest
|
||||
from compose.config.types import VolumeFromSpec
|
||||
from compose.const import LABEL_SERVICE
|
||||
from compose.container import Container
|
||||
from compose.project import Project
|
||||
|
|
@ -33,29 +34,6 @@ class ProjectTest(unittest.TestCase):
|
|||
self.assertEqual(project.get_service('db').name, 'db')
|
||||
self.assertEqual(project.get_service('db').options['image'], 'busybox:latest')
|
||||
|
||||
def test_from_dict_sorts_in_dependency_order(self):
|
||||
project = Project.from_dicts('composetest', [
|
||||
{
|
||||
'name': 'web',
|
||||
'image': 'busybox:latest',
|
||||
'links': ['db'],
|
||||
},
|
||||
{
|
||||
'name': 'db',
|
||||
'image': 'busybox:latest',
|
||||
'volumes_from': ['volume']
|
||||
},
|
||||
{
|
||||
'name': 'volume',
|
||||
'image': 'busybox:latest',
|
||||
'volumes': ['/tmp'],
|
||||
}
|
||||
], None)
|
||||
|
||||
self.assertEqual(project.services[0].name, 'volume')
|
||||
self.assertEqual(project.services[1].name, 'db')
|
||||
self.assertEqual(project.services[2].name, 'web')
|
||||
|
||||
def test_from_config(self):
|
||||
dicts = [
|
||||
{
|
||||
|
|
@ -167,7 +145,7 @@ class ProjectTest(unittest.TestCase):
|
|||
{
|
||||
'name': 'test',
|
||||
'image': 'busybox:latest',
|
||||
'volumes_from': ['aaa']
|
||||
'volumes_from': [VolumeFromSpec('aaa', 'rw')]
|
||||
}
|
||||
], self.mock_client)
|
||||
self.assertEqual(project.get_service('test')._get_volumes_from(), [container_id + ":rw"])
|
||||
|
|
@ -190,17 +168,13 @@ class ProjectTest(unittest.TestCase):
|
|||
{
|
||||
'name': 'test',
|
||||
'image': 'busybox:latest',
|
||||
'volumes_from': ['vol']
|
||||
'volumes_from': [VolumeFromSpec('vol', 'rw')]
|
||||
}
|
||||
], self.mock_client)
|
||||
self.assertEqual(project.get_service('test')._get_volumes_from(), [container_name + ":rw"])
|
||||
|
||||
@mock.patch.object(Service, 'containers')
|
||||
def test_use_volumes_from_service_container(self, mock_return):
|
||||
def test_use_volumes_from_service_container(self):
|
||||
container_ids = ['aabbccddee', '12345']
|
||||
mock_return.return_value = [
|
||||
mock.Mock(id=container_id, spec=Container)
|
||||
for container_id in container_ids]
|
||||
|
||||
project = Project.from_dicts('test', [
|
||||
{
|
||||
|
|
@ -210,10 +184,16 @@ class ProjectTest(unittest.TestCase):
|
|||
{
|
||||
'name': 'test',
|
||||
'image': 'busybox:latest',
|
||||
'volumes_from': ['vol']
|
||||
'volumes_from': [VolumeFromSpec('vol', 'rw')]
|
||||
}
|
||||
], None)
|
||||
self.assertEqual(project.get_service('test')._get_volumes_from(), [container_ids[0] + ':rw'])
|
||||
with mock.patch.object(Service, 'containers') as mock_return:
|
||||
mock_return.return_value = [
|
||||
mock.Mock(id=container_id, spec=Container)
|
||||
for container_id in container_ids]
|
||||
self.assertEqual(
|
||||
project.get_service('test')._get_volumes_from(),
|
||||
[container_ids[0] + ':rw'])
|
||||
|
||||
def test_net_unset(self):
|
||||
project = Project.from_dicts('test', [
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@ from __future__ import absolute_import
|
|||
from __future__ import unicode_literals
|
||||
|
||||
import docker
|
||||
import pytest
|
||||
|
||||
from .. import mock
|
||||
from .. import unittest
|
||||
from compose.const import IS_WINDOWS_PLATFORM
|
||||
from compose.config.types import VolumeFromSpec
|
||||
from compose.config.types import VolumeSpec
|
||||
from compose.const import LABEL_CONFIG_HASH
|
||||
from compose.const import LABEL_ONE_OFF
|
||||
from compose.const import LABEL_PROJECT
|
||||
|
|
@ -14,7 +14,6 @@ from compose.const import LABEL_SERVICE
|
|||
from compose.container import Container
|
||||
from compose.service import build_ulimits
|
||||
from compose.service import build_volume_binding
|
||||
from compose.service import ConfigError
|
||||
from compose.service import ContainerNet
|
||||
from compose.service import get_container_data_volumes
|
||||
from compose.service import merge_volume_bindings
|
||||
|
|
@ -22,11 +21,8 @@ from compose.service import NeedsBuildError
|
|||
from compose.service import Net
|
||||
from compose.service import NoSuchImageError
|
||||
from compose.service import parse_repository_tag
|
||||
from compose.service import parse_volume_spec
|
||||
from compose.service import Service
|
||||
from compose.service import ServiceNet
|
||||
from compose.service import VolumeFromSpec
|
||||
from compose.service import VolumeSpec
|
||||
from compose.service import warn_on_masked_volume
|
||||
|
||||
|
||||
|
|
@ -35,11 +31,6 @@ class ServiceTest(unittest.TestCase):
|
|||
def setUp(self):
|
||||
self.mock_client = mock.create_autospec(docker.Client)
|
||||
|
||||
def test_project_validation(self):
|
||||
self.assertRaises(ConfigError, lambda: Service(name='foo', project='>', image='foo'))
|
||||
|
||||
Service(name='foo', project='bar.bar__', image='foo')
|
||||
|
||||
def test_containers(self):
|
||||
service = Service('db', self.mock_client, 'myproject', image='foo')
|
||||
self.mock_client.containers.return_value = []
|
||||
|
|
@ -589,46 +580,12 @@ 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'))
|
||||
|
||||
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'))
|
||||
|
||||
spec = parse_volume_spec('external:interval:z')
|
||||
self.assertEqual(spec, ('external', 'interval', 'z'))
|
||||
|
||||
def test_parse_volume_spec_too_many_parts(self):
|
||||
with self.assertRaises(ConfigError):
|
||||
parse_volume_spec('one:two:three:four')
|
||||
|
||||
@pytest.mark.xfail((not IS_WINDOWS_PLATFORM), reason='does not have a drive')
|
||||
def test_parse_volume_windows_absolute_path(self):
|
||||
windows_absolute_path = "c:\\Users\\me\\Documents\\shiny\\config:\\opt\\shiny\\config:ro"
|
||||
|
||||
spec = parse_volume_spec(windows_absolute_path)
|
||||
|
||||
self.assertEqual(
|
||||
spec,
|
||||
(
|
||||
"/c/Users/me/Documents/shiny/config",
|
||||
"/opt/shiny/config",
|
||||
"ro"
|
||||
)
|
||||
)
|
||||
|
||||
def test_build_volume_binding(self):
|
||||
binding = build_volume_binding(parse_volume_spec('/outside:/inside'))
|
||||
self.assertEqual(binding, ('/inside', '/outside:/inside:rw'))
|
||||
binding = build_volume_binding(VolumeSpec.parse('/outside:/inside'))
|
||||
assert binding == ('/inside', '/outside:/inside:rw')
|
||||
|
||||
def test_get_container_data_volumes(self):
|
||||
options = [parse_volume_spec(v) for v in [
|
||||
options = [VolumeSpec.parse(v) for v in [
|
||||
'/host/volume:/host/volume:ro',
|
||||
'/new/volume',
|
||||
'/existing/volume',
|
||||
|
|
@ -652,19 +609,19 @@ class ServiceVolumesTest(unittest.TestCase):
|
|||
}, has_been_inspected=True)
|
||||
|
||||
expected = [
|
||||
parse_volume_spec('/var/lib/docker/aaaaaaaa:/existing/volume:rw'),
|
||||
parse_volume_spec('/var/lib/docker/cccccccc:/mnt/image/data:rw'),
|
||||
VolumeSpec.parse('/var/lib/docker/aaaaaaaa:/existing/volume:rw'),
|
||||
VolumeSpec.parse('/var/lib/docker/cccccccc:/mnt/image/data:rw'),
|
||||
]
|
||||
|
||||
volumes = get_container_data_volumes(container, options)
|
||||
self.assertEqual(sorted(volumes), sorted(expected))
|
||||
assert sorted(volumes) == sorted(expected)
|
||||
|
||||
def test_merge_volume_bindings(self):
|
||||
options = [
|
||||
'/host/volume:/host/volume:ro',
|
||||
'/host/rw/volume:/host/rw/volume',
|
||||
'/new/volume',
|
||||
'/existing/volume',
|
||||
VolumeSpec.parse('/host/volume:/host/volume:ro'),
|
||||
VolumeSpec.parse('/host/rw/volume:/host/rw/volume'),
|
||||
VolumeSpec.parse('/new/volume'),
|
||||
VolumeSpec.parse('/existing/volume'),
|
||||
]
|
||||
|
||||
self.mock_client.inspect_image.return_value = {
|
||||
|
|
@ -690,8 +647,8 @@ class ServiceVolumesTest(unittest.TestCase):
|
|||
'web',
|
||||
image='busybox',
|
||||
volumes=[
|
||||
'/host/path:/data1',
|
||||
'/host/path:/data2',
|
||||
VolumeSpec.parse('/host/path:/data1'),
|
||||
VolumeSpec.parse('/host/path:/data2'),
|
||||
],
|
||||
client=self.mock_client,
|
||||
)
|
||||
|
|
@ -720,7 +677,7 @@ class ServiceVolumesTest(unittest.TestCase):
|
|||
service = Service(
|
||||
'web',
|
||||
image='busybox',
|
||||
volumes=['/host/path:/data'],
|
||||
volumes=[VolumeSpec.parse('/host/path:/data')],
|
||||
client=self.mock_client,
|
||||
)
|
||||
|
||||
|
|
@ -788,22 +745,17 @@ class ServiceVolumesTest(unittest.TestCase):
|
|||
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']
|
||||
self.mock_client.create_container.return_value = {'Id': 'containerid'}
|
||||
|
||||
volume = '/tmp:/foo:z'
|
||||
Service(
|
||||
'web',
|
||||
client=self.mock_client,
|
||||
image='busybox',
|
||||
volumes=volumes,
|
||||
volumes=[VolumeSpec.parse(volume)],
|
||||
).create_container()
|
||||
|
||||
self.assertEqual(len(create_calls), 1)
|
||||
self.assertEqual(self.mock_client.create_host_config.call_args[1]['binds'], volumes)
|
||||
assert self.mock_client.create_container.call_count == 1
|
||||
self.assertEqual(
|
||||
self.mock_client.create_host_config.call_args[1]['binds'],
|
||||
[volume])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue