blob: 59c896c51b3fdcc2a56ec585e87623340c023a19 [file] [log] [blame]
[email protected]982cc4d2014-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 time
16import base64
17import io
18import os
19import signal
20import tempfile
21import unittest
22
23import docker
24import six
25
26# FIXME: missing tests for
27# export; history; import_image; insert; port; push; tag
28
29
30class BaseTestCase(unittest.TestCase):
31 tmp_imgs = []
32 tmp_containers = []
33
34 def setUp(self):
35 self.client = docker.Client()
36 self.client.pull('busybox')
37 self.tmp_imgs = []
38 self.tmp_containers = []
39
40 def tearDown(self):
41 for img in self.tmp_imgs:
42 try:
43 self.client.remove_image(img)
44 except docker.APIError:
45 pass
46 for container in self.tmp_containers:
47 try:
48 self.client.stop(container, timeout=1)
49 self.client.remove_container(container)
50 except docker.APIError:
51 pass
52
53#########################
54## INFORMATION TESTS ##
55#########################
56
57
58class TestVersion(BaseTestCase):
59 def runTest(self):
60 res = self.client.version()
61 self.assertIn('GoVersion', res)
62 self.assertIn('Version', res)
63 self.assertEqual(len(res['Version'].split('.')), 3)
64
65
66class TestInfo(BaseTestCase):
67 def runTest(self):
68 res = self.client.info()
69 self.assertIn('Containers', res)
70 self.assertIn('Images', res)
71 self.assertIn('Debug', res)
72
73
74class TestSearch(BaseTestCase):
75 def runTest(self):
76 res = self.client.search('busybox')
77 self.assertTrue(len(res) >= 1)
78 base_img = [x for x in res if x['name'] == 'busybox']
79 self.assertEqual(len(base_img), 1)
80 self.assertIn('description', base_img[0])
81
82###################
83## LISTING TESTS ##
84###################
85
86
87class TestImages(BaseTestCase):
88 def runTest(self):
89 res1 = self.client.images(all=True)
90 self.assertIn('Id', res1[0])
91 res10 = [x for x in res1 if x['Id'].startswith('e9aa60c60128')][0]
92 self.assertIn('Created', res10)
93 self.assertIn('Repository', res10)
94 self.assertIn('Tag', res10)
95 self.assertEqual(res10['Tag'], 'latest')
96 self.assertEqual(res10['Repository'], 'busybox')
97 distinct = []
98 for img in res1:
99 if img['Id'] not in distinct:
100 distinct.append(img['Id'])
101 self.assertEqual(len(distinct), self.client.info()['Images'])
102
103
104class TestImageIds(BaseTestCase):
105 def runTest(self):
106 res1 = self.client.images(quiet=True)
107 self.assertEqual(type(res1[0]), six.text_type)
108
109
110class TestListContainers(BaseTestCase):
111 def runTest(self):
112 res0 = self.client.containers(all=True)
113 size = len(res0)
114 res1 = self.client.create_container('busybox', 'true')
115 self.assertIn('Id', res1)
116 self.client.start(res1['Id'])
117 self.tmp_containers.append(res1['Id'])
118 res2 = self.client.containers(all=True)
119 self.assertEqual(size + 1, len(res2))
120 retrieved = [x for x in res2 if x['Id'].startswith(res1['Id'])]
121 self.assertEqual(len(retrieved), 1)
122 retrieved = retrieved[0]
123 self.assertIn('Command', retrieved)
124 self.assertEqual(retrieved['Command'], 'true ')
125 self.assertIn('Image', retrieved)
126 self.assertEqual(retrieved['Image'], 'busybox:latest')
127 self.assertIn('Status', retrieved)
128
129#####################
130## CONTAINER TESTS ##
131#####################
132
133
134class TestCreateContainer(BaseTestCase):
135 def runTest(self):
136 res = self.client.create_container('busybox', 'true')
137 self.assertIn('Id', res)
138 self.tmp_containers.append(res['Id'])
139
140
141class TestCreateContainerWithBinds(BaseTestCase):
142 def runTest(self):
143 mount_dest = '/mnt'
144 mount_origin = '/tmp'
145
146 filename = 'shared.txt'
147 shared_file = os.path.join(mount_origin, filename)
148
149 with open(shared_file, 'w'):
150 container = self.client.create_container(
151 'busybox',
152 ['ls', mount_dest], volumes={mount_dest: {}}
153 )
154 container_id = container['Id']
155 self.client.start(container_id, binds={mount_origin: mount_dest})
156 self.tmp_containers.append(container_id)
157 exitcode = self.client.wait(container_id)
158 self.assertEqual(exitcode, 0)
159 logs = self.client.logs(container_id)
160
161 os.unlink(shared_file)
162 self.assertIn(filename, logs)
163
164
165class TestCreateContainerWithName(BaseTestCase):
166 def runTest(self):
167 res = self.client.create_container('busybox', 'true', name='foobar')
168 self.assertIn('Id', res)
169 self.tmp_containers.append(res['Id'])
170 inspect = self.client.inspect_container(res['Id'])
171 self.assertIn('Name', inspect)
172 self.assertEqual('/foobar', inspect['Name'])
173
174
175class TestStartContainer(BaseTestCase):
176 def runTest(self):
177 res = self.client.create_container('busybox', 'true')
178 self.assertIn('Id', res)
179 self.tmp_containers.append(res['Id'])
180 self.client.start(res['Id'])
181 inspect = self.client.inspect_container(res['Id'])
182 self.assertIn('Config', inspect)
183 self.assertIn('ID', inspect)
184 self.assertTrue(inspect['ID'].startswith(res['Id']))
185 self.assertIn('Image', inspect)
186 self.assertIn('State', inspect)
187 self.assertIn('Running', inspect['State'])
188 if not inspect['State']['Running']:
189 self.assertIn('ExitCode', inspect['State'])
190 self.assertEqual(inspect['State']['ExitCode'], 0)
191
192
193class TestStartContainerWithDictInsteadOfId(BaseTestCase):
194 def runTest(self):
195 res = self.client.create_container('busybox', 'true')
196 self.assertIn('Id', res)
197 self.tmp_containers.append(res['Id'])
198 self.client.start(res)
199 inspect = self.client.inspect_container(res['Id'])
200 self.assertIn('Config', inspect)
201 self.assertIn('ID', inspect)
202 self.assertTrue(inspect['ID'].startswith(res['Id']))
203 self.assertIn('Image', inspect)
204 self.assertIn('State', inspect)
205 self.assertIn('Running', inspect['State'])
206 if not inspect['State']['Running']:
207 self.assertIn('ExitCode', inspect['State'])
208 self.assertEqual(inspect['State']['ExitCode'], 0)
209
210
211class TestStartContainerPrivileged(BaseTestCase):
212 def runTest(self):
213 res = self.client.create_container('busybox', 'true')
214 self.assertIn('Id', res)
215 self.tmp_containers.append(res['Id'])
216 self.client.start(res['Id'], privileged=True)
217 inspect = self.client.inspect_container(res['Id'])
218 self.assertIn('Config', inspect)
219 self.assertIn('ID', inspect)
220 self.assertTrue(inspect['ID'].startswith(res['Id']))
221 self.assertIn('Image', inspect)
222 self.assertIn('State', inspect)
223 self.assertIn('Running', inspect['State'])
224 if not inspect['State']['Running']:
225 self.assertIn('ExitCode', inspect['State'])
226 self.assertEqual(inspect['State']['ExitCode'], 0)
227 # Since Nov 2013, the Privileged flag is no longer part of the
228 # container's config exposed via the API (safety concerns?).
229 #
230 # self.assertEqual(inspect['Config']['Privileged'], True)
231
232
233class TestWait(BaseTestCase):
234 def runTest(self):
235 res = self.client.create_container('busybox', ['sleep', '10'])
236 id = res['Id']
237 self.tmp_containers.append(id)
238 self.client.start(id)
239 exitcode = self.client.wait(id)
240 self.assertEqual(exitcode, 0)
241 inspect = self.client.inspect_container(id)
242 self.assertIn('Running', inspect['State'])
243 self.assertEqual(inspect['State']['Running'], False)
244 self.assertIn('ExitCode', inspect['State'])
245 self.assertEqual(inspect['State']['ExitCode'], exitcode)
246
247
248class TestWaitWithDictInsteadOfId(BaseTestCase):
249 def runTest(self):
250 res = self.client.create_container('busybox', ['sleep', '10'])
251 id = res['Id']
252 self.tmp_containers.append(id)
253 self.client.start(res)
254 exitcode = self.client.wait(res)
255 self.assertEqual(exitcode, 0)
256 inspect = self.client.inspect_container(res)
257 self.assertIn('Running', inspect['State'])
258 self.assertEqual(inspect['State']['Running'], False)
259 self.assertIn('ExitCode', inspect['State'])
260 self.assertEqual(inspect['State']['ExitCode'], exitcode)
261
262
263class TestLogs(BaseTestCase):
264 def runTest(self):
265 snippet = 'Flowering Nights (Sakuya Iyazoi)'
266 container = self.client.create_container(
267 'busybox', 'echo {0}'.format(snippet)
268 )
269 id = container['Id']
270 self.client.start(id)
271 self.tmp_containers.append(id)
272 exitcode = self.client.wait(id)
273 self.assertEqual(exitcode, 0)
274 logs = self.client.logs(id)
275 self.assertEqual(logs, snippet + '\n')
276
277
278class TestLogsStreaming(BaseTestCase):
279 def runTest(self):
280 snippet = 'Flowering Nights (Sakuya Iyazoi)'
281 container = self.client.create_container(
282 'busybox', 'echo {0}'.format(snippet)
283 )
284 id = container['Id']
285 self.client.start(id)
286 self.tmp_containers.append(id)
287 logs = ''
288 for chunk in self.client.logs(id, stream=True):
289 logs += chunk
290
291 exitcode = self.client.wait(id)
292 self.assertEqual(exitcode, 0)
293
294 self.assertEqual(logs, snippet + '\n')
295
296
297class TestLogsWithDictInsteadOfId(BaseTestCase):
298 def runTest(self):
299 snippet = 'Flowering Nights (Sakuya Iyazoi)'
300 container = self.client.create_container(
301 'busybox', 'echo {0}'.format(snippet)
302 )
303 id = container['Id']
304 self.client.start(id)
305 self.tmp_containers.append(id)
306 exitcode = self.client.wait(id)
307 self.assertEqual(exitcode, 0)
308 logs = self.client.logs(container)
309 self.assertEqual(logs, snippet + '\n')
310
311
312class TestDiff(BaseTestCase):
313 def runTest(self):
314 container = self.client.create_container('busybox', ['touch', '/test'])
315 id = container['Id']
316 self.client.start(id)
317 self.tmp_containers.append(id)
318 exitcode = self.client.wait(id)
319 self.assertEqual(exitcode, 0)
320 diff = self.client.diff(id)
321 test_diff = [x for x in diff if x.get('Path', None) == '/test']
322 self.assertEqual(len(test_diff), 1)
323 self.assertIn('Kind', test_diff[0])
324 self.assertEqual(test_diff[0]['Kind'], 1)
325
326
327class TestDiffWithDictInsteadOfId(BaseTestCase):
328 def runTest(self):
329 container = self.client.create_container('busybox', ['touch', '/test'])
330 id = container['Id']
331 self.client.start(id)
332 self.tmp_containers.append(id)
333 exitcode = self.client.wait(id)
334 self.assertEqual(exitcode, 0)
335 diff = self.client.diff(container)
336 test_diff = [x for x in diff if x.get('Path', None) == '/test']
337 self.assertEqual(len(test_diff), 1)
338 self.assertIn('Kind', test_diff[0])
339 self.assertEqual(test_diff[0]['Kind'], 1)
340
341
342class TestStop(BaseTestCase):
343 def runTest(self):
344 container = self.client.create_container('busybox', ['sleep', '9999'])
345 id = container['Id']
346 self.client.start(id)
347 self.tmp_containers.append(id)
348 self.client.stop(id, timeout=2)
349 container_info = self.client.inspect_container(id)
350 self.assertIn('State', container_info)
351 state = container_info['State']
352 self.assertIn('ExitCode', state)
353 self.assertNotEqual(state['ExitCode'], 0)
354 self.assertIn('Running', state)
355 self.assertEqual(state['Running'], False)
356
357
358class TestStopWithDictInsteadOfId(BaseTestCase):
359 def runTest(self):
360 container = self.client.create_container('busybox', ['sleep', '9999'])
361 self.assertIn('Id', container)
362 id = container['Id']
363 self.client.start(container)
364 self.tmp_containers.append(id)
365 self.client.stop(container, timeout=2)
366 container_info = self.client.inspect_container(id)
367 self.assertIn('State', container_info)
368 state = container_info['State']
369 self.assertIn('ExitCode', state)
370 self.assertNotEqual(state['ExitCode'], 0)
371 self.assertIn('Running', state)
372 self.assertEqual(state['Running'], False)
373
374
375class TestKill(BaseTestCase):
376 def runTest(self):
377 container = self.client.create_container('busybox', ['sleep', '9999'])
378 id = container['Id']
379 self.client.start(id)
380 self.tmp_containers.append(id)
381 self.client.kill(id)
382 container_info = self.client.inspect_container(id)
383 self.assertIn('State', container_info)
384 state = container_info['State']
385 self.assertIn('ExitCode', state)
386 self.assertNotEqual(state['ExitCode'], 0)
387 self.assertIn('Running', state)
388 self.assertEqual(state['Running'], False)
389
390
391class TestKillWithDictInsteadOfId(BaseTestCase):
392 def runTest(self):
393 container = self.client.create_container('busybox', ['sleep', '9999'])
394 id = container['Id']
395 self.client.start(id)
396 self.tmp_containers.append(id)
397 self.client.kill(container)
398 container_info = self.client.inspect_container(id)
399 self.assertIn('State', container_info)
400 state = container_info['State']
401 self.assertIn('ExitCode', state)
402 self.assertNotEqual(state['ExitCode'], 0)
403 self.assertIn('Running', state)
404 self.assertEqual(state['Running'], False)
405
406
407class TestKillWithSignal(BaseTestCase):
408 def runTest(self):
409 container = self.client.create_container('busybox', ['sleep', '60'])
410 id = container['Id']
411 self.client.start(id)
412 self.tmp_containers.append(id)
413 self.client.kill(id, signal=signal.SIGTERM)
414 exitcode = self.client.wait(id)
415 self.assertNotEqual(exitcode, 0)
416 container_info = self.client.inspect_container(id)
417 self.assertIn('State', container_info)
418 state = container_info['State']
419 self.assertIn('ExitCode', state)
420 self.assertNotEqual(state['ExitCode'], 0)
421 self.assertIn('Running', state)
422 self.assertEqual(state['Running'], False, state)
423
424
425class TestPort(BaseTestCase):
426 def runTest(self):
427
428 port_bindings = {
429 1111: ('127.0.0.1', '4567'),
430 2222: ('192.168.0.100', '4568')
431 }
432
433 container = self.client.create_container(
434 'busybox', ['sleep', '60'], ports=port_bindings.keys()
435 )
436 id = container['Id']
437
438 self.client.start(container, port_bindings=port_bindings)
439
440 #Call the port function on each biding and compare expected vs actual
441 for port in port_bindings:
442 actual_bindings = self.client.port(container, port)
443 port_binding = actual_bindings.pop()
444
445 ip, host_port = port_binding['HostIp'], port_binding['HostPort']
446
447 self.assertEqual(ip, port_bindings[port][0])
448 self.assertEqual(host_port, port_bindings[port][1])
449
450 self.client.kill(id)
451
452
453class TestRestart(BaseTestCase):
454 def runTest(self):
455 container = self.client.create_container('busybox', ['sleep', '9999'])
456 id = container['Id']
457 self.client.start(id)
458 self.tmp_containers.append(id)
459 info = self.client.inspect_container(id)
460 self.assertIn('State', info)
461 self.assertIn('StartedAt', info['State'])
462 start_time1 = info['State']['StartedAt']
463 self.client.restart(id, timeout=2)
464 info2 = self.client.inspect_container(id)
465 self.assertIn('State', info2)
466 self.assertIn('StartedAt', info2['State'])
467 start_time2 = info2['State']['StartedAt']
468 self.assertNotEqual(start_time1, start_time2)
469 self.assertIn('Running', info2['State'])
470 self.assertEqual(info2['State']['Running'], True)
471 self.client.kill(id)
472
473
474class TestRestartWithDictInsteadOfId(BaseTestCase):
475 def runTest(self):
476 container = self.client.create_container('busybox', ['sleep', '9999'])
477 self.assertIn('Id', container)
478 id = container['Id']
479 self.client.start(container)
480 self.tmp_containers.append(id)
481 info = self.client.inspect_container(id)
482 self.assertIn('State', info)
483 self.assertIn('StartedAt', info['State'])
484 start_time1 = info['State']['StartedAt']
485 self.client.restart(container, timeout=2)
486 info2 = self.client.inspect_container(id)
487 self.assertIn('State', info2)
488 self.assertIn('StartedAt', info2['State'])
489 start_time2 = info2['State']['StartedAt']
490 self.assertNotEqual(start_time1, start_time2)
491 self.assertIn('Running', info2['State'])
492 self.assertEqual(info2['State']['Running'], True)
493 self.client.kill(id)
494
495
496class TestRemoveContainer(BaseTestCase):
497 def runTest(self):
498 container = self.client.create_container('busybox', ['true'])
499 id = container['Id']
500 self.client.start(id)
501 self.client.wait(id)
502 self.client.remove_container(id)
503 containers = self.client.containers(all=True)
504 res = [x for x in containers if 'Id' in x and x['Id'].startswith(id)]
505 self.assertEqual(len(res), 0)
506
507
508class TestRemoveContainerWithDictInsteadOfId(BaseTestCase):
509 def runTest(self):
510 container = self.client.create_container('busybox', ['true'])
511 id = container['Id']
512 self.client.start(id)
513 self.client.wait(id)
514 self.client.remove_container(container)
515 containers = self.client.containers(all=True)
516 res = [x for x in containers if 'Id' in x and x['Id'].startswith(id)]
517 self.assertEqual(len(res), 0)
518
519
520class TestStartContainerWithLinks(BaseTestCase):
521 def runTest(self):
522 res0 = self.client.create_container(
523 'busybox', 'cat',
524 detach=True, stdin_open=True,
525 environment={'FOO': '1'})
526
527 container1_id = res0['Id']
528 self.tmp_containers.append(container1_id)
529
530 self.client.start(container1_id)
531
532 res1 = self.client.create_container(
533 'busybox', 'cat',
534 detach=True, stdin_open=True,
535 environment={'FOO': '1'})
536
537 container2_id = res1['Id']
538 self.tmp_containers.append(container2_id)
539
540 self.client.start(container2_id)
541
542 # we don't want the first /
543 link_path1 = self.client.inspect_container(container1_id)['Name'][1:]
544 link_alias1 = 'mylink1'
545 link_env_prefix1 = link_alias1.upper()
546
547 link_path2 = self.client.inspect_container(container2_id)['Name'][1:]
548 link_alias2 = 'mylink2'
549 link_env_prefix2 = link_alias2.upper()
550
551 res2 = self.client.create_container('busybox', 'env')
552 container3_id = res2['Id']
553 self.tmp_containers.append(container3_id)
554 self.client.start(
555 container3_id,
556 links={link_path1: link_alias1, link_path2: link_alias2}
557 )
558 self.assertEqual(self.client.wait(container3_id), 0)
559
560 logs = self.client.logs(container3_id)
561 self.assertIn('{0}_NAME='.format(link_env_prefix1), logs)
562 self.assertIn('{0}_ENV_FOO=1'.format(link_env_prefix1), logs)
563 self.assertIn('{0}_NAME='.format(link_env_prefix2), logs)
564 self.assertIn('{0}_ENV_FOO=1'.format(link_env_prefix2), logs)
565
566#################
567## LINKS TESTS ##
568#################
569
570
571class TestRemoveLink(BaseTestCase):
572 def runTest(self):
573 # Create containers
574 container1 = self.client.create_container(
575 'busybox', 'cat', detach=True, stdin_open=True)
576 container1_id = container1['Id']
577 self.tmp_containers.append(container1_id)
578 self.client.start(container1_id)
579
580 # Create Link
581 # we don't want the first /
582 link_path = self.client.inspect_container(container1_id)['Name'][1:]
583 link_alias = 'mylink'
584
585 container2 = self.client.create_container('busybox', 'cat')
586 container2_id = container2['Id']
587 self.tmp_containers.append(container2_id)
588 self.client.start(container2_id, links={link_path: link_alias})
589
590 # Remove link
591 linked_name = self.client.inspect_container(container2_id)['Name'][1:]
592 link_name = '%s/%s' % (linked_name, link_alias)
593 self.client.remove_container(link_name, link=True)
594
595 # Link is gone
596 containers = self.client.containers(all=True)
597 retrieved = [x for x in containers if link_name in x['Names']]
598 self.assertEqual(len(retrieved), 0)
599
600 # Containers are still there
601 retrieved = [
602 x for x in containers if x['Id'].startswith(container1_id)
603 or x['Id'].startswith(container2_id)
604 ]
605 self.assertEqual(len(retrieved), 2)
606
607##################
608## IMAGES TESTS ##
609##################
610
611
612class TestPull(BaseTestCase):
613 def runTest(self):
614 try:
615 self.client.remove_image('joffrey/test001')
616 self.client.remove_image('376968a23351')
617 except docker.APIError:
618 pass
619 info = self.client.info()
620 self.assertIn('Images', info)
621 img_count = info['Images']
622 res = self.client.pull('joffrey/test001')
623 self.assertEqual(type(res), six.text_type)
624 self.assertEqual(img_count + 2, self.client.info()['Images'])
625 img_info = self.client.inspect_image('joffrey/test001')
626 self.assertIn('id', img_info)
627 self.tmp_imgs.append('joffrey/test001')
628 self.tmp_imgs.append('376968a23351')
629
630
631class TestPullStream(BaseTestCase):
632 def runTest(self):
633 try:
634 self.client.remove_image('joffrey/test001')
635 self.client.remove_image('376968a23351')
636 except docker.APIError:
637 pass
638 info = self.client.info()
639 self.assertIn('Images', info)
640 img_count = info['Images']
641 stream = self.client.pull('joffrey/test001', stream=True)
642 res = u''
643 for chunk in stream:
644 res += chunk
645 self.assertEqual(type(res), six.text_type)
646 self.assertEqual(img_count + 2, self.client.info()['Images'])
647 img_info = self.client.inspect_image('joffrey/test001')
648 self.assertIn('id', img_info)
649 self.tmp_imgs.append('joffrey/test001')
650 self.tmp_imgs.append('376968a23351')
651
652
653class TestCommit(BaseTestCase):
654 def runTest(self):
655 container = self.client.create_container('busybox', ['touch', '/test'])
656 id = container['Id']
657 self.client.start(id)
658 self.tmp_containers.append(id)
659 res = self.client.commit(id)
660 self.assertIn('Id', res)
661 img_id = res['Id']
662 self.tmp_imgs.append(img_id)
663 img = self.client.inspect_image(img_id)
664 self.assertIn('container', img)
665 self.assertTrue(img['container'].startswith(id))
666 self.assertIn('container_config', img)
667 self.assertIn('Image', img['container_config'])
668 self.assertEqual('busybox', img['container_config']['Image'])
669 busybox_id = self.client.inspect_image('busybox')['id']
670 self.assertIn('parent', img)
671 self.assertEqual(img['parent'], busybox_id)
672
673
674class TestRemoveImage(BaseTestCase):
675 def runTest(self):
676 container = self.client.create_container('busybox', ['touch', '/test'])
677 id = container['Id']
678 self.client.start(id)
679 self.tmp_containers.append(id)
680 res = self.client.commit(id)
681 self.assertIn('Id', res)
682 img_id = res['Id']
683 self.tmp_imgs.append(img_id)
684 self.client.remove_image(img_id)
685 images = self.client.images(all=True)
686 res = [x for x in images if x['Id'].startswith(img_id)]
687 self.assertEqual(len(res), 0)
688
689#################
690# BUILDER TESTS #
691#################
692
693
694class TestBuild(BaseTestCase):
695 def runTest(self):
696 script = io.BytesIO('\n'.join([
697 'FROM busybox',
698 'MAINTAINER docker-py',
699 'RUN mkdir -p /tmp/test',
700 'EXPOSE 8080',
701 'ADD https://dl.dropboxusercontent.com/u/20637798/silence.tar.gz'
702 ' /tmp/silence.tar.gz'
703 ]).encode('ascii'))
704 img, logs = self.client.build(fileobj=script)
705 self.assertNotEqual(img, None)
706 self.assertNotEqual(img, '')
707 self.assertNotEqual(logs, '')
708 container1 = self.client.create_container(img, 'test -d /tmp/test')
709 id1 = container1['Id']
710 self.client.start(id1)
711 self.tmp_containers.append(id1)
712 exitcode1 = self.client.wait(id1)
713 self.assertEqual(exitcode1, 0)
714 container2 = self.client.create_container(img, 'test -d /tmp/test')
715 id2 = container2['Id']
716 self.client.start(id2)
717 self.tmp_containers.append(id2)
718 exitcode2 = self.client.wait(id2)
719 self.assertEqual(exitcode2, 0)
720 self.tmp_imgs.append(img)
721
722
723class TestBuildStream(BaseTestCase):
724 def runTest(self):
725 script = io.BytesIO('\n'.join([
726 'FROM busybox',
727 'MAINTAINER docker-py',
728 'RUN mkdir -p /tmp/test',
729 'EXPOSE 8080',
730 'ADD https://dl.dropboxusercontent.com/u/20637798/silence.tar.gz'
731 ' /tmp/silence.tar.gz'
732 ]).encode('ascii'))
733 stream = self.client.build(fileobj=script, stream=True)
734 logs = ''
735 for chunk in stream:
736 logs += chunk
737 self.assertNotEqual(logs, '')
738
739
740class TestBuildFromStringIO(BaseTestCase):
741 def runTest(self):
742 if six.PY3:
743 return
744 script = io.StringIO(u'\n'.join([
745 'FROM busybox',
746 'MAINTAINER docker-py',
747 'RUN mkdir -p /tmp/test',
748 'EXPOSE 8080',
749 'ADD https://dl.dropboxusercontent.com/u/20637798/silence.tar.gz'
750 ' /tmp/silence.tar.gz'
751 ]))
752 img, logs = self.client.build(fileobj=script)
753 self.assertNotEqual(img, None)
754 self.assertNotEqual(img, '')
755 self.assertNotEqual(logs, '')
756 container1 = self.client.create_container(img, 'test -d /tmp/test')
757 id1 = container1['Id']
758 self.client.start(id1)
759 self.tmp_containers.append(id1)
760 exitcode1 = self.client.wait(id1)
761 self.assertEqual(exitcode1, 0)
762 container2 = self.client.create_container(img, 'test -d /tmp/test')
763 id2 = container2['Id']
764 self.client.start(id2)
765 self.tmp_containers.append(id2)
766 exitcode2 = self.client.wait(id2)
767 self.assertEqual(exitcode2, 0)
768 self.tmp_imgs.append(img)
769
770#######################
771## PY SPECIFIC TESTS ##
772#######################
773
774
775class TestRunShlex(BaseTestCase):
776 def runTest(self):
777 commands = [
778 'true',
779 'echo "The Young Descendant of Tepes & Septette for the '
780 'Dead Princess"',
781 'echo -n "The Young Descendant of Tepes & Septette for the '
782 'Dead Princess"',
783 '/bin/sh -c "echo Hello World"',
784 '/bin/sh -c \'echo "Hello World"\'',
785 'echo "\"Night of Nights\""',
786 'true && echo "Night of Nights"'
787 ]
788 for cmd in commands:
789 container = self.client.create_container('busybox', cmd)
790 id = container['Id']
791 self.client.start(id)
792 self.tmp_containers.append(id)
793 exitcode = self.client.wait(id)
794 self.assertEqual(exitcode, 0, msg=cmd)
795
796
797class TestLoadConfig(BaseTestCase):
798 def runTest(self):
799 folder = tempfile.mkdtemp()
800 f = open(os.path.join(folder, '.dockercfg'), 'w')
801 auth_ = base64.b64encode(b'sakuya:izayoi').decode('ascii')
802 f.write('auth = {0}\n'.format(auth_))
803 f.write('email = [email protected]')
804 f.close()
805 cfg = docker.auth.load_config(folder)
806 self.assertNotEqual(cfg[docker.auth.INDEX_URL], None)
807 cfg = cfg[docker.auth.INDEX_URL]
808 self.assertEqual(cfg['username'], b'sakuya')
809 self.assertEqual(cfg['password'], b'izayoi')
810 self.assertEqual(cfg['email'], '[email protected]')
811 self.assertEqual(cfg.get('Auth'), None)
812
813
814class TestLoadJSONConfig(BaseTestCase):
815 def runTest(self):
816 folder = tempfile.mkdtemp()
817 f = open(os.path.join(folder, '.dockercfg'), 'w')
818 auth_ = base64.b64encode(b'sakuya:izayoi').decode('ascii')
819 email_ = '[email protected]'
820 f.write('{{"{}": {{"auth": "{}", "email": "{}"}}}}\n'.format(
821 docker.auth.INDEX_URL, auth_, email_))
822 f.close()
823 cfg = docker.auth.load_config(folder)
824 self.assertNotEqual(cfg[docker.auth.INDEX_URL], None)
825 cfg = cfg[docker.auth.INDEX_URL]
826 self.assertEqual(cfg['username'], b'sakuya')
827 self.assertEqual(cfg['password'], b'izayoi')
828 self.assertEqual(cfg['email'], '[email protected]')
829 self.assertEqual(cfg.get('Auth'), None)
830
831
832class TestConnectionTimeout(unittest.TestCase):
833 def setUp(self):
834 self.timeout = 0.5
835 self.client = docker.client.Client(base_url='http://192.168.10.2:4243',
836 timeout=self.timeout)
837
838 def runTest(self):
839 start = time.time()
840 res = None
841 # This call isn't supposed to complete, and it should fail fast.
842 try:
843 res = self.client.inspect_container('id')
844 except:
845 pass
846 end = time.time()
847 self.assertTrue(res is None)
848 self.assertTrue(end - start < 2 * self.timeout)
849
850
851if __name__ == '__main__':
852 unittest.main()