Skip to content

Commit 4a88112

Browse files
committed
Merge branch 'pr-3121'
#3121
2 parents c38656d + b70cbd0 commit 4a88112

File tree

3 files changed

+374
-130
lines changed

3 files changed

+374
-130
lines changed

docker/models/containers.py

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@
22
import ntpath
33
from collections import namedtuple
44

5+
from .images import Image
6+
from .resource import Collection, Model
57
from ..api import APIClient
68
from ..constants import DEFAULT_DATA_CHUNK_SIZE
79
from ..errors import (
810
ContainerError, DockerException, ImageNotFound,
911
NotFound, create_unexpected_kwargs_error
1012
)
11-
from ..types import HostConfig
13+
from ..types import HostConfig, NetworkingConfig
1214
from ..utils import version_gte
13-
from .images import Image
14-
from .resource import Collection, Model
1515

1616

1717
class Container(Model):
@@ -21,6 +21,7 @@ class Container(Model):
2121
query the Docker daemon for the current properties, causing
2222
:py:attr:`attrs` to be refreshed.
2323
"""
24+
2425
@property
2526
def name(self):
2627
"""
@@ -681,10 +682,14 @@ def run(self, image, command=None, stdout=True, stderr=False,
681682
This mode is incompatible with ``ports``.
682683
683684
Incompatible with ``network``.
684-
network_driver_opt (dict): A dictionary of options to provide
685-
to the network driver. Defaults to ``None``. Used in
686-
conjuction with ``network``. Incompatible
687-
with ``network_mode``.
685+
networking_config (Dict[str, EndpointConfig]):
686+
Dictionary of EndpointConfig objects for each container network.
687+
The key is the name of the network.
688+
Defaults to ``None``.
689+
690+
Used in conjuction with ``network``.
691+
692+
Incompatible with ``network_mode``.
688693
oom_kill_disable (bool): Whether to disable OOM killer.
689694
oom_score_adj (int): An integer value containing the score given
690695
to the container in order to tune OOM killer preferences.
@@ -849,9 +854,9 @@ def run(self, image, command=None, stdout=True, stderr=False,
849854
'together.'
850855
)
851856

852-
if kwargs.get('network_driver_opt') and not kwargs.get('network'):
857+
if kwargs.get('networking_config') and not kwargs.get('network'):
853858
raise RuntimeError(
854-
'The options "network_driver_opt" can not be used '
859+
'The option "networking_config" can not be used '
855860
'without "network".'
856861
)
857862

@@ -1007,6 +1012,7 @@ def list(self, all=False, before=None, filters=None, limit=-1, since=None,
10071012

10081013
def prune(self, filters=None):
10091014
return self.client.api.prune_containers(filters=filters)
1015+
10101016
prune.__doc__ = APIClient.prune_containers.__doc__
10111017

10121018

@@ -1125,12 +1131,17 @@ def _create_container_args(kwargs):
11251131
host_config_kwargs['binds'] = volumes
11261132

11271133
network = kwargs.pop('network', None)
1128-
network_driver_opt = kwargs.pop('network_driver_opt', None)
1134+
networking_config = kwargs.pop('networking_config', None)
11291135
if network:
1130-
network_configuration = {'driver_opt': network_driver_opt} \
1131-
if network_driver_opt else None
1132-
1133-
create_kwargs['networking_config'] = {network: network_configuration}
1136+
if networking_config:
1137+
# Sanity check: check if the network is defined in the
1138+
# networking config dict, otherwise switch to None
1139+
if network not in networking_config:
1140+
networking_config = None
1141+
1142+
create_kwargs['networking_config'] = NetworkingConfig(
1143+
networking_config
1144+
) if networking_config else {network: None}
11341145
host_config_kwargs['network_mode'] = network
11351146

11361147
# All kwargs should have been consumed by this point, so raise

tests/integration/models_containers_test.py

Lines changed: 93 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
import pytest
66

77
import docker
8-
from ..helpers import random_name
9-
from ..helpers import requires_api_version
108
from .base import BaseIntegrationTest
119
from .base import TEST_API_VERSION
10+
from ..helpers import random_name
11+
from ..helpers import requires_api_version
1212

1313

1414
class ContainerCollectionTest(BaseIntegrationTest):
@@ -104,6 +104,96 @@ def test_run_with_network(self):
104104
assert 'Networks' in attrs['NetworkSettings']
105105
assert list(attrs['NetworkSettings']['Networks'].keys()) == [net_name]
106106

107+
def test_run_with_networking_config(self):
108+
net_name = random_name()
109+
client = docker.from_env(version=TEST_API_VERSION)
110+
client.networks.create(net_name)
111+
self.tmp_networks.append(net_name)
112+
113+
test_aliases = ['hello']
114+
test_driver_opt = {'key1': 'a'}
115+
116+
networking_config = {
117+
net_name: client.api.create_endpoint_config(
118+
aliases=test_aliases,
119+
driver_opt=test_driver_opt
120+
)
121+
}
122+
123+
container = client.containers.run(
124+
'alpine', 'echo hello world', network=net_name,
125+
networking_config=networking_config,
126+
detach=True
127+
)
128+
self.tmp_containers.append(container.id)
129+
130+
attrs = container.attrs
131+
132+
assert 'NetworkSettings' in attrs
133+
assert 'Networks' in attrs['NetworkSettings']
134+
assert list(attrs['NetworkSettings']['Networks'].keys()) == [net_name]
135+
assert attrs['NetworkSettings']['Networks'][net_name]['Aliases'] == \
136+
test_aliases
137+
assert attrs['NetworkSettings']['Networks'][net_name]['DriverOpts'] \
138+
== test_driver_opt
139+
140+
def test_run_with_networking_config_with_undeclared_network(self):
141+
net_name = random_name()
142+
client = docker.from_env(version=TEST_API_VERSION)
143+
client.networks.create(net_name)
144+
self.tmp_networks.append(net_name)
145+
146+
test_aliases = ['hello']
147+
test_driver_opt = {'key1': 'a'}
148+
149+
networking_config = {
150+
net_name: client.api.create_endpoint_config(
151+
aliases=test_aliases,
152+
driver_opt=test_driver_opt
153+
),
154+
'bar': client.api.create_endpoint_config(
155+
aliases=['test'],
156+
driver_opt={'key2': 'b'}
157+
),
158+
}
159+
160+
with pytest.raises(docker.errors.APIError) as e:
161+
container = client.containers.run(
162+
'alpine', 'echo hello world', network=net_name,
163+
networking_config=networking_config,
164+
detach=True
165+
)
166+
self.tmp_containers.append(container.id)
167+
168+
def test_run_with_networking_config_only_undeclared_network(self):
169+
net_name = random_name()
170+
client = docker.from_env(version=TEST_API_VERSION)
171+
client.networks.create(net_name)
172+
self.tmp_networks.append(net_name)
173+
174+
networking_config = {
175+
'bar': client.api.create_endpoint_config(
176+
aliases=['hello'],
177+
driver_opt={'key1': 'a'}
178+
),
179+
}
180+
181+
container = client.containers.run(
182+
'alpine', 'echo hello world', network=net_name,
183+
networking_config=networking_config,
184+
detach=True
185+
)
186+
self.tmp_containers.append(container.id)
187+
188+
attrs = container.attrs
189+
190+
assert 'NetworkSettings' in attrs
191+
assert 'Networks' in attrs['NetworkSettings']
192+
assert list(attrs['NetworkSettings']['Networks'].keys()) == [net_name]
193+
assert attrs['NetworkSettings']['Networks'][net_name]['Aliases'] is None
194+
assert (attrs['NetworkSettings']['Networks'][net_name]['DriverOpts']
195+
is None)
196+
107197
def test_run_with_none_driver(self):
108198
client = docker.from_env(version=TEST_API_VERSION)
109199

@@ -187,7 +277,7 @@ def test_get(self):
187277
container = client.containers.run("alpine", "sleep 300", detach=True)
188278
self.tmp_containers.append(container.id)
189279
assert client.containers.get(container.id).attrs[
190-
'Config']['Image'] == "alpine"
280+
'Config']['Image'] == "alpine"
191281

192282
def test_list(self):
193283
client = docker.from_env(version=TEST_API_VERSION)

0 commit comments

Comments
 (0)