Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 52 additions & 39 deletions docker/types/containers.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ def __init__(self, version, binds=None, port_bindings=None,
tmpfs=None, oom_score_adj=None, dns_opt=None, cpu_shares=None,
cpuset_cpus=None, userns_mode=None, pids_limit=None,
isolation=None, auto_remove=False, storage_opt=None,
init=None, init_path=None):
init=None, init_path=None, volume_driver=None):

if mem_limit is not None:
self['Memory'] = parse_bytes(mem_limit)
Expand Down Expand Up @@ -428,6 +428,11 @@ def __init__(self, version, binds=None, port_bindings=None,
raise host_config_version_error('init_path', '1.25')
self['InitPath'] = init_path

if volume_driver is not None:
if version_lt(version, '1.21'):
raise host_config_version_error('volume_driver', '1.21')
self['VolumeDriver'] = volume_driver


def host_config_type_error(param, param_value, expected):
error_msg = 'Invalid type for {0} param: expected {1} but found {2}'
Expand Down Expand Up @@ -456,43 +461,27 @@ def __init__(
stop_signal=None, networking_config=None, healthcheck=None,
stop_timeout=None
):
if isinstance(command, six.string_types):
command = split_command(command)

if isinstance(entrypoint, six.string_types):
entrypoint = split_command(entrypoint)

if isinstance(environment, dict):
environment = format_environment(environment)

if labels is not None and version_lt(version, '1.18'):
raise errors.InvalidVersion(
'labels were only introduced in API version 1.18'
)
if version_gte(version, '1.10'):
message = ('{0!r} parameter has no effect on create_container().'
' It has been moved to host_config')
if dns is not None:
raise errors.InvalidVersion(message.format('dns'))
if volumes_from is not None:
raise errors.InvalidVersion(message.format('volumes_from'))

if cpuset is not None or cpu_shares is not None:
if version_gte(version, '1.18'):
if version_lt(version, '1.18'):
if labels is not None:
raise errors.InvalidVersion(
'labels were only introduced in API version 1.18'
)
else:
if cpuset is not None or cpu_shares is not None:
warnings.warn(
'The cpuset_cpus and cpu_shares options have been moved to'
' host_config in API version 1.18, and will be removed',
DeprecationWarning
)

if stop_signal is not None and version_lt(version, '1.21'):
raise errors.InvalidVersion(
'stop_signal was only introduced in API version 1.21'
)

if stop_timeout is not None and version_lt(version, '1.25'):
raise errors.InvalidVersion(
'stop_timeout was only introduced in API version 1.25'
)

if healthcheck is not None and version_lt(version, '1.24'):
raise errors.InvalidVersion(
'Health options were only introduced in API version 1.24'
)

if version_lt(version, '1.19'):
if volume_driver is not None:
raise errors.InvalidVersion(
Expand All @@ -513,6 +502,38 @@ def __init__(
'version 1.19'
)

if version_lt(version, '1.21'):
if stop_signal is not None:
raise errors.InvalidVersion(
'stop_signal was only introduced in API version 1.21'
)
else:
if volume_driver is not None:
warnings.warn(
'The volume_driver option has been moved to'
' host_config in API version 1.21, and will be removed',
DeprecationWarning
)

if stop_timeout is not None and version_lt(version, '1.25'):
raise errors.InvalidVersion(
'stop_timeout was only introduced in API version 1.25'
)

if healthcheck is not None and version_lt(version, '1.24'):
raise errors.InvalidVersion(
'Health options were only introduced in API version 1.24'
)

if isinstance(command, six.string_types):
command = split_command(command)

if isinstance(entrypoint, six.string_types):
entrypoint = split_command(entrypoint)

if isinstance(environment, dict):
environment = format_environment(environment)

if isinstance(labels, list):
labels = dict((lbl, six.text_type('')) for lbl in labels)

Expand Down Expand Up @@ -566,14 +587,6 @@ def __init__(
attach_stdin = True
stdin_once = True

if version_gte(version, '1.10'):
message = ('{0!r} parameter has no effect on create_container().'
' It has been moved to host_config')
if dns is not None:
raise errors.InvalidVersion(message.format('dns'))
if volumes_from is not None:
raise errors.InvalidVersion(message.format('volumes_from'))

self.update({
'Hostname': hostname,
'Domainname': domainname,
Expand Down
11 changes: 4 additions & 7 deletions tests/unit/api_container_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -407,11 +407,8 @@ def test_create_container_with_volumes_from(self):
{'Content-Type': 'application/json'})

def test_create_container_empty_volumes_from(self):
self.client.create_container('busybox', 'true', volumes_from=[])

args = fake_request.call_args
data = json.loads(args[1]['data'])
self.assertTrue('VolumesFrom' not in data)
with pytest.raises(docker.errors.InvalidVersion):
self.client.create_container('busybox', 'true', volumes_from=[])

def test_create_named_container(self):
self.client.create_container('busybox', 'true',
Expand Down Expand Up @@ -978,20 +975,20 @@ def test_create_container_with_named_volume(self):
self.client.create_container(
'busybox', 'true',
host_config=self.client.create_host_config(
volume_driver='foodriver',
binds={volume_name: {
"bind": mount_dest,
"ro": False
}}),
volume_driver='foodriver',
)

args = fake_request.call_args
self.assertEqual(
args[0][1], url_prefix + 'containers/create'
)
expected_payload = self.base_create_payload()
expected_payload['VolumeDriver'] = 'foodriver'
expected_payload['HostConfig'] = self.client.create_host_config()
expected_payload['HostConfig']['VolumeDriver'] = 'foodriver'
expected_payload['HostConfig']['Binds'] = ["name:/mnt:rw"]
self.assertEqual(json.loads(args[1]['data']), expected_payload)
self.assertEqual(args[1]['headers'],
Expand Down
25 changes: 23 additions & 2 deletions tests/unit/dockertypes_test.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
# -*- coding: utf-8 -*-

import unittest
import warnings

import pytest

from docker.constants import DEFAULT_DOCKER_API_VERSION
from docker.errors import InvalidArgument, InvalidVersion
from docker.types import (
EndpointConfig, HostConfig, IPAMConfig, IPAMPool, LogConfig, Mount,
ServiceMode, Ulimit,
ContainerConfig, EndpointConfig, HostConfig, IPAMConfig, IPAMPool,
LogConfig, Mount, ServiceMode, Ulimit,
)

try:
Expand Down Expand Up @@ -165,6 +166,26 @@ def test_create_host_config_invalid_mem_swappiness(self):
with pytest.raises(TypeError):
create_host_config(version='1.24', mem_swappiness='40')

def test_create_host_config_with_volume_driver(self):
with pytest.raises(InvalidVersion):
create_host_config(version='1.20', volume_driver='local')

config = create_host_config(version='1.21', volume_driver='local')
assert config.get('VolumeDriver') == 'local'


class ContainerConfigTest(unittest.TestCase):
def test_create_container_config_volume_driver_warning(self):
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
ContainerConfig(
version='1.21', image='scratch', command=None,
volume_driver='local'
)

assert len(w) == 1
assert 'The volume_driver option has been moved' in str(w[0].message)


class UlimitTest(unittest.TestCase):
def test_create_host_config_dict_ulimit(self):
Expand Down