Merge branch 'timeout-support' of github.com:mpetazzoni/docker-py into mpetazzoni-timeout-support

Conflicts:
	docker/client.py
	tests/integration_test.py
	tests/test.py
This commit is contained in:
shin- 2013-11-15 21:44:18 +01:00
commit 35d3a3c977
5 changed files with 229 additions and 130 deletions

View File

@ -8,7 +8,8 @@ An API client for docker written in Python
API API
=== ===
`docker.Client(base_url='unix://var/run/docker.sock', version="1.4")` `docker.Client(base_url='unix://var/run/docker.sock', version="1.4",
timeout=60)`
Client class. `base_url` refers to the protocol+hostname+port where the docker Client class. `base_url` refers to the protocol+hostname+port where the docker
server is hosted. Version is the version of the API the client will use. server is hosted. Version is the version of the API the client will use.

View File

@ -28,6 +28,8 @@ import docker.utils as utils
if not six.PY3: if not six.PY3:
import websocket import websocket
DEFAULT_TIMEOUT_SECONDS = 60
class APIError(requests.exceptions.HTTPError): class APIError(requests.exceptions.HTTPError):
def __init__(self, message, response, explanation=None): def __init__(self, message, response, explanation=None):
@ -62,18 +64,36 @@ class APIError(requests.exceptions.HTTPError):
class Client(requests.Session): class Client(requests.Session):
def __init__(self, base_url="unix://var/run/docker.sock", version="1.6"): def __init__(self, base_url="unix://var/run/docker.sock", version="1.6",
timeout=DEFAULT_TIMEOUT_SECONDS):
super(Client, self).__init__() super(Client, self).__init__()
if base_url.startswith('unix:///'): if base_url.startswith('unix:///'):
base_url = base_url.replace('unix:/', 'unix:') base_url = base_url.replace('unix:/', 'unix:')
self.mount('unix://', unixconn.UnixAdapter(base_url))
self.base_url = base_url self.base_url = base_url
self._version = version self._version = version
self._timeout = timeout
self.mount('unix://', unixconn.UnixAdapter(base_url, timeout))
try: try:
self._cfg = auth.load_config() self._cfg = auth.load_config()
except Exception: except Exception:
pass pass
def _set_request_timeout(self, kwargs):
"""Prepare the kwargs for an HTTP request by inserting the timeout
parameter, if not already present."""
kwargs.setdefault('timeout', self._timeout)
return kwargs
def _post(self, url, **kwargs):
return self.post(url, **self._set_request_timeout(kwargs))
def _get(self, url, **kwargs):
return self.get(url, **self._set_request_timeout(kwargs))
def _delete(self, url, **kwargs):
return self.delete(url, **self._set_request_timeout(kwargs))
def _url(self, path): def _url(self, path):
return '{0}/v{1}{2}'.format(self.base_url, self._version, path) return '{0}/v{1}{2}'.format(self.base_url, self._version, path)
@ -155,7 +175,7 @@ class Client(requests.Session):
if 'headers' not in kwargs: if 'headers' not in kwargs:
kwargs['headers'] = {} kwargs['headers'] = {}
kwargs['headers']['Content-Type'] = 'application/json' kwargs['headers']['Content-Type'] = 'application/json'
return self.post(url, json.dumps(data2), **kwargs) return self._post(url, data=json.dumps(data2), **kwargs)
def _attach_params(self, override=None): def _attach_params(self, override=None):
return override or { return override or {
@ -243,8 +263,11 @@ class Client(requests.Session):
} }
if context is not None: if context is not None:
headers = {'Content-Type': 'application/tar'} headers = {'Content-Type': 'application/tar'}
response = self.post(
u, context, params=params, headers=headers, stream=stream) response = self._post(
u, data=context, params=params, headers=headers, stream=stream
)
if context is not None: if context is not None:
context.close() context.close()
if stream: if stream:
@ -267,7 +290,8 @@ class Client(requests.Session):
'author': author 'author': author
} }
u = self._url("/commit") u = self._url("/commit")
return self._result(self._post_json(u, conf, params=params), json=True) return self._result(self._post_json(u, data=conf, params=params),
json=True)
def containers(self, quiet=False, all=False, trunc=True, latest=False, def containers(self, quiet=False, all=False, trunc=True, latest=False,
since=None, before=None, limit=-1): since=None, before=None, limit=-1):
@ -279,7 +303,8 @@ class Client(requests.Session):
'before': before 'before': before
} }
u = self._url("/containers/json") u = self._url("/containers/json")
res = self._result(self.get(u, params=params), True) res = self._result(self._get(u, params=params), True)
if quiet: if quiet:
return [{'Id': x['Id']} for x in res] return [{'Id': x['Id']} for x in res]
return res return res
@ -287,7 +312,7 @@ class Client(requests.Session):
def copy(self, container, resource): def copy(self, container, resource):
res = self._post_json( res = self._post_json(
self._url("/containers/{0}/copy".format(container)), self._url("/containers/{0}/copy".format(container)),
{"Resource": resource}, data={"Resource": resource},
stream=True stream=True
) )
self._raise_for_status(res) self._raise_for_status(res)
@ -310,13 +335,13 @@ class Client(requests.Session):
params = { params = {
'name': name 'name': name
} }
res = self._post_json(u, config, params=params) res = self._post_json(u, data=config, params=params)
return self._result(res, True) return self._result(res, True)
def diff(self, container): def diff(self, container):
if isinstance(container, dict): if isinstance(container, dict):
container = container.get('Id') container = container.get('Id')
return self._result(self.get(self._url("/containers/{0}/changes". return self._result(self._get(self._url("/containers/{0}/changes".
format(container))), True) format(container))), True)
def events(self): def events(self):
@ -339,25 +364,25 @@ class Client(requests.Session):
def export(self, container): def export(self, container):
if isinstance(container, dict): if isinstance(container, dict):
container = container.get('Id') container = container.get('Id')
res = self.get(self._url("/containers/{0}/export".format(container)), res = self._get(self._url("/containers/{0}/export".format(container)),
stream=True) stream=True)
self._raise_for_status(res) self._raise_for_status(res)
return res.raw return res.raw
def history(self, image): def history(self, image):
res = self.get(self._url("/images/{0}/history".format(image))) res = self._get(self._url("/images/{0}/history".format(image)))
self._raise_for_status(res) self._raise_for_status(res)
return self._result(res) return self._result(res)
def images(self, name=None, quiet=False, all=False, viz=False): def images(self, name=None, quiet=False, all=False, viz=False):
if viz: if viz:
return self._result(self.get(self._url("images/viz"))) return self._result(self._get(self._url("images/viz")))
params = { params = {
'filter': name, 'filter': name,
'only_ids': 1 if quiet else 0, 'only_ids': 1 if quiet else 0,
'all': 1 if all else 0, 'all': 1 if all else 0,
} }
res = self._result(self.get(self._url("/images/json"), params=params), res = self._result(self._get(self._url("/images/json"), params=params),
True) True)
if quiet: if quiet:
return [x['Id'] for x in res] return [x['Id'] for x in res]
@ -381,12 +406,13 @@ class Client(requests.Session):
data = None data = None
if isinstance(src, six.string_types): if isinstance(src, six.string_types):
params['fromSrc'] = src params['fromSrc'] = src
return self._result(self.post(u, data, params=params)) return self._result(self._post(u, data=data, params=params))
return self._result(self.post(u, src, params=params)) return self._result(self._post(u, data=src, params=params))
def info(self): def info(self):
return self._result(self.get(self._url("/info")), True) return self._result(self._get(self._url("/info")),
True)
def insert(self, image, url, path): def insert(self, image, url, path):
api_url = self._url("/images/" + image + "/insert") api_url = self._url("/images/" + image + "/insert")
@ -394,19 +420,20 @@ class Client(requests.Session):
'url': url, 'url': url,
'path': path 'path': path
} }
return self._result(self.post(api_url, None, params=params)) return self._result(self._post(api_url, params=params))
def inspect_container(self, container): def inspect_container(self, container):
if isinstance(container, dict): if isinstance(container, dict):
container = container.get('Id') container = container.get('Id')
return self._result(self.get( return self._result(
self._url("/containers/{0}/json".format(container)) self._get(self._url("/containers/{0}/json".format(container))),
), True) True)
def inspect_image(self, image_id): def inspect_image(self, image_id):
return self._result(self.get( return self._result(
self._url("/images/{0}/json".format(image_id)) self._get(self._url("/images/{0}/json".format(image_id))),
), True) True
)
def kill(self, container, signal=None): def kill(self, container, signal=None):
if isinstance(container, dict): if isinstance(container, dict):
@ -415,7 +442,8 @@ class Client(requests.Session):
params = {} params = {}
if signal is not None: if signal is not None:
params['signal'] = signal params['signal'] = signal
res = self.post(url, None, params=params) res = self._post(url, params=params)
self._raise_for_status(res) self._raise_for_status(res)
def login(self, username, password=None, email=None, registry=None): def login(self, username, password=None, email=None, registry=None):
@ -432,7 +460,7 @@ class Client(requests.Session):
'password': password, 'password': password,
'email': email 'email': email
} }
res = self._result(self._post_json(url, req_data), True) res = self._result(self._post_json(url, data=req_data), True)
if res['Status'] == 'Login Succeeded': if res['Status'] == 'Login Succeeded':
self._cfg['Configs'][registry] = req_data self._cfg['Configs'][registry] = req_data
return res return res
@ -447,9 +475,9 @@ class Client(requests.Session):
} }
u = self._url("/containers/{0}/attach".format(container)) u = self._url("/containers/{0}/attach".format(container))
if utils.compare_version('1.6', self._version) < 0: if utils.compare_version('1.6', self._version) < 0:
return self._result(self.post(u, None, params=params)) return self._result(self._post(u, params=params))
res = '' res = ''
response = self._result(self.post(u, None, params=params)) response = self._result(self._post(u, params=params))
walker = 0 walker = 0
while walker < len(response): while walker < len(response):
header = response[walker:walker+8] header = response[walker:walker+8]
@ -464,7 +492,7 @@ class Client(requests.Session):
def port(self, container, private_port): def port(self, container, private_port):
if isinstance(container, dict): if isinstance(container, dict):
container = container.get('Id') container = container.get('Id')
res = self.get(self._url("/containers/{0}/json".format(container))) res = self._get(self._url("/containers/{0}/json".format(container)))
self._raise_for_status(res) self._raise_for_status(res)
json_ = res.json() json_ = res.json()
s_port = str(private_port) s_port = str(private_port)
@ -496,7 +524,7 @@ class Client(requests.Session):
if authcfg: if authcfg:
headers['X-Registry-Auth'] = auth.encode_header(authcfg) headers['X-Registry-Auth'] = auth.encode_header(authcfg)
u = self._url("/images/create") u = self._url("/images/create")
response = self.post(u, params=params, headers=headers, stream=stream) response = self._post(u, params=params, headers=headers, stream=stream)
if stream: if stream:
return self._stream_helper(response) return self._stream_helper(response)
@ -515,6 +543,7 @@ class Client(requests.Session):
# for this specific registry as we can have an anon push # for this specific registry as we can have an anon push
if authcfg: if authcfg:
headers['X-Registry-Auth'] = auth.encode_header(authcfg) headers['X-Registry-Auth'] = auth.encode_header(authcfg)
if stream: if stream:
return self._stream_helper( return self._stream_helper(
self._post_json(u, None, headers=headers, stream=True)) self._post_json(u, None, headers=headers, stream=True))
@ -531,11 +560,12 @@ class Client(requests.Session):
if isinstance(container, dict): if isinstance(container, dict):
container = container.get('Id') container = container.get('Id')
params = {'v': v, 'link': link} params = {'v': v, 'link': link}
res = self.delete(self._url("/containers/" + container), params=params) res = self._delete(self._url("/containers/" + container),
params=params)
self._raise_for_status(res) self._raise_for_status(res)
def remove_image(self, image): def remove_image(self, image):
res = self.delete(self._url("/images/" + image)) res = self._delete(self._url("/images/" + image))
self._raise_for_status(res) self._raise_for_status(res)
def restart(self, container, timeout=10): def restart(self, container, timeout=10):
@ -543,12 +573,13 @@ class Client(requests.Session):
container = container.get('Id') container = container.get('Id')
params = {'t': timeout} params = {'t': timeout}
url = self._url("/containers/{0}/restart".format(container)) url = self._url("/containers/{0}/restart".format(container))
res = self.post(url, None, params=params) res = self._post(url, params=params)
self._raise_for_status(res) self._raise_for_status(res)
def search(self, term): def search(self, term):
return self._result(self.get(self._url("/images/search"), return self._result(self._get(self._url("/images/search"),
params={'term': term}), True) params={'term': term}),
True)
def start(self, container, binds=None, port_bindings=None, lxc_conf=None, def start(self, container, binds=None, port_bindings=None, lxc_conf=None,
publish_all_ports=False, links=None): publish_all_ports=False, links=None):
@ -583,7 +614,7 @@ class Client(requests.Session):
start_config['Links'] = formatted_links start_config['Links'] = formatted_links
url = self._url("/containers/{0}/start".format(container)) url = self._url("/containers/{0}/start".format(container))
res = self._post_json(url, start_config) res = self._post_json(url, data=start_config)
self._raise_for_status(res) self._raise_for_status(res)
def stop(self, container, timeout=10): def stop(self, container, timeout=10):
@ -591,7 +622,8 @@ class Client(requests.Session):
container = container.get('Id') container = container.get('Id')
params = {'t': timeout} params = {'t': timeout}
url = self._url("/containers/{0}/stop".format(container)) url = self._url("/containers/{0}/stop".format(container))
res = self.post(url, None, params=params) res = self._post(url, params=params,
timeout=max(timeout, self._timeout))
self._raise_for_status(res) self._raise_for_status(res)
def tag(self, image, repository, tag=None, force=False): def tag(self, image, repository, tag=None, force=False):
@ -601,22 +633,22 @@ class Client(requests.Session):
'force': 1 if force else 0 'force': 1 if force else 0
} }
url = self._url("/images/{0}/tag".format(image)) url = self._url("/images/{0}/tag".format(image))
res = self.post(url, None, params=params) res = self._post(url, params=params)
self._raise_for_status(res) self._raise_for_status(res)
return res.status_code == 201 return res.status_code == 201
def top(self, container): def top(self, container):
u = self._url("/containers/{0}/top".format(container)) u = self._url("/containers/{0}/top".format(container))
return self._result(self.get(u), True) return self._result(self._get(u), True)
def version(self): def version(self):
return self._result(self.get(self._url("/version")), True) return self._result(self._get(self._url("/version")), True)
def wait(self, container): def wait(self, container):
if isinstance(container, dict): if isinstance(container, dict):
container = container.get('Id') container = container.get('Id')
url = self._url("/containers/{0}/wait".format(container)) url = self._url("/containers/{0}/wait".format(container))
res = self.post(url, None, timeout=None) res = self._post(url, timeout=None)
self._raise_for_status(res) self._raise_for_status(res)
json_ = res.json() json_ = res.json()
if 'StatusCode' in json_: if 'StatusCode' in json_:

View File

@ -27,13 +27,15 @@ except ImportError:
class UnixHTTPConnection(httplib.HTTPConnection, object): class UnixHTTPConnection(httplib.HTTPConnection, object):
def __init__(self, base_url, unix_socket): def __init__(self, base_url, unix_socket, timeout=60):
httplib.HTTPConnection.__init__(self, 'localhost') httplib.HTTPConnection.__init__(self, 'localhost', timeout=timeout)
self.base_url = base_url self.base_url = base_url
self.unix_socket = unix_socket self.unix_socket = unix_socket
self.timeout = timeout
def connect(self): def connect(self):
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.settimeout(self.timeout)
sock.connect(self.base_url.replace("unix:/", "")) sock.connect(self.base_url.replace("unix:/", ""))
self.sock = sock self.sock = sock
@ -47,19 +49,23 @@ class UnixHTTPConnection(httplib.HTTPConnection, object):
class UnixHTTPConnectionPool(connectionpool.HTTPConnectionPool): class UnixHTTPConnectionPool(connectionpool.HTTPConnectionPool):
def __init__(self, base_url, socket_path): def __init__(self, base_url, socket_path, timeout=60):
self.socket_path = socket_path connectionpool.HTTPConnectionPool.__init__(self, 'localhost',
timeout=timeout)
self.base_url = base_url self.base_url = base_url
super(UnixHTTPConnectionPool, self).__init__(self, 'localhost') self.socket_path = socket_path
self.timeout = timeout
def _new_conn(self): def _new_conn(self):
return UnixHTTPConnection(self.base_url, self.socket_path) return UnixHTTPConnection(self.base_url, self.socket_path,
self.timeout)
class UnixAdapter(requests.adapters.HTTPAdapter): class UnixAdapter(requests.adapters.HTTPAdapter):
def __init__(self, base_url): def __init__(self, base_url, timeout=60):
self.base_url = base_url self.base_url = base_url
self.timeout = timeout
super(UnixAdapter, self).__init__() super(UnixAdapter, self).__init__()
def get_connection(self, socket_path, proxies=None): def get_connection(self, socket_path, proxies=None):
return UnixHTTPConnectionPool(self.base_url, socket_path) return UnixHTTPConnectionPool(self.base_url, socket_path, self.timeout)

View File

@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import time
import base64 import base64
import io import io
import os import os
@ -74,9 +75,9 @@ class TestSearch(BaseTestCase):
def runTest(self): def runTest(self):
res = self.client.search('busybox') res = self.client.search('busybox')
self.assertTrue(len(res) >= 1) self.assertTrue(len(res) >= 1)
base_img = [x for x in res if x['Name'] == 'busybox'] base_img = [x for x in res if x['name'] == 'busybox']
self.assertEqual(len(base_img), 1) self.assertEqual(len(base_img), 1)
self.assertIn('Description', base_img[0]) self.assertIn('description', base_img[0])
################### ###################
## LISTING TESTS ## ## LISTING TESTS ##
@ -166,8 +167,9 @@ class TestCreateContainerPrivileged(BaseTestCase):
res = self.client.create_container('busybox', 'true', privileged=True) res = self.client.create_container('busybox', 'true', privileged=True)
inspect = self.client.inspect_container(res['Id']) inspect = self.client.inspect_container(res['Id'])
self.assertIn('Config', inspect) self.assertIn('Config', inspect)
# In newer versions of docker, the "Privileged" flag is no # Since Nov 2013, the Privileged flag is no longer part of the
# longer exposed in the API # container's config exposed via the API (safety concerns?).
#
# self.assertEqual(inspect['Config']['Privileged'], True) # self.assertEqual(inspect['Config']['Privileged'], True)
@ -750,5 +752,25 @@ class TestLoadConfig(BaseTestCase):
self.assertEqual(cfg['Email'], 'sakuya@scarlet.net') self.assertEqual(cfg['Email'], 'sakuya@scarlet.net')
self.assertEqual(cfg.get('Auth'), None) self.assertEqual(cfg.get('Auth'), None)
class TestConnectionTimeout(unittest.TestCase):
def setUp(self):
self.timeout = 0.5
self.client = docker.client.Client(base_url='http://192.168.10.2:4243',
timeout=self.timeout)
def runTest(self):
start = time.time()
res = None
# This call isn't supposed to complete, and it should fail fast.
try:
res = self.client.inspect_container('id')
except:
pass
end = time.time()
self.assertTrue(res is None)
self.assertTrue(end - start < 2 * self.timeout)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()

View File

@ -79,7 +79,8 @@ class DockerClientTest(unittest.TestCase):
self.fail('Command should not raise exception: {0}'.format(e)) self.fail('Command should not raise exception: {0}'.format(e))
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/version' 'unix://var/run/docker.sock/v1.6/version',
timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
) )
def test_info(self): def test_info(self):
@ -88,7 +89,10 @@ class DockerClientTest(unittest.TestCase):
except Exception as e: except Exception as e:
self.fail('Command should not raise exception: {0}'.format(e)) self.fail('Command should not raise exception: {0}'.format(e))
fake_request.assert_called_with('unix://var/run/docker.sock/v1.6/info') fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/info',
timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
)
def test_search(self): def test_search(self):
try: try:
@ -98,7 +102,8 @@ class DockerClientTest(unittest.TestCase):
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/images/search', 'unix://var/run/docker.sock/v1.6/images/search',
params={'term': 'busybox'} params={'term': 'busybox'},
timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
) )
################### ###################
@ -112,7 +117,8 @@ class DockerClientTest(unittest.TestCase):
self.fail('Command should not raise exception: {0}'.format(e)) self.fail('Command should not raise exception: {0}'.format(e))
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/images/json', 'unix://var/run/docker.sock/v1.6/images/json',
params={'filter': None, 'only_ids': 0, 'all': 1} params={'filter': None, 'only_ids': 0, 'all': 1},
timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
) )
def test_images_quiet(self): def test_images_quiet(self):
@ -122,7 +128,8 @@ class DockerClientTest(unittest.TestCase):
self.fail('Command should not raise exception: {0}'.format(e)) self.fail('Command should not raise exception: {0}'.format(e))
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/images/json', 'unix://var/run/docker.sock/v1.6/images/json',
params={'filter': None, 'only_ids': 1, 'all': 1} params={'filter': None, 'only_ids': 1, 'all': 1},
timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
) )
def test_image_ids(self): def test_image_ids(self):
@ -133,7 +140,8 @@ class DockerClientTest(unittest.TestCase):
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/images/json', 'unix://var/run/docker.sock/v1.6/images/json',
params={'filter': None, 'only_ids': 1, 'all': 0} params={'filter': None, 'only_ids': 1, 'all': 0},
timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
) )
def test_list_containers(self): def test_list_containers(self):
@ -150,7 +158,8 @@ class DockerClientTest(unittest.TestCase):
'limit': -1, 'limit': -1,
'trunc_cmd': 1, 'trunc_cmd': 1,
'before': None 'before': None
} },
timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
) )
##################### #####################
@ -166,7 +175,7 @@ class DockerClientTest(unittest.TestCase):
args = fake_request.call_args args = fake_request.call_args
self.assertEqual(args[0][0], self.assertEqual(args[0][0],
'unix://var/run/docker.sock/v1.6/containers/create') 'unix://var/run/docker.sock/v1.6/containers/create')
self.assertEqual(json.loads(args[0][1]), self.assertEqual(json.loads(args[1]['data']),
json.loads(''' json.loads('''
{"Tty": false, "Image": "busybox", "Cmd": ["true"], {"Tty": false, "Image": "busybox", "Cmd": ["true"],
"AttachStdin": false, "Memory": 0, "AttachStdin": false, "Memory": 0,
@ -188,7 +197,7 @@ class DockerClientTest(unittest.TestCase):
args = fake_request.call_args args = fake_request.call_args
self.assertEqual(args[0][0], self.assertEqual(args[0][0],
'unix://var/run/docker.sock/v1.6/containers/create') 'unix://var/run/docker.sock/v1.6/containers/create')
self.assertEqual(json.loads(args[0][1]), self.assertEqual(json.loads(args[1]['data']),
json.loads(''' json.loads('''
{"Tty": false, "Image": "busybox", {"Tty": false, "Image": "busybox",
"Cmd": ["ls", "/mnt"], "AttachStdin": false, "Cmd": ["ls", "/mnt"], "AttachStdin": false,
@ -207,7 +216,7 @@ class DockerClientTest(unittest.TestCase):
args = fake_request.call_args args = fake_request.call_args
self.assertEqual(args[0][0], self.assertEqual(args[0][0],
'unix://var/run/docker.sock/v1.6/containers/create') 'unix://var/run/docker.sock/v1.6/containers/create')
self.assertEqual(json.loads(args[0][1]), self.assertEqual(json.loads(args[1]['data']),
json.loads(''' json.loads('''
{"Tty": false, "Image": "busybox", "Cmd": ["true"], {"Tty": false, "Image": "busybox", "Cmd": ["true"],
"AttachStdin": false, "Memory": 0, "AttachStdin": false, "Memory": 0,
@ -226,7 +235,7 @@ class DockerClientTest(unittest.TestCase):
args = fake_request.call_args args = fake_request.call_args
self.assertEqual(args[0][0], self.assertEqual(args[0][0],
'unix://var/run/docker.sock/v1.6/containers/create') 'unix://var/run/docker.sock/v1.6/containers/create')
self.assertEqual(json.loads(args[0][1]), self.assertEqual(json.loads(args[1]['data']),
json.loads(''' json.loads('''
{"Tty": false, "Image": "busybox", "Cmd": ["true"], {"Tty": false, "Image": "busybox", "Cmd": ["true"],
"AttachStdin": false, "Memory": 0, "AttachStdin": false, "Memory": 0,
@ -244,8 +253,9 @@ class DockerClientTest(unittest.TestCase):
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/start', 'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/start',
'{"PublishAllPorts": false}', data='{"PublishAllPorts": false}',
headers={'Content-Type': 'application/json'} headers={'Content-Type': 'application/json'},
timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
) )
def test_start_container_with_lxc_conf(self): def test_start_container_with_lxc_conf(self):
@ -257,15 +267,19 @@ class DockerClientTest(unittest.TestCase):
except Exception as e: except Exception as e:
self.fail('Command should not raise exception: {0}'.format(e)) self.fail('Command should not raise exception: {0}'.format(e))
args = fake_request.call_args args = fake_request.call_args
self.assertEqual(args[0][0], 'unix://var/run/docker.sock/v1.6/'
'containers/3cc2351ab11b/start')
self.assertEqual( self.assertEqual(
json.loads(args[0][1]), args[0][0],
'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/start'
)
self.assertEqual(
json.loads(args[1]['data']),
{"LxcConf": [{"Value": "lxc.conf.value", "Key": "lxc.conf.k"}], {"LxcConf": [{"Value": "lxc.conf.value", "Key": "lxc.conf.k"}],
"PublishAllPorts": False} "PublishAllPorts": False}
) )
self.assertEqual(args[1]['headers'], self.assertEqual(
{'Content-Type': 'application/json'}) args[1]['headers'],
{'Content-Type': 'application/json'}
)
def test_start_container_with_lxc_conf_compat(self): def test_start_container_with_lxc_conf_compat(self):
try: try:
@ -275,13 +289,16 @@ class DockerClientTest(unittest.TestCase):
) )
except Exception as e: except Exception as e:
self.fail('Command should not raise exception: {0}'.format(e)) self.fail('Command should not raise exception: {0}'.format(e))
args = fake_request.call_args args = fake_request.call_args
self.assertEqual(args[0][0], 'unix://var/run/docker.sock/v1.6/' self.assertEqual(args[0][0], 'unix://var/run/docker.sock/v1.6/'
'containers/3cc2351ab11b/start') 'containers/3cc2351ab11b/start')
self.assertEqual( self.assertEqual(
json.loads(args[0][1]), json.loads(args[1]['data']),
{"LxcConf": [{"Value": "lxc.conf.value", "Key": "lxc.conf.k"}], {
"PublishAllPorts": False} "LxcConf": [{"Value": "lxc.conf.value", "Key": "lxc.conf.k"}],
"PublishAllPorts": False
}
) )
self.assertEqual(args[1]['headers'], self.assertEqual(args[1]['headers'],
{'Content-Type': 'application/json'}) {'Content-Type': 'application/json'})
@ -298,10 +315,14 @@ class DockerClientTest(unittest.TestCase):
args = fake_request.call_args args = fake_request.call_args
self.assertEqual(args[0][0], 'unix://var/run/docker.sock/v1.6/' self.assertEqual(args[0][0], 'unix://var/run/docker.sock/v1.6/'
'containers/3cc2351ab11b/start') 'containers/3cc2351ab11b/start')
self.assertEqual(json.loads(args[0][1]), self.assertEqual(json.loads(args[1]['data']),
{"Binds": ["/tmp:/mnt"], "PublishAllPorts": False}) {"Binds": ["/tmp:/mnt"], "PublishAllPorts": False})
self.assertEqual(args[1]['headers'], self.assertEqual(args[1]['headers'],
{'Content-Type': 'application/json'}) {'Content-Type': 'application/json'})
self.assertEqual(
args[1]['timeout'],
docker.client.DEFAULT_TIMEOUT_SECONDS
)
def test_start_container_with_links(self): def test_start_container_with_links(self):
# one link # one link
@ -319,7 +340,7 @@ class DockerClientTest(unittest.TestCase):
'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/start' 'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/start'
) )
self.assertEqual( self.assertEqual(
json.loads(args[0][1]), json.loads(args[1]['data']),
{"PublishAllPorts": False, "Links": ["path:alias"]} {"PublishAllPorts": False, "Links": ["path:alias"]}
) )
self.assertEqual( self.assertEqual(
@ -347,7 +368,7 @@ class DockerClientTest(unittest.TestCase):
'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/start' 'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/start'
) )
self.assertEqual( self.assertEqual(
json.loads(args[0][1]), json.loads(args[1]['data']),
{ {
"PublishAllPorts": False, "PublishAllPorts": False,
"Links": ["path2:alias2", "path1:alias1"] "Links": ["path2:alias2", "path1:alias1"]
@ -365,8 +386,9 @@ class DockerClientTest(unittest.TestCase):
self.fail('Command should not raise exception: {0}'.format(e)) self.fail('Command should not raise exception: {0}'.format(e))
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/start', 'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/start',
'{"PublishAllPorts": false}', data='{"PublishAllPorts": false}',
headers={'Content-Type': 'application/json'} headers={'Content-Type': 'application/json'},
timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
) )
def test_wait(self): def test_wait(self):
@ -377,7 +399,6 @@ class DockerClientTest(unittest.TestCase):
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/wait', 'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/wait',
None,
timeout=None timeout=None
) )
@ -389,7 +410,6 @@ class DockerClientTest(unittest.TestCase):
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/wait', 'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/wait',
None,
timeout=None timeout=None
) )
@ -401,8 +421,8 @@ class DockerClientTest(unittest.TestCase):
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/attach', 'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/attach',
None, params={'logs': 1, 'stderr': 1, 'stdout': 1},
params={'logs': 1, 'stderr': 1, 'stdout': 1} timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
) )
def test_logs_with_dict_instead_of_id(self): def test_logs_with_dict_instead_of_id(self):
@ -413,8 +433,8 @@ class DockerClientTest(unittest.TestCase):
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/attach', 'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/attach',
None, params={'logs': 1, 'stderr': 1, 'stdout': 1},
params={'logs': 1, 'stderr': 1, 'stdout': 1} timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
) )
def test_diff(self): def test_diff(self):
@ -424,7 +444,9 @@ class DockerClientTest(unittest.TestCase):
self.fail('Command should not raise exception: {0}'.format(e)) self.fail('Command should not raise exception: {0}'.format(e))
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/changes') 'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/changes',
timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
)
def test_diff_with_dict_instead_of_id(self): def test_diff_with_dict_instead_of_id(self):
try: try:
@ -433,7 +455,9 @@ class DockerClientTest(unittest.TestCase):
self.fail('Command should not raise exception: {0}'.format(e)) self.fail('Command should not raise exception: {0}'.format(e))
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/changes') 'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/changes',
timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
)
def test_stop_container(self): def test_stop_container(self):
try: try:
@ -443,8 +467,8 @@ class DockerClientTest(unittest.TestCase):
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/stop', 'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/stop',
None, params={'t': 2},
params={'t': 2} timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
) )
def test_stop_container_with_dict_instead_of_id(self): def test_stop_container_with_dict_instead_of_id(self):
@ -455,8 +479,8 @@ class DockerClientTest(unittest.TestCase):
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/stop', 'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/stop',
None, params={'t': 2},
params={'t': 2} timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
) )
def test_kill_container(self): def test_kill_container(self):
@ -467,8 +491,8 @@ class DockerClientTest(unittest.TestCase):
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/kill', 'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/kill',
None, params={},
params={} timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
) )
def test_kill_container_with_dict_instead_of_id(self): def test_kill_container_with_dict_instead_of_id(self):
@ -479,8 +503,8 @@ class DockerClientTest(unittest.TestCase):
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/kill', 'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/kill',
None, params={},
params={} timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
) )
def test_kill_container_with_signal(self): def test_kill_container_with_signal(self):
@ -491,8 +515,8 @@ class DockerClientTest(unittest.TestCase):
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/kill', 'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/kill',
None, params={'signal': signal.SIGTERM},
params={'signal': signal.SIGTERM} timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
) )
def test_restart_container(self): def test_restart_container(self):
@ -503,8 +527,8 @@ class DockerClientTest(unittest.TestCase):
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/restart', 'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/restart',
None, params={'t': 2},
params={'t': 2} timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
) )
def test_restart_container_with_dict_instead_of_id(self): def test_restart_container_with_dict_instead_of_id(self):
@ -515,8 +539,8 @@ class DockerClientTest(unittest.TestCase):
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/restart', 'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/restart',
None, params={'t': 2},
params={'t': 2} timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
) )
def test_remove_container(self): def test_remove_container(self):
@ -527,7 +551,8 @@ class DockerClientTest(unittest.TestCase):
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b', 'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b',
params={'v': False, 'link': False} params={'v': False, 'link': False},
timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
) )
def test_remove_container_with_dict_instead_of_id(self): def test_remove_container_with_dict_instead_of_id(self):
@ -538,7 +563,8 @@ class DockerClientTest(unittest.TestCase):
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b', 'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b',
params={'v': False, 'link': False} params={'v': False, 'link': False},
timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
) )
def test_remove_link(self): def test_remove_link(self):
@ -549,7 +575,8 @@ class DockerClientTest(unittest.TestCase):
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b', 'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b',
params={'v': False, 'link': True} params={'v': False, 'link': True},
timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
) )
def test_export(self): def test_export(self):
@ -560,7 +587,8 @@ class DockerClientTest(unittest.TestCase):
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/export', 'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/export',
stream=True stream=True,
timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
) )
def test_export_with_dict_instead_of_id(self): def test_export_with_dict_instead_of_id(self):
@ -571,7 +599,8 @@ class DockerClientTest(unittest.TestCase):
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/export', 'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/export',
stream=True stream=True,
timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
) )
def test_inspect_container(self): def test_inspect_container(self):
@ -581,7 +610,8 @@ class DockerClientTest(unittest.TestCase):
self.fail('Command should not raise exception: {0}'.format(e)) self.fail('Command should not raise exception: {0}'.format(e))
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/json' 'unix://var/run/docker.sock/v1.6/containers/3cc2351ab11b/json',
timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
) )
################## ##################
@ -630,7 +660,7 @@ class DockerClientTest(unittest.TestCase):
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/commit', 'unix://var/run/docker.sock/v1.6/commit',
'{}', data='{}',
headers={'Content-Type': 'application/json'}, headers={'Content-Type': 'application/json'},
params={ params={
'repo': None, 'repo': None,
@ -638,7 +668,8 @@ class DockerClientTest(unittest.TestCase):
'tag': None, 'tag': None,
'container': '3cc2351ab11b', 'container': '3cc2351ab11b',
'author': None 'author': None
} },
timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
) )
def test_remove_image(self): def test_remove_image(self):
@ -648,7 +679,8 @@ class DockerClientTest(unittest.TestCase):
self.fail('Command should not raise exception: {0}'.format(e)) self.fail('Command should not raise exception: {0}'.format(e))
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/images/e9aa60c60128' 'unix://var/run/docker.sock/v1.6/images/e9aa60c60128',
timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
) )
def test_image_history(self): def test_image_history(self):
@ -658,7 +690,8 @@ class DockerClientTest(unittest.TestCase):
self.fail('Command should not raise exception: {0}'.format(e)) self.fail('Command should not raise exception: {0}'.format(e))
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/images/test_image/history' 'unix://var/run/docker.sock/v1.6/images/test_image/history',
timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
) )
def test_import_image(self): def test_import_image(self):
@ -673,12 +706,13 @@ class DockerClientTest(unittest.TestCase):
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/images/create', 'unix://var/run/docker.sock/v1.6/images/create',
None,
params={ params={
'repo': fake_api.FAKE_REPO_NAME, 'repo': fake_api.FAKE_REPO_NAME,
'tag': fake_api.FAKE_TAG_NAME, 'tag': fake_api.FAKE_TAG_NAME,
'fromSrc': fake_api.FAKE_TARBALL_PATH 'fromSrc': fake_api.FAKE_TARBALL_PATH
} },
data=None,
timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
) )
def test_import_image_from_file(self): def test_import_image_from_file(self):
@ -695,12 +729,13 @@ class DockerClientTest(unittest.TestCase):
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/images/create', 'unix://var/run/docker.sock/v1.6/images/create',
'',
params={ params={
'repo': fake_api.FAKE_REPO_NAME, 'repo': fake_api.FAKE_REPO_NAME,
'tag': fake_api.FAKE_TAG_NAME, 'tag': fake_api.FAKE_TAG_NAME,
'fromSrc': '-' 'fromSrc': '-'
} },
data='',
timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
) )
buf.close() buf.close()
os.remove(buf.name) os.remove(buf.name)
@ -712,7 +747,8 @@ class DockerClientTest(unittest.TestCase):
self.fail('Command should not raise exception: {0}'.format(e)) self.fail('Command should not raise exception: {0}'.format(e))
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/images/test_image/json' 'unix://var/run/docker.sock/v1.6/images/test_image/json',
timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
) )
def test_insert_image(self): def test_insert_image(self):
@ -724,11 +760,11 @@ class DockerClientTest(unittest.TestCase):
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/images/test_image/insert', 'unix://var/run/docker.sock/v1.6/images/test_image/insert',
None,
params={ params={
'url': fake_api.FAKE_URL, 'url': fake_api.FAKE_URL,
'path': fake_api.FAKE_PATH 'path': fake_api.FAKE_PATH
} },
timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
) )
def test_push_image(self): def test_push_image(self):
@ -739,9 +775,10 @@ class DockerClientTest(unittest.TestCase):
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/images/test_image/push', 'unix://var/run/docker.sock/v1.6/images/test_image/push',
'{}', data='{}',
headers={'Content-Type': 'application/json'}, headers={'Content-Type': 'application/json'},
stream=False stream=False,
timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
) )
def test_push_image_stream(self): def test_push_image_stream(self):
@ -752,9 +789,10 @@ class DockerClientTest(unittest.TestCase):
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/images/test_image/push', 'unix://var/run/docker.sock/v1.6/images/test_image/push',
'{}', data='{}',
headers={'Content-Type': 'application/json'}, headers={'Content-Type': 'application/json'},
stream=True stream=True,
timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
) )
def test_tag_image(self): def test_tag_image(self):
@ -765,12 +803,12 @@ class DockerClientTest(unittest.TestCase):
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/images/e9aa60c60128/tag', 'unix://var/run/docker.sock/v1.6/images/e9aa60c60128/tag',
None,
params={ params={
'tag': None, 'tag': None,
'repo': 'repo', 'repo': 'repo',
'force': 0 'force': 0
} },
timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
) )
def test_tag_image_tag(self): def test_tag_image_tag(self):
@ -785,12 +823,12 @@ class DockerClientTest(unittest.TestCase):
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/images/e9aa60c60128/tag', 'unix://var/run/docker.sock/v1.6/images/e9aa60c60128/tag',
None,
params={ params={
'tag': 'tag', 'tag': 'tag',
'repo': 'repo', 'repo': 'repo',
'force': 0 'force': 0
} },
timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
) )
def test_tag_image_force(self): def test_tag_image_force(self):
@ -802,12 +840,12 @@ class DockerClientTest(unittest.TestCase):
fake_request.assert_called_with( fake_request.assert_called_with(
'unix://var/run/docker.sock/v1.6/images/e9aa60c60128/tag', 'unix://var/run/docker.sock/v1.6/images/e9aa60c60128/tag',
None,
params={ params={
'tag': None, 'tag': None,
'repo': 'repo', 'repo': 'repo',
'force': 1 'force': 1
} },
timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
) )
################# #################