Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 35 additions & 4 deletions docker/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from .auth import auth
from .unixconn import unixconn
from .ssladapter import ssladapter
from .utils import utils
from .utils import utils, check_resource
from . import errors
from .tls import TLSConfig

Expand Down Expand Up @@ -154,6 +154,7 @@ def _attach_params(self, override=None):
'stream': 1
}

@check_resource
def _attach_websocket(self, container, params=None):
if six.PY3:
raise NotImplementedError("This method is not currently supported "
Expand Down Expand Up @@ -249,6 +250,7 @@ def _multiplexed_response_stream_helper(self, response):
def api_version(self):
return self._version

@check_resource
def attach(self, container, stdout=True, stderr=True,
stream=False, logs=False):
if isinstance(container, dict):
Expand Down Expand Up @@ -285,6 +287,7 @@ def stream_result():
[x for x in self._multiplexed_buffer_helper(response)]
)

@check_resource
def attach_socket(self, container, params=None, ws=False):
if params is None:
params = {
Expand Down Expand Up @@ -398,6 +401,7 @@ def build(self, path=None, tag=None, quiet=False, fileobj=None,
return None, output
return match.group(1), output

@check_resource
def commit(self, container, repository=None, tag=None, message=None,
author=None, conf=None):
params = {
Expand Down Expand Up @@ -434,6 +438,7 @@ def containers(self, quiet=False, all=False, trunc=False, latest=False,
x['Id'] = x['Id'][:12]
return res

@check_resource
def copy(self, container, resource):
if isinstance(container, dict):
container = container.get('Id')
Expand Down Expand Up @@ -478,6 +483,7 @@ def create_container_from_config(self, config, name=None):
res = self._post_json(u, data=config, params=params)
return self._result(res, True)

@check_resource
def diff(self, container):
if isinstance(container, dict):
container = container.get('Id')
Expand All @@ -504,6 +510,7 @@ def events(self, since=None, until=None, filters=None, decode=None):
params=params, stream=True),
decode=decode)

@check_resource
def execute(self, container, cmd, detach=False, stdout=True, stderr=True,
stream=False, tty=False):
if utils.compare_version('1.15', self._version) < 0:
Expand Down Expand Up @@ -546,6 +553,7 @@ def execute(self, container, cmd, detach=False, stdout=True, stderr=True,
[x for x in self._multiplexed_buffer_helper(res)]
)

@check_resource
def export(self, container):
if isinstance(container, dict):
container = container.get('Id')
Expand All @@ -554,12 +562,14 @@ def export(self, container):
self._raise_for_status(res)
return res.raw

@check_resource
def get_image(self, image):
res = self._get(self._url("/images/{0}/get".format(image)),
stream=True)
self._raise_for_status(res)
return res.raw

@check_resource
def history(self, image):
res = self._get(self._url("/images/{0}/history".format(image)))
return self._result(res, True)
Expand Down Expand Up @@ -669,31 +679,35 @@ def info(self):
return self._result(self._get(self._url("/info")),
True)

@check_resource
def insert(self, image, url, path):
if utils.compare_version('1.12', self._version) >= 0:
raise errors.DeprecatedMethod(
'insert is not available for API version >=1.12'
)
api_url = self._url("/images/" + image + "/insert")
api_url = self._url("/images/{0}/insert".fornat(image))
params = {
'url': url,
'path': path
}
return self._result(self._post(api_url, params=params))

@check_resource
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))),
True)

def inspect_image(self, image_id):
@check_resource
def inspect_image(self, image):
return self._result(
self._get(self._url("/images/{0}/json".format(image_id))),
self._get(self._url("/images/{0}/json".format(image))),
True
)

@check_resource
def kill(self, container, signal=None):
if isinstance(container, dict):
container = container.get('Id')
Expand Down Expand Up @@ -741,6 +755,7 @@ def login(self, username, password=None, email=None, registry=None,
self._auth_configs[registry] = req_data
return self._result(response, json=True)

@check_resource
def logs(self, container, stdout=True, stderr=True, stream=False,
timestamps=False, tail='all'):
if isinstance(container, dict):
Expand Down Expand Up @@ -775,6 +790,7 @@ def logs(self, container, stdout=True, stderr=True, stream=False,
logs=True
)

@check_resource
def pause(self, container):
if isinstance(container, dict):
container = container.get('Id')
Expand All @@ -785,6 +801,7 @@ def pause(self, container):
def ping(self):
return self._result(self._get(self._url('/_ping')))

@check_resource
def port(self, container, private_port):
if isinstance(container, dict):
container = container.get('Id')
Expand Down Expand Up @@ -882,6 +899,7 @@ def push(self, repository, tag=None, stream=False,
return stream and self._stream_helper(response) \
or self._result(response)

@check_resource
def remove_container(self, container, v=False, link=False, force=False):
if isinstance(container, dict):
container = container.get('Id')
Expand All @@ -890,13 +908,15 @@ def remove_container(self, container, v=False, link=False, force=False):
params=params)
self._raise_for_status(res)

@check_resource
def remove_image(self, image, force=False, noprune=False):
if isinstance(image, dict):
image = image.get('Id')
params = {'force': force, 'noprune': noprune}
res = self._delete(self._url("/images/" + image), params=params)
self._raise_for_status(res)

@check_resource
def rename(self, container, name):
if utils.compare_version('1.17', self._version) < 0:
raise errors.InvalidVersion(
Expand All @@ -909,6 +929,7 @@ def rename(self, container, name):
res = self._post(url, params=params)
self._raise_for_status(res)

@check_resource
def resize(self, container, height, width):
if isinstance(container, dict):
container = container.get('Id')
Expand All @@ -918,6 +939,7 @@ def resize(self, container, height, width):
res = self._post(url, params=params)
self._raise_for_status(res)

@check_resource
def restart(self, container, timeout=10):
if isinstance(container, dict):
container = container.get('Id')
Expand All @@ -931,6 +953,7 @@ def search(self, term):
params={'term': term}),
True)

@check_resource
def start(self, container, binds=None, port_bindings=None, lxc_conf=None,
publish_all_ports=False, links=None, privileged=False,
dns=None, dns_search=None, volumes_from=None, network_mode=None,
Expand Down Expand Up @@ -993,6 +1016,7 @@ def start(self, container, binds=None, port_bindings=None, lxc_conf=None,
res = self._post_json(url, data=start_config)
self._raise_for_status(res)

@check_resource
def stats(self, container, decode=None):
if utils.compare_version('1.17', self._version) < 0:
raise errors.InvalidVersion(
Expand All @@ -1003,6 +1027,7 @@ def stats(self, container, decode=None):
url = self._url("/containers/{0}/stats".format(container))
return self._stream_helper(self._get(url, stream=True), decode=decode)

@check_resource
def stop(self, container, timeout=10):
if isinstance(container, dict):
container = container.get('Id')
Expand All @@ -1013,6 +1038,7 @@ def stop(self, container, timeout=10):
timeout=(timeout + self.timeout))
self._raise_for_status(res)

@check_resource
def tag(self, image, repository, tag=None, force=False):
params = {
'tag': tag,
Expand All @@ -1024,21 +1050,26 @@ def tag(self, image, repository, tag=None, force=False):
self._raise_for_status(res)
return res.status_code == 201

@check_resource
def top(self, container):
if isinstance(container, dict):
container = container.get('Id')
u = self._url("/containers/{0}/top".format(container))
return self._result(self._get(u), True)

def version(self, api_version=True):
url = self._url("/version", versioned_api=api_version)
return self._result(self._get(url), json=True)

@check_resource
def unpause(self, container):
if isinstance(container, dict):
container = container.get('Id')
url = self._url('/containers/{0}/unpause'.format(container))
res = self._post(url)
self._raise_for_status(res)

@check_resource
def wait(self, container, timeout=None):
if isinstance(container, dict):
container = container.get('Id')
Expand Down
4 changes: 4 additions & 0 deletions docker/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,7 @@ def __str__(self):
"client configurations. See "
"http://docs.docker.com/examples/https/ for "
"API details.")


class NullResource(DockerException, ValueError):
pass
3 changes: 2 additions & 1 deletion docker/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@
create_container_config, parse_bytes, ping_registry
) # flake8: noqa

from .types import Ulimit, LogConfig # flake8: noqa
from .types import Ulimit, LogConfig # flake8: noqa
from .decorators import check_resource #flake8: noqa
13 changes: 13 additions & 0 deletions docker/utils/decorators.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import docker.errors


def check_resource(f):
def wrapped(self, resource_id=None, *args, **kwargs):
if resource_id is None and (
kwargs.get('container') is None and kwargs.get('image') is None
):
raise docker.errors.NullResource(
'image or container param is None'
)
return f(self, resource_id, *args, **kwargs)
return wrapped
15 changes: 15 additions & 0 deletions tests/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,21 @@ def test_start_container(self):
args[1]['timeout'], docker.client.DEFAULT_TIMEOUT_SECONDS
)

def test_start_container_none(self):
try:
self.client.start(container=None)
except ValueError as e:
self.assertEqual(str(e), 'image or container param is None')
else:
self.fail('Command should raise ValueError')

try:
self.client.start(None)
except ValueError as e:
self.assertEqual(str(e), 'image or container param is None')
else:
self.fail('Command should raise ValueError')

def test_create_container_with_lxc_conf(self):
try:
self.client.create_container(
Expand Down