Skip to content

Commit 2359646

Browse files
authored
Merge pull request #1178 from docker/1105-network-api
Network labels, EnableIPv6 flag, force disconnect
2 parents 24bfb99 + 6552076 commit 2359646

File tree

4 files changed

+94
-12
lines changed

4 files changed

+94
-12
lines changed

docker/api/network.py

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ def networks(self, names=None, ids=None):
2222

2323
@minimum_version('1.21')
2424
def create_network(self, name, driver=None, options=None, ipam=None,
25-
check_duplicate=None, internal=False):
25+
check_duplicate=None, internal=False, labels=None,
26+
enable_ipv6=False):
2627
if options is not None and not isinstance(options, dict):
2728
raise TypeError('options must be a dictionary')
2829

@@ -34,6 +35,22 @@ def create_network(self, name, driver=None, options=None, ipam=None,
3435
'CheckDuplicate': check_duplicate
3536
}
3637

38+
if labels is not None:
39+
if version_lt(self._version, '1.23'):
40+
raise InvalidVersion(
41+
'network labels were introduced in API 1.23'
42+
)
43+
if not isinstance(labels, dict):
44+
raise TypeError('labels must be a dictionary')
45+
data["Labels"] = labels
46+
47+
if enable_ipv6:
48+
if version_lt(self._version, '1.23'):
49+
raise InvalidVersion(
50+
'enable_ipv6 was introduced in API 1.23'
51+
)
52+
data['EnableIPv6'] = True
53+
3754
if internal:
3855
if version_lt(self._version, '1.22'):
3956
raise InvalidVersion('Internal networks are not '
@@ -76,8 +93,15 @@ def connect_container_to_network(self, container, net_id,
7693

7794
@check_resource
7895
@minimum_version('1.21')
79-
def disconnect_container_from_network(self, container, net_id):
80-
data = {"container": container}
96+
def disconnect_container_from_network(self, container, net_id,
97+
force=False):
98+
data = {"Container": container}
99+
if force:
100+
if version_lt(self._version, '1.22'):
101+
raise InvalidVersion(
102+
'Forced disconnect was introduced in API 1.22'
103+
)
104+
data['Force'] = force
81105
url = self._url("/networks/{0}/disconnect", net_id)
82106
res = self._post_json(url, data=data)
83107
self._raise_for_status(res)

docs/api.md

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -283,22 +283,25 @@ The utility can be used as follows:
283283
```python
284284
>>> import docker.utils
285285
>>> my_envs = docker.utils.parse_env_file('/path/to/file')
286-
>>> docker.utils.create_container_config('1.18', '_mongodb', 'foobar', environment=my_envs)
286+
>>> client.create_container('myimage', 'command', environment=my_envs)
287287
```
288288

289-
You can now use this with 'environment' for `create_container`.
290-
291-
292289
## create_network
293290

294-
Create a network, similar to the `docker network create` command.
291+
Create a network, similar to the `docker network create` command. See the
292+
[networks documentation](networks.md) for details.
295293

296294
**Params**:
297295

298296
* name (str): Name of the network
299297
* driver (str): Name of the driver used to create the network
300-
301298
* options (dict): Driver options as a key-value dictionary
299+
* ipam (dict): Optional custom IP scheme for the network
300+
* check_duplicate (bool): Request daemon to check for networks with same name.
301+
Default: `True`.
302+
* internal (bool): Restrict external access to the network. Default `False`.
303+
* labels (dict): Map of labels to set on the network. Default `None`.
304+
* enable_ipv6 (bool): Enable IPv6 on the network. Default `False`.
302305

303306
**Returns** (dict): The created network reference object
304307

@@ -352,6 +355,8 @@ Inspect changes on a container's filesystem.
352355

353356
* container (str): container-id/name to be disconnected from a network
354357
* net_id (str): network id
358+
* force (bool): Force the container to disconnect from a network.
359+
Default: `False`
355360

356361
## events
357362

tests/integration/network_test.py

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,8 @@ def test_connect_and_disconnect_container(self):
115115
network_data = self.client.inspect_network(net_id)
116116
self.assertEqual(
117117
list(network_data['Containers'].keys()),
118-
[container['Id']])
118+
[container['Id']]
119+
)
119120

120121
with pytest.raises(docker.errors.APIError):
121122
self.client.connect_container_to_network(container, net_id)
@@ -127,6 +128,33 @@ def test_connect_and_disconnect_container(self):
127128
with pytest.raises(docker.errors.APIError):
128129
self.client.disconnect_container_from_network(container, net_id)
129130

131+
@requires_api_version('1.22')
132+
def test_connect_and_force_disconnect_container(self):
133+
net_name, net_id = self.create_network()
134+
135+
container = self.client.create_container('busybox', 'top')
136+
self.tmp_containers.append(container)
137+
self.client.start(container)
138+
139+
network_data = self.client.inspect_network(net_id)
140+
self.assertFalse(network_data.get('Containers'))
141+
142+
self.client.connect_container_to_network(container, net_id)
143+
network_data = self.client.inspect_network(net_id)
144+
self.assertEqual(
145+
list(network_data['Containers'].keys()),
146+
[container['Id']]
147+
)
148+
149+
self.client.disconnect_container_from_network(container, net_id, True)
150+
network_data = self.client.inspect_network(net_id)
151+
self.assertFalse(network_data.get('Containers'))
152+
153+
with pytest.raises(docker.errors.APIError):
154+
self.client.disconnect_container_from_network(
155+
container, net_id, force=True
156+
)
157+
130158
@requires_api_version('1.22')
131159
def test_connect_with_aliases(self):
132160
net_name, net_id = self.create_network()
@@ -300,7 +328,8 @@ def test_create_check_duplicate(self):
300328
net_name, net_id = self.create_network()
301329
with self.assertRaises(docker.errors.APIError):
302330
self.client.create_network(net_name, check_duplicate=True)
303-
self.client.create_network(net_name, check_duplicate=False)
331+
net_id = self.client.create_network(net_name, check_duplicate=False)
332+
self.tmp_networks.append(net_id['Id'])
304333

305334
@requires_api_version('1.22')
306335
def test_connect_with_links(self):
@@ -387,3 +416,27 @@ def test_create_internal_networks(self):
387416
_, net_id = self.create_network(internal=True)
388417
net = self.client.inspect_network(net_id)
389418
assert net['Internal'] is True
419+
420+
@requires_api_version('1.23')
421+
def test_create_network_with_labels(self):
422+
_, net_id = self.create_network(labels={
423+
'com.docker.py.test': 'label'
424+
})
425+
426+
net = self.client.inspect_network(net_id)
427+
assert 'Labels' in net
428+
assert len(net['Labels']) == 1
429+
assert net['Labels'] == {
430+
'com.docker.py.test': 'label'
431+
}
432+
433+
@requires_api_version('1.23')
434+
def test_create_network_with_labels_wrong_type(self):
435+
with pytest.raises(TypeError):
436+
self.create_network(labels=['com.docker.py.test=label', ])
437+
438+
@requires_api_version('1.23')
439+
def test_create_network_ipv6_enabled(self):
440+
_, net_id = self.create_network(enable_ipv6=True)
441+
net = self.client.inspect_network(net_id)
442+
assert net['EnableIPv6'] is True

tests/unit/network_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,4 +184,4 @@ def test_disconnect_container_from_network(self):
184184

185185
self.assertEqual(
186186
json.loads(post.call_args[1]['data']),
187-
{'container': container_id})
187+
{'Container': container_id})

0 commit comments

Comments
 (0)