mirror of https://github.com/docker/compose.git
Merge branch 'cuckoohello-5360-add-runtime-support'
This commit is contained in:
commit
ddbc9e30b0
|
@ -98,6 +98,7 @@ DOCKER_CONFIG_KEYS = [
|
||||||
'privileged',
|
'privileged',
|
||||||
'read_only',
|
'read_only',
|
||||||
'restart',
|
'restart',
|
||||||
|
'runtime',
|
||||||
'secrets',
|
'secrets',
|
||||||
'security_opt',
|
'security_opt',
|
||||||
'shm_size',
|
'shm_size',
|
||||||
|
|
|
@ -261,6 +261,7 @@
|
||||||
"privileged": {"type": "boolean"},
|
"privileged": {"type": "boolean"},
|
||||||
"read_only": {"type": "boolean"},
|
"read_only": {"type": "boolean"},
|
||||||
"restart": {"type": "string"},
|
"restart": {"type": "string"},
|
||||||
|
"runtime": {"type": "string"},
|
||||||
"scale": {"type": "integer"},
|
"scale": {"type": "integer"},
|
||||||
"security_opt": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
"security_opt": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||||
"shm_size": {"type": ["number", "string"]},
|
"shm_size": {"type": ["number", "string"]},
|
||||||
|
|
|
@ -87,6 +87,7 @@ HOST_CONFIG_KEYS = [
|
||||||
'pids_limit',
|
'pids_limit',
|
||||||
'privileged',
|
'privileged',
|
||||||
'restart',
|
'restart',
|
||||||
|
'runtime',
|
||||||
'security_opt',
|
'security_opt',
|
||||||
'shm_size',
|
'shm_size',
|
||||||
'storage_opt',
|
'storage_opt',
|
||||||
|
@ -878,6 +879,7 @@ class Service(object):
|
||||||
dns_opt=options.get('dns_opt'),
|
dns_opt=options.get('dns_opt'),
|
||||||
dns_search=options.get('dns_search'),
|
dns_search=options.get('dns_search'),
|
||||||
restart_policy=options.get('restart'),
|
restart_policy=options.get('restart'),
|
||||||
|
runtime=options.get('runtime'),
|
||||||
cap_add=options.get('cap_add'),
|
cap_add=options.get('cap_add'),
|
||||||
cap_drop=options.get('cap_drop'),
|
cap_drop=options.get('cap_drop'),
|
||||||
mem_limit=options.get('mem_limit'),
|
mem_limit=options.get('mem_limit'),
|
||||||
|
|
|
@ -22,6 +22,7 @@ from compose.config.types import VolumeSpec
|
||||||
from compose.const import COMPOSEFILE_V2_0 as V2_0
|
from compose.const import COMPOSEFILE_V2_0 as V2_0
|
||||||
from compose.const import COMPOSEFILE_V2_1 as V2_1
|
from compose.const import COMPOSEFILE_V2_1 as V2_1
|
||||||
from compose.const import COMPOSEFILE_V2_2 as V2_2
|
from compose.const import COMPOSEFILE_V2_2 as V2_2
|
||||||
|
from compose.const import COMPOSEFILE_V2_3 as V2_3
|
||||||
from compose.const import COMPOSEFILE_V3_1 as V3_1
|
from compose.const import COMPOSEFILE_V3_1 as V3_1
|
||||||
from compose.const import LABEL_PROJECT
|
from compose.const import LABEL_PROJECT
|
||||||
from compose.const import LABEL_SERVICE
|
from compose.const import LABEL_SERVICE
|
||||||
|
@ -31,6 +32,7 @@ from compose.errors import NoHealthCheckConfigured
|
||||||
from compose.project import Project
|
from compose.project import Project
|
||||||
from compose.project import ProjectError
|
from compose.project import ProjectError
|
||||||
from compose.service import ConvergenceStrategy
|
from compose.service import ConvergenceStrategy
|
||||||
|
from tests.integration.testcases import if_runtime_available
|
||||||
from tests.integration.testcases import is_cluster
|
from tests.integration.testcases import is_cluster
|
||||||
from tests.integration.testcases import no_cluster
|
from tests.integration.testcases import no_cluster
|
||||||
from tests.integration.testcases import v2_1_only
|
from tests.integration.testcases import v2_1_only
|
||||||
|
@ -832,11 +834,11 @@ class ProjectTest(DockerClientTestCase):
|
||||||
|
|
||||||
service_container = project.get_service('web').containers()[0]
|
service_container = project.get_service('web').containers()[0]
|
||||||
|
|
||||||
IPAMConfig = (service_container.inspect().get('NetworkSettings', {}).
|
ipam_config = (service_container.inspect().get('NetworkSettings', {}).
|
||||||
get('Networks', {}).get('composetest_static_test', {}).
|
get('Networks', {}).get('composetest_static_test', {}).
|
||||||
get('IPAMConfig', {}))
|
get('IPAMConfig', {}))
|
||||||
assert IPAMConfig.get('IPv4Address') == '172.16.100.100'
|
assert ipam_config.get('IPv4Address') == '172.16.100.100'
|
||||||
assert IPAMConfig.get('IPv6Address') == 'fe80::1001:102'
|
assert ipam_config.get('IPv6Address') == 'fe80::1001:102'
|
||||||
|
|
||||||
@v2_1_only()
|
@v2_1_only()
|
||||||
def test_up_with_enable_ipv6(self):
|
def test_up_with_enable_ipv6(self):
|
||||||
|
@ -1029,6 +1031,67 @@ class ProjectTest(DockerClientTestCase):
|
||||||
with self.assertRaises(ProjectError):
|
with self.assertRaises(ProjectError):
|
||||||
project.up()
|
project.up()
|
||||||
|
|
||||||
|
@v2_3_only()
|
||||||
|
@if_runtime_available('runc')
|
||||||
|
def test_up_with_runtime(self):
|
||||||
|
self.require_api_version('1.30')
|
||||||
|
config_data = build_config(
|
||||||
|
version=V2_3,
|
||||||
|
services=[{
|
||||||
|
'name': 'web',
|
||||||
|
'image': 'busybox:latest',
|
||||||
|
'runtime': 'runc'
|
||||||
|
}],
|
||||||
|
)
|
||||||
|
project = Project.from_config(
|
||||||
|
client=self.client,
|
||||||
|
name='composetest',
|
||||||
|
config_data=config_data
|
||||||
|
)
|
||||||
|
project.up(detached=True)
|
||||||
|
service_container = project.get_service('web').containers(stopped=True)[0]
|
||||||
|
assert service_container.inspect()['HostConfig']['Runtime'] == 'runc'
|
||||||
|
|
||||||
|
@v2_3_only()
|
||||||
|
def test_up_with_invalid_runtime(self):
|
||||||
|
self.require_api_version('1.30')
|
||||||
|
config_data = build_config(
|
||||||
|
version=V2_3,
|
||||||
|
services=[{
|
||||||
|
'name': 'web',
|
||||||
|
'image': 'busybox:latest',
|
||||||
|
'runtime': 'foobar'
|
||||||
|
}],
|
||||||
|
)
|
||||||
|
project = Project.from_config(
|
||||||
|
client=self.client,
|
||||||
|
name='composetest',
|
||||||
|
config_data=config_data
|
||||||
|
)
|
||||||
|
with self.assertRaises(ProjectError):
|
||||||
|
project.up()
|
||||||
|
|
||||||
|
@v2_3_only()
|
||||||
|
@if_runtime_available('nvidia')
|
||||||
|
def test_up_with_nvidia_runtime(self):
|
||||||
|
self.require_api_version('1.30')
|
||||||
|
config_data = build_config(
|
||||||
|
version=V2_3,
|
||||||
|
services=[{
|
||||||
|
'name': 'web',
|
||||||
|
'image': 'busybox:latest',
|
||||||
|
'runtime': 'nvidia'
|
||||||
|
}],
|
||||||
|
)
|
||||||
|
project = Project.from_config(
|
||||||
|
client=self.client,
|
||||||
|
name='composetest',
|
||||||
|
config_data=config_data
|
||||||
|
)
|
||||||
|
project.up(detached=True)
|
||||||
|
service_container = project.get_service('web').containers(stopped=True)[0]
|
||||||
|
assert service_container.inspect()['HostConfig']['Runtime'] == 'nvidia'
|
||||||
|
|
||||||
@v2_only()
|
@v2_only()
|
||||||
def test_project_up_with_network_internal(self):
|
def test_project_up_with_network_internal(self):
|
||||||
self.require_api_version('1.23')
|
self.require_api_version('1.23')
|
||||||
|
|
|
@ -155,6 +155,18 @@ class DockerClientTestCase(unittest.TestCase):
|
||||||
return self.client.inspect_volume(volumes[0]['Name'])
|
return self.client.inspect_volume(volumes[0]['Name'])
|
||||||
|
|
||||||
|
|
||||||
|
def if_runtime_available(runtime):
|
||||||
|
def decorator(f):
|
||||||
|
@functools.wraps(f)
|
||||||
|
def wrapper(self, *args, **kwargs):
|
||||||
|
if runtime not in self.client.info().get('Runtimes', {}):
|
||||||
|
return pytest.skip("This daemon does not support the '{}'' runtime".format(runtime))
|
||||||
|
return f(self, *args, **kwargs)
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
def is_cluster(client):
|
def is_cluster(client):
|
||||||
if SWARM_ASSUME_MULTINODE:
|
if SWARM_ASSUME_MULTINODE:
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -1784,6 +1784,25 @@ class ConfigTest(unittest.TestCase):
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def test_runtime_option(self):
|
||||||
|
actual = config.load(build_config_details({
|
||||||
|
'version': str(V2_3),
|
||||||
|
'services': {
|
||||||
|
'web': {
|
||||||
|
'image': 'nvidia/cuda',
|
||||||
|
'runtime': 'nvidia'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
assert actual.services == [
|
||||||
|
{
|
||||||
|
'name': 'web',
|
||||||
|
'image': 'nvidia/cuda',
|
||||||
|
'runtime': 'nvidia',
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
def test_merge_service_dicts_from_files_with_extends_in_base(self):
|
def test_merge_service_dicts_from_files_with_extends_in_base(self):
|
||||||
base = {
|
base = {
|
||||||
'volumes': ['.:/app'],
|
'volumes': ['.:/app'],
|
||||||
|
|
Loading…
Reference in New Issue