summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoffrey F <joffrey@docker.com>2015-10-08 07:56:50 -0700
committerJoffrey F <joffrey@docker.com>2015-10-08 07:56:50 -0700
commitc5e68e6fc6c45c4761e5dd31c50fd5249eacdea3 (patch)
tree10fdb46ecbd9ed961c92ca43ea0f774781a15cf8
parent73e45ef3598dafd2ffbcc2e14b779f2ae0aa761d (diff)
parent1df3226c9bd9d2e8ff79d5929741c1e8f1a92b0d (diff)
downloaddocker-py-c5e68e6fc6c45c4761e5dd31c50fd5249eacdea3.tar.gz
Merge branch 'networking' of https://github.com/aanand/docker-py into aanand-networking
-rw-r--r--docker/api/__init__.py1
-rw-r--r--docker/api/network.py49
-rw-r--r--docker/client.py3
-rw-r--r--tests/integration_test.py104
-rw-r--r--tests/test.py134
5 files changed, 290 insertions, 1 deletions
diff --git a/docker/api/__init__.py b/docker/api/__init__.py
index 7979634..9e74428 100644
--- a/docker/api/__init__.py
+++ b/docker/api/__init__.py
@@ -5,3 +5,4 @@ from .daemon import DaemonApiMixin
from .exec_api import ExecApiMixin
from .image import ImageApiMixin
from .volume import VolumeApiMixin
+from .network import NetworkApiMixin
diff --git a/docker/api/network.py b/docker/api/network.py
new file mode 100644
index 0000000..f6ad4a7
--- /dev/null
+++ b/docker/api/network.py
@@ -0,0 +1,49 @@
+import json
+
+from ..utils import check_resource
+
+
+class NetworkApiMixin(object):
+ def networks(self, names=None, ids=None):
+ filters = {}
+ if names:
+ filters['name'] = names
+ if ids:
+ filters['id'] = ids
+
+ params = {'filters': json.dumps(filters)}
+
+ url = self._url("/networks")
+ res = self._get(url, params=params)
+ return self._result(res, json=True)
+
+ def create_network(self, name, driver=None):
+ data = {
+ 'name': name,
+ 'driver': driver,
+ }
+ url = self._url("/networks/create")
+ res = self._post_json(url, data=data)
+ return self._result(res, json=True)
+
+ def remove_network(self, net_id):
+ url = self._url("/networks/{0}", net_id)
+ res = self._delete(url)
+ self._raise_for_status(res)
+
+ def inspect_network(self, net_id):
+ url = self._url("/networks/{0}", net_id)
+ res = self._get(url)
+ return self._result(res, json=True)
+
+ @check_resource
+ def connect_container_to_network(self, container, net_id):
+ data = {"container": container}
+ url = self._url("/networks/{0}/connect", net_id)
+ self._post_json(url, data=data)
+
+ @check_resource
+ def disconnect_container_from_network(self, container, net_id):
+ data = {"container": container}
+ url = self._url("/networks/{0}/disconnect", net_id)
+ self._post_json(url, data=data)
diff --git a/docker/client.py b/docker/client.py
index 9decd61..79efc9f 100644
--- a/docker/client.py
+++ b/docker/client.py
@@ -39,7 +39,8 @@ class Client(
api.DaemonApiMixin,
api.ExecApiMixin,
api.ImageApiMixin,
- api.VolumeApiMixin):
+ api.VolumeApiMixin,
+ api.NetworkApiMixin):
def __init__(self, base_url=None, version=None,
timeout=constants.DEFAULT_TIMEOUT_SECONDS, tls=False):
super(Client, self).__init__()
diff --git a/tests/integration_test.py b/tests/integration_test.py
index a715ef6..f4e2089 100644
--- a/tests/integration_test.py
+++ b/tests/integration_test.py
@@ -21,6 +21,7 @@ import random
import shutil
import signal
import socket
+import sys
import tarfile
import tempfile
import threading
@@ -95,6 +96,7 @@ class BaseTestCase(unittest.TestCase):
self.tmp_containers = []
self.tmp_folders = []
self.tmp_volumes = []
+ self.tmp_networks = []
def tearDown(self):
for img in self.tmp_imgs:
@@ -108,6 +110,11 @@ class BaseTestCase(unittest.TestCase):
self.client.remove_container(container)
except docker.errors.APIError:
pass
+ for network in self.tmp_networks:
+ try:
+ self.client.remove_network(network)
+ except docker.errors.APIError:
+ pass
for folder in self.tmp_folders:
shutil.rmtree(folder)
@@ -1590,6 +1597,103 @@ class TestBuildWithDockerignore(Cleanup, BaseTestCase):
['not-ignored'],
)
+
+#######################
+# NETWORK TESTS #
+#######################
+
+
+@requires_api_version('1.21')
+class TestNetworks(BaseTestCase):
+ def create_network(self, *args, **kwargs):
+ net_name = 'dockerpy{}'.format(random.randrange(sys.maxint))[:14]
+ net_id = self.client.create_network(net_name, *args, **kwargs)['id']
+ self.tmp_networks.append(net_id)
+ return (net_name, net_id)
+
+ def test_list_networks(self):
+ networks = self.client.networks()
+ initial_size = len(networks)
+
+ net_name, net_id = self.create_network()
+
+ networks = self.client.networks()
+ self.assertEqual(len(networks), initial_size + 1)
+ self.assertTrue(net_id in [n['id'] for n in networks])
+
+ networks_by_name = self.client.networks(names=[net_name])
+ self.assertEqual([n['id'] for n in networks_by_name], [net_id])
+
+ networks_by_partial_id = self.client.networks(ids=[net_id[:8]])
+ self.assertEqual([n['id'] for n in networks_by_partial_id], [net_id])
+
+ def test_inspect_network(self):
+ net_name, net_id = self.create_network()
+
+ net = self.client.inspect_network(net_id)
+ self.assertEqual(net, {
+ u'name': net_name,
+ u'id': net_id,
+ u'driver': 'bridge',
+ u'containers': {},
+ })
+
+ def test_create_network_with_host_driver_fails(self):
+ net_name = 'dockerpy{}'.format(random.randrange(sys.maxint))[:14]
+
+ with pytest.raises(APIError):
+ self.client.create_network(net_name, driver='host')
+
+ def test_remove_network(self):
+ initial_size = len(self.client.networks())
+
+ net_name, net_id = self.create_network()
+ self.assertEqual(len(self.client.networks()), initial_size + 1)
+
+ self.client.remove_network(net_id)
+ self.assertEqual(len(self.client.networks()), initial_size)
+
+ def test_connect_and_disconnect_container(self):
+ net_name, net_id = self.create_network()
+
+ container = self.client.create_container('busybox', 'top')
+ self.tmp_containers.append(container)
+ self.client.start(container)
+
+ network_data = self.client.inspect_network(net_id)
+ self.assertFalse(network_data.get('containers'))
+
+ self.client.connect_container_to_network(container, net_id)
+ network_data = self.client.inspect_network(net_id)
+ self.assertEqual(
+ list(network_data['containers'].keys()),
+ [container['Id']])
+
+ self.client.disconnect_container_from_network(container, net_id)
+ network_data = self.client.inspect_network(net_id)
+ self.assertFalse(network_data.get('containers'))
+
+ def test_connect_on_container_create(self):
+ net_name, net_id = self.create_network()
+
+ container = self.client.create_container(
+ image='busybox',
+ command='top',
+ host_config=self.client.create_host_config(network_mode=net_name),
+ )
+ self.tmp_containers.append(container)
+ self.client.start(container)
+
+ network_data = self.client.inspect_network(net_id)
+ self.assertEqual(
+ list(network_data['containers'].keys()),
+ [container['Id']])
+
+ self.client.disconnect_container_from_network(container, net_id)
+ network_data = self.client.inspect_network(net_id)
+ self.assertFalse(network_data.get('containers'))
+
+
#######################
# PY SPECIFIC TESTS #
#######################
diff --git a/tests/test.py b/tests/test.py
index 719ac9e..42c925f 100644
--- a/tests/test.py
+++ b/tests/test.py
@@ -369,6 +369,41 @@ class DockerClientTest(Cleanup, base.BaseTestCase):
timeout=DEFAULT_TIMEOUT_SECONDS
)
+ def test_list_networks(self):
+ networks = [
+ {
+ "name": "none",
+ "id": "8e4e55c6863ef424",
+ "type": "null",
+ "endpoints": []
+ },
+ {
+ "name": "host",
+ "id": "062b6d9ea7913fde",
+ "type": "host",
+ "endpoints": []
+ },
+ ]
+
+ get = mock.Mock(return_value=response(
+ status_code=200, content=json.dumps(networks).encode('utf-8')))
+
+ with mock.patch('docker.Client.get', get):
+ self.assertEqual(self.client.networks(), networks)
+
+ self.assertEqual(get.call_args[0][0], url_prefix + 'networks')
+
+ filters = json.loads(get.call_args[1]['params']['filters'])
+ self.assertFalse(filters)
+
+ self.client.networks(names=['foo'])
+ filters = json.loads(get.call_args[1]['params']['filters'])
+ self.assertEqual(filters, {'name': ['foo']})
+
+ self.client.networks(ids=['123'])
+ filters = json.loads(get.call_args[1]['params']['filters'])
+ self.assertEqual(filters, {'id': ['123']})
+
#####################
# CONTAINER TESTS #
#####################
@@ -2229,6 +2264,105 @@ class DockerClientTest(Cleanup, base.BaseTestCase):
self.assertEqual(args[0][0], 'DELETE')
self.assertEqual(args[0][1], '{0}volumes/{1}'.format(url_prefix, name))
+ #####################
+ # NETWORK TESTS #
+ #####################
+
+ def test_create_network(self):
+ network_data = {
+ "id": 'abc12345',
+ "warning": "",
+ }
+
+ network_response = response(status_code=200, content=network_data)
+ post = mock.Mock(return_value=network_response)
+
+ with mock.patch('docker.Client.post', post):
+ result = self.client.create_network('foo')
+ self.assertEqual(result, network_data)
+
+ self.assertEqual(
+ post.call_args[0][0],
+ url_prefix + 'networks/create')
+
+ self.assertEqual(
+ json.loads(post.call_args[1]['data']),
+ {"name": "foo"})
+
+ self.client.create_network('foo', 'bridge')
+
+ self.assertEqual(
+ json.loads(post.call_args[1]['data']),
+ {"name": "foo", "driver": "bridge"})
+
+ def test_remove_network(self):
+ network_id = 'abc12345'
+ delete = mock.Mock(return_value=response(status_code=200))
+
+ with mock.patch('docker.Client.delete', delete):
+ self.client.remove_network(network_id)
+
+ args = delete.call_args
+ self.assertEqual(args[0][0],
+ url_prefix + 'networks/{0}'.format(network_id))
+
+ def test_inspect_network(self):
+ network_id = 'abc12345'
+ network_name = 'foo'
+ network_data = {
+ six.u('name'): network_name,
+ six.u('id'): network_id,
+ six.u('driver'): 'bridge',
+ six.u('containers'): {},
+ }
+
+ network_response = response(status_code=200, content=network_data)
+ get = mock.Mock(return_value=network_response)
+
+ with mock.patch('docker.Client.get', get):
+ result = self.client.inspect_network(network_id)
+ self.assertEqual(result, network_data)
+
+ args = get.call_args
+ self.assertEqual(args[0][0],
+ url_prefix + 'networks/{0}'.format(network_id))
+
+ def test_connect_container_to_network(self):
+ network_id = 'abc12345'
+ container_id = 'def45678'
+
+ post = mock.Mock(return_value=response(status_code=201))
+
+ with mock.patch('docker.Client.post', post):
+ self.client.connect_container_to_network(
+ {'Id': container_id}, network_id)
+
+ self.assertEqual(
+ post.call_args[0][0],
+ url_prefix + 'networks/{0}/connect'.format(network_id))
+
+ self.assertEqual(
+ json.loads(post.call_args[1]['data']),
+ {'container': container_id})
+
+ def test_disconnect_container_from_network(self):
+ network_id = 'abc12345'
+ container_id = 'def45678'
+
+ post = mock.Mock(return_value=response(status_code=201))
+
+ with mock.patch('docker.Client.post', post):
+ self.client.disconnect_container_from_network(
+ {'Id': container_id}, network_id)
+
+ self.assertEqual(
+ post.call_args[0][0],
+ url_prefix + 'networks/{0}/disconnect'.format(network_id))
+
+ self.assertEqual(
+ json.loads(post.call_args[1]['data']),
+ {'container': container_id})
+
#######################
# PY SPECIFIC TESTS #
#######################