mirror of https://github.com/docker/docker-py.git
Merge branch 'master' into 0.2.0-dev
This commit is contained in:
commit
e2e5b9e0fd
10
README.md
10
README.md
|
@ -53,13 +53,11 @@ Identical to the `docker info` command.
|
|||
* `c.insert(url, path)`
|
||||
Identical to the `docker insert` command.
|
||||
|
||||
* `c.inspect_container(container_id)`
|
||||
Identical to the `docker inspect` command, but can only be used with a
|
||||
container ID.
|
||||
* `c.inspect_container(container)`
|
||||
Identical to the `docker inspect` command, but only for containers.
|
||||
|
||||
* `c.inspect_image(container_id)`
|
||||
Identical to the `docker inspect` command, but can only be used with an
|
||||
image ID.
|
||||
* `c.inspect_image(image_id)`
|
||||
Identical to the `docker inspect` command, but only for images.
|
||||
|
||||
* `c.kill(container)`
|
||||
Kill a container. Similar to the `docker kill` command.
|
||||
|
|
|
@ -94,6 +94,18 @@ class Client(requests.Session):
|
|||
command = shlex.split(str(command))
|
||||
if isinstance(environment, dict):
|
||||
environment = ['{0}={1}'.format(k, v) for k, v in environment.items()]
|
||||
|
||||
attach_stdin = False
|
||||
attach_stdout = False
|
||||
attach_stderr = False
|
||||
|
||||
if not detach:
|
||||
attach_stdout = True
|
||||
attach_stderr = True
|
||||
|
||||
if stdin_open:
|
||||
attach_stdin = True
|
||||
|
||||
return {
|
||||
'Hostname': hostname,
|
||||
'PortSpecs': ports,
|
||||
|
@ -101,9 +113,9 @@ class Client(requests.Session):
|
|||
'Tty': tty,
|
||||
'OpenStdin': stdin_open,
|
||||
'Memory': mem_limit,
|
||||
'AttachStdin': False,
|
||||
'AttachStdout': False,
|
||||
'AttachStderr': False,
|
||||
'AttachStdin': attach_stdin,
|
||||
'AttachStdout': attach_stdout,
|
||||
'AttachStderr': attach_stderr,
|
||||
'Env': environment,
|
||||
'Cmd': command,
|
||||
'Dns': dns,
|
||||
|
@ -127,19 +139,26 @@ class Client(requests.Session):
|
|||
kwargs['headers']['Content-Type'] = 'application/json'
|
||||
return self.post(url, json.dumps(data2), **kwargs)
|
||||
|
||||
def attach(self, container):
|
||||
params = {
|
||||
'stdout': 1,
|
||||
'stderr': 1,
|
||||
'stream': 1
|
||||
}
|
||||
def attach_socket(self, container, params=None):
|
||||
if params is None:
|
||||
params = {
|
||||
'stdout': 1,
|
||||
'stderr': 1,
|
||||
'stream': 1
|
||||
}
|
||||
if isinstance(container, dict):
|
||||
container = container.get('Id')
|
||||
|
||||
u = self._url("/containers/{0}/attach".format(container))
|
||||
res = self.post(u, None, params=params, stream=True)
|
||||
self._raise_for_status(res)
|
||||
# hijack the underlying socket from requests, icky
|
||||
# but for some reason requests.iter_contents and ilk
|
||||
# eventually block
|
||||
socket = res.raw._fp.fp._sock
|
||||
return res.raw._fp.fp._sock
|
||||
|
||||
def attach(self, container):
|
||||
socket = self.attach_socket(container)
|
||||
|
||||
while True:
|
||||
chunk = socket.recv(4096)
|
||||
|
@ -225,10 +244,14 @@ class Client(requests.Session):
|
|||
return self._result(res, True)
|
||||
|
||||
def diff(self, container):
|
||||
if isinstance(container, dict):
|
||||
container = container.get('Id')
|
||||
return self._result(self.get(self._url("/containers/{0}/changes".
|
||||
format(container))), True)
|
||||
|
||||
def export(self, container):
|
||||
if isinstance(container, dict):
|
||||
container = container.get('Id')
|
||||
res = self.get(self._url("/containers/{0}/export".format(container)),
|
||||
stream=True)
|
||||
self._raise_for_status(res)
|
||||
|
@ -276,15 +299,19 @@ class Client(requests.Session):
|
|||
}
|
||||
return self._result(self.post(api_url, None, params=params))
|
||||
|
||||
def inspect_container(self, container_id):
|
||||
def inspect_container(self, container):
|
||||
if isinstance(container, dict):
|
||||
container = container.get('Id')
|
||||
return self._result(self.get(self._url("/containers/{0}/json".
|
||||
format(container_id))), True)
|
||||
format(container))), True)
|
||||
|
||||
def inspect_image(self, image_id):
|
||||
return self._result(self.get(self._url("/images/{0}/json".
|
||||
format(image_id))), True)
|
||||
|
||||
def kill(self, container):
|
||||
if isinstance(container, dict):
|
||||
container = container.get('Id')
|
||||
url = self._url("/containers/{0}/kill".format(container))
|
||||
res = self.post(url, None)
|
||||
self._raise_for_status(res)
|
||||
|
@ -307,6 +334,8 @@ class Client(requests.Session):
|
|||
return res
|
||||
|
||||
def logs(self, container):
|
||||
if isinstance(container, dict):
|
||||
container = container.get('Id')
|
||||
params = {
|
||||
'logs': 1,
|
||||
'stdout': 1,
|
||||
|
@ -316,6 +345,8 @@ class Client(requests.Session):
|
|||
return self._result(self.post(u, None, params=params))
|
||||
|
||||
def port(self, container, private_port):
|
||||
if isinstance(container, dict):
|
||||
container = container.get('Id')
|
||||
res = self.get(self._url("/containers/{0}/json".format(container)))
|
||||
self._raise_for_status(res)
|
||||
json_ = res.json()
|
||||
|
@ -360,6 +391,8 @@ class Client(requests.Session):
|
|||
return self._result(self._post_json(u, authcfg))
|
||||
|
||||
def remove_container(self, container, v=False):
|
||||
if isinstance(container, dict):
|
||||
container = container.get('Id')
|
||||
params = { 'v': v }
|
||||
res = self.delete(self._url("/containers/" + container), params=params)
|
||||
self._raise_for_status(res)
|
||||
|
@ -369,6 +402,8 @@ class Client(requests.Session):
|
|||
self._raise_for_status(res)
|
||||
|
||||
def restart(self, container, timeout=10):
|
||||
if isinstance(container, dict):
|
||||
container = container.get('Id')
|
||||
params = { 't': timeout }
|
||||
url = self._url("/containers/{0}/restart".format(container))
|
||||
res = self.post(url, None, params=params)
|
||||
|
@ -379,18 +414,21 @@ class Client(requests.Session):
|
|||
params={'term': term}), True)
|
||||
|
||||
def start(self, container, binds=None):
|
||||
if isinstance(container, dict):
|
||||
container = container.get('Id')
|
||||
start_config = {}
|
||||
if binds:
|
||||
bind_pairs = ['{0}:{1}'.format(host, dest) for host, dest in binds.items()]
|
||||
start_config = {
|
||||
'Binds': bind_pairs,
|
||||
}
|
||||
|
||||
url = self._url("/containers/{0}/start".format(container))
|
||||
res = self._post_json(url, start_config)
|
||||
self._raise_for_status(res)
|
||||
|
||||
def stop(self, container, timeout=10):
|
||||
if isinstance(container, dict):
|
||||
container = container.get('Id')
|
||||
params = { 't': timeout }
|
||||
url = self._url("/containers/{0}/stop".format(container))
|
||||
res = self.post(url, None, params=params)
|
||||
|
@ -408,13 +446,15 @@ class Client(requests.Session):
|
|||
return res.status_code == 201
|
||||
|
||||
def top(self, container):
|
||||
u = self._url("/containers/{0}/top".format(container)
|
||||
return self._result(self.get(u)), True)
|
||||
u = self._url("/containers/{0}/top".format(container))
|
||||
return self._result(self.get(u), True)
|
||||
|
||||
def version(self):
|
||||
return self._result(self.get(self._url("/version")), True)
|
||||
|
||||
def wait(self, container):
|
||||
if isinstance(container, dict):
|
||||
container = container.get('Id')
|
||||
url = self._url("/containers/{0}/wait".format(container))
|
||||
res = self.post(url, None, timeout=None)
|
||||
self._raise_for_status(res)
|
||||
|
|
121
tests/test.py
121
tests/test.py
|
@ -173,6 +173,23 @@ class TestStartContainer(BaseTestCase):
|
|||
self.assertIn('ExitCode', inspect['State'])
|
||||
self.assertEqual(inspect['State']['ExitCode'], 0)
|
||||
|
||||
class TestStartContainerWithDictInsteadOfId(BaseTestCase):
|
||||
def runTest(self):
|
||||
res = self.client.create_container('busybox', 'true')
|
||||
self.assertIn('Id', res)
|
||||
self.tmp_containers.append(res['Id'])
|
||||
self.client.start(res)
|
||||
inspect = self.client.inspect_container(res['Id'])
|
||||
self.assertIn('Config', inspect)
|
||||
self.assertIn('ID', inspect)
|
||||
self.assertTrue(inspect['ID'].startswith(res['Id']))
|
||||
self.assertIn('Image', inspect)
|
||||
self.assertIn('State', inspect)
|
||||
self.assertIn('Running', inspect['State'])
|
||||
if not inspect['State']['Running']:
|
||||
self.assertIn('ExitCode', inspect['State'])
|
||||
self.assertEqual(inspect['State']['ExitCode'], 0)
|
||||
|
||||
class TestWait(BaseTestCase):
|
||||
def runTest(self):
|
||||
res = self.client.create_container('busybox', ['sleep', '10'])
|
||||
|
@ -187,6 +204,20 @@ class TestWait(BaseTestCase):
|
|||
self.assertIn('ExitCode', inspect['State'])
|
||||
self.assertEqual(inspect['State']['ExitCode'], exitcode)
|
||||
|
||||
class TestWaitWithDictInsteadOfId(BaseTestCase):
|
||||
def runTest(self):
|
||||
res = self.client.create_container('busybox', ['sleep', '10'])
|
||||
id = res['Id']
|
||||
self.tmp_containers.append(id)
|
||||
self.client.start(res)
|
||||
exitcode = self.client.wait(res)
|
||||
self.assertEqual(exitcode, 0)
|
||||
inspect = self.client.inspect_container(res)
|
||||
self.assertIn('Running', inspect['State'])
|
||||
self.assertEqual(inspect['State']['Running'], False)
|
||||
self.assertIn('ExitCode', inspect['State'])
|
||||
self.assertEqual(inspect['State']['ExitCode'], exitcode)
|
||||
|
||||
class TestLogs(BaseTestCase):
|
||||
def runTest(self):
|
||||
snippet = 'Flowering Nights (Sakuya Iyazoi)'
|
||||
|
@ -200,6 +231,19 @@ class TestLogs(BaseTestCase):
|
|||
logs = self.client.logs(id)
|
||||
self.assertEqual(logs, snippet + '\n')
|
||||
|
||||
class TestLogsWithDictInsteadOfId(BaseTestCase):
|
||||
def runTest(self):
|
||||
snippet = 'Flowering Nights (Sakuya Iyazoi)'
|
||||
container = self.client.create_container('busybox',
|
||||
'echo {0}'.format(snippet))
|
||||
id = container['Id']
|
||||
self.client.start(id)
|
||||
self.tmp_containers.append(id)
|
||||
exitcode = self.client.wait(id)
|
||||
self.assertEqual(exitcode, 0)
|
||||
logs = self.client.logs(container)
|
||||
self.assertEqual(logs, snippet + '\n')
|
||||
|
||||
class TestDiff(BaseTestCase):
|
||||
def runTest(self):
|
||||
container = self.client.create_container('busybox', ['touch', '/test'])
|
||||
|
@ -214,6 +258,20 @@ class TestDiff(BaseTestCase):
|
|||
self.assertIn('Kind', test_diff[0])
|
||||
self.assertEqual(test_diff[0]['Kind'], 1)
|
||||
|
||||
class TestDiffWithDictInsteadOfId(BaseTestCase):
|
||||
def runTest(self):
|
||||
container = self.client.create_container('busybox', ['touch', '/test'])
|
||||
id = container['Id']
|
||||
self.client.start(id)
|
||||
self.tmp_containers.append(id)
|
||||
exitcode = self.client.wait(id)
|
||||
self.assertEqual(exitcode, 0)
|
||||
diff = self.client.diff(container)
|
||||
test_diff = [x for x in diff if x.get('Path', None) == '/test']
|
||||
self.assertEqual(len(test_diff), 1)
|
||||
self.assertIn('Kind', test_diff[0])
|
||||
self.assertEqual(test_diff[0]['Kind'], 1)
|
||||
|
||||
class TestStop(BaseTestCase):
|
||||
def runTest(self):
|
||||
container = self.client.create_container('busybox', ['sleep', '9999'])
|
||||
|
@ -229,6 +287,22 @@ class TestStop(BaseTestCase):
|
|||
self.assertIn('Running', state)
|
||||
self.assertEqual(state['Running'], False)
|
||||
|
||||
class TestStopWithDictInsteadOfId(BaseTestCase):
|
||||
def runTest(self):
|
||||
container = self.client.create_container('busybox', ['sleep', '9999'])
|
||||
self.assertIn('Id', container)
|
||||
id = container['Id']
|
||||
self.client.start(container)
|
||||
self.tmp_containers.append(id)
|
||||
self.client.stop(container, timeout=2)
|
||||
container_info = self.client.inspect_container(id)
|
||||
self.assertIn('State', container_info)
|
||||
state = container_info['State']
|
||||
self.assertIn('ExitCode', state)
|
||||
self.assertNotEqual(state['ExitCode'], 0)
|
||||
self.assertIn('Running', state)
|
||||
self.assertEqual(state['Running'], False)
|
||||
|
||||
class TestKill(BaseTestCase):
|
||||
def runTest(self):
|
||||
container = self.client.create_container('busybox', ['sleep', '9999'])
|
||||
|
@ -244,6 +318,21 @@ class TestKill(BaseTestCase):
|
|||
self.assertIn('Running', state)
|
||||
self.assertEqual(state['Running'], False)
|
||||
|
||||
class TestKillWithDictInsteadOfId(BaseTestCase):
|
||||
def runTest(self):
|
||||
container = self.client.create_container('busybox', ['sleep', '9999'])
|
||||
id = container['Id']
|
||||
self.client.start(id)
|
||||
self.tmp_containers.append(id)
|
||||
self.client.kill(container)
|
||||
container_info = self.client.inspect_container(id)
|
||||
self.assertIn('State', container_info)
|
||||
state = container_info['State']
|
||||
self.assertIn('ExitCode', state)
|
||||
self.assertNotEqual(state['ExitCode'], 0)
|
||||
self.assertIn('Running', state)
|
||||
self.assertEqual(state['Running'], False)
|
||||
|
||||
class TestRestart(BaseTestCase):
|
||||
def runTest(self):
|
||||
container = self.client.create_container('busybox', ['sleep', '9999'])
|
||||
|
@ -264,6 +353,27 @@ class TestRestart(BaseTestCase):
|
|||
self.assertEqual(info2['State']['Running'], True)
|
||||
self.client.kill(id)
|
||||
|
||||
class TestRestartWithDictInsteadOfId(BaseTestCase):
|
||||
def runTest(self):
|
||||
container = self.client.create_container('busybox', ['sleep', '9999'])
|
||||
self.assertIn('Id', container)
|
||||
id = container['Id']
|
||||
self.client.start(container)
|
||||
self.tmp_containers.append(id)
|
||||
info = self.client.inspect_container(id)
|
||||
self.assertIn('State', info)
|
||||
self.assertIn('StartedAt', info['State'])
|
||||
start_time1 = info['State']['StartedAt']
|
||||
self.client.restart(container, timeout=2)
|
||||
info2 = self.client.inspect_container(id)
|
||||
self.assertIn('State', info2)
|
||||
self.assertIn('StartedAt', info2['State'])
|
||||
start_time2 = info2['State']['StartedAt']
|
||||
self.assertNotEqual(start_time1, start_time2)
|
||||
self.assertIn('Running', info2['State'])
|
||||
self.assertEqual(info2['State']['Running'], True)
|
||||
self.client.kill(id)
|
||||
|
||||
class TestRemoveContainer(BaseTestCase):
|
||||
def runTest(self):
|
||||
container = self.client.create_container('busybox', ['true'])
|
||||
|
@ -275,6 +385,17 @@ class TestRemoveContainer(BaseTestCase):
|
|||
res = [x for x in containers if 'Id' in x and x['Id'].startswith(id)]
|
||||
self.assertEqual(len(res), 0)
|
||||
|
||||
class TestRemoveContainerWithDictInsteadOfId(BaseTestCase):
|
||||
def runTest(self):
|
||||
container = self.client.create_container('busybox', ['true'])
|
||||
id = container['Id']
|
||||
self.client.start(id)
|
||||
self.client.wait(id)
|
||||
self.client.remove_container(container)
|
||||
containers = self.client.containers(all=True)
|
||||
res = [x for x in containers if 'Id' in x and x['Id'].startswith(id)]
|
||||
self.assertEqual(len(res), 0)
|
||||
|
||||
##################
|
||||
## IMAGES TESTS ##
|
||||
##################
|
||||
|
|
Loading…
Reference in New Issue