Skip to content

Commit 2b153a6

Browse files
committed
Merge pull request #564 from docker/check_resource_not_none
Added check_resource decorator
2 parents 8d3dedf + 019751d commit 2b153a6

File tree

5 files changed

+69
-5
lines changed

5 files changed

+69
-5
lines changed

docker/client.py

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
from .auth import auth
2727
from .unixconn import unixconn
2828
from .ssladapter import ssladapter
29-
from .utils import utils
29+
from .utils import utils, check_resource
3030
from . import errors
3131
from .tls import TLSConfig
3232

@@ -154,6 +154,7 @@ def _attach_params(self, override=None):
154154
'stream': 1
155155
}
156156

157+
@check_resource
157158
def _attach_websocket(self, container, params=None):
158159
if six.PY3:
159160
raise NotImplementedError("This method is not currently supported "
@@ -249,6 +250,7 @@ def _multiplexed_response_stream_helper(self, response):
249250
def api_version(self):
250251
return self._version
251252

253+
@check_resource
252254
def attach(self, container, stdout=True, stderr=True,
253255
stream=False, logs=False):
254256
if isinstance(container, dict):
@@ -285,6 +287,7 @@ def stream_result():
285287
[x for x in self._multiplexed_buffer_helper(response)]
286288
)
287289

290+
@check_resource
288291
def attach_socket(self, container, params=None, ws=False):
289292
if params is None:
290293
params = {
@@ -398,6 +401,7 @@ def build(self, path=None, tag=None, quiet=False, fileobj=None,
398401
return None, output
399402
return match.group(1), output
400403

404+
@check_resource
401405
def commit(self, container, repository=None, tag=None, message=None,
402406
author=None, conf=None):
403407
if isinstance(container, dict):
@@ -436,6 +440,7 @@ def containers(self, quiet=False, all=False, trunc=False, latest=False,
436440
x['Id'] = x['Id'][:12]
437441
return res
438442

443+
@check_resource
439444
def copy(self, container, resource):
440445
if isinstance(container, dict):
441446
container = container.get('Id')
@@ -480,6 +485,7 @@ def create_container_from_config(self, config, name=None):
480485
res = self._post_json(u, data=config, params=params)
481486
return self._result(res, True)
482487

488+
@check_resource
483489
def diff(self, container):
484490
if isinstance(container, dict):
485491
container = container.get('Id')
@@ -506,6 +512,7 @@ def events(self, since=None, until=None, filters=None, decode=None):
506512
params=params, stream=True),
507513
decode=decode)
508514

515+
@check_resource
509516
def execute(self, container, cmd, detach=False, stdout=True, stderr=True,
510517
stream=False, tty=False):
511518
if utils.compare_version('1.15', self._version) < 0:
@@ -548,6 +555,7 @@ def execute(self, container, cmd, detach=False, stdout=True, stderr=True,
548555
[x for x in self._multiplexed_buffer_helper(res)]
549556
)
550557

558+
@check_resource
551559
def export(self, container):
552560
if isinstance(container, dict):
553561
container = container.get('Id')
@@ -556,12 +564,14 @@ def export(self, container):
556564
self._raise_for_status(res)
557565
return res.raw
558566

567+
@check_resource
559568
def get_image(self, image):
560569
res = self._get(self._url("/images/{0}/get".format(image)),
561570
stream=True)
562571
self._raise_for_status(res)
563572
return res.raw
564573

574+
@check_resource
565575
def history(self, image):
566576
res = self._get(self._url("/images/{0}/history".format(image)))
567577
return self._result(res, True)
@@ -671,31 +681,35 @@ def info(self):
671681
return self._result(self._get(self._url("/info")),
672682
True)
673683

684+
@check_resource
674685
def insert(self, image, url, path):
675686
if utils.compare_version('1.12', self._version) >= 0:
676687
raise errors.DeprecatedMethod(
677688
'insert is not available for API version >=1.12'
678689
)
679-
api_url = self._url("/images/" + image + "/insert")
690+
api_url = self._url("/images/{0}/insert".fornat(image))
680691
params = {
681692
'url': url,
682693
'path': path
683694
}
684695
return self._result(self._post(api_url, params=params))
685696

697+
@check_resource
686698
def inspect_container(self, container):
687699
if isinstance(container, dict):
688700
container = container.get('Id')
689701
return self._result(
690702
self._get(self._url("/containers/{0}/json".format(container))),
691703
True)
692704

693-
def inspect_image(self, image_id):
705+
@check_resource
706+
def inspect_image(self, image):
694707
return self._result(
695-
self._get(self._url("/images/{0}/json".format(image_id))),
708+
self._get(self._url("/images/{0}/json".format(image))),
696709
True
697710
)
698711

712+
@check_resource
699713
def kill(self, container, signal=None):
700714
if isinstance(container, dict):
701715
container = container.get('Id')
@@ -743,6 +757,7 @@ def login(self, username, password=None, email=None, registry=None,
743757
self._auth_configs[registry] = req_data
744758
return self._result(response, json=True)
745759

760+
@check_resource
746761
def logs(self, container, stdout=True, stderr=True, stream=False,
747762
timestamps=False, tail='all'):
748763
if isinstance(container, dict):
@@ -777,6 +792,7 @@ def logs(self, container, stdout=True, stderr=True, stream=False,
777792
logs=True
778793
)
779794

795+
@check_resource
780796
def pause(self, container):
781797
if isinstance(container, dict):
782798
container = container.get('Id')
@@ -787,6 +803,7 @@ def pause(self, container):
787803
def ping(self):
788804
return self._result(self._get(self._url('/_ping')))
789805

806+
@check_resource
790807
def port(self, container, private_port):
791808
if isinstance(container, dict):
792809
container = container.get('Id')
@@ -884,6 +901,7 @@ def push(self, repository, tag=None, stream=False,
884901
return stream and self._stream_helper(response) \
885902
or self._result(response)
886903

904+
@check_resource
887905
def remove_container(self, container, v=False, link=False, force=False):
888906
if isinstance(container, dict):
889907
container = container.get('Id')
@@ -892,13 +910,15 @@ def remove_container(self, container, v=False, link=False, force=False):
892910
params=params)
893911
self._raise_for_status(res)
894912

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

921+
@check_resource
902922
def rename(self, container, name):
903923
if utils.compare_version('1.17', self._version) < 0:
904924
raise errors.InvalidVersion(
@@ -911,6 +931,7 @@ def rename(self, container, name):
911931
res = self._post(url, params=params)
912932
self._raise_for_status(res)
913933

934+
@check_resource
914935
def resize(self, container, height, width):
915936
if isinstance(container, dict):
916937
container = container.get('Id')
@@ -920,6 +941,7 @@ def resize(self, container, height, width):
920941
res = self._post(url, params=params)
921942
self._raise_for_status(res)
922943

944+
@check_resource
923945
def restart(self, container, timeout=10):
924946
if isinstance(container, dict):
925947
container = container.get('Id')
@@ -933,6 +955,7 @@ def search(self, term):
933955
params={'term': term}),
934956
True)
935957

958+
@check_resource
936959
def start(self, container, binds=None, port_bindings=None, lxc_conf=None,
937960
publish_all_ports=False, links=None, privileged=False,
938961
dns=None, dns_search=None, volumes_from=None, network_mode=None,
@@ -995,6 +1018,7 @@ def start(self, container, binds=None, port_bindings=None, lxc_conf=None,
9951018
res = self._post_json(url, data=start_config)
9961019
self._raise_for_status(res)
9971020

1021+
@check_resource
9981022
def stats(self, container, decode=None):
9991023
if utils.compare_version('1.17', self._version) < 0:
10001024
raise errors.InvalidVersion(
@@ -1005,6 +1029,7 @@ def stats(self, container, decode=None):
10051029
url = self._url("/containers/{0}/stats".format(container))
10061030
return self._stream_helper(self._get(url, stream=True), decode=decode)
10071031

1032+
@check_resource
10081033
def stop(self, container, timeout=10):
10091034
if isinstance(container, dict):
10101035
container = container.get('Id')
@@ -1015,6 +1040,7 @@ def stop(self, container, timeout=10):
10151040
timeout=(timeout + self.timeout))
10161041
self._raise_for_status(res)
10171042

1043+
@check_resource
10181044
def tag(self, image, repository, tag=None, force=False):
10191045
params = {
10201046
'tag': tag,
@@ -1026,21 +1052,26 @@ def tag(self, image, repository, tag=None, force=False):
10261052
self._raise_for_status(res)
10271053
return res.status_code == 201
10281054

1055+
@check_resource
10291056
def top(self, container):
1057+
if isinstance(container, dict):
1058+
container = container.get('Id')
10301059
u = self._url("/containers/{0}/top".format(container))
10311060
return self._result(self._get(u), True)
10321061

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

1066+
@check_resource
10371067
def unpause(self, container):
10381068
if isinstance(container, dict):
10391069
container = container.get('Id')
10401070
url = self._url('/containers/{0}/unpause'.format(container))
10411071
res = self._post(url)
10421072
self._raise_for_status(res)
10431073

1074+
@check_resource
10441075
def wait(self, container, timeout=None):
10451076
if isinstance(container, dict):
10461077
container = container.get('Id')

docker/errors.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,7 @@ def __str__(self):
7878
"client configurations. See "
7979
"http://docs.docker.com/examples/https/ for "
8080
"API details.")
81+
82+
83+
class NullResource(DockerException, ValueError):
84+
pass

docker/utils/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@
55
create_container_config, parse_bytes, ping_registry
66
) # flake8: noqa
77

8-
from .types import Ulimit, LogConfig # flake8: noqa
8+
from .types import Ulimit, LogConfig # flake8: noqa
9+
from .decorators import check_resource #flake8: noqa

docker/utils/decorators.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import docker.errors
2+
3+
4+
def check_resource(f):
5+
def wrapped(self, resource_id=None, *args, **kwargs):
6+
if resource_id is None and (
7+
kwargs.get('container') is None and kwargs.get('image') is None
8+
):
9+
raise docker.errors.NullResource(
10+
'image or container param is None'
11+
)
12+
return f(self, resource_id, *args, **kwargs)
13+
return wrapped

tests/test.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,21 @@ def test_start_container(self):
669669
args[1]['timeout'], docker.client.DEFAULT_TIMEOUT_SECONDS
670670
)
671671

672+
def test_start_container_none(self):
673+
try:
674+
self.client.start(container=None)
675+
except ValueError as e:
676+
self.assertEqual(str(e), 'image or container param is None')
677+
else:
678+
self.fail('Command should raise ValueError')
679+
680+
try:
681+
self.client.start(None)
682+
except ValueError as e:
683+
self.assertEqual(str(e), 'image or container param is None')
684+
else:
685+
self.fail('Command should raise ValueError')
686+
672687
def test_create_container_with_lxc_conf(self):
673688
try:
674689
self.client.create_container(

0 commit comments

Comments
 (0)