Use DockerRegistryMirror to proxy requests
This change consumes the DockerRegistryMirror parameter and uses that to proxy requests to docker.io for auth and inspect calls. This should improve the reliability of CI when unproxied calls to docker.io can fail. Change-Id: I11664091272d9bd216788217c0293b31d88e2758 Depends-On: If896c22bf449a3ac91ca363648f84dd5b9aef227 Closes-Bug: #1800958
This commit is contained in:
parent
0c0a25ac93
commit
e703ec1aa8
@ -77,7 +77,8 @@ class ImageUploadManager(BaseImageManager):
|
||||
"""
|
||||
|
||||
def __init__(self, config_files=None,
|
||||
dry_run=False, cleanup=CLEANUP_FULL):
|
||||
dry_run=False, cleanup=CLEANUP_FULL,
|
||||
mirrors=None):
|
||||
if config_files is None:
|
||||
config_files = []
|
||||
super(ImageUploadManager, self).__init__(config_files)
|
||||
@ -87,13 +88,14 @@ class ImageUploadManager(BaseImageManager):
|
||||
}
|
||||
self.dry_run = dry_run
|
||||
self.cleanup = cleanup
|
||||
self.mirrors = mirrors
|
||||
|
||||
def discover_image_tag(self, image, tag_from_label=None,
|
||||
username=None, password=None):
|
||||
uploader = self.uploader(DEFAULT_UPLOADER)
|
||||
return uploader.discover_image_tag(
|
||||
image, tag_from_label=tag_from_label,
|
||||
username=username, password=password)
|
||||
username=username, password=password, mirrors=self.mirrors)
|
||||
|
||||
def uploader(self, uploader):
|
||||
if uploader not in self.uploaders:
|
||||
@ -136,7 +138,7 @@ class ImageUploadManager(BaseImageManager):
|
||||
task = UploadTask(
|
||||
image_name, pull_source, push_destination,
|
||||
append_tag, modify_role, modify_vars, self.dry_run,
|
||||
self.cleanup)
|
||||
self.cleanup, self.mirrors)
|
||||
uploader.add_upload_task(task)
|
||||
|
||||
for uploader in self.uploaders.values():
|
||||
@ -221,13 +223,14 @@ class BaseImageUploader(object):
|
||||
'Modifying image %s failed' % target_image)
|
||||
|
||||
@classmethod
|
||||
def _images_match(cls, image1, image2, session1=None):
|
||||
def _images_match(cls, image1, image2, session1=None, mirrors=None):
|
||||
try:
|
||||
image1_digest = cls._image_digest(image1, session=session1)
|
||||
image1_digest = cls._image_digest(image1, session=session1,
|
||||
mirrors=mirrors)
|
||||
except Exception:
|
||||
return False
|
||||
try:
|
||||
image2_digest = cls._image_digest(image2)
|
||||
image2_digest = cls._image_digest(image2, mirrors=mirrors)
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
@ -237,22 +240,22 @@ class BaseImageUploader(object):
|
||||
return image1_digest == image2_digest
|
||||
|
||||
@classmethod
|
||||
def _image_digest(cls, image, session=None):
|
||||
def _image_digest(cls, image, session=None, mirrors=None):
|
||||
image_url = cls._image_to_url(image)
|
||||
insecure = image_url.netloc in cls.insecure_registries
|
||||
i = cls._inspect(image_url, insecure, session)
|
||||
i = cls._inspect(image_url, insecure, session, mirrors=mirrors)
|
||||
return i.get('Digest')
|
||||
|
||||
@classmethod
|
||||
def _image_labels(cls, image_url, insecure, session=None):
|
||||
i = cls._inspect(image_url, insecure, session)
|
||||
def _image_labels(cls, image_url, insecure, session=None, mirrors=None):
|
||||
i = cls._inspect(image_url, insecure, session, mirrors=mirrors)
|
||||
return i.get('Labels', {}) or {}
|
||||
|
||||
@classmethod
|
||||
def _image_exists(cls, image, session=None):
|
||||
def _image_exists(cls, image, session=None, mirrors=None):
|
||||
try:
|
||||
cls._image_digest(
|
||||
image, session=session)
|
||||
image, session=session, mirrors=mirrors)
|
||||
except ImageNotFoundException:
|
||||
return False
|
||||
else:
|
||||
@ -268,15 +271,11 @@ class BaseImageUploader(object):
|
||||
stop=tenacity.stop_after_attempt(5)
|
||||
)
|
||||
def authenticate(cls, image_url, username=None, password=None,
|
||||
insecure=False):
|
||||
image_url = cls._fix_dockerio_url(image_url)
|
||||
netloc = image_url.netloc
|
||||
if insecure:
|
||||
scheme = 'http'
|
||||
else:
|
||||
scheme = 'https'
|
||||
insecure=False, mirrors=None):
|
||||
image, tag = image_url.path.split(':')
|
||||
url = '%s://%s/v2/' % (scheme, netloc)
|
||||
url = cls._build_url(image_url, path='/',
|
||||
insecure=insecure,
|
||||
mirrors=mirrors)
|
||||
session = requests.Session()
|
||||
r = session.get(url, timeout=30)
|
||||
LOG.debug('%s status code %s' % (url, r.status_code))
|
||||
@ -308,14 +307,19 @@ class BaseImageUploader(object):
|
||||
return session
|
||||
|
||||
@classmethod
|
||||
def _fix_dockerio_url(cls, url):
|
||||
one = 'docker.io'
|
||||
two = 'registry-1.docker.io'
|
||||
if url.netloc != one:
|
||||
return url
|
||||
return parse.ParseResult(url.scheme, two,
|
||||
url.path, url.params,
|
||||
url.query, url.fragment)
|
||||
def _build_url(cls, url, path, insecure=False, mirrors=None):
|
||||
netloc = url.netloc
|
||||
if mirrors and netloc in mirrors:
|
||||
mirror = mirrors[netloc]
|
||||
return '%sv2%s' % (mirror, path)
|
||||
else:
|
||||
if insecure:
|
||||
scheme = 'http'
|
||||
else:
|
||||
scheme = 'https'
|
||||
if netloc == 'docker.io':
|
||||
netloc = 'registry-1.docker.io'
|
||||
return '%s://%s/v2%s' % (scheme, netloc, path)
|
||||
|
||||
@classmethod
|
||||
@tenacity.retry( # Retry up to 5 times with jittered exponential backoff
|
||||
@ -326,24 +330,21 @@ class BaseImageUploader(object):
|
||||
wait=tenacity.wait_random_exponential(multiplier=1, max=10),
|
||||
stop=tenacity.stop_after_attempt(5)
|
||||
)
|
||||
def _inspect(cls, image_url, insecure=False, session=None):
|
||||
original_image_url = image_url
|
||||
image_url = cls._fix_dockerio_url(image_url)
|
||||
parts = {
|
||||
'netloc': image_url.netloc
|
||||
}
|
||||
if insecure:
|
||||
parts['scheme'] = 'http'
|
||||
else:
|
||||
parts['scheme'] = 'https'
|
||||
def _inspect(cls, image_url, insecure=False, session=None, mirrors=None):
|
||||
image, tag = image_url.path.split(':')
|
||||
parts['image'] = image
|
||||
parts['tag'] = tag
|
||||
parts = {
|
||||
'image': image,
|
||||
'tag': tag
|
||||
}
|
||||
|
||||
manifest_url = ('%(scheme)s://%(netloc)s/v2'
|
||||
'%(image)s/manifests/%(tag)s' % parts)
|
||||
tags_url = ('%(scheme)s://%(netloc)s/v2'
|
||||
'%(image)s/tags/list' % parts)
|
||||
manifest_url = cls._build_url(
|
||||
image_url, '%(image)s/manifests/%(tag)s' % parts,
|
||||
insecure, mirrors
|
||||
)
|
||||
tags_url = cls._build_url(
|
||||
image_url, '%(image)s/tags/list' % parts,
|
||||
insecure, mirrors
|
||||
)
|
||||
manifest_headers = {
|
||||
'Accept': 'application/vnd.docker.distribution.manifest.v2+json'
|
||||
}
|
||||
@ -369,8 +370,9 @@ class BaseImageUploader(object):
|
||||
config_headers = {
|
||||
'Accept': manifest['config']['mediaType']
|
||||
}
|
||||
config_url = ('%(scheme)s://%(netloc)s/v2'
|
||||
'%(image)s/blobs/%(config_digest)s' % parts)
|
||||
config_url = cls._build_url(
|
||||
image_url, '%(image)s/blobs/%(config_digest)s' % parts,
|
||||
insecure, mirrors)
|
||||
config_f = p.submit(
|
||||
session.get, config_url, headers=config_headers, timeout=30)
|
||||
config_r = config_f.result()
|
||||
@ -379,7 +381,7 @@ class BaseImageUploader(object):
|
||||
tags = tags_r.json()['tags']
|
||||
digest = manifest_r.headers['Docker-Content-Digest']
|
||||
config = config_r.json()
|
||||
name = '%s%s' % (original_image_url.netloc, image)
|
||||
name = '%s%s' % (image_url.netloc, image)
|
||||
|
||||
return {
|
||||
'Name': name,
|
||||
@ -445,7 +447,7 @@ class BaseImageUploader(object):
|
||||
)
|
||||
return tag_label
|
||||
|
||||
def discover_image_tags(self, images, tag_from_label=None):
|
||||
def discover_image_tags(self, images, tag_from_label=None, mirrors=None):
|
||||
image_urls = [self._image_to_url(i) for i in images]
|
||||
|
||||
# prime self.insecure_registries by testing every image
|
||||
@ -455,7 +457,7 @@ class BaseImageUploader(object):
|
||||
discover_args = []
|
||||
for image in images:
|
||||
discover_args.append((image, tag_from_label,
|
||||
self.insecure_registries))
|
||||
self.insecure_registries, mirrors))
|
||||
p = futures.ThreadPoolExecutor(max_workers=16)
|
||||
|
||||
versioned_images = {}
|
||||
@ -465,25 +467,28 @@ class BaseImageUploader(object):
|
||||
return versioned_images
|
||||
|
||||
def discover_image_tag(self, image, tag_from_label=None,
|
||||
fallback_tag=None, username=None, password=None):
|
||||
fallback_tag=None, username=None, password=None,
|
||||
mirrors=None):
|
||||
image_url = self._image_to_url(image)
|
||||
insecure = self.is_insecure_registry(image_url.netloc)
|
||||
session = self.authenticate(
|
||||
image_url, insecure=insecure, username=username, password=password)
|
||||
i = self._inspect(image_url, insecure, session)
|
||||
image_url, insecure=insecure, username=username, password=password,
|
||||
mirrors=mirrors)
|
||||
i = self._inspect(image_url, insecure, session, mirrors=mirrors)
|
||||
return self._discover_tag_from_inspect(i, image, tag_from_label,
|
||||
fallback_tag)
|
||||
|
||||
def filter_images_with_labels(self, images, labels,
|
||||
username=None, password=None):
|
||||
username=None, password=None, mirrors=None):
|
||||
images_with_labels = []
|
||||
for image in images:
|
||||
url = self._image_to_url(image)
|
||||
insecure = self.is_insecure_registry(url.netloc)
|
||||
session = self.authenticate(
|
||||
url, insecure=insecure, username=username, password=password)
|
||||
url, insecure=insecure, username=username, password=password,
|
||||
mirrors=mirrors)
|
||||
image_labels = self._image_labels(
|
||||
url, insecure=insecure, session=session)
|
||||
url, insecure=insecure, session=session, mirrors=mirrors)
|
||||
if set(labels).issubset(set(image_labels)):
|
||||
images_with_labels.append(image)
|
||||
|
||||
@ -558,17 +563,20 @@ class DockerImageUploader(BaseImageUploader):
|
||||
|
||||
if t.modify_role:
|
||||
target_session = self.authenticate(
|
||||
t.target_image_url, insecure=target_insecure)
|
||||
t.target_image_url, insecure=target_insecure,
|
||||
mirrors=t.mirrors)
|
||||
if self._image_exists(t.target_image,
|
||||
session=target_session):
|
||||
session=target_session,
|
||||
mirrors=t.mirrors):
|
||||
LOG.warning('Skipping upload for modified image %s' %
|
||||
t.target_image)
|
||||
return []
|
||||
else:
|
||||
source_session = self.authenticate(
|
||||
t.source_image_url, insecure=source_insecure)
|
||||
t.source_image_url, insecure=source_insecure,
|
||||
mirrors=t.mirrors)
|
||||
if self._images_match(t.source_image, t.target_image,
|
||||
session1=source_session):
|
||||
session1=source_session, mirrors=t.mirrors):
|
||||
LOG.warning('Skipping upload for image %s' % t.image_name)
|
||||
return []
|
||||
|
||||
@ -689,21 +697,25 @@ class SkopeoImageUploader(BaseImageUploader):
|
||||
return []
|
||||
|
||||
target_session = self.authenticate(
|
||||
t.target_image_url, insecure=target_insecure)
|
||||
t.target_image_url, insecure=target_insecure,
|
||||
mirrors=t.mirrors)
|
||||
|
||||
if t.modify_role and self._image_exists(
|
||||
t.target_image, target_session):
|
||||
t.target_image, target_session,
|
||||
mirrors=t.mirrors):
|
||||
LOG.warning('Skipping upload for modified image %s' %
|
||||
t.target_image)
|
||||
return []
|
||||
|
||||
source_session = self.authenticate(
|
||||
t.source_image_url, insecure=source_insecure)
|
||||
t.source_image_url, insecure=source_insecure,
|
||||
mirrors=t.mirrors)
|
||||
|
||||
source_inspect = self._inspect(
|
||||
t.source_image_url,
|
||||
insecure=source_insecure,
|
||||
session=source_session)
|
||||
session=source_session,
|
||||
mirrors=t.mirrors)
|
||||
source_layers = source_inspect.get('Layers', [])
|
||||
self._cross_repo_mount(
|
||||
t.target_image_url, self.image_layers, source_layers,
|
||||
@ -835,7 +847,8 @@ class SkopeoImageUploader(BaseImageUploader):
|
||||
class UploadTask(object):
|
||||
|
||||
def __init__(self, image_name, pull_source, push_destination,
|
||||
append_tag, modify_role, modify_vars, dry_run, cleanup):
|
||||
append_tag, modify_role, modify_vars, dry_run, cleanup,
|
||||
mirrors):
|
||||
self.image_name = image_name
|
||||
self.pull_source = pull_source
|
||||
self.push_destination = push_destination
|
||||
@ -844,6 +857,7 @@ class UploadTask(object):
|
||||
self.modify_vars = modify_vars
|
||||
self.dry_run = dry_run
|
||||
self.cleanup = cleanup
|
||||
self.mirrors = mirrors
|
||||
|
||||
if ':' in image_name:
|
||||
image = image_name.rpartition(':')[0]
|
||||
@ -875,12 +889,13 @@ def upload_task(args):
|
||||
|
||||
|
||||
def discover_tag_from_inspect(args):
|
||||
image, tag_from_label, insecure_registries = args
|
||||
image, tag_from_label, insecure_registries, mirrors = args
|
||||
image_url = BaseImageUploader._image_to_url(image)
|
||||
insecure = image_url.netloc in insecure_registries
|
||||
session = BaseImageUploader.authenticate(image_url, insecure=insecure)
|
||||
session = BaseImageUploader.authenticate(image_url, insecure=insecure,
|
||||
mirrors=mirrors)
|
||||
i = BaseImageUploader._inspect(image_url, insecure=insecure,
|
||||
session=session)
|
||||
session=session, mirrors=mirrors)
|
||||
if ':' in image_url.path:
|
||||
# break out the tag from the url to be the fallback tag
|
||||
path = image.rpartition(':')
|
||||
|
@ -141,6 +141,11 @@ def container_images_prepare_multi(environment, roles_data, dry_run=False,
|
||||
if not cip:
|
||||
return
|
||||
|
||||
mirrors = {}
|
||||
mirror = pd.get('DockerRegistryMirror')
|
||||
if mirror:
|
||||
mirrors['docker.io'] = mirror
|
||||
|
||||
env_params = {}
|
||||
service_filter = build_service_filter(environment, roles_data)
|
||||
|
||||
@ -176,6 +181,7 @@ def container_images_prepare_multi(environment, roles_data, dry_run=False,
|
||||
modify_role=modify_role,
|
||||
modify_vars=modify_vars,
|
||||
modify_only_with_labels=modify_only_with_labels,
|
||||
mirrors=mirrors
|
||||
)
|
||||
env_params.update(prepare_data['image_params'])
|
||||
|
||||
@ -187,7 +193,8 @@ def container_images_prepare_multi(environment, roles_data, dry_run=False,
|
||||
uploader = image_uploader.ImageUploadManager(
|
||||
[f.name],
|
||||
dry_run=dry_run,
|
||||
cleanup=cleanup
|
||||
cleanup=cleanup,
|
||||
mirrors=mirrors
|
||||
)
|
||||
uploader.upload()
|
||||
return env_params
|
||||
@ -209,7 +216,8 @@ def container_images_prepare(template_file=DEFAULT_TEMPLATE_FILE,
|
||||
mapping_args=None, output_env_file=None,
|
||||
output_images_file=None, tag_from_label=None,
|
||||
append_tag=None, modify_role=None,
|
||||
modify_vars=None, modify_only_with_labels=None):
|
||||
modify_vars=None, modify_only_with_labels=None,
|
||||
mirrors=None):
|
||||
"""Perform container image preparation
|
||||
|
||||
:param template_file: path to Jinja2 file containing all image entries
|
||||
@ -235,6 +243,7 @@ def container_images_prepare(template_file=DEFAULT_TEMPLATE_FILE,
|
||||
:param modify_vars: dict of variables to pass to modify_role
|
||||
:param modify_only_with_labels: only modify the container images with the
|
||||
given labels
|
||||
:param mirrors: dict of registry netloc values to mirror urls
|
||||
:returns: dict with entries for the supplied output_env_file or
|
||||
output_images_file
|
||||
"""
|
||||
@ -269,7 +278,7 @@ def container_images_prepare(template_file=DEFAULT_TEMPLATE_FILE,
|
||||
|
||||
if tag_from_label:
|
||||
image_version_tags = uploader.discover_image_tags(
|
||||
images, tag_from_label)
|
||||
images, tag_from_label, mirrors=mirrors)
|
||||
for entry in result:
|
||||
imagename = entry.get('imagename', '')
|
||||
image_no_tag = imagename.rpartition(':')[0]
|
||||
@ -279,7 +288,7 @@ def container_images_prepare(template_file=DEFAULT_TEMPLATE_FILE,
|
||||
|
||||
if modify_only_with_labels:
|
||||
images_with_labels = uploader.filter_images_with_labels(
|
||||
images, modify_only_with_labels)
|
||||
images, modify_only_with_labels, mirrors=mirrors)
|
||||
|
||||
params = {}
|
||||
modify_append_tag = append_tag
|
||||
|
@ -285,63 +285,63 @@ class TestBaseImageUploader(base.TestCase):
|
||||
self.assertEqual(
|
||||
('docker.io/t/foo', 'a'),
|
||||
image_uploader.discover_tag_from_inspect(
|
||||
('docker.io/t/foo', 'rdo_version', sr))
|
||||
('docker.io/t/foo', 'rdo_version', sr, None))
|
||||
)
|
||||
|
||||
# templated labels -> tag
|
||||
self.assertEqual(
|
||||
('docker.io/t/foo', '1.0.0-20180125'),
|
||||
image_uploader.discover_tag_from_inspect(
|
||||
('docker.io/t/foo', '{release}-{version}', sr))
|
||||
('docker.io/t/foo', '{release}-{version}', sr, None))
|
||||
)
|
||||
|
||||
# simple label -> tag with fallback
|
||||
self.assertEqual(
|
||||
('docker.io/t/foo', 'a'),
|
||||
image_uploader.discover_tag_from_inspect(
|
||||
('docker.io/t/foo:a', 'bar', sr))
|
||||
('docker.io/t/foo:a', 'bar', sr, None))
|
||||
)
|
||||
|
||||
# templated labels -> tag with fallback
|
||||
self.assertEqual(
|
||||
('docker.io/t/foo', 'a'),
|
||||
image_uploader.discover_tag_from_inspect(
|
||||
('docker.io/t/foo:a', '{releases}-{versions}', sr))
|
||||
('docker.io/t/foo:a', '{releases}-{versions}', sr, None))
|
||||
)
|
||||
|
||||
# Invalid template
|
||||
self.assertRaises(
|
||||
ImageUploaderException,
|
||||
image_uploader.discover_tag_from_inspect,
|
||||
('docker.io/t/foo', '{release}-{version', sr)
|
||||
('docker.io/t/foo', '{release}-{version', sr, None)
|
||||
)
|
||||
|
||||
# Missing label in template
|
||||
self.assertRaises(
|
||||
ImageUploaderException,
|
||||
image_uploader.discover_tag_from_inspect,
|
||||
('docker.io/t/foo', '{releases}-{version}', sr)
|
||||
('docker.io/t/foo', '{releases}-{version}', sr, None)
|
||||
)
|
||||
|
||||
# no tag_from_label specified
|
||||
self.assertRaises(
|
||||
ImageUploaderException,
|
||||
image_uploader.discover_tag_from_inspect,
|
||||
('docker.io/t/foo', None, sr)
|
||||
('docker.io/t/foo', None, sr, None)
|
||||
)
|
||||
|
||||
# missing RepoTags entry
|
||||
self.assertRaises(
|
||||
ImageUploaderException,
|
||||
image_uploader.discover_tag_from_inspect,
|
||||
('docker.io/t/foo', 'build_version', sr)
|
||||
('docker.io/t/foo', 'build_version', sr, None)
|
||||
)
|
||||
|
||||
# missing Labels entry
|
||||
self.assertRaises(
|
||||
ImageUploaderException,
|
||||
image_uploader.discover_tag_from_inspect,
|
||||
('docker.io/t/foo', 'version', sr)
|
||||
('docker.io/t/foo', 'version', sr, None)
|
||||
)
|
||||
|
||||
# inspect call failed
|
||||
@ -349,7 +349,7 @@ class TestBaseImageUploader(base.TestCase):
|
||||
self.assertRaises(
|
||||
ImageUploaderException,
|
||||
image_uploader.discover_tag_from_inspect,
|
||||
('docker.io/t/foo', 'rdo_version', sr)
|
||||
('docker.io/t/foo', 'rdo_version', sr, None)
|
||||
)
|
||||
|
||||
@mock.patch('concurrent.futures.ThreadPoolExecutor')
|
||||
@ -375,9 +375,9 @@ class TestBaseImageUploader(base.TestCase):
|
||||
mock_pool.return_value.map.assert_called_once_with(
|
||||
image_uploader.discover_tag_from_inspect,
|
||||
[
|
||||
('docker.io/t/foo', 'rdo_release', set()),
|
||||
('docker.io/t/bar', 'rdo_release', set()),
|
||||
('docker.io/t/baz', 'rdo_release', set())
|
||||
('docker.io/t/foo', 'rdo_release', set(), None),
|
||||
('docker.io/t/bar', 'rdo_release', set(), None),
|
||||
('docker.io/t/baz', 'rdo_release', set(), None)
|
||||
])
|
||||
|
||||
@mock.patch('tripleo_common.image.image_uploader.'
|
||||
@ -450,17 +450,38 @@ class TestBaseImageUploader(base.TestCase):
|
||||
auth(url1).headers['Authorization']
|
||||
)
|
||||
|
||||
def test_fix_dockerio_url(self):
|
||||
def test_build_url(self):
|
||||
url1 = urlparse('docker://docker.io/t/nova-api:latest')
|
||||
url2 = urlparse('docker://registry-1.docker.io/t/nova-api:latest')
|
||||
url3 = urlparse('docker://192.0.2.1:8787/t/nova-api:latest')
|
||||
fix = image_uploader.BaseImageUploader._fix_dockerio_url
|
||||
build = image_uploader.BaseImageUploader._build_url
|
||||
# fix urls
|
||||
self.assertEqual(url2, fix(url1))
|
||||
self.assertEqual(
|
||||
'https://registry-1.docker.io/v2/',
|
||||
build(url1, '/')
|
||||
)
|
||||
|
||||
# no change urls
|
||||
self.assertEqual(url2, fix(url2))
|
||||
self.assertEqual(url3, fix(url3))
|
||||
self.assertEqual(
|
||||
'http://registry-1.docker.io/v2/t/nova-api/manifests/latest',
|
||||
build(url2, '/t/nova-api/manifests/latest',
|
||||
insecure=True)
|
||||
)
|
||||
self.assertEqual(
|
||||
'https://192.0.2.1:8787/v2/t/nova-api/tags/list',
|
||||
build(url3, '/t/nova-api/tags/list')
|
||||
)
|
||||
|
||||
# test mirrors
|
||||
mirrors = {
|
||||
'docker.io': 'http://192.0.2.2:8081/registry-1.docker/'
|
||||
}
|
||||
self.assertEqual(
|
||||
'http://192.0.2.2:8081/registry-1.docker/v2/'
|
||||
't/nova-api/blobs/asdf1234',
|
||||
build(url1, '/t/nova-api/blobs/asdf1234',
|
||||
mirrors=mirrors)
|
||||
)
|
||||
|
||||
def test_inspect(self):
|
||||
req = self.requests
|
||||
@ -577,7 +598,8 @@ class TestDockerImageUploader(base.TestCase):
|
||||
None,
|
||||
None,
|
||||
False,
|
||||
'full')
|
||||
'full',
|
||||
None)
|
||||
)
|
||||
)
|
||||
|
||||
@ -616,7 +638,8 @@ class TestDockerImageUploader(base.TestCase):
|
||||
None,
|
||||
None,
|
||||
False,
|
||||
'full')
|
||||
'full',
|
||||
None)
|
||||
)
|
||||
)
|
||||
|
||||
@ -669,7 +692,8 @@ class TestDockerImageUploader(base.TestCase):
|
||||
'add-foo-plugin',
|
||||
{'foo_version': '1.0.1'},
|
||||
False,
|
||||
'partial')
|
||||
'partial',
|
||||
None)
|
||||
)
|
||||
)
|
||||
|
||||
@ -712,7 +736,8 @@ class TestDockerImageUploader(base.TestCase):
|
||||
self.uploader.upload_image, image_uploader.UploadTask(
|
||||
image + ':' + tag, None, push_destination,
|
||||
append_tag, 'add-foo-plugin', {'foo_version': '1.0.1'},
|
||||
False, 'full')
|
||||
False, 'full',
|
||||
None)
|
||||
)
|
||||
|
||||
self.dockermock.assert_called_once_with(
|
||||
@ -743,7 +768,8 @@ class TestDockerImageUploader(base.TestCase):
|
||||
'add-foo-plugin',
|
||||
{'foo_version': '1.0.1'},
|
||||
True,
|
||||
'full')
|
||||
'full',
|
||||
None)
|
||||
)
|
||||
|
||||
self.dockermock.assert_not_called()
|
||||
@ -774,7 +800,8 @@ class TestDockerImageUploader(base.TestCase):
|
||||
'add-foo-plugin',
|
||||
{'foo_version': '1.0.1'},
|
||||
False,
|
||||
'full')
|
||||
'full',
|
||||
None)
|
||||
)
|
||||
|
||||
self.dockermock.assert_not_called()
|
||||
@ -894,7 +921,8 @@ class TestSkopeoImageUploader(base.TestCase):
|
||||
None,
|
||||
None,
|
||||
False,
|
||||
'full')
|
||||
'full',
|
||||
None)
|
||||
)
|
||||
)
|
||||
mock_popen.assert_called_once_with([
|
||||
@ -958,14 +986,15 @@ class TestSkopeoImageUploader(base.TestCase):
|
||||
'add-foo-plugin',
|
||||
{'foo_version': '1.0.1'},
|
||||
False,
|
||||
'partial')
|
||||
'partial',
|
||||
None)
|
||||
)
|
||||
)
|
||||
|
||||
mock_inspect.assert_has_calls([
|
||||
mock.call(urlparse(
|
||||
'docker://docker.io/t/nova-api:latest'
|
||||
), insecure=False, session=mock.ANY)
|
||||
), insecure=False, mirrors=None, session=mock.ANY)
|
||||
])
|
||||
mock_copy.assert_has_calls([
|
||||
mock.call(
|
||||
@ -1014,7 +1043,7 @@ class TestSkopeoImageUploader(base.TestCase):
|
||||
self.uploader.upload_image, image_uploader.UploadTask(
|
||||
image + ':' + tag, None, push_destination,
|
||||
append_tag, 'add-foo-plugin', {'foo_version': '1.0.1'},
|
||||
False, 'full')
|
||||
False, 'full', None)
|
||||
)
|
||||
|
||||
mock_copy.assert_called_once_with(
|
||||
@ -1042,7 +1071,8 @@ class TestSkopeoImageUploader(base.TestCase):
|
||||
'add-foo-plugin',
|
||||
{'foo_version': '1.0.1'},
|
||||
True,
|
||||
'full')
|
||||
'full',
|
||||
None)
|
||||
)
|
||||
|
||||
mock_ansible.assert_not_called()
|
||||
@ -1072,7 +1102,8 @@ class TestSkopeoImageUploader(base.TestCase):
|
||||
'add-foo-plugin',
|
||||
{'foo_version': '1.0.1'},
|
||||
False,
|
||||
'full')
|
||||
'full',
|
||||
None)
|
||||
)
|
||||
|
||||
mock_ansible.assert_not_called()
|
||||
|
@ -840,6 +840,7 @@ class TestPrepare(base.TestCase):
|
||||
env = {
|
||||
'parameter_defaults': {
|
||||
'LocalContainerRegistry': '192.0.2.1',
|
||||
'DockerRegistryMirror': 'http://192.0.2.2/reg/',
|
||||
'ContainerImagePrepare': [{
|
||||
'set': mapping_args,
|
||||
'tag_from_label': 'foo',
|
||||
@ -896,7 +897,10 @@ class TestPrepare(base.TestCase):
|
||||
append_tag=mock.ANY,
|
||||
modify_role=None,
|
||||
modify_only_with_labels=None,
|
||||
modify_vars=None
|
||||
modify_vars=None,
|
||||
mirrors={
|
||||
'docker.io': 'http://192.0.2.2/reg/'
|
||||
}
|
||||
),
|
||||
mock.call(
|
||||
excludes=['nova', 'neutron'],
|
||||
@ -911,7 +915,10 @@ class TestPrepare(base.TestCase):
|
||||
append_tag=mock.ANY,
|
||||
modify_role='add-foo-plugin',
|
||||
modify_only_with_labels=['kolla_version'],
|
||||
modify_vars={'foo_version': '1.0.1'}
|
||||
modify_vars={'foo_version': '1.0.1'},
|
||||
mirrors={
|
||||
'docker.io': 'http://192.0.2.2/reg/'
|
||||
}
|
||||
)
|
||||
])
|
||||
|
||||
@ -995,7 +1002,8 @@ class TestPrepare(base.TestCase):
|
||||
append_tag=mock.ANY,
|
||||
modify_role=None,
|
||||
modify_only_with_labels=None,
|
||||
modify_vars=None
|
||||
modify_vars=None,
|
||||
mirrors={}
|
||||
),
|
||||
mock.call(
|
||||
excludes=['nova', 'neutron'],
|
||||
@ -1010,11 +1018,13 @@ class TestPrepare(base.TestCase):
|
||||
append_tag=mock.ANY,
|
||||
modify_role='add-foo-plugin',
|
||||
modify_only_with_labels=['kolla_version'],
|
||||
modify_vars={'foo_version': '1.0.1'}
|
||||
modify_vars={'foo_version': '1.0.1'},
|
||||
mirrors={}
|
||||
)
|
||||
])
|
||||
|
||||
mock_im.assert_called_once_with(mock.ANY, dry_run=True, cleanup='full')
|
||||
mock_im.assert_called_once_with(mock.ANY, dry_run=True, cleanup='full',
|
||||
mirrors={})
|
||||
|
||||
self.assertEqual(
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user