diff --git a/zun/common/utils.py b/zun/common/utils.py index 7b4c3adac..4f3a4cacf 100644 --- a/zun/common/utils.py +++ b/zun/common/utils.py @@ -176,6 +176,10 @@ def parse_image_name(image, driver=None): if image_parts['tag']: image_tag = image_parts['tag'] + registry, _ = image_parts.split_hostname() + if not registry and CONF.docker.default_registry: + image_repo = '%s/%s' % (CONF.docker.default_registry, image_repo) + return image_repo, image_tag diff --git a/zun/conf/docker.py b/zun/conf/docker.py index 278fa9f24..94f97f168 100644 --- a/zun/conf/docker.py +++ b/zun/conf/docker.py @@ -57,6 +57,10 @@ docker_opts = [ default='/var/lib/docker', deprecated_for_removal=True, help='Root directory of persistent Docker state.'), + cfg.StrOpt('default_registry', + help='The default registry from which docker images are ' + 'pulled. Its value can be the registry domain name ' + '(e.g. docker.io) or None.'), ] ALL_OPTS = (docker_opts) diff --git a/zun/container/docker/driver.py b/zun/container/docker/driver.py index 86f8035e1..36235bd85 100644 --- a/zun/container/docker/driver.py +++ b/zun/container/docker/driver.py @@ -191,6 +191,8 @@ class DockerDriver(driver.ContainerDriver): context, repo, tag, image_pull_policy) if image: image['driver'] = driver_name.split('.')[0] + except exception.ZunException: + raise except Exception as e: LOG.exception('Unknown exception occurred while loading ' 'image: %s', six.text_type(e)) diff --git a/zun/image/docker/driver.py b/zun/image/docker/driver.py index efa90d5bd..77561670a 100644 --- a/zun/image/docker/driver.py +++ b/zun/image/docker/driver.py @@ -23,10 +23,13 @@ from zun.common.docker_image import reference as docker_image from zun.common import exception from zun.common.i18n import _ from zun.common import utils +import zun.conf from zun.container.docker import utils as docker_utils from zun.image import driver +CONF = zun.conf.CONF + LOG = logging.getLogger(__name__) @@ -68,6 +71,11 @@ class DockerDriver(driver.ContainerImageDriver): docker.pull(repo, tag=tag) except errors.NotFound as e: raise exception.ImageNotFound(message=six.text_type(e)) + except errors.APIError as e: + LOG.exception('Error on pulling image') + message = _('Error on pulling image: %(repo)s:%(tag)s') % { + 'repo': repo, 'tag': tag} + raise exception.ZunException(message) def pull_image(self, context, repo, tag, image_pull_policy): image_loaded = True diff --git a/zun/tests/unit/common/test_utils.py b/zun/tests/unit/common/test_utils.py index 279903c96..7a40ef79f 100644 --- a/zun/tests/unit/common/test_utils.py +++ b/zun/tests/unit/common/test_utils.py @@ -20,12 +20,16 @@ from zun.common import exception from zun.common import utils from zun.common.utils import check_container_id from zun.common.utils import translate_exception +import zun.conf from zun import objects from zun.objects.container import Container from zun.tests import base from zun.tests.unit.db import utils as db_utils +CONF = zun.conf.CONF + + class TestUtils(base.TestCase): """Test cases for zun.common.utils""" @@ -60,6 +64,15 @@ class TestUtils(base.TestCase): self.assertEqual(('test-test', 'test'), utils.parse_image_name('test-test:test')) + def test_parse_image_name_with_registry(self): + CONF.set_override('default_registry', 'test.io', group='docker') + self.assertEqual(('test.io/test', 'latest'), + utils.parse_image_name('test')) + self.assertEqual(('test.io/test/test', 'latest'), + utils.parse_image_name('test/test')) + self.assertEqual(('other.com/test/test', 'latest'), + utils.parse_image_name('other.com/test/test')) + def test_get_image_pull_policy(self): self.assertEqual('always', utils.get_image_pull_policy('always', diff --git a/zun/tests/unit/image/docker/test_driver.py b/zun/tests/unit/image/docker/test_driver.py index 00d05b3ad..7ace5e3f1 100644 --- a/zun/tests/unit/image/docker/test_driver.py +++ b/zun/tests/unit/image/docker/test_driver.py @@ -80,16 +80,13 @@ class TestDriver(base.BaseTestCase): mock_should_pull_image.return_value = True mock_search.return_value = {'image': 'nginx', 'path': 'xyz'} mock_parse_image.return_value = ('repo', 'tag') - with mock.patch.object(errors.APIError, '__str__', - return_value='404 Not Found') as mock_init: - self.mock_docker.pull = mock.Mock( - side_effect=errors.APIError('Error', '', '')) - self.assertRaises(exception.ZunException, self.driver.pull_image, - None, 'repo', 'tag', 'always') - self.mock_docker.pull.assert_called_once_with( - 'repo', - tag='tag') - self.assertEqual(1, mock_init.call_count) + self.mock_docker.pull = mock.Mock( + side_effect=errors.APIError('Error', '', '')) + self.assertRaises(exception.ZunException, self.driver.pull_image, + None, 'repo', 'tag', 'always') + self.mock_docker.pull.assert_called_once_with( + 'repo', + tag='tag') @mock.patch('zun.common.utils.parse_image_name') @mock.patch.object(driver.DockerDriver,