mirror of https://github.com/docker/docker-py.git
293 lines
9.2 KiB
Python
293 lines
9.2 KiB
Python
import base64
|
|
import json
|
|
import os
|
|
import shutil
|
|
import tempfile
|
|
import time
|
|
import unittest
|
|
import warnings
|
|
|
|
import docker
|
|
import six
|
|
|
|
BUSYBOX = 'busybox:buildroot-2014.02'
|
|
EXEC_DRIVER = []
|
|
|
|
|
|
def exec_driver_is_native():
|
|
global EXEC_DRIVER
|
|
if not EXEC_DRIVER:
|
|
c = docker_client()
|
|
EXEC_DRIVER = c.info()['ExecutionDriver']
|
|
c.close()
|
|
return EXEC_DRIVER.startswith('native')
|
|
|
|
|
|
def docker_client(**kwargs):
|
|
return docker.Client(**docker_client_kwargs(**kwargs))
|
|
|
|
|
|
def docker_client_kwargs(**kwargs):
|
|
client_kwargs = docker.utils.kwargs_from_env(assert_hostname=False)
|
|
client_kwargs.update(kwargs)
|
|
return client_kwargs
|
|
|
|
|
|
def setup_module():
|
|
warnings.simplefilter('error')
|
|
c = docker_client()
|
|
try:
|
|
c.inspect_image(BUSYBOX)
|
|
except docker.errors.NotFound:
|
|
os.write(2, "\npulling busybox\n".encode('utf-8'))
|
|
for data in c.pull(BUSYBOX, stream=True):
|
|
data = json.loads(data.decode('utf-8'))
|
|
os.write(2, ("%c[2K\r" % 27).encode('utf-8'))
|
|
status = data.get("status")
|
|
progress = data.get("progress")
|
|
detail = "{0} - {1}".format(status, progress).encode('utf-8')
|
|
os.write(2, detail)
|
|
os.write(2, "\npulled busybox\n".encode('utf-8'))
|
|
|
|
# Double make sure we now have busybox
|
|
c.inspect_image(BUSYBOX)
|
|
c.close()
|
|
|
|
|
|
class BaseTestCase(unittest.TestCase):
|
|
tmp_imgs = []
|
|
tmp_containers = []
|
|
tmp_folders = []
|
|
tmp_volumes = []
|
|
|
|
def setUp(self):
|
|
if six.PY2:
|
|
self.assertRegex = self.assertRegexpMatches
|
|
self.assertCountEqual = self.assertItemsEqual
|
|
self.client = docker_client(timeout=60)
|
|
self.tmp_imgs = []
|
|
self.tmp_containers = []
|
|
self.tmp_folders = []
|
|
self.tmp_volumes = []
|
|
self.tmp_networks = []
|
|
|
|
def tearDown(self):
|
|
for img in self.tmp_imgs:
|
|
try:
|
|
self.client.remove_image(img)
|
|
except docker.errors.APIError:
|
|
pass
|
|
for container in self.tmp_containers:
|
|
try:
|
|
self.client.stop(container, timeout=1)
|
|
self.client.remove_container(container)
|
|
except docker.errors.APIError:
|
|
pass
|
|
for network in self.tmp_networks:
|
|
try:
|
|
self.client.remove_network(network)
|
|
except docker.errors.APIError:
|
|
pass
|
|
for folder in self.tmp_folders:
|
|
shutil.rmtree(folder)
|
|
|
|
for volume in self.tmp_volumes:
|
|
try:
|
|
self.client.remove_volume(volume)
|
|
except docker.errors.APIError:
|
|
pass
|
|
|
|
self.client.close()
|
|
|
|
def run_container(self, *args, **kwargs):
|
|
container = self.client.create_container(*args, **kwargs)
|
|
self.tmp_containers.append(container)
|
|
self.client.start(container)
|
|
exitcode = self.client.wait(container)
|
|
|
|
if exitcode != 0:
|
|
output = self.client.logs(container)
|
|
raise Exception(
|
|
"Container exited with code {}:\n{}"
|
|
.format(exitcode, output))
|
|
|
|
return container
|
|
|
|
|
|
#########################
|
|
# INFORMATION TESTS #
|
|
#########################
|
|
|
|
|
|
class InformationTest(BaseTestCase):
|
|
def test_version(self):
|
|
res = self.client.version()
|
|
self.assertIn('GoVersion', res)
|
|
self.assertIn('Version', res)
|
|
self.assertEqual(len(res['Version'].split('.')), 3)
|
|
|
|
def test_info(self):
|
|
res = self.client.info()
|
|
self.assertIn('Containers', res)
|
|
self.assertIn('Images', res)
|
|
self.assertIn('Debug', res)
|
|
|
|
def test_search(self):
|
|
self.client = docker_client(timeout=10)
|
|
res = self.client.search('busybox')
|
|
self.assertTrue(len(res) >= 1)
|
|
base_img = [x for x in res if x['name'] == 'busybox']
|
|
self.assertEqual(len(base_img), 1)
|
|
self.assertIn('description', base_img[0])
|
|
|
|
|
|
#################
|
|
# LINKS TESTS #
|
|
#################
|
|
|
|
|
|
class LinkTest(BaseTestCase):
|
|
def test_remove_link(self):
|
|
# Create containers
|
|
container1 = self.client.create_container(
|
|
BUSYBOX, 'cat', detach=True, stdin_open=True
|
|
)
|
|
container1_id = container1['Id']
|
|
self.tmp_containers.append(container1_id)
|
|
self.client.start(container1_id)
|
|
|
|
# Create Link
|
|
# we don't want the first /
|
|
link_path = self.client.inspect_container(container1_id)['Name'][1:]
|
|
link_alias = 'mylink'
|
|
|
|
container2 = self.client.create_container(
|
|
BUSYBOX, 'cat', host_config=self.client.create_host_config(
|
|
links={link_path: link_alias}, network_mode='none'
|
|
)
|
|
)
|
|
container2_id = container2['Id']
|
|
self.tmp_containers.append(container2_id)
|
|
self.client.start(container2_id)
|
|
|
|
# Remove link
|
|
linked_name = self.client.inspect_container(container2_id)['Name'][1:]
|
|
link_name = '%s/%s' % (linked_name, link_alias)
|
|
self.client.remove_container(link_name, link=True)
|
|
|
|
# Link is gone
|
|
containers = self.client.containers(all=True)
|
|
retrieved = [x for x in containers if link_name in x['Names']]
|
|
self.assertEqual(len(retrieved), 0)
|
|
|
|
# Containers are still there
|
|
retrieved = [
|
|
x for x in containers if x['Id'].startswith(container1_id) or
|
|
x['Id'].startswith(container2_id)
|
|
]
|
|
self.assertEqual(len(retrieved), 2)
|
|
|
|
|
|
#######################
|
|
# PY SPECIFIC TESTS #
|
|
#######################
|
|
|
|
class LoadConfigTest(BaseTestCase):
|
|
def test_load_legacy_config(self):
|
|
folder = tempfile.mkdtemp()
|
|
self.tmp_folders.append(folder)
|
|
cfg_path = os.path.join(folder, '.dockercfg')
|
|
f = open(cfg_path, 'w')
|
|
auth_ = base64.b64encode(b'sakuya:izayoi').decode('ascii')
|
|
f.write('auth = {0}\n'.format(auth_))
|
|
f.write('email = sakuya@scarlet.net')
|
|
f.close()
|
|
cfg = docker.auth.load_config(cfg_path)
|
|
self.assertNotEqual(cfg[docker.auth.INDEX_NAME], None)
|
|
cfg = cfg[docker.auth.INDEX_NAME]
|
|
self.assertEqual(cfg['username'], 'sakuya')
|
|
self.assertEqual(cfg['password'], 'izayoi')
|
|
self.assertEqual(cfg['email'], 'sakuya@scarlet.net')
|
|
self.assertEqual(cfg.get('Auth'), None)
|
|
|
|
def test_load_json_config(self):
|
|
folder = tempfile.mkdtemp()
|
|
self.tmp_folders.append(folder)
|
|
cfg_path = os.path.join(folder, '.dockercfg')
|
|
f = open(os.path.join(folder, '.dockercfg'), 'w')
|
|
auth_ = base64.b64encode(b'sakuya:izayoi').decode('ascii')
|
|
email_ = 'sakuya@scarlet.net'
|
|
f.write('{{"{0}": {{"auth": "{1}", "email": "{2}"}}}}\n'.format(
|
|
docker.auth.INDEX_URL, auth_, email_))
|
|
f.close()
|
|
cfg = docker.auth.load_config(cfg_path)
|
|
self.assertNotEqual(cfg[docker.auth.INDEX_URL], None)
|
|
cfg = cfg[docker.auth.INDEX_URL]
|
|
self.assertEqual(cfg['username'], 'sakuya')
|
|
self.assertEqual(cfg['password'], 'izayoi')
|
|
self.assertEqual(cfg['email'], 'sakuya@scarlet.net')
|
|
self.assertEqual(cfg.get('Auth'), None)
|
|
|
|
|
|
class AutoDetectVersionTest(unittest.TestCase):
|
|
def test_client_init(self):
|
|
client = docker_client(version='auto')
|
|
client_version = client._version
|
|
api_version = client.version(api_version=False)['ApiVersion']
|
|
self.assertEqual(client_version, api_version)
|
|
api_version_2 = client.version()['ApiVersion']
|
|
self.assertEqual(client_version, api_version_2)
|
|
client.close()
|
|
|
|
def test_auto_client(self):
|
|
client = docker.AutoVersionClient(**docker_client_kwargs())
|
|
client_version = client._version
|
|
api_version = client.version(api_version=False)['ApiVersion']
|
|
self.assertEqual(client_version, api_version)
|
|
api_version_2 = client.version()['ApiVersion']
|
|
self.assertEqual(client_version, api_version_2)
|
|
client.close()
|
|
with self.assertRaises(docker.errors.DockerException):
|
|
docker.AutoVersionClient(**docker_client_kwargs(version='1.11'))
|
|
|
|
|
|
class ConnectionTimeoutTest(unittest.TestCase):
|
|
def setUp(self):
|
|
self.timeout = 0.5
|
|
self.client = docker.client.Client(base_url='http://192.168.10.2:4243',
|
|
timeout=self.timeout)
|
|
|
|
def test_timeout(self):
|
|
start = time.time()
|
|
res = None
|
|
# This call isn't supposed to complete, and it should fail fast.
|
|
try:
|
|
res = self.client.inspect_container('id')
|
|
except:
|
|
pass
|
|
end = time.time()
|
|
self.assertTrue(res is None)
|
|
self.assertTrue(end - start < 2 * self.timeout)
|
|
|
|
|
|
class UnixconnTest(unittest.TestCase):
|
|
"""
|
|
Test UNIX socket connection adapter.
|
|
"""
|
|
|
|
def test_resource_warnings(self):
|
|
"""
|
|
Test no warnings are produced when using the client.
|
|
"""
|
|
|
|
with warnings.catch_warnings(record=True) as w:
|
|
warnings.simplefilter('always')
|
|
|
|
client = docker_client()
|
|
client.images()
|
|
client.close()
|
|
del client
|
|
|
|
assert len(w) == 0, \
|
|
"No warnings produced: {0}".format(w[0].message)
|