Add support for local image push
The --local option for container image push requires a change in tripleo-common to support pushing local images. This change implements the required logic to tell the uploader that the source is local instead of a remote source. Depends-On: https://review.opendev.org/#/c/678890/ Change-Id: If279770212d5edb871e5f69a56c6c01681b1574f
This commit is contained in:
parent
bdfd3bfb1b
commit
83f1c6c760
|
@ -27,7 +27,6 @@ from osc_lib import exceptions as oscexc
|
|||
from six.moves.urllib import parse
|
||||
from tripleo_common.image import image_uploader
|
||||
from tripleo_common.image import kolla_builder
|
||||
from tripleoclient import exceptions as tcexc
|
||||
from tripleoclient.tests.v1.test_plugin import TestPluginV1
|
||||
from tripleoclient.v1 import container_image
|
||||
|
||||
|
@ -103,13 +102,6 @@ class TestContainerImagePush(TestPluginV1):
|
|||
mock_uploader = mock.Mock()
|
||||
mock_mgr.uploader.return_value = mock_uploader
|
||||
|
||||
# mock return url object from uploader._image_to_url
|
||||
mock_url = mock.Mock()
|
||||
container_url = parse.urlparse("docker://docker.io/namespace/foo")
|
||||
registry_url = parse.urlparse("docker://127.0.0.1:8787")
|
||||
mock_url.side_effect = [container_url, registry_url]
|
||||
mock_uploader._image_to_url = mock_url
|
||||
|
||||
# mock return session object from uploader.authenticate
|
||||
mock_session = mock.Mock()
|
||||
mock_uploader.authenticate.return_value = mock_session
|
||||
|
@ -144,13 +136,105 @@ class TestContainerImagePush(TestPluginV1):
|
|||
mock_add_upload.assert_called_once_with(mock_uploadtask)
|
||||
mock_run_tasks.assert_called_once()
|
||||
|
||||
def test_take_action_local(self):
|
||||
@mock.patch('tripleo_common.image.image_uploader.UploadTask')
|
||||
@mock.patch('tripleo_common.image.image_uploader.ImageUploadManager')
|
||||
def test_take_action_local(self, mock_manager, mock_task):
|
||||
arglist = ['docker.io/namespace/foo', '--local']
|
||||
verifylist = [('image_to_push', 'docker.io/namespace/foo'),
|
||||
('local', True)]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
self.assertRaises(tcexc.NotFound, self.cmd.take_action, parsed_args)
|
||||
# mock manager object
|
||||
mock_mgr = mock.Mock()
|
||||
mock_manager.return_value = mock_mgr
|
||||
|
||||
# mock uploader object
|
||||
mock_uploader = mock.Mock()
|
||||
mock_mgr.uploader.return_value = mock_uploader
|
||||
|
||||
# mock return session object from uploader.authenticate
|
||||
mock_session = mock.Mock()
|
||||
mock_uploader.authenticate.return_value = mock_session
|
||||
|
||||
# mock upload task
|
||||
mock_uploadtask = mock.Mock()
|
||||
mock_task.return_value = mock_uploadtask
|
||||
|
||||
# mock add upload task action
|
||||
mock_add_upload = mock.Mock()
|
||||
data = []
|
||||
mock_add_upload.return_value = data
|
||||
mock_uploader.add_upload_task = mock_add_upload
|
||||
|
||||
# mock run tasks action
|
||||
mock_run_tasks = mock.Mock()
|
||||
mock_uploader.run_tasks = mock_run_tasks
|
||||
|
||||
self.cmd.take_action(parsed_args)
|
||||
|
||||
mock_task.assert_called_once_with(
|
||||
image_name='containers-storage:docker.io/namespace/foo',
|
||||
pull_source=None,
|
||||
push_destination=parsed_args.registry_url,
|
||||
append_tag=parsed_args.append_tag,
|
||||
modify_role=None,
|
||||
modify_vars=None,
|
||||
dry_run=parsed_args.dry_run,
|
||||
cleanup=False,
|
||||
multi_arch=parsed_args.multi_arch)
|
||||
|
||||
mock_add_upload.assert_called_once_with(mock_uploadtask)
|
||||
mock_run_tasks.assert_called_once()
|
||||
|
||||
@mock.patch('tripleo_common.image.image_uploader.UploadTask')
|
||||
@mock.patch('tripleo_common.image.image_uploader.ImageUploadManager')
|
||||
def test_take_action_local_path(self, mock_manager, mock_task):
|
||||
arglist = ['containers-storage:docker.io/namespace/foo']
|
||||
verifylist = [('image_to_push',
|
||||
'containers-storage:docker.io/namespace/foo')]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
# mock manager object
|
||||
mock_mgr = mock.Mock()
|
||||
mock_manager.return_value = mock_mgr
|
||||
|
||||
# mock uploader object
|
||||
mock_uploader = mock.Mock()
|
||||
mock_mgr.uploader.return_value = mock_uploader
|
||||
|
||||
# mock return session object from uploader.authenticate
|
||||
mock_session = mock.Mock()
|
||||
mock_uploader.authenticate.return_value = mock_session
|
||||
|
||||
# mock upload task
|
||||
mock_uploadtask = mock.Mock()
|
||||
mock_task.return_value = mock_uploadtask
|
||||
|
||||
# mock add upload task action
|
||||
mock_add_upload = mock.Mock()
|
||||
data = []
|
||||
mock_add_upload.return_value = data
|
||||
mock_uploader.add_upload_task = mock_add_upload
|
||||
|
||||
# mock run tasks action
|
||||
mock_run_tasks = mock.Mock()
|
||||
mock_uploader.run_tasks = mock_run_tasks
|
||||
|
||||
self.cmd.take_action(parsed_args)
|
||||
|
||||
mock_task.assert_called_once_with(
|
||||
image_name='containers-storage:docker.io/namespace/foo',
|
||||
pull_source=None,
|
||||
push_destination=parsed_args.registry_url,
|
||||
append_tag=parsed_args.append_tag,
|
||||
modify_role=None,
|
||||
modify_vars=None,
|
||||
dry_run=parsed_args.dry_run,
|
||||
cleanup=False,
|
||||
multi_arch=parsed_args.multi_arch)
|
||||
|
||||
mock_add_upload.assert_called_once_with(mock_uploadtask)
|
||||
mock_run_tasks.assert_called_once()
|
||||
|
||||
@mock.patch('tripleo_common.image.image_uploader.UploadTask')
|
||||
@mock.patch('tripleo_common.image.image_uploader.ImageUploadManager')
|
||||
|
@ -167,13 +251,6 @@ class TestContainerImagePush(TestPluginV1):
|
|||
mock_uploader = mock.Mock()
|
||||
mock_mgr.uploader.return_value = mock_uploader
|
||||
|
||||
# mock return url object from uploader._image_to_url
|
||||
mock_url = mock.Mock()
|
||||
container_url = parse.urlparse("docker://docker.io/namespace/foo")
|
||||
registry_url = parse.urlparse("docker://127.0.0.1:8787")
|
||||
mock_url.side_effect = [container_url, registry_url]
|
||||
mock_uploader._image_to_url = mock_url
|
||||
|
||||
# mock return session object from uploader.authenticate
|
||||
mock_session = mock.Mock()
|
||||
mock_uploader.authenticate.return_value = mock_session
|
||||
|
@ -226,13 +303,6 @@ class TestContainerImagePush(TestPluginV1):
|
|||
mock_uploader = mock.Mock()
|
||||
mock_mgr.uploader.return_value = mock_uploader
|
||||
|
||||
# mock return url object from uploader._image_to_url
|
||||
mock_url = mock.Mock()
|
||||
container_url = parse.urlparse("docker://docker.io/namespace/foo:tag")
|
||||
registry_url = parse.urlparse("docker://127.0.0.1:8787")
|
||||
mock_url.side_effect = [container_url, registry_url]
|
||||
mock_uploader._image_to_url = mock_url
|
||||
|
||||
# mock return session object from uploader.authenticate
|
||||
mock_session = mock.Mock()
|
||||
mock_uploader.authenticate.return_value = mock_session
|
||||
|
@ -253,6 +323,7 @@ class TestContainerImagePush(TestPluginV1):
|
|||
|
||||
self.cmd.take_action(parsed_args)
|
||||
|
||||
registry_url = parse.urlparse("docker://127.0.0.1:8787")
|
||||
mock_uploader.authenticate.assert_called_once_with(
|
||||
registry_url, parsed_args.username, parsed_args.password)
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ import time
|
|||
from osc_lib import exceptions as oscexc
|
||||
from osc_lib.i18n import _
|
||||
import six
|
||||
from six.moves.urllib import parse
|
||||
import yaml
|
||||
|
||||
from tripleo_common.image.builder import buildah
|
||||
|
@ -589,23 +590,39 @@ class TripleOContainerImagePush(command.Command):
|
|||
def take_action(self, parsed_args):
|
||||
self.log.debug("take_action(%s)" % parsed_args)
|
||||
|
||||
# TODO(aschultz): need to fix upload to be able to handle local source
|
||||
if parsed_args.local:
|
||||
raise exceptions.NotFound('--local is currently not implemented')
|
||||
|
||||
manager = image_uploader.ImageUploadManager()
|
||||
uploader = manager.uploader('python')
|
||||
|
||||
source_url = uploader._image_to_url(parsed_args.image_to_push)
|
||||
image_name = source_url.path[1:]
|
||||
if len(image_name.split('/')) != 2:
|
||||
raise exceptions.DownloadError('Invalid container. Provided '
|
||||
'container image should be '
|
||||
'<registry>/<namespace>/<name>:'
|
||||
'<tag>')
|
||||
image_source = source_url.netloc
|
||||
source_image = parsed_args.image_to_push
|
||||
|
||||
reg_url = uploader._image_to_url(parsed_args.registry_url)
|
||||
if parsed_args.local or source_image.startswith('containers-storage:'):
|
||||
storage = 'containers-storage:'
|
||||
if not source_image.startswith(storage):
|
||||
source_image = storage + source_image.replace('docker://', '')
|
||||
elif not parsed_args.local:
|
||||
self.log.warning('Assuming local container based on provided '
|
||||
'container path. (e.g. starts with '
|
||||
'containers-storage:)')
|
||||
source_url = parse.urlparse(source_image)
|
||||
image_name = source_url.geturl()
|
||||
image_source = None
|
||||
else:
|
||||
storage = 'docker://'
|
||||
if not source_image.startswith(storage):
|
||||
source_image = storage + source_image
|
||||
source_url = parse.urlparse(source_image)
|
||||
image_source = source_url.netloc
|
||||
image_name = source_url.path[1:]
|
||||
if len(image_name.split('/')) != 2:
|
||||
raise exceptions.DownloadError('Invalid container. Provided '
|
||||
'container image should be '
|
||||
'<registry>/<namespace>/<name>:'
|
||||
'<tag>')
|
||||
|
||||
registry_url = parsed_args.registry_url
|
||||
if not registry_url.startswith('docker://'):
|
||||
registry_url = 'docker://%s' % registry_url
|
||||
reg_url = parse.urlparse(registry_url)
|
||||
|
||||
uploader.authenticate(reg_url,
|
||||
parsed_args.username,
|
||||
|
|
Loading…
Reference in New Issue