blob: 5ab00318748271de3915cc2498d94866acad94fd [file] [log] [blame]
richmond@google.com982cc4d2014-04-04 22:36:481# Copyright 2013 dotCloud inc.
2
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6
7# http://www.apache.org/licenses/LICENSE-2.0
8
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15import base64
16import datetime
17import io
18import json
19import os
20import signal
21import tempfile
22import unittest
23
24import docker
25import requests
26import six
27
28import fake_api
29
30
31try:
32 from unittest import mock
33except ImportError:
34 import mock
35
36
37def response(status_code=200, content='', headers=None, reason=None, elapsed=0,
38 request=None):
39 res = requests.Response()
40 res.status_code = status_code
41 if not isinstance(content, six.string_types):
42 content = json.dumps(content)
43 if six.PY3:
44 content = content.encode('ascii')
45 res._content = content
46 res.headers = requests.structures.CaseInsensitiveDict(headers or {})
47 res.reason = reason
48 res.elapsed = datetime.timedelta(elapsed)
49 res.request = request
50 return res
51
52
53def fake_resp(url, data=None, **kwargs):
54 status_code, content = fake_api.fake_responses[url]()
55 return response(status_code=status_code, content=content)
56
57fake_request = mock.Mock(side_effect=fake_resp)
58url_prefix = 'http+unix://var/run/docker.sock/v{0}/'.format(
59 docker.client.DEFAULT_DOCKER_API_VERSION)
60
61
62@mock.patch.multiple('docker.Client', get=fake_request, post=fake_request,
63 put=fake_request, delete=fake_request)
64class DockerClientTest(unittest.TestCase):
65 def setUp(self):
66 self.client = docker.Client()
67 # Force-clear authconfig to avoid tampering with the tests
68 self.client._cfg = {'Configs': {}}
69
70 #########################
71 ## INFORMATION TESTS ##
72 #########################
73 def test_version(self):
74 try:
75 self.client.version()
76 except Exception as e:
77 self.fail('Command should not raise exception: {0}'.format(e))
78
79 fake_request.assert_called_with(
80 url_prefix + 'version',
81 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
82 )
83
84 def test_info(self):
85 try:
86 self.client.info()
87 except Exception as e:
88 self.fail('Command should not raise exception: {0}'.format(e))
89
90 fake_request.assert_called_with(
91 url_prefix + 'info',
92 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
93 )
94
95 def test_search(self):
96 try:
97 self.client.search('busybox')
98 except Exception as e:
99 self.fail('Command should not raise exception: {0}'.format(e))
100
101 fake_request.assert_called_with(
102 url_prefix + 'images/search',
103 params={'term': 'busybox'},
104 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
105 )
106
107 def test_image_viz(self):
108 try:
109 self.client.images('busybox', viz=True)
110 self.fail('Viz output should not be supported!')
111 except Exception:
112 pass
113
114 ###################
115 ## LISTING TESTS ##
116 ###################
117
118 def test_images(self):
119 try:
120 self.client.images(all=True)
121 except Exception as e:
122 self.fail('Command should not raise exception: {0}'.format(e))
123 fake_request.assert_called_with(
124 url_prefix + 'images/json',
125 params={'filter': None, 'only_ids': 0, 'all': 1},
126 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
127 )
128
129 def test_images_quiet(self):
130 try:
131 self.client.images(all=True, quiet=True)
132 except Exception as e:
133 self.fail('Command should not raise exception: {0}'.format(e))
134 fake_request.assert_called_with(
135 url_prefix + 'images/json',
136 params={'filter': None, 'only_ids': 1, 'all': 1},
137 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
138 )
139
140 def test_image_ids(self):
141 try:
142 self.client.images(quiet=True)
143 except Exception as e:
144 self.fail('Command should not raise exception: {0}'.format(e))
145
146 fake_request.assert_called_with(
147 url_prefix + 'images/json',
148 params={'filter': None, 'only_ids': 1, 'all': 0},
149 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
150 )
151
152 def test_list_containers(self):
153 try:
154 self.client.containers(all=True)
155 except Exception as e:
156 self.fail('Command should not raise exception: {0}'.format(e))
157
158 fake_request.assert_called_with(
159 url_prefix + 'containers/json',
160 params={
161 'all': 1,
162 'since': None,
163 'limit': -1,
164 'trunc_cmd': 1,
165 'before': None
166 },
167 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
168 )
169
170 #####################
171 ## CONTAINER TESTS ##
172 #####################
173
174 def test_create_container(self):
175 try:
176 self.client.create_container('busybox', 'true')
177 except Exception as e:
178 self.fail('Command should not raise exception: {0}'.format(e))
179
180 args = fake_request.call_args
181 self.assertEqual(args[0][0],
182 url_prefix + 'containers/create')
183 self.assertEqual(json.loads(args[1]['data']),
184 json.loads('''
185 {"Tty": false, "Image": "busybox", "Cmd": ["true"],
186 "AttachStdin": false, "Memory": 0,
187 "AttachStderr": true, "AttachStdout": true,
188 "StdinOnce": false,
189 "OpenStdin": false, "NetworkDisabled": false}'''))
190 self.assertEqual(args[1]['headers'],
191 {'Content-Type': 'application/json'})
192
193 def test_create_container_with_binds(self):
194 mount_dest = '/mnt'
195 #mount_origin = '/tmp'
196
197 try:
198 self.client.create_container('busybox', ['ls', mount_dest],
199 volumes=[mount_dest])
200 except Exception as e:
201 self.fail('Command should not raise exception: {0}'.format(e))
202
203 args = fake_request.call_args
204 self.assertEqual(args[0][0],
205 url_prefix + 'containers/create')
206 self.assertEqual(json.loads(args[1]['data']),
207 json.loads('''
208 {"Tty": false, "Image": "busybox",
209 "Cmd": ["ls", "/mnt"], "AttachStdin": false,
210 "Volumes": {"/mnt": {}}, "Memory": 0,
211 "AttachStderr": true,
212 "AttachStdout": true, "OpenStdin": false,
213 "StdinOnce": false,
214 "NetworkDisabled": false}'''))
215 self.assertEqual(args[1]['headers'],
216 {'Content-Type': 'application/json'})
217
218 def test_create_container_with_ports(self):
219 try:
220 self.client.create_container('busybox', 'ls',
221 ports=[1111, (2222, 'udp'), (3333,)])
222 except Exception as e:
223 self.fail('Command should not raise exception: {0}'.format(e))
224
225 args = fake_request.call_args
226 self.assertEqual(args[0][0],
227 url_prefix + 'containers/create')
228 self.assertEqual(json.loads(args[1]['data']),
229 json.loads('''
230 {"Tty": false, "Image": "busybox",
231 "Cmd": ["ls"], "AttachStdin": false,
232 "Memory": 0, "ExposedPorts": {
233 "1111/tcp": {},
234 "2222/udp": {},
235 "3333/tcp": {}
236 },
237 "AttachStderr": true,
238 "AttachStdout": true, "OpenStdin": false,
239 "StdinOnce": false,
240 "NetworkDisabled": false}'''))
241 self.assertEqual(args[1]['headers'],
242 {'Content-Type': 'application/json'})
243
244 def test_create_container_with_entrypoint(self):
245 try:
246 self.client.create_container('busybox', 'hello',
247 entrypoint='cowsay')
248 except Exception as e:
249 self.fail('Command should not raise exception: {0}'.format(e))
250
251 args = fake_request.call_args
252 self.assertEqual(args[0][0],
253 url_prefix + 'containers/create')
254 self.assertEqual(json.loads(args[1]['data']),
255 json.loads('''
256 {"Tty": false, "Image": "busybox",
257 "Cmd": ["hello"], "AttachStdin": false,
258 "Memory": 0,
259 "AttachStderr": true,
260 "AttachStdout": true, "OpenStdin": false,
261 "StdinOnce": false,
262 "NetworkDisabled": false,
263 "Entrypoint": "cowsay"}'''))
264 self.assertEqual(args[1]['headers'],
265 {'Content-Type': 'application/json'})
266
267 def test_create_container_with_cpu_shares(self):
268 try:
269 self.client.create_container('busybox', 'ls',
270 cpu_shares=5)
271 except Exception as e:
272 self.fail('Command should not raise exception: {0}'.format(e))
273
274 args = fake_request.call_args
275 self.assertEqual(args[0][0],
276 url_prefix + 'containers/create')
277 self.assertEqual(json.loads(args[1]['data']),
278 json.loads('''
279 {"Tty": false, "Image": "busybox",
280 "Cmd": ["ls"], "AttachStdin": false,
281 "Memory": 0,
282 "AttachStderr": true,
283 "AttachStdout": true, "OpenStdin": false,
284 "StdinOnce": false,
285 "NetworkDisabled": false,
286 "CpuShares": 5}'''))
287 self.assertEqual(args[1]['headers'],
288 {'Content-Type': 'application/json'})
289
290 def test_create_container_with_working_dir(self):
291 try:
292 self.client.create_container('busybox', 'ls',
293 working_dir='/root')
294 except Exception as e:
295 self.fail('Command should not raise exception: {0}'.format(e))
296
297 args = fake_request.call_args
298 self.assertEqual(args[0][0],
299 url_prefix + 'containers/create')
300 self.assertEqual(json.loads(args[1]['data']),
301 json.loads('''
302 {"Tty": false, "Image": "busybox",
303 "Cmd": ["ls"], "AttachStdin": false,
304 "Memory": 0,
305 "AttachStderr": true,
306 "AttachStdout": true, "OpenStdin": false,
307 "StdinOnce": false,
308 "NetworkDisabled": false,
309 "WorkingDir": "/root"}'''))
310 self.assertEqual(args[1]['headers'],
311 {'Content-Type': 'application/json'})
312
313 def test_create_container_with_stdin_open(self):
314 try:
315 self.client.create_container('busybox', 'true', stdin_open=True)
316 except Exception as e:
317 self.fail('Command should not raise exception: {0}'.format(e))
318
319 args = fake_request.call_args
320 self.assertEqual(args[0][0],
321 url_prefix + 'containers/create')
322 self.assertEqual(json.loads(args[1]['data']),
323 json.loads('''
324 {"Tty": false, "Image": "busybox", "Cmd": ["true"],
325 "AttachStdin": true, "Memory": 0,
326 "AttachStderr": true, "AttachStdout": true,
327 "StdinOnce": true,
328 "OpenStdin": true, "NetworkDisabled": false}'''))
329 self.assertEqual(args[1]['headers'],
330 {'Content-Type': 'application/json'})
331
332 def test_create_named_container(self):
333 try:
334 self.client.create_container('busybox', 'true',
335 name='marisa-kirisame')
336 except Exception as e:
337 self.fail('Command should not raise exception: {0}'.format(e))
338
339 args = fake_request.call_args
340 self.assertEqual(args[0][0],
341 url_prefix + 'containers/create')
342 self.assertEqual(json.loads(args[1]['data']),
343 json.loads('''
344 {"Tty": false, "Image": "busybox", "Cmd": ["true"],
345 "AttachStdin": false, "Memory": 0,
346 "AttachStderr": true, "AttachStdout": true,
347 "StdinOnce": false,
348 "OpenStdin": false, "NetworkDisabled": false}'''))
349 self.assertEqual(args[1]['headers'],
350 {'Content-Type': 'application/json'})
351 self.assertEqual(args[1]['params'], {'name': 'marisa-kirisame'})
352
353 def test_start_container(self):
354 try:
355 self.client.start(fake_api.FAKE_CONTAINER_ID)
356 except Exception as e:
357 raise e
358 self.fail('Command should not raise exception: {0}'.format(e))
359 args = fake_request.call_args
360 self.assertEqual(
361 args[0][0],
362 url_prefix + 'containers/3cc2351ab11b/start'
363 )
364 self.assertEqual(
365 json.loads(args[1]['data']),
366 {"PublishAllPorts": False, "Privileged": False}
367 )
368 self.assertEqual(
369 args[1]['headers'],
370 {'Content-Type': 'application/json'}
371 )
372 self.assertEqual(
373 args[1]['timeout'],
374 docker.client.DEFAULT_TIMEOUT_SECONDS
375 )
376
377 def test_start_container_with_lxc_conf(self):
378 try:
379 self.client.start(
380 fake_api.FAKE_CONTAINER_ID,
381 lxc_conf={'lxc.conf.k': 'lxc.conf.value'}
382 )
383 except Exception as e:
384 self.fail('Command should not raise exception: {0}'.format(e))
385 args = fake_request.call_args
386 self.assertEqual(
387 args[0][0],
388 url_prefix + 'containers/3cc2351ab11b/start'
389 )
390 self.assertEqual(
391 json.loads(args[1]['data']),
392 {"LxcConf": [{"Value": "lxc.conf.value", "Key": "lxc.conf.k"}],
393 "PublishAllPorts": False, "Privileged": False}
394 )
395 self.assertEqual(
396 args[1]['headers'],
397 {'Content-Type': 'application/json'}
398 )
399 self.assertEqual(
400 args[1]['timeout'],
401 docker.client.DEFAULT_TIMEOUT_SECONDS
402 )
403
404 def test_start_container_with_lxc_conf_compat(self):
405 try:
406 self.client.start(
407 fake_api.FAKE_CONTAINER_ID,
408 lxc_conf=[{'Key': 'lxc.conf.k', 'Value': 'lxc.conf.value'}]
409 )
410 except Exception as e:
411 self.fail('Command should not raise exception: {0}'.format(e))
412
413 args = fake_request.call_args
414 self.assertEqual(args[0][0], url_prefix +
415 'containers/3cc2351ab11b/start')
416 self.assertEqual(
417 json.loads(args[1]['data']),
418 {
419 "LxcConf": [{"Key": "lxc.conf.k", "Value": "lxc.conf.value"}],
420 "PublishAllPorts": False,
421 "Privileged": False,
422 }
423 )
424 self.assertEqual(args[1]['headers'],
425 {'Content-Type': 'application/json'})
426 self.assertEqual(
427 args[1]['timeout'],
428 docker.client.DEFAULT_TIMEOUT_SECONDS
429 )
430
431 def test_start_container_with_binds(self):
432 try:
433 mount_dest = '/mnt'
434 mount_origin = '/tmp'
435 self.client.start(fake_api.FAKE_CONTAINER_ID,
436 binds={mount_origin: mount_dest})
437 except Exception as e:
438 self.fail('Command should not raise exception: {0}'.format(e))
439
440 args = fake_request.call_args
441 self.assertEqual(args[0][0], url_prefix +
442 'containers/3cc2351ab11b/start')
443 self.assertEqual(json.loads(args[1]['data']),
444 {"Binds": ["/tmp:/mnt"],
445 "PublishAllPorts": False,
446 "Privileged": False})
447 self.assertEqual(args[1]['headers'],
448 {'Content-Type': 'application/json'})
449 self.assertEqual(
450 args[1]['timeout'],
451 docker.client.DEFAULT_TIMEOUT_SECONDS
452 )
453
454 def test_start_container_with_port_binds(self):
455 self.maxDiff = None
456 try:
457 self.client.start(fake_api.FAKE_CONTAINER_ID, port_bindings={
458 1111: None,
459 2222: 2222,
460 '3333/udp': (3333,),
461 4444: ('127.0.0.1',),
462 5555: ('127.0.0.1', 5555),
463 6666: [('127.0.0.1',), ('192.168.0.1',)]
464 })
465 except Exception as e:
466 self.fail('Command should not raise exception: {0}'.format(e))
467
468 args = fake_request.call_args
469 self.assertEqual(args[0][0], url_prefix +
470 'containers/3cc2351ab11b/start')
471 data = json.loads(args[1]['data'])
472 self.assertEqual(data['PublishAllPorts'], False)
473 self.assertTrue('1111/tcp' in data['PortBindings'])
474 self.assertTrue('2222/tcp' in data['PortBindings'])
475 self.assertTrue('3333/udp' in data['PortBindings'])
476 self.assertTrue('4444/tcp' in data['PortBindings'])
477 self.assertTrue('5555/tcp' in data['PortBindings'])
478 self.assertTrue('6666/tcp' in data['PortBindings'])
479 self.assertEqual(
480 [{"HostPort": "", "HostIp": ""}],
481 data['PortBindings']['1111/tcp']
482 )
483 self.assertEqual(
484 [{"HostPort": "2222", "HostIp": ""}],
485 data['PortBindings']['2222/tcp']
486 )
487 self.assertEqual(
488 [{"HostPort": "3333", "HostIp": ""}],
489 data['PortBindings']['3333/udp']
490 )
491 self.assertEqual(
492 [{"HostPort": "", "HostIp": "127.0.0.1"}],
493 data['PortBindings']['4444/tcp']
494 )
495 self.assertEqual(
496 [{"HostPort": "5555", "HostIp": "127.0.0.1"}],
497 data['PortBindings']['5555/tcp']
498 )
499 self.assertEqual(len(data['PortBindings']['6666/tcp']), 2)
500 self.assertEqual(args[1]['headers'],
501 {'Content-Type': 'application/json'})
502 self.assertEqual(
503 args[1]['timeout'],
504 docker.client.DEFAULT_TIMEOUT_SECONDS
505 )
506
507 def test_start_container_with_links(self):
508 # one link
509 try:
510 link_path = 'path'
511 alias = 'alias'
512 self.client.start(fake_api.FAKE_CONTAINER_ID,
513 links={link_path: alias})
514 except Exception as e:
515 self.fail('Command should not raise exception: {0}'.format(e))
516
517 args = fake_request.call_args
518 self.assertEqual(
519 args[0][0],
520 url_prefix + 'containers/3cc2351ab11b/start'
521 )
522 self.assertEqual(
523 json.loads(args[1]['data']),
524 {"PublishAllPorts": False, "Privileged": False,
525 "Links": ["path:alias"]}
526 )
527 self.assertEqual(
528 args[1]['headers'],
529 {'Content-Type': 'application/json'}
530 )
531
532 def test_start_container_with_multiple_links(self):
533 try:
534 link_path = 'path'
535 alias = 'alias'
536 self.client.start(
537 fake_api.FAKE_CONTAINER_ID,
538 links={
539 link_path + '1': alias + '1',
540 link_path + '2': alias + '2'
541 }
542 )
543 except Exception as e:
544 self.fail('Command should not raise exception: {0}'.format(e))
545
546 args = fake_request.call_args
547 self.assertEqual(
548 args[0][0],
549 url_prefix + 'containers/3cc2351ab11b/start'
550 )
551 self.assertEqual(
552 json.loads(args[1]['data']),
553 {
554 "PublishAllPorts": False,
555 "Privileged": False,
556 "Links": ["path1:alias1", "path2:alias2"]
557 }
558 )
559 self.assertEqual(
560 args[1]['headers'],
561 {'Content-Type': 'application/json'}
562 )
563
564 def test_start_container_with_links_as_list_of_tuples(self):
565 # one link
566 try:
567 link_path = 'path'
568 alias = 'alias'
569 self.client.start(fake_api.FAKE_CONTAINER_ID,
570 links=[(link_path, alias)])
571 except Exception as e:
572 self.fail('Command should not raise exception: {0}'.format(e))
573
574 args = fake_request.call_args
575 self.assertEqual(
576 args[0][0],
577 url_prefix + 'containers/3cc2351ab11b/start'
578 )
579 self.assertEqual(
580 json.loads(args[1]['data']),
581 {"PublishAllPorts": False, "Privileged": False,
582 "Links": ["path:alias"]}
583 )
584 self.assertEqual(
585 args[1]['headers'],
586 {'Content-Type': 'application/json'}
587 )
588
589 def test_start_container_privileged(self):
590 try:
591 self.client.start(fake_api.FAKE_CONTAINER_ID, privileged=True)
592 except Exception as e:
593 self.fail('Command should not raise exception: {0}'.format(e))
594
595 args = fake_request.call_args
596 self.assertEqual(
597 args[0][0],
598 url_prefix + 'containers/3cc2351ab11b/start'
599 )
600 self.assertEqual(json.loads(args[1]['data']),
601 {"PublishAllPorts": False, "Privileged": True})
602 self.assertEqual(args[1]['headers'],
603 {'Content-Type': 'application/json'})
604 self.assertEqual(
605 args[1]['timeout'],
606 docker.client.DEFAULT_TIMEOUT_SECONDS
607 )
608
609 def test_start_container_with_dict_instead_of_id(self):
610 try:
611 self.client.start({'Id': fake_api.FAKE_CONTAINER_ID})
612 except Exception as e:
613 self.fail('Command should not raise exception: {0}'.format(e))
614 args = fake_request.call_args
615 self.assertEqual(
616 args[0][0],
617 url_prefix + 'containers/3cc2351ab11b/start'
618 )
619 self.assertEqual(
620 json.loads(args[1]['data']),
621 {"PublishAllPorts": False, "Privileged": False}
622 )
623 self.assertEqual(
624 args[1]['headers'],
625 {'Content-Type': 'application/json'}
626 )
627 self.assertEqual(
628 args[1]['timeout'],
629 docker.client.DEFAULT_TIMEOUT_SECONDS
630 )
631
632 def test_wait(self):
633 try:
634 self.client.wait(fake_api.FAKE_CONTAINER_ID)
635 except Exception as e:
636 self.fail('Command should not raise exception: {0}'.format(e))
637
638 fake_request.assert_called_with(
639 url_prefix + 'containers/3cc2351ab11b/wait',
640 timeout=None
641 )
642
643 def test_wait_with_dict_instead_of_id(self):
644 try:
645 self.client.wait({'Id': fake_api.FAKE_CONTAINER_ID})
646 except Exception as e:
647 raise e
648 self.fail('Command should not raise exception: {0}'.format(e))
649
650 fake_request.assert_called_with(
651 url_prefix + 'containers/3cc2351ab11b/wait',
652 timeout=None
653 )
654
655 def test_url_compatibility_unix(self):
656 c = docker.Client(base_url="unix://socket")
657
658 assert c.base_url == "http+unix://socket"
659
660 def test_url_compatibility_unix_triple_slash(self):
661 c = docker.Client(base_url="unix:///socket")
662
663 assert c.base_url == "http+unix://socket"
664
665 def test_url_compatibility_http_unix_triple_slash(self):
666 c = docker.Client(base_url="http+unix:///socket")
667
668 assert c.base_url == "http+unix://socket"
669
670 def test_url_compatibility_http(self):
671 c = docker.Client(base_url="http://hostname")
672
673 assert c.base_url == "http://hostname"
674
675 def test_url_compatibility_tcp(self):
676 c = docker.Client(base_url="tcp://hostname")
677
678 assert c.base_url == "http://hostname"
679
680 def test_logs(self):
681 try:
682 self.client.logs(fake_api.FAKE_CONTAINER_ID)
683 except Exception as e:
684 self.fail('Command should not raise exception: {0}'.format(e))
685
686 fake_request.assert_called_with(
687 url_prefix + 'containers/3cc2351ab11b/attach',
688 params={'stream': 0, 'logs': 1, 'stderr': 1, 'stdout': 1},
689 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS,
690 stream=False
691 )
692
693 def test_logs_with_dict_instead_of_id(self):
694 try:
695 self.client.logs({'Id': fake_api.FAKE_CONTAINER_ID})
696 except Exception as e:
697 self.fail('Command should not raise exception: {0}'.format(e))
698
699 fake_request.assert_called_with(
700 url_prefix + 'containers/3cc2351ab11b/attach',
701 params={'stream': 0, 'logs': 1, 'stderr': 1, 'stdout': 1},
702 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS,
703 stream=False
704 )
705
706 def test_log_streaming(self):
707 try:
708 self.client.logs(fake_api.FAKE_CONTAINER_ID, stream=True)
709 except Exception as e:
710 self.fail('Command should not raise exception: {0}'.format(e))
711
712 fake_request.assert_called_with(
713 url_prefix + 'containers/3cc2351ab11b/attach',
714 params={'stream': 1, 'logs': 1, 'stderr': 1, 'stdout': 1},
715 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS,
716 stream=True
717 )
718
719 def test_diff(self):
720 try:
721 self.client.diff(fake_api.FAKE_CONTAINER_ID)
722 except Exception as e:
723 self.fail('Command should not raise exception: {0}'.format(e))
724
725 fake_request.assert_called_with(
726 url_prefix + 'containers/3cc2351ab11b/changes',
727 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
728 )
729
730 def test_diff_with_dict_instead_of_id(self):
731 try:
732 self.client.diff({'Id': fake_api.FAKE_CONTAINER_ID})
733 except Exception as e:
734 self.fail('Command should not raise exception: {0}'.format(e))
735
736 fake_request.assert_called_with(
737 url_prefix + 'containers/3cc2351ab11b/changes',
738 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
739 )
740
741 def test_port(self):
742 try:
743 self.client.port({'Id': fake_api.FAKE_CONTAINER_ID}, 1111)
744 except Exception as e:
745 self.fail('Command should not raise exception: {0}'.format(e))
746
747 fake_request.assert_called_with(
748 url_prefix + 'containers/3cc2351ab11b/json',
749 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
750 )
751
752 def test_stop_container(self):
753 try:
754 self.client.stop(fake_api.FAKE_CONTAINER_ID, timeout=2)
755 except Exception as e:
756 self.fail('Command should not raise exception: {0}'.format(e))
757
758 fake_request.assert_called_with(
759 url_prefix + 'containers/3cc2351ab11b/stop',
760 params={'t': 2},
761 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
762 )
763
764 def test_stop_container_with_dict_instead_of_id(self):
765 try:
766 self.client.stop({'Id': fake_api.FAKE_CONTAINER_ID}, timeout=2)
767 except Exception as e:
768 self.fail('Command should not raise exception: {0}'.format(e))
769
770 fake_request.assert_called_with(
771 url_prefix + 'containers/3cc2351ab11b/stop',
772 params={'t': 2},
773 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
774 )
775
776 def test_kill_container(self):
777 try:
778 self.client.kill(fake_api.FAKE_CONTAINER_ID)
779 except Exception as e:
780 self.fail('Command should not raise exception: {0}'.format(e))
781
782 fake_request.assert_called_with(
783 url_prefix + 'containers/3cc2351ab11b/kill',
784 params={},
785 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
786 )
787
788 def test_kill_container_with_dict_instead_of_id(self):
789 try:
790 self.client.kill({'Id': fake_api.FAKE_CONTAINER_ID})
791 except Exception as e:
792 self.fail('Command should not raise exception: {0}'.format(e))
793
794 fake_request.assert_called_with(
795 url_prefix + 'containers/3cc2351ab11b/kill',
796 params={},
797 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
798 )
799
800 def test_kill_container_with_signal(self):
801 try:
802 self.client.kill(fake_api.FAKE_CONTAINER_ID, signal=signal.SIGTERM)
803 except Exception as e:
804 self.fail('Command should not raise exception: {0}'.format(e))
805
806 fake_request.assert_called_with(
807 url_prefix + 'containers/3cc2351ab11b/kill',
808 params={'signal': signal.SIGTERM},
809 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
810 )
811
812 def test_restart_container(self):
813 try:
814 self.client.restart(fake_api.FAKE_CONTAINER_ID, timeout=2)
815 except Exception as e:
816 self.fail('Command should not raise exception : {0}'.format(e))
817
818 fake_request.assert_called_with(
819 url_prefix + 'containers/3cc2351ab11b/restart',
820 params={'t': 2},
821 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
822 )
823
824 def test_restart_container_with_dict_instead_of_id(self):
825 try:
826 self.client.restart({'Id': fake_api.FAKE_CONTAINER_ID}, timeout=2)
827 except Exception as e:
828 self.fail('Command should not raise exception: {0}'.format(e))
829
830 fake_request.assert_called_with(
831 url_prefix + 'containers/3cc2351ab11b/restart',
832 params={'t': 2},
833 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
834 )
835
836 def test_remove_container(self):
837 try:
838 self.client.remove_container(fake_api.FAKE_CONTAINER_ID)
839 except Exception as e:
840 self.fail('Command should not raise exception: {0}'.format(e))
841
842 fake_request.assert_called_with(
843 url_prefix + 'containers/3cc2351ab11b',
844 params={'v': False, 'link': False},
845 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
846 )
847
848 def test_remove_container_with_dict_instead_of_id(self):
849 try:
850 self.client.remove_container({'Id': fake_api.FAKE_CONTAINER_ID})
851 except Exception as e:
852 self.fail('Command should not raise exception: {0}'.format(e))
853
854 fake_request.assert_called_with(
855 url_prefix + 'containers/3cc2351ab11b',
856 params={'v': False, 'link': False},
857 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
858 )
859
860 def test_remove_link(self):
861 try:
862 self.client.remove_container(fake_api.FAKE_CONTAINER_ID, link=True)
863 except Exception as e:
864 self.fail('Command should not raise exception: {0}'.format(e))
865
866 fake_request.assert_called_with(
867 url_prefix + 'containers/3cc2351ab11b',
868 params={'v': False, 'link': True},
869 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
870 )
871
872 def test_export(self):
873 try:
874 self.client.export(fake_api.FAKE_CONTAINER_ID)
875 except Exception as e:
876 self.fail('Command should not raise exception: {0}'.format(e))
877
878 fake_request.assert_called_with(
879 url_prefix + 'containers/3cc2351ab11b/export',
880 stream=True,
881 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
882 )
883
884 def test_export_with_dict_instead_of_id(self):
885 try:
886 self.client.export({'Id': fake_api.FAKE_CONTAINER_ID})
887 except Exception as e:
888 self.fail('Command should not raise exception: {0}'.format(e))
889
890 fake_request.assert_called_with(
891 url_prefix + 'containers/3cc2351ab11b/export',
892 stream=True,
893 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
894 )
895
896 def test_inspect_container(self):
897 try:
898 self.client.inspect_container(fake_api.FAKE_CONTAINER_ID)
899 except Exception as e:
900 self.fail('Command should not raise exception: {0}'.format(e))
901
902 fake_request.assert_called_with(
903 url_prefix + 'containers/3cc2351ab11b/json',
904 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
905 )
906
907 ##################
908 ## IMAGES TESTS ##
909 ##################
910
911 def test_pull(self):
912 try:
913 self.client.pull('joffrey/test001')
914 except Exception as e:
915 self.fail('Command should not raise exception: {0}'.format(e))
916
917 args = fake_request.call_args
918 self.assertEqual(
919 args[0][0],
920 url_prefix + 'images/create'
921 )
922 self.assertEqual(
923 args[1]['params'],
924 {'tag': None, 'fromImage': 'joffrey/test001'}
925 )
926 self.assertFalse(args[1]['stream'])
927
928 def test_pull_stream(self):
929 try:
930 self.client.pull('joffrey/test001', stream=True)
931 except Exception as e:
932 self.fail('Command should not raise exception: {0}'.format(e))
933
934 args = fake_request.call_args
935 self.assertEqual(
936 args[0][0],
937 url_prefix + 'images/create'
938 )
939 self.assertEqual(
940 args[1]['params'],
941 {'tag': None, 'fromImage': 'joffrey/test001'}
942 )
943 self.assertTrue(args[1]['stream'])
944
945 def test_commit(self):
946 try:
947 self.client.commit(fake_api.FAKE_CONTAINER_ID)
948 except Exception as e:
949 self.fail('Command should not raise exception: {0}'.format(e))
950
951 fake_request.assert_called_with(
952 url_prefix + 'commit',
953 data='{}',
954 headers={'Content-Type': 'application/json'},
955 params={
956 'repo': None,
957 'comment': None,
958 'tag': None,
959 'container': '3cc2351ab11b',
960 'author': None
961 },
962 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
963 )
964
965 def test_remove_image(self):
966 try:
967 self.client.remove_image(fake_api.FAKE_IMAGE_ID)
968 except Exception as e:
969 self.fail('Command should not raise exception: {0}'.format(e))
970
971 fake_request.assert_called_with(
972 url_prefix + 'images/e9aa60c60128',
973 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
974 )
975
976 def test_image_history(self):
977 try:
978 self.client.history(fake_api.FAKE_IMAGE_NAME)
979 except Exception as e:
980 self.fail('Command should not raise exception: {0}'.format(e))
981
982 fake_request.assert_called_with(
983 url_prefix + 'images/test_image/history',
984 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
985 )
986
987 def test_import_image(self):
988 try:
989 self.client.import_image(
990 fake_api.FAKE_TARBALL_PATH,
991 repository=fake_api.FAKE_REPO_NAME,
992 tag=fake_api.FAKE_TAG_NAME
993 )
994 except Exception as e:
995 self.fail('Command should not raise exception: {0}'.format(e))
996
997 fake_request.assert_called_with(
998 url_prefix + 'images/create',
999 params={
1000 'repo': fake_api.FAKE_REPO_NAME,
1001 'tag': fake_api.FAKE_TAG_NAME,
1002 'fromSrc': fake_api.FAKE_TARBALL_PATH
1003 },
1004 data=None,
1005 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
1006 )
1007
1008 def test_import_image_from_file(self):
1009 buf = tempfile.NamedTemporaryFile(delete=False)
1010 try:
1011 # pretent the buffer is a file
1012 self.client.import_image(
1013 buf.name,
1014 repository=fake_api.FAKE_REPO_NAME,
1015 tag=fake_api.FAKE_TAG_NAME
1016 )
1017 except Exception as e:
1018 self.fail('Command should not raise exception: {0}'.format(e))
1019
1020 fake_request.assert_called_with(
1021 url_prefix + 'images/create',
1022 params={
1023 'repo': fake_api.FAKE_REPO_NAME,
1024 'tag': fake_api.FAKE_TAG_NAME,
1025 'fromSrc': '-'
1026 },
1027 data='',
1028 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
1029 )
1030 buf.close()
1031 os.remove(buf.name)
1032
1033 def test_import_image_from_image(self):
1034 try:
1035 self.client.import_image(
1036 image=fake_api.FAKE_IMAGE_NAME,
1037 repository=fake_api.FAKE_REPO_NAME,
1038 tag=fake_api.FAKE_TAG_NAME
1039 )
1040 except Exception as e:
1041 self.fail('Command should not raise exception: {0}'.format(e))
1042
1043 fake_request.assert_called_with(
1044 url_prefix + 'images/create',
1045 params={
1046 'repo': fake_api.FAKE_REPO_NAME,
1047 'tag': fake_api.FAKE_TAG_NAME,
1048 'fromImage': fake_api.FAKE_IMAGE_NAME
1049 },
1050 data=None,
1051 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
1052 )
1053
1054 def test_inspect_image(self):
1055 try:
1056 self.client.inspect_image(fake_api.FAKE_IMAGE_NAME)
1057 except Exception as e:
1058 self.fail('Command should not raise exception: {0}'.format(e))
1059
1060 fake_request.assert_called_with(
1061 url_prefix + 'images/test_image/json',
1062 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
1063 )
1064
1065 def test_insert_image(self):
1066 try:
1067 self.client.insert(fake_api.FAKE_IMAGE_NAME,
1068 fake_api.FAKE_URL, fake_api.FAKE_PATH)
1069 except Exception as e:
1070 self.fail('Command should not raise exception: {0}'.format(e))
1071
1072 fake_request.assert_called_with(
1073 url_prefix + 'images/test_image/insert',
1074 params={
1075 'url': fake_api.FAKE_URL,
1076 'path': fake_api.FAKE_PATH
1077 },
1078 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
1079 )
1080
1081 def test_push_image(self):
1082 try:
1083 self.client.push(fake_api.FAKE_IMAGE_NAME)
1084 except Exception as e:
1085 self.fail('Command should not raise exception: {0}'.format(e))
1086
1087 fake_request.assert_called_with(
1088 url_prefix + 'images/test_image/push',
1089 data='{}',
1090 headers={'Content-Type': 'application/json'},
1091 stream=False,
1092 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
1093 )
1094
1095 def test_push_image_stream(self):
1096 try:
1097 self.client.push(fake_api.FAKE_IMAGE_NAME, stream=True)
1098 except Exception as e:
1099 self.fail('Command should not raise exception: {0}'.format(e))
1100
1101 fake_request.assert_called_with(
1102 url_prefix + 'images/test_image/push',
1103 data='{}',
1104 headers={'Content-Type': 'application/json'},
1105 stream=True,
1106 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
1107 )
1108
1109 def test_tag_image(self):
1110 try:
1111 self.client.tag(fake_api.FAKE_IMAGE_ID, fake_api.FAKE_REPO_NAME)
1112 except Exception as e:
1113 self.fail('Command should not raise exception: {0}'.format(e))
1114
1115 fake_request.assert_called_with(
1116 url_prefix + 'images/e9aa60c60128/tag',
1117 params={
1118 'tag': None,
1119 'repo': 'repo',
1120 'force': 0
1121 },
1122 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
1123 )
1124
1125 def test_tag_image_tag(self):
1126 try:
1127 self.client.tag(
1128 fake_api.FAKE_IMAGE_ID,
1129 fake_api.FAKE_REPO_NAME,
1130 tag=fake_api.FAKE_TAG_NAME
1131 )
1132 except Exception as e:
1133 self.fail('Command should not raise exception: {0}'.format(e))
1134
1135 fake_request.assert_called_with(
1136 url_prefix + 'images/e9aa60c60128/tag',
1137 params={
1138 'tag': 'tag',
1139 'repo': 'repo',
1140 'force': 0
1141 },
1142 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
1143 )
1144
1145 def test_tag_image_force(self):
1146 try:
1147 self.client.tag(
1148 fake_api.FAKE_IMAGE_ID, fake_api.FAKE_REPO_NAME, force=True)
1149 except Exception as e:
1150 self.fail('Command should not raise exception: {0}'.format(e))
1151
1152 fake_request.assert_called_with(
1153 url_prefix + 'images/e9aa60c60128/tag',
1154 params={
1155 'tag': None,
1156 'repo': 'repo',
1157 'force': 1
1158 },
1159 timeout=docker.client.DEFAULT_TIMEOUT_SECONDS
1160 )
1161
1162 #################
1163 # BUILDER TESTS #
1164 #################
1165
1166 def test_build_container(self):
1167 script = io.BytesIO('\n'.join([
1168 'FROM busybox',
1169 'MAINTAINER docker-py',
1170 'RUN mkdir -p /tmp/test',
1171 'EXPOSE 8080',
1172 'ADD https://dl.dropboxusercontent.com/u/20637798/silence.tar.gz'
1173 ' /tmp/silence.tar.gz'
1174 ]).encode('ascii'))
1175 try:
1176 self.client.build(fileobj=script)
1177 except Exception as e:
1178 self.fail('Command should not raise exception: {0}'.format(e))
1179
1180 def test_build_container_stream(self):
1181 script = io.BytesIO('\n'.join([
1182 'FROM busybox',
1183 'MAINTAINER docker-py',
1184 'RUN mkdir -p /tmp/test',
1185 'EXPOSE 8080',
1186 'ADD https://dl.dropboxusercontent.com/u/20637798/silence.tar.gz'
1187 ' /tmp/silence.tar.gz'
1188 ]).encode('ascii'))
1189 try:
1190 self.client.build(fileobj=script, stream=True)
1191 except Exception as e:
1192 self.fail('Command should not raise exception: {0}'.format(e))
1193
1194 #######################
1195 ## PY SPECIFIC TESTS ##
1196 #######################
1197
1198 def test_load_config_no_file(self):
1199 folder = tempfile.mkdtemp()
1200 cfg = docker.auth.load_config(folder)
1201 self.assertTrue(cfg is not None)
1202
1203 def test_load_config(self):
1204 folder = tempfile.mkdtemp()
1205 f = open(os.path.join(folder, '.dockercfg'), 'w')
1206 auth_ = base64.b64encode(b'sakuya:izayoi').decode('ascii')
1207 f.write('auth = {0}\n'.format(auth_))
1208 f.write('email = sakuya@scarlet.net')
1209 f.close()
1210 cfg = docker.auth.load_config(folder)
1211 self.assertTrue(docker.auth.INDEX_URL in cfg)
1212 self.assertNotEqual(cfg[docker.auth.INDEX_URL], None)
1213 cfg = cfg[docker.auth.INDEX_URL]
1214 self.assertEqual(cfg['username'], 'sakuya')
1215 self.assertEqual(cfg['password'], 'izayoi')
1216 self.assertEqual(cfg['email'], 'sakuya@scarlet.net')
1217 self.assertEqual(cfg.get('auth'), None)
1218
1219
1220if __name__ == '__main__':
1221 unittest.main()