From f5924c386384dec09c69c34f08bba4dd08736109 Mon Sep 17 00:00:00 2001 From: Ulises Reyes Date: Sat, 14 Dec 2013 22:00:08 -0500 Subject: [PATCH 1/5] Updated the port function in order to parse the new NetworkSettings Port dict (fixes #88) --- docker/client.py | 12 +++---- tests/fake_api.py | 66 +++++++++++++++++++++++++++++++++++++++ tests/integration_test.py | 16 ++++++++++ tests/test.py | 16 +++++++--- 4 files changed, 99 insertions(+), 11 deletions(-) diff --git a/docker/client.py b/docker/client.py index fd4c9e19..68088d89 100644 --- a/docker/client.py +++ b/docker/client.py @@ -540,13 +540,13 @@ class Client(requests.Session): self._raise_for_status(res) json_ = res.json() s_port = str(private_port) - f_port = None - if s_port in json_['NetworkSettings']['PortMapping']['Udp']: - f_port = json_['NetworkSettings']['PortMapping']['Udp'][s_port] - elif s_port in json_['NetworkSettings']['PortMapping']['Tcp']: - f_port = json_['NetworkSettings']['PortMapping']['Tcp'][s_port] + host_port_bindings = None - return f_port + host_port_bindings = json_['NetworkSettings']['Ports'].get(s_port +'/udp') + if host_port_bindings is None: + host_port_bindings = json_['NetworkSettings']['Ports'].get(s_port + '/tcp') + + return host_port_bindings def pull(self, repository, tag=None, stream=False): registry, repo_name = auth.resolve_repository_name(repository) diff --git a/tests/fake_api.py b/tests/fake_api.py index 3d5a1605..ce89dc94 100644 --- a/tests/fake_api.py +++ b/tests/fake_api.py @@ -156,6 +156,70 @@ def get_fake_inspect_image(): } return status_code, response +def get_fake_port(): + status_code = 200 + response = {'Args': [], + 'Config': {'AttachStderr': True, + 'AttachStdin': False, + 'AttachStdout': True, + 'Cmd': ['yes'], + 'CpuShares': 0, + 'Dns': None, + 'Domainname': '', + 'Entrypoint': None, + 'Env': None, + 'ExposedPorts': {'1111': {}, '2222': {}}, + 'Hostname': 'a398832bc87e', + 'Image': 'ubuntu', + 'Memory': 0, + 'MemorySwap': 0, + 'NetworkDisabled': False, + 'OpenStdin': False, + 'PortSpecs': None, + 'StdinOnce': False, + 'Tty': False, + 'User': '', + 'Volumes': None, + 'VolumesFrom': '', + 'WorkingDir': ''}, + 'Created': '2013-12-14T17:41:13.976760086Z', + 'Driver': 'aufs', + 'HostConfig': {'Binds': None, + 'ContainerIDFile': '', + 'Links': None, + 'LxcConf': None, + 'PortBindings': {'1111': None, + '1111/tcp': [{'HostIp': '127.0.0.1', 'HostPort': '4567'}], + '2222': None}, + 'Privileged': False, + 'PublishAllPorts': False}, + 'HostnamePath': '/var/lib/docker/containers/a398832bc87e15b220d710a98386493559df2448480fc9243e86ee5544eea767/hostname', + 'HostsPath': '/var/lib/docker/containers/a398832bc87e15b220d710a98386493559df2448480fc9243e86ee5544eea767/hosts', + 'ID': 'a398832bc87e15b220d710a98386493559df2448480fc9243e86ee5544eea767', + 'Image': '8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c', + 'Name': '/sad_tesla7', + 'NetworkSettings': {'Bridge': 'docker0', + 'Gateway': '172.17.42.1', + 'IPAddress': '172.17.0.19', + 'IPPrefixLen': 16, + 'PortMapping': None, + 'Ports': {'1111': None, + '1111/tcp': [{'HostIp': '127.0.0.1', 'HostPort': '4567'}], + '2222': None}}, + 'Path': 'yes', + 'ResolvConfPath': '/var/lib/docker/containers/a398832bc87e15b220d710a98386493559df2448480fc9243e86ee5544eea767/resolv.conf', + 'State': {'ExitCode': 0, + 'FinishedAt': '0001-01-01T00:00:00Z', + 'Ghost': False, + 'Pid': 11703, + 'Running': True, + 'StartedAt': '2013-12-14T17:41:27.844076587Z'}, + 'SysInitPath': '/usr/bin/docker', + 'Volumes': {}, + 'VolumesRW': {}} + + + return status_code, response def get_fake_insert_image(): status_code = 200 @@ -282,6 +346,8 @@ fake_responses = { post_fake_stop_container, '{1}/{0}/containers/3cc2351ab11b/kill'.format(CURRENT_VERSION, prefix): post_fake_kill_container, + '{1}/{0}/containers/3cc2351ab11b/json'.format(CURRENT_VERSION, prefix): + get_fake_port, '{1}/{0}/containers/3cc2351ab11b/restart'.format(CURRENT_VERSION, prefix): post_fake_restart_container, '{1}/{0}/containers/3cc2351ab11b'.format(CURRENT_VERSION, prefix): diff --git a/tests/integration_test.py b/tests/integration_test.py index c81cbaa2..8461483a 100644 --- a/tests/integration_test.py +++ b/tests/integration_test.py @@ -402,6 +402,22 @@ class TestKillWithSignal(BaseTestCase): self.assertIn('Running', state) self.assertEqual(state['Running'], False, state) +class TestPort(BaseTestCase): + def runTest(self): + container = self.client.create_container('busybox', ['sleep', '9999'], ports=[1111, 2222]) + id = container['Id'] + self.client.start(container, port_bindings={1111: ('127.0.0.1', 4567)}) + port_bindings = self.client.port(container, 1111) + self.assertIsInstance(port_bindings, list) + self.assertEqual(len(port_bindings), 1) + + port_binding = port_bindings.pop() + self.assertIn('HostPort', port_binding) + self.assertIn('HostIp', port_binding) + + self.assertTrue(port_binding['HostPort']) + + self.client.kill(id) class TestRestart(BaseTestCase): def runTest(self): diff --git a/tests/test.py b/tests/test.py index 5d0ce38d..a6625718 100644 --- a/tests/test.py +++ b/tests/test.py @@ -33,11 +33,6 @@ try: except ImportError: import mock - -# FIXME: missing tests for -# port; - - def response(status_code=200, content='', headers=None, reason=None, elapsed=0, request=None): res = requests.Response() @@ -587,6 +582,17 @@ class DockerClientTest(unittest.TestCase): timeout=docker.client.DEFAULT_TIMEOUT_SECONDS ) + def test_port(self): + try: + self.client.port({'Id': fake_api.FAKE_CONTAINER_ID}, 1111) + except Exception as e: + self.fail('Command should not raise exception: {0}'.format(e)) + + fake_request.assert_called_with( + 'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/json', + timeout=docker.client.DEFAULT_TIMEOUT_SECONDS + ) + def test_stop_container(self): try: self.client.stop(fake_api.FAKE_CONTAINER_ID, timeout=2) From a7c1449757bb471eb86291295cf206dcc55c1b78 Mon Sep 17 00:00:00 2001 From: Ulises Reyes Date: Sat, 14 Dec 2013 22:24:19 -0500 Subject: [PATCH 2/5] Improved assertions in the port test --- tests/integration_test.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/integration_test.py b/tests/integration_test.py index 8461483a..694005bb 100644 --- a/tests/integration_test.py +++ b/tests/integration_test.py @@ -402,20 +402,25 @@ class TestKillWithSignal(BaseTestCase): self.assertIn('Running', state) self.assertEqual(state['Running'], False, state) + class TestPort(BaseTestCase): def runTest(self): container = self.client.create_container('busybox', ['sleep', '9999'], ports=[1111, 2222]) id = container['Id'] - self.client.start(container, port_bindings={1111: ('127.0.0.1', 4567)}) + self.client.start(container, port_bindings={ + 1111: ('127.0.0.1', 4567), + }) port_bindings = self.client.port(container, 1111) self.assertIsInstance(port_bindings, list) self.assertEqual(len(port_bindings), 1) + print port_bindings port_binding = port_bindings.pop() self.assertIn('HostPort', port_binding) self.assertIn('HostIp', port_binding) - self.assertTrue(port_binding['HostPort']) + self.assertEqual(port_binding['HostPort'], '4567') + self.assertEqual(port_binding['HostIp'], '127.0.0.1') self.client.kill(id) From daa3a1e2ef3ea43f034af6ca665442247f65ae1e Mon Sep 17 00:00:00 2001 From: Ulises Reyes Date: Sat, 14 Dec 2013 22:28:45 -0500 Subject: [PATCH 3/5] Shortened lines --- docker/client.py | 10 +++++----- tests/integration_test.py | 3 ++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/docker/client.py b/docker/client.py index 68088d89..5b90f249 100644 --- a/docker/client.py +++ b/docker/client.py @@ -540,13 +540,13 @@ class Client(requests.Session): self._raise_for_status(res) json_ = res.json() s_port = str(private_port) - host_port_bindings = None + h_ports = None - host_port_bindings = json_['NetworkSettings']['Ports'].get(s_port +'/udp') - if host_port_bindings is None: - host_port_bindings = json_['NetworkSettings']['Ports'].get(s_port + '/tcp') + h_ports = json_['NetworkSettings']['Ports'].get(s_port + '/udp') + if h_ports is None: + h_ports = json_['NetworkSettings']['Ports'].get(s_port + '/tcp') - return host_port_bindings + return h_ports def pull(self, repository, tag=None, stream=False): registry, repo_name = auth.resolve_repository_name(repository) diff --git a/tests/integration_test.py b/tests/integration_test.py index 694005bb..4da31642 100644 --- a/tests/integration_test.py +++ b/tests/integration_test.py @@ -405,7 +405,8 @@ class TestKillWithSignal(BaseTestCase): class TestPort(BaseTestCase): def runTest(self): - container = self.client.create_container('busybox', ['sleep', '9999'], ports=[1111, 2222]) + container = self.client.create_container('busybox', ['sleep', '9999'], + ports=[1111, 2222]) id = container['Id'] self.client.start(container, port_bindings={ 1111: ('127.0.0.1', 4567), From 844e41088e62fbc4d7aec42f31a25fe902426644 Mon Sep 17 00:00:00 2001 From: Ulises Reyes Date: Sun, 15 Dec 2013 02:11:02 -0500 Subject: [PATCH 4/5] Refactored test. It now makes 2 calls to port --- tests/integration_test.py | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/tests/integration_test.py b/tests/integration_test.py index 4da31642..1720d53d 100644 --- a/tests/integration_test.py +++ b/tests/integration_test.py @@ -402,26 +402,29 @@ class TestKillWithSignal(BaseTestCase): self.assertIn('Running', state) self.assertEqual(state['Running'], False, state) - class TestPort(BaseTestCase): def runTest(self): - container = self.client.create_container('busybox', ['sleep', '9999'], - ports=[1111, 2222]) + + port_bindings = { + 1111 :('127.0.0.1', '4567'), + 2222 :('192.168.0.100', '4568') + } + + container = self.client.create_container('busybox', ['sleep', '60'], + ports=port_bindings.keys()) id = container['Id'] - self.client.start(container, port_bindings={ - 1111: ('127.0.0.1', 4567), - }) - port_bindings = self.client.port(container, 1111) - self.assertIsInstance(port_bindings, list) - self.assertEqual(len(port_bindings), 1) - print port_bindings - port_binding = port_bindings.pop() - self.assertIn('HostPort', port_binding) - self.assertIn('HostIp', port_binding) + self.client.start(container, port_bindings= port_bindings) - self.assertEqual(port_binding['HostPort'], '4567') - self.assertEqual(port_binding['HostIp'], '127.0.0.1') + #Call the port function on each biding and compare expected vs actual + for port in port_bindings: + actual_bindings = self.client.port(container, port) + port_binding = actual_bindings.pop() + + ip, host_port = port_binding['HostIp'], port_binding['HostPort'] + + self.assertEqual(ip, port_bindings[port][0]) + self.assertEqual(host_port, port_bindings[port][1]) self.client.kill(id) From d8e0f5a66f209a667045722a0cd4ae3ead170e34 Mon Sep 17 00:00:00 2001 From: Ulises Reyes Date: Sun, 15 Dec 2013 20:28:38 -0500 Subject: [PATCH 5/5] Improves code style --- tests/fake_api.py | 86 ++++++++++++--------------------------- tests/integration_test.py | 13 +++--- tests/test.py | 1 + 3 files changed, 34 insertions(+), 66 deletions(-) diff --git a/tests/fake_api.py b/tests/fake_api.py index ce89dc94..47f44188 100644 --- a/tests/fake_api.py +++ b/tests/fake_api.py @@ -156,71 +156,35 @@ def get_fake_inspect_image(): } return status_code, response + def get_fake_port(): status_code = 200 - response = {'Args': [], - 'Config': {'AttachStderr': True, - 'AttachStdin': False, - 'AttachStdout': True, - 'Cmd': ['yes'], - 'CpuShares': 0, - 'Dns': None, - 'Domainname': '', - 'Entrypoint': None, - 'Env': None, - 'ExposedPorts': {'1111': {}, '2222': {}}, - 'Hostname': 'a398832bc87e', - 'Image': 'ubuntu', - 'Memory': 0, - 'MemorySwap': 0, - 'NetworkDisabled': False, - 'OpenStdin': False, - 'PortSpecs': None, - 'StdinOnce': False, - 'Tty': False, - 'User': '', - 'Volumes': None, - 'VolumesFrom': '', - 'WorkingDir': ''}, - 'Created': '2013-12-14T17:41:13.976760086Z', - 'Driver': 'aufs', - 'HostConfig': {'Binds': None, - 'ContainerIDFile': '', - 'Links': None, - 'LxcConf': None, - 'PortBindings': {'1111': None, - '1111/tcp': [{'HostIp': '127.0.0.1', 'HostPort': '4567'}], - '2222': None}, - 'Privileged': False, - 'PublishAllPorts': False}, - 'HostnamePath': '/var/lib/docker/containers/a398832bc87e15b220d710a98386493559df2448480fc9243e86ee5544eea767/hostname', - 'HostsPath': '/var/lib/docker/containers/a398832bc87e15b220d710a98386493559df2448480fc9243e86ee5544eea767/hosts', - 'ID': 'a398832bc87e15b220d710a98386493559df2448480fc9243e86ee5544eea767', - 'Image': '8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c', - 'Name': '/sad_tesla7', - 'NetworkSettings': {'Bridge': 'docker0', - 'Gateway': '172.17.42.1', - 'IPAddress': '172.17.0.19', - 'IPPrefixLen': 16, - 'PortMapping': None, - 'Ports': {'1111': None, - '1111/tcp': [{'HostIp': '127.0.0.1', 'HostPort': '4567'}], - '2222': None}}, - 'Path': 'yes', - 'ResolvConfPath': '/var/lib/docker/containers/a398832bc87e15b220d710a98386493559df2448480fc9243e86ee5544eea767/resolv.conf', - 'State': {'ExitCode': 0, - 'FinishedAt': '0001-01-01T00:00:00Z', - 'Ghost': False, - 'Pid': 11703, - 'Running': True, - 'StartedAt': '2013-12-14T17:41:27.844076587Z'}, - 'SysInitPath': '/usr/bin/docker', - 'Volumes': {}, - 'VolumesRW': {}} - - + response = { + 'HostConfig': { + 'Binds': None, + 'ContainerIDFile': '', + 'Links': None, + 'LxcConf': None, + 'PortBindings': { + '1111': None, + '1111/tcp': [{'HostIp': '127.0.0.1', 'HostPort': '4567'}], + '2222': None + }, + 'Privileged': False, + 'PublishAllPorts': False + }, + 'NetworkSettings': { + 'Bridge': 'docker0', + 'PortMapping': None, + 'Ports': { + '1111': None, + '1111/tcp': [{'HostIp': '127.0.0.1', 'HostPort': '4567'}], + '2222': None} + } + } return status_code, response + def get_fake_insert_image(): status_code = 200 response = {'StatusCode': 0} diff --git a/tests/integration_test.py b/tests/integration_test.py index 1720d53d..7405d227 100644 --- a/tests/integration_test.py +++ b/tests/integration_test.py @@ -402,19 +402,21 @@ class TestKillWithSignal(BaseTestCase): self.assertIn('Running', state) self.assertEqual(state['Running'], False, state) + class TestPort(BaseTestCase): def runTest(self): port_bindings = { - 1111 :('127.0.0.1', '4567'), - 2222 :('192.168.0.100', '4568') + 1111: ('127.0.0.1', '4567'), + 2222: ('192.168.0.100', '4568') } - container = self.client.create_container('busybox', ['sleep', '60'], - ports=port_bindings.keys()) + container = self.client.create_container( + 'busybox', ['sleep', '60'], ports=port_bindings.keys() + ) id = container['Id'] - self.client.start(container, port_bindings= port_bindings) + self.client.start(container, port_bindings=port_bindings) #Call the port function on each biding and compare expected vs actual for port in port_bindings: @@ -428,6 +430,7 @@ class TestPort(BaseTestCase): self.client.kill(id) + class TestRestart(BaseTestCase): def runTest(self): container = self.client.create_container('busybox', ['sleep', '9999']) diff --git a/tests/test.py b/tests/test.py index a6625718..e497cdcf 100644 --- a/tests/test.py +++ b/tests/test.py @@ -33,6 +33,7 @@ try: except ImportError: import mock + def response(status_code=200, content='', headers=None, reason=None, elapsed=0, request=None): res = requests.Response()