Merge branch '5360-add-runtime-support' of https://github.com/cuckoohello/compose into cuckoohello-5360-add-runtime-support

Signed-off-by: Joffrey F <joffrey@docker.com>
This commit is contained in:
Joffrey F 2018-01-04 12:33:30 -08:00
commit f22a1b6a2e
6 changed files with 105 additions and 0 deletions

View File

@ -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',

View File

@ -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"]},

View File

@ -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'),

View File

@ -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
@ -1029,6 +1031,66 @@ class ProjectTest(DockerClientTestCase):
with self.assertRaises(ProjectError): with self.assertRaises(ProjectError):
project.up() project.up()
@v2_3_only()
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')

View File

@ -5,6 +5,7 @@ import functools
import os import os
import pytest import pytest
import six
from docker.errors import APIError from docker.errors import APIError
from docker.utils import version_lt from docker.utils import version_lt
@ -155,6 +156,25 @@ 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):
if runtime == 'nvidia':
command = 'nvidia-container-runtime'
if six.PY3:
import shutil
return pytest.mark.skipif(
shutil.which(command) is None,
reason="Nvida runtime not exists"
)
return pytest.mark.skipif(
any(
os.access(os.path.join(path, command), os.X_OK)
for path in os.environ["PATH"].split(os.pathsep)
) is False,
reason="Nvida runtime not exists"
)
return pytest.skip("Runtime %s not exists", runtime)
def is_cluster(client): def is_cluster(client):
if SWARM_ASSUME_MULTINODE: if SWARM_ASSUME_MULTINODE:
return True return True

View File

@ -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'],