commit 2014a746753e7f4133e1d13516c4cbadbdd424e8
Author: Tim Waugh <twaugh@redhat.com>
Date: Fri Jul 14 10:17:43 2017 +0100
Add minimal support for docker-py-2.x module
Signed-off-by: Tim Waugh <twaugh@redhat.com>
diff --git a/atomic_reactor/core.py b/atomic_reactor/core.py
index ffea392..c3d413d 100644
--- a/atomic_reactor/core.py
+++ b/atomic_reactor/core.py
@@ -31,7 +31,6 @@ import requests
import docker
from docker.errors import APIError
-from docker.utils import create_host_config
from atomic_reactor.constants import CONTAINER_SHARE_PATH, CONTAINER_SHARE_SOURCE_SUBDIR,\
BUILD_JSON, DOCKER_SOCKET_PATH
@@ -163,11 +162,9 @@ class BuildContainerFactory(object):
container_id = self.tasker.run(
ImageName.parse(build_image),
- create_kwargs={'volumes': [DOCKER_SOCKET_PATH, json_args_path],
- 'host_config': create_host_config(
- binds=volume_bindings,
- privileged=True)
- }
+ create_kwargs={'volumes': [DOCKER_SOCKET_PATH, json_args_path]},
+ volume_bindings=volume_bindings,
+ privileged=True,
)
return container_id
@@ -206,11 +203,9 @@ class BuildContainerFactory(object):
container_id = self.tasker.run(
ImageName.parse(build_image),
- create_kwargs={'volumes': [json_args_path],
- 'host_config': create_host_config(
- binds=volume_bindings,
- privileged=True)
- }
+ create_kwargs={'volumes': [json_args_path]},
+ volume_bindings=volume_bindings,
+ privileged=True,
)
return container_id
@@ -226,7 +221,7 @@ class DockerTasker(LastLogger):
"""
super(DockerTasker, self).__init__(**kwargs)
- client_kwargs = {}
+ client_kwargs = {'timeout': timeout}
if base_url:
client_kwargs['base_url'] = base_url
elif os.environ.get('DOCKER_CONNECTION'):
@@ -235,7 +230,12 @@ class DockerTasker(LastLogger):
if hasattr(docker, 'AutoVersionClient'):
client_kwargs['version'] = 'auto'
- self.d = docker.Client(timeout=timeout, **client_kwargs)
+ try:
+ # docker-py 2.x
+ self.d = docker.APIClient(**client_kwargs)
+ except AttributeError:
+ # docker-py 1.x
+ self.d = docker.Client(**client_kwargs)
def build_image_from_path(self, path, image, stream=False, use_cache=False, remove_im=True):
"""
@@ -301,7 +301,8 @@ class DockerTasker(LastLogger):
logger.info("build finished")
return response
- def run(self, image, command=None, create_kwargs=None, start_kwargs=None):
+ def run(self, image, command=None, create_kwargs=None, start_kwargs=None,
+ volume_bindings=None, privileged=None):
"""
create container from provided image and start it
@@ -317,6 +318,17 @@ class DockerTasker(LastLogger):
"""
logger.info("creating container from image '%s' and running it", image)
create_kwargs = create_kwargs or {}
+
+ if 'host_config' not in create_kwargs:
+ conf = {}
+ if volume_bindings is not None:
+ conf['binds'] = volume_bindings
+
+ if privileged is not None:
+ conf['privileged'] = privileged
+
+ create_kwargs['host_config'] = self.d.create_host_config(**conf)
+
start_kwargs = start_kwargs or {}
logger.debug("image = '%s', command = '%s', create_kwargs = '%s', start_kwargs = '%s'",
image, command, create_kwargs, start_kwargs)
diff --git a/tests/README b/tests/README
index f59150b..f9d4a29 100644
--- a/tests/README
+++ b/tests/README
@@ -3,7 +3,7 @@ Requirements: see requirements.txt
How to run:
$ py.test -v
-By default all docker.Client methods are mocked, so you don't need docker to run these tests.
+By default all docker.APIClient methods are mocked, so you don't need docker to run these tests.
If you want to run 'integration' tests, i.e. test with running docker instance, you need:
$ yum install docker docker-registry
$ systemctl start docker docker-registry
diff --git a/tests/docker_mock.py b/tests/docker_mock.py
index 367924d..0987bda 100644
--- a/tests/docker_mock.py
+++ b/tests/docker_mock.py
@@ -270,7 +270,7 @@ def mock_docker(build_should_fail=False,
push_should_fail=False,
build_should_fail_generator=False):
"""
- mock all used docker.Client methods
+ mock all used docker.APIClient methods
:param build_should_fail: True == build() log will contain error
:param inspect_should_fail: True == inspect_image() will raise docker.errors.NotFound
@@ -291,11 +291,14 @@ def mock_docker(build_should_fail=False,
else:
build_result = iter(mock_build_logs)
- flexmock(docker.Client, build=lambda **kwargs: build_result)
- flexmock(docker.Client, commit=lambda cid, **kwargs: mock_containers[0])
- flexmock(docker.Client, containers=lambda **kwargs: mock_containers)
- flexmock(docker.Client, create_container=lambda img, **kwargs: mock_containers[0])
- flexmock(docker.Client, images=lambda **kwargs: [mock_image])
+ if not hasattr(docker, 'APIClient'):
+ setattr(docker, 'APIClient', docker.Client)
+
+ flexmock(docker.APIClient, build=lambda **kwargs: build_result)
+ flexmock(docker.APIClient, commit=lambda cid, **kwargs: mock_containers[0])
+ flexmock(docker.APIClient, containers=lambda **kwargs: mock_containers)
+ flexmock(docker.APIClient, create_container=lambda img, **kwargs: mock_containers[0])
+ flexmock(docker.APIClient, images=lambda **kwargs: [mock_image])
def mock_inspect_image(image_id):
if inspect_should_fail:
@@ -303,21 +306,21 @@ def mock_docker(build_should_fail=False,
else:
return mock_image
- flexmock(docker.Client, inspect_image=mock_inspect_image)
- flexmock(docker.Client, inspect_container=lambda im_id: mock_inspect_container)
- flexmock(docker.Client, logs=lambda cid, **kwargs: iter([mock_logs]) if kwargs.get('stream')
+ flexmock(docker.APIClient, inspect_image=mock_inspect_image)
+ flexmock(docker.APIClient, inspect_container=lambda im_id: mock_inspect_container)
+ flexmock(docker.APIClient, logs=lambda cid, **kwargs: iter([mock_logs]) if kwargs.get('stream')
else mock_logs)
- flexmock(docker.Client, pull=lambda img, **kwargs: iter(mock_pull_logs))
- flexmock(docker.Client, push=lambda iid, **kwargs: iter(push_result))
- flexmock(docker.Client, remove_container=lambda cid, **kwargs: None)
- flexmock(docker.Client, remove_image=lambda iid, **kwargs: None)
- flexmock(docker.Client, start=lambda cid, **kwargs: None)
- flexmock(docker.Client, tag=lambda img, rep, **kwargs: True)
- flexmock(docker.Client, wait=lambda cid: 1 if wait_should_fail else 0)
- flexmock(docker.Client, version=lambda **kwargs: mock_version)
- flexmock(docker.Client, info=lambda **kwargs: mock_info)
- flexmock(docker.Client, import_image_from_data=lambda url: mock_import_image)
- flexmock(docker.Client, import_image_from_stream=lambda url: mock_import_image)
+ flexmock(docker.APIClient, pull=lambda img, **kwargs: iter(mock_pull_logs))
+ flexmock(docker.APIClient, push=lambda iid, **kwargs: iter(push_result))
+ flexmock(docker.APIClient, remove_container=lambda cid, **kwargs: None)
+ flexmock(docker.APIClient, remove_image=lambda iid, **kwargs: None)
+ flexmock(docker.APIClient, start=lambda cid, **kwargs: None)
+ flexmock(docker.APIClient, tag=lambda img, rep, **kwargs: True)
+ flexmock(docker.APIClient, wait=lambda cid: 1 if wait_should_fail else 0)
+ flexmock(docker.APIClient, version=lambda **kwargs: mock_version)
+ flexmock(docker.APIClient, info=lambda **kwargs: mock_info)
+ flexmock(docker.APIClient, import_image_from_data=lambda url: mock_import_image)
+ flexmock(docker.APIClient, import_image_from_stream=lambda url: mock_import_image)
class GetImageResult(object):
data = b''
@@ -334,7 +337,7 @@ def mock_docker(build_should_fail=False,
def __exit__(self, tp, val, tb):
self.fp.close()
- flexmock(docker.Client, get_image=lambda img, **kwargs: GetImageResult())
+ flexmock(docker.APIClient, get_image=lambda img, **kwargs: GetImageResult())
flexmock(os.path, exists=lambda p: True if p == DOCKER_SOCKET_PATH else old_ope(p))
def remove_volume(volume_name):
@@ -346,24 +349,27 @@ def mock_docker(build_should_fail=False,
raise docker.errors.APIError("failed to remove volume %s" % volume_name, response)
return None
- flexmock(docker.Client, remove_volume=lambda iid, **kwargs: remove_volume(iid))
+ flexmock(docker.APIClient, remove_volume=lambda iid, **kwargs: remove_volume(iid))
for method, args in should_raise_error.items():
response = flexmock(content="abc", status_code=123)
if args:
- flexmock(docker.Client).should_receive(method).with_args(*args).and_raise(
- docker.errors.APIError, "xyz", response)
+ (flexmock(docker.APIClient)
+ .should_receive(method)
+ .with_args(*args).and_raise(docker.errors.APIError, "xyz",
+ response))
else:
- flexmock(docker.Client).should_receive(method).and_raise(docker.errors.APIError, "xyz",
- response)
+ (flexmock(docker.APIClient)
+ .should_receive(method)
+ .and_raise(docker.errors.APIError, "xyz", response))
if remember_images:
global mock_images
mock_images = [mock_image]
- flexmock(docker.Client, inspect_image=_mock_inspect)
- flexmock(docker.Client, pull=_mock_pull)
- flexmock(docker.Client, remove_image=_mock_remove_image)
- flexmock(docker.Client, tag=_mock_tag)
+ flexmock(docker.APIClient, inspect_image=_mock_inspect)
+ flexmock(docker.APIClient, pull=_mock_pull)
+ flexmock(docker.APIClient, remove_image=_mock_remove_image)
+ flexmock(docker.APIClient, tag=_mock_tag)
- flexmock(docker.Client, _retrieve_server_version=lambda: '1.20')
+ flexmock(docker.APIClient, _retrieve_server_version=lambda: '1.20')
diff --git a/tests/plugins/test_rpmqa.py b/tests/plugins/test_rpmqa.py
index ba5cbc5..fe7afe8 100644
--- a/tests/plugins/test_rpmqa.py
+++ b/tests/plugins/test_rpmqa.py
@@ -69,7 +69,7 @@ def test_rpmqa_plugin(remove_container_error, ignore_autogenerated):
setattr(workflow.builder.source, 'dockerfile_path', "/non/existent")
setattr(workflow.builder.source, 'path', "/non/existent")
- flexmock(docker.Client, logs=mock_logs)
+ flexmock(docker.APIClient, logs=mock_logs)
runner = PostBuildPluginsRunner(
tasker,
workflow,
@@ -95,7 +95,8 @@ def test_rpmqa_plugin_exception(docker_tasker): # noqa
setattr(workflow.builder.source, 'dockerfile_path', "/non/existent")
setattr(workflow.builder.source, 'path', "/non/existent")
- flexmock(docker.Client, logs=mock_logs_raise)
+ mock_docker()
+ flexmock(docker.APIClient, logs=mock_logs_raise)
runner = PostBuildPluginsRunner(docker_tasker, workflow,
[{"name": PostBuildRPMqaPlugin.key,
"args": {'image_id': TEST_IMAGE}}])
diff --git a/tests/plugins/test_tag_and_push.py b/tests/plugins/test_tag_and_push.py
index 2e5b773..9fce57c 100644
--- a/tests/plugins/test_tag_and_push.py
+++ b/tests/plugins/test_tag_and_push.py
@@ -103,7 +103,7 @@ def test_tag_and_push_plugin(
if MOCK:
mock_docker()
- flexmock(docker.Client, push=lambda iid, **kwargs: iter(logs),
+ flexmock(docker.APIClient, push=lambda iid, **kwargs: iter(logs),
login=lambda username, registry, dockercfg_path: {'Status': 'Login Succeeded'})
tasker = DockerTasker()
diff --git a/tests/test_tasker.py b/tests/test_tasker.py
index 8978d0c..db0423d 100644
--- a/tests/test_tasker.py
+++ b/tests/test_tasker.py
@@ -327,12 +327,45 @@ def test_get_version():
(60, 60),
])
def test_timeout(timeout, expected_timeout):
- (flexmock(docker.Client)
+ if not hasattr(docker, 'APIClient'):
+ setattr(docker, 'APIClient', docker.Client)
+
+ expected_kwargs = {
+ 'timeout': expected_timeout,
+ }
+ if hasattr(docker, 'AutoVersionClient'):
+ expected_kwargs['version'] = 'auto'
+
+ (flexmock(docker.APIClient)
.should_receive('__init__')
- .with_args(version=str, timeout=expected_timeout))
+ .with_args(**expected_kwargs))
kwargs = {}
if timeout is not None:
kwargs['timeout'] = timeout
DockerTasker(**kwargs)
+
+
+def test_docker2():
+ class MockClient(object):
+ def __init__(self, **kwargs):
+ pass
+
+ def version(self):
+ return {}
+
+ for client in ['APIClient', 'Client']:
+ if not hasattr(docker, client):
+ setattr(docker, client, MockClient)
+
+ (flexmock(docker)
+ .should_receive('APIClient')
+ .once()
+ .and_raise(AttributeError))
+
+ (flexmock(docker)
+ .should_receive('Client')
+ .once())
+
+ DockerTasker()
diff --git a/tests/test_util.py b/tests/test_util.py
index c2ec701..3b4c6c8 100644
--- a/tests/test_util.py
+++ b/tests/test_util.py
@@ -85,7 +85,7 @@ def test_wait_for_command():
if MOCK:
mock_docker()
- d = docker.Client()
+ d = docker.APIClient()
logs_gen = d.pull(INPUT_IMAGE, stream=True)
assert wait_for_command(logs_gen) is not None