From f321bb4688994462e84e958f32dc1917c5edd695 Mon Sep 17 00:00:00 2001 From: Alex Schultz Date: Wed, 17 Nov 2021 08:17:13 -0700 Subject: [PATCH] Removed overcloud container commands The following commands have been removed: overcloud container image upload overcloud container image build overcloud container image prepare overcloud container image tag discover They were replaced by the tripleo container based commands and no longer function. Change-Id: Ic1f4d76c9e7bf3579b7e47d87b0ee2c86251c0d6 --- doc/source/commands.rst | 3 - ...d-container-commands-fe7185ee87aeda3a.yaml | 7 + setup.cfg | 4 - .../tests/v1/test_container_image.py | 671 ------------------ tripleoclient/v1/container_image.py | 501 ------------- 5 files changed, 7 insertions(+), 1179 deletions(-) create mode 100644 releasenotes/notes/remove-overcloud-container-commands-fe7185ee87aeda3a.yaml diff --git a/doc/source/commands.rst b/doc/source/commands.rst index b671d97df..ac6ec0666 100644 --- a/doc/source/commands.rst +++ b/doc/source/commands.rst @@ -12,9 +12,6 @@ Container Commands .. autoprogram-cliff:: openstack.tripleoclient.v2 :command: tripleo container * -.. autoprogram-cliff:: openstack.tripleoclient.v2 - :command: overcloud container image [!prep]* - =================== Undercloud Commands =================== diff --git a/releasenotes/notes/remove-overcloud-container-commands-fe7185ee87aeda3a.yaml b/releasenotes/notes/remove-overcloud-container-commands-fe7185ee87aeda3a.yaml new file mode 100644 index 000000000..7b36558b7 --- /dev/null +++ b/releasenotes/notes/remove-overcloud-container-commands-fe7185ee87aeda3a.yaml @@ -0,0 +1,7 @@ +--- +upgrade: + - | + Removed `overcloud container image upload`, `overcloud container image build`, + `overcloud container image prepare` and `overcloud container image tag` + commands as the `tripleo container` command replaced those in Train and + they no longer work. diff --git a/setup.cfg b/setup.cfg index 58acb1f16..4981c9fee 100644 --- a/setup.cfg +++ b/setup.cfg @@ -44,10 +44,6 @@ openstack.tripleoclient.v2 = overcloud_cell_export = tripleoclient.v1.overcloud_cell:ExportCell overcloud_ceph_deploy = tripleoclient.v2.overcloud_ceph:OvercloudCephDeploy overcloud_config_download = tripleoclient.v1.overcloud_config:DownloadConfig - overcloud_container_image_upload = tripleoclient.v1.container_image:UploadImage - overcloud_container_image_build = tripleoclient.v1.container_image:BuildImage - overcloud_container_image_prepare = tripleoclient.v1.container_image:PrepareImageFiles - overcloud_container_image_tag_discover = tripleoclient.v1.container_image:DiscoverImageTag overcloud_delete = tripleoclient.v2.overcloud_delete:DeleteOvercloud overcloud_credentials = tripleoclient.v1.overcloud_credentials:OvercloudCredentials overcloud_deploy = tripleoclient.v1.overcloud_deploy:DeployOvercloud diff --git a/tripleoclient/tests/v1/test_container_image.py b/tripleoclient/tests/v1/test_container_image.py index 0499ee59f..efa8478b4 100644 --- a/tripleoclient/tests/v1/test_container_image.py +++ b/tripleoclient/tests/v1/test_container_image.py @@ -13,76 +13,20 @@ # under the License. # -import fixtures from io import StringIO import os -import requests import shutil -import sys import tempfile from urllib import parse -import uuid import yaml from unittest import mock from osc_lib import exceptions as oscexc from tripleo_common.image import kolla_builder -from tripleoclient import constants from tripleoclient.tests.v1.test_plugin import TestPluginV1 from tripleoclient.v1 import container_image -class TestContainerImageUpload(TestPluginV1): - - def setUp(self): - super(TestContainerImageUpload, self).setUp() - - # Get the command object to test - self.cmd = container_image.UploadImage(self.app, None) - - @mock.patch('tripleo_common.utils.locks.processlock.' - 'ProcessLock') - @mock.patch('sys.exit') - @mock.patch('tripleo_common.image.image_uploader.ImageUploadManager') - def test_container_image_upload_noargs(self, mock_manager, exit_mock, - mock_lock): - arglist = [] - verifylist = [] - - mock_lockobj = mock.MagicMock() - mock_lock.return_value = mock_lockobj - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - self.cmd.take_action(parsed_args) - # argparse will complain that --config-file is missing and exit with 2 - exit_mock.assert_called_with(2) - - @mock.patch('tripleo_common.utils.locks.processlock.' - 'ProcessLock') - @mock.patch('tripleo_common.image.image_uploader.ImageUploadManager') - def test_container_image_upload_conf_files(self, mock_manager, mock_lock): - arglist = [ - '--config-file', - '/tmp/foo.yaml', - '--config-file', - '/tmp/bar.yaml' - ] - verifylist = [] - - mock_lockobj = mock.MagicMock() - mock_lock.return_value = mock_lockobj - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - self.cmd.take_action(parsed_args) - - mock_manager.assert_called_once_with( - ['/tmp/foo.yaml', '/tmp/bar.yaml'], cleanup='full', - lock=mock_lockobj) - mock_manager.return_value.upload.assert_called_once_with() - - class TestContainerImagePush(TestPluginV1): def setUp(self): super(TestContainerImagePush, self).setUp() @@ -535,345 +479,6 @@ class TestContainerImageShow(TestPluginV1): (['Name', 'Layers'], ['foo', 'bar'])) -class TestContainerImagePrepare(TestPluginV1): - - def setUp(self): - super(TestContainerImagePrepare, self).setUp() - - # Get the command object to test - self.cmd = container_image.PrepareImageFiles(self.app, None) - kolla_builder.DEFAULT_TEMPLATE_FILE = os.path.join( - '/tmp/overcloud_containers.yaml.j2' - ) - self.roles_yaml = ''' - - name: EnabledRole - CountDefault: 1 - ServicesDefault: - - OS::TripleO::Services::AodhEvaluator - - name: RoleDisabledViaRolesData - CountDefault: 0 - ServicesDefault: - - OS::TripleO::Services::AodhApi - - name: RoleDisabledViaEnvironment - CountDefault: 1 - ServicesDefault: - - OS::TripleO::Services::Disabled - - name: RoleOverwrittenViaEnvironment - CountDefault: 1 - ServicesDefault: - - OS::TripleO::Services::Overwritten - ''' - - @mock.patch('tripleo_common.image.kolla_builder.' - 'container_images_prepare_defaults', create=True) - @mock.patch('tripleo_common.image.kolla_builder.' - 'container_images_prepare', create=True) - @mock.patch('requests.get') - @mock.patch('tripleo_common.image.kolla_builder.' - 'build_service_filter') - def test_container_image_prepare_noargs(self, mock_bsf, mock_get, mock_cip, - mock_cipd): - mock_bsf.return_value = None - mock_cipd.return_value = { - 'neutron_driver': 'ovn', - 'name_suffix': '', - 'tag': 'latest', - 'namespace': 'docker.io/tripleomaster', - 'name_prefix': - 'centos-binary-' - } - arglist = [] - verifylist = [] - - mock_cip.return_value = {'container_images.yaml': {}} - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - self.cmd.take_action(parsed_args) - - mock_cip.assert_called_with( - excludes=[], - includes=[], - mapping_args={ - 'neutron_driver': 'ovn', - 'name_suffix': '', - 'tag': 'latest', - 'namespace': 'docker.io/tripleomaster', - 'name_prefix': - 'centos-binary-' - }, - output_env_file=None, - output_images_file='container_images.yaml', - push_destination=None, - service_filter=None, - tag_from_label=None, - modify_role=None, - modify_vars=None, - append_tag=None, - template_file=kolla_builder.DEFAULT_TEMPLATE_FILE - ) - - @mock.patch('tripleoclient.utils.fetch_roles_file') - @mock.patch('tripleo_common.image.kolla_builder.' - 'container_images_prepare_defaults', create=True) - @mock.patch('tripleo_common.image.kolla_builder.' - 'container_images_prepare', create=True) - @mock.patch('heatclient.common.template_utils.' - 'process_multiple_environments_and_files') - @mock.patch('tripleo_common.image.kolla_builder.' - 'build_service_filter') - @mock.patch('requests.get') - def test_container_image_prepare(self, mock_get, mock_bsf, pmef, mock_cip, - mock_cipd, mock_roles): - - temp = tempfile.mkdtemp() - self.addCleanup(shutil.rmtree, temp) - images_file = os.path.join(temp, 'overcloud_containers.yaml') - env_file = os.path.join(temp, 'containers_env.yaml') - tmpl_file = os.path.join(temp, 'overcloud_containers.yaml.j2') - aodh_file = os.path.join(temp, 'docker', 'services', 'aodh.yaml') - roles_file = os.path.join(temp, 'roles_data.yaml') - with open(roles_file, 'w') as f: - f.write(self.roles_yaml) - modify_vars_file = os.path.join(temp, 'modify_vars.yaml') - with open(modify_vars_file, 'w') as f: - f.write('foo: bar') - mock_get.side_effect = requests.exceptions.SSLError('ouch') - mock_bsf.return_value = set(['OS::TripleO::Services::AodhEvaluator']) - - resource_registry = { - 'parameter_defaults': { - 'NeutronMechanismDrivers': 'ovn', - }, - 'resource_registry': { - 'OS::TripleO::Services::AodhEvaluator': aodh_file, - 'OS::TripleO::Services::AodhApi': aodh_file - } - } - pmef.return_value = None, resource_registry - - arglist = [ - '--template-file', - tmpl_file, - '--tag', - 'passed-ci', - '--namespace', - '192.0.2.0:8787/t', - '--prefix', - 'os-', - '--suffix', - 'foo', - '--output-images-file', - images_file, - '--output-env-file', - env_file, - '--set', - 'ceph_namespace=myceph', - '--set', - 'ceph_image=mydaemon', - '--set', - 'ceph_tag=mytag', - '-e', - 'environment/docker-ha.yaml', - '--roles-file', - roles_file, - '--modify-role', - 'foo-role', - '--modify-vars', - modify_vars_file - ] - self.cmd.app.command_options = arglist - verifylist = [] - mock_cip.return_value = {images_file: [{ - 'imagename': '192.0.2.0:8787/t/os-aodh-apifoo:passed-ci', - }, { - 'imagename': '192.0.2.0:8787/t/os-aodh-evaluatorfoo:passed-ci', - }], env_file: { - 'DockerAodhApiImage': - '192.0.2.0:8787/t/os-aodh-apifoo:passed-ci', - 'DockerAodhConfigImage': - '192.0.2.0:8787/t/os-aodh-apifoo:passed-ci', - 'DockerAodhEvaluatorImage': - '192.0.2.0:8787/t/os-aodh-evaluatorfoo:passed-ci', - 'DockerInsecureRegistryAddress': ['192.0.2.0:8787'] - } - } - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - self.cmd.take_action(parsed_args) - - pmef.assert_called_once_with(['environment/docker-ha.yaml'], - env_path_is_object=mock.ANY, - object_request=mock.ANY) - mock_cip.assert_called_once_with( - excludes=[], - includes=[], - mapping_args={ - 'namespace': '192.0.2.0:8787/t', - 'name_suffix': 'foo', - 'ceph_tag': 'mytag', - 'ceph_image': 'mydaemon', - 'tag': 'passed-ci', - 'neutron_driver': 'ovn', - 'ceph_namespace': 'myceph', - 'name_prefix': 'os-' - }, - output_env_file=env_file, - output_images_file=images_file, - push_destination=None, - service_filter=set([ - 'OS::TripleO::Services::AodhEvaluator', - ]), - tag_from_label=None, - modify_role='foo-role', - modify_vars={'foo': 'bar'}, - append_tag=mock.ANY, - template_file=tmpl_file - ) - ci_data = { - 'container_images': [{ - 'imagename': '192.0.2.0:8787/t/os-aodh-apifoo:passed-ci', - }, { - 'imagename': '192.0.2.0:8787/t/os-aodh-evaluatorfoo:passed-ci', - }] - } - env_data = { - 'parameter_defaults': { - 'DockerAodhApiImage': - '192.0.2.0:8787/t/os-aodh-apifoo:passed-ci', - 'DockerAodhConfigImage': - '192.0.2.0:8787/t/os-aodh-apifoo:passed-ci', - 'DockerAodhEvaluatorImage': - '192.0.2.0:8787/t/os-aodh-evaluatorfoo:passed-ci', - 'DockerInsecureRegistryAddress': ['192.0.2.0:8787'] - } - } - with open(images_file) as f: - self.assertEqual(ci_data, yaml.safe_load(f)) - with open(env_file) as f: - self.assertEqual(env_data, yaml.safe_load(f)) - - -class TestTripleoImagePrepare(TestPluginV1): - - def setUp(self): - super(TestTripleoImagePrepare, self).setUp() - # Get the command object to test - self.cmd = container_image.TripleOImagePrepare(self.app, None) - self.cmd.app_args = mock.Mock() - self.cmd.app_args.verbose_level = 3 - self.temp_dir = tempfile.mkdtemp() - self.addCleanup(shutil.rmtree, self.temp_dir) - self.prepare_default_file = os.path.join( - self.temp_dir, 'prepare_env.yaml') - default_param = kolla_builder.CONTAINER_IMAGE_PREPARE_PARAM - self.default_env = { - 'parameter_defaults': { - 'ContainerImagePrepare': default_param - } - } - with open(self.prepare_default_file, 'w') as f: - yaml.safe_dump(self.default_env, f) - - self.roles_yaml = ''' - - name: EnabledRole - CountDefault: 1 - ServicesDefault: - - OS::TripleO::Services::AodhEvaluator - - name: RoleDisabledViaRolesData - CountDefault: 0 - ServicesDefault: - - OS::TripleO::Services::AodhApi - - name: RoleDisabledViaEnvironment - CountDefault: 1 - ServicesDefault: - - OS::TripleO::Services::Disabled - - name: RoleOverwrittenViaEnvironment - CountDefault: 1 - ServicesDefault: - - OS::TripleO::Services::Overwritten - ''' - self.roles_data_file = os.path.join( - self.temp_dir, 'roles_data.yaml') - with open(self.roles_data_file, 'w') as f: - f.write(self.roles_yaml) - - @mock.patch('tripleoclient.utils.run_ansible_playbook', - autospec=True) - def test_tripleo_container_image_prepare(self, mock_playbook): - - env_file = os.path.join(self.temp_dir, 'containers_env.yaml') - - arglist = [ - '--environment-file', self.prepare_default_file, - '--roles-file', self.roles_data_file, - '--output-env-file', env_file - ] - verifylist = [] - - self.app.command_options = [ - 'tripleo', 'container', 'image', 'prepare' - ] + arglist - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - self.cmd.take_action(parsed_args) - e_vars = {'roles_file': self.roles_data_file, - 'environment_directories': [mock.ANY], - 'environment_files': [self.temp_dir + '/prepare_env.yaml'], - 'cleanup': 'full', 'dry_run': False, - 'log_file': 'container_image_prepare.log', 'debug': True, - 'output_env_file': self.temp_dir + '/containers_env.yaml'} - - mock_playbook.assert_called_with( - extra_vars=e_vars, - inventory='localhost,', - playbook='cli-container-image-prepare.yaml', - playbook_dir='/usr/share/ansible/tripleo-playbooks', - verbosity=3, workdir=mock.ANY) - - @mock.patch('tripleoclient.utils.rel_or_abs_path') - @mock.patch('tripleoclient.utils.run_ansible_playbook', - autospec=True) - def test_tripleo_container_image_prepare_paths(self, mock_playbook, - mock_path): - arglist = ['-e', 'foo.yaml', - '-e', '/bar.yaml', - '--environment-directory', 'foo', - '--environment-directory', '/bar', - '-r', 'foo.yaml'] - verifylist = [] - self.app.command_options = [ - 'tripleo', 'container', 'image', 'prepare' - ] + arglist - - mock_path.return_value = ('/usr/share/openstack-tripleo-heat-templates' - '/foo.yaml') - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - self.cmd.take_action(parsed_args) - e_vars = {'roles_file': ('/usr/share/' - 'openstack-tripleo-heat-templates/foo.yaml'), - 'environment_directories': [ - os.path.expanduser(constants.DEFAULT_ENV_DIRECTORY), - os.getcwd() + '/foo', - '/bar' - ], - 'environment_files': [ - os.getcwd() + '/foo.yaml', - '/bar.yaml' - ], - 'cleanup': 'full', 'dry_run': False, - 'log_file': 'container_image_prepare.log', 'debug': True} - - mock_playbook.assert_called_with( - extra_vars=e_vars, - inventory='localhost,', - playbook='cli-container-image-prepare.yaml', - playbook_dir='/usr/share/ansible/tripleo-playbooks', - verbosity=3, workdir=mock.ANY) - - class TestTripleoImagePrepareDefault(TestPluginV1): def setUp(self): @@ -949,279 +554,3 @@ class TestTripleoImagePrepareDefault(TestPluginV1): True, result['parameter_defaults']['ContainerImageRegistryLogin'] ) - - -class TestContainerImageBuild(TestPluginV1): - - def setUp(self): - super(TestContainerImageBuild, self).setUp() - - # Get the command object to test - self.cmd = container_image.BuildImage(self.app, None) - self.cmd.app.stdout = StringIO() - self.uuid = str(uuid.uuid4()) - self.temp_dir = os.path.join(self.useFixture( - fixtures.TempDir()).join()) - self.temp_dir_uuid = os.path.join(self.temp_dir, self.uuid) - - # Default conf file - self.default_kolla_conf = os.path.join( - sys.prefix, 'share', 'tripleo-common', 'container-images', - 'tripleo_kolla_config_overrides.conf') - - @mock.patch('sys.exit') - @mock.patch('tripleo_common.image.kolla_builder.KollaImageBuilder', - autospec=True) - @mock.patch('os.makedirs') - def test_container_image_build_noargs(self, mock_mkdirs, mock_builder, - exit_mock): - arglist = [] - verifylist = [] - mock_builder.return_value.build_images.return_value = 'done' - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - f, path = tempfile.mkstemp(dir=self.temp_dir) - with mock.patch('tempfile.mkstemp') as mock_mkstemp: - mock_mkstemp.return_value = f, path - self.cmd.take_action(parsed_args) - - # argparse will complain that --config-file is missing and exit with 2 - exit_mock.assert_called_with(2) - - @mock.patch('tripleo_common.image.kolla_builder.KollaImageBuilder', - autospec=True) - @mock.patch('uuid.uuid4') - def test_container_image_build(self, mock_uuid, mock_builder): - arglist = [ - '--config-file', - '/tmp/foo.yaml', - '--config-file', - '/tmp/bar.yaml', - '--work-dir', - self.temp_dir, - '--kolla-config-file', - '/tmp/kolla.conf' - ] - verifylist = [] - mock_builder.return_value.build_images.return_value = 'done' - mock_uuid.return_value = self.uuid - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - f, path = tempfile.mkstemp(dir=self.temp_dir) - with mock.patch('tempfile.mkstemp') as mock_mkstemp: - with mock.patch('os.chdir'): - mock_mkstemp.return_value = f, path - self.cmd.take_action(parsed_args) - - mock_builder.assert_called_once_with([ - '/tmp/foo.yaml', '/tmp/bar.yaml']) - mock_builder.return_value.build_images.assert_called_once_with([ - self.default_kolla_conf, '/tmp/kolla.conf', - path - ], [], False, self.temp_dir_uuid) - - @mock.patch('os.chdir') - @mock.patch('os.fdopen', autospec=True) - @mock.patch('tempfile.mkstemp') - @mock.patch( - 'tripleoclient.utils.get_from_cfg') - @mock.patch( - 'tripleoclient.utils.getboolean_from_cfg') - @mock.patch('tripleo_common.image.builder.buildah.BuildahBuilder', - autospec=True) - @mock.patch('tripleo_common.image.kolla_builder.KollaImageBuilder', - autospec=True) - @mock.patch('tripleoclient.utils.get_read_config') - @mock.patch('os.remove') - def test_container_image_build_with_buildah(self, mock_remove, - mock_read_conf, - mock_builder, mock_buildah, - mock_kolla_boolean_cfg, - mock_kolla_cfg, mock_mkstemp, - mock_fdopen, mock_chdir): - arglist = [ - '--config-file', - '/tmp/bar.yaml', - '--kolla-config-file', - '/tmp/kolla.conf', - '--use-buildah', - '--work-dir', - self.temp_dir, - ] - - parsed_args = self.check_parser(self.cmd, arglist, []) - deps = '{"base": ["qrouterd"]}' - mock_builder.return_value.build_images.return_value = deps - - mock_mkstemp.return_value = (1, '/tmp/whatever_file') - - mock_bb = mock.MagicMock() - mock_bb.build_all = mock.MagicMock() - mock_buildah.return_value = mock_bb - self.cmd.take_action(parsed_args) - - cfg_files = list(parsed_args.kolla_config_files) - cfg_files.append('/tmp/whatever_file') - mock_read_conf.assert_any_call(cfg_files) - cfg_calls = [ - mock.call(mock_read_conf.return_value, 'base'), - mock.call(mock_read_conf.return_value, 'type'), - mock.call(mock_read_conf.return_value, 'tag'), - mock.call(mock_read_conf.return_value, 'namespace'), - mock.call(mock_read_conf.return_value, 'registry'), - ] - cfg_boolean_calls = [ - mock.call(mock_read_conf.return_value, 'push'), - ] - mock_kolla_cfg.assert_has_calls(cfg_calls) - mock_kolla_boolean_cfg.assert_has_calls(cfg_boolean_calls) - mock_bb.build_all.assert_called_once() - - @mock.patch('tripleo_common.image.kolla_builder.KollaImageBuilder', - autospec=True) - @mock.patch('uuid.uuid4') - def test_container_image_build_with_exclude(self, mock_uuid, mock_builder): - arglist = [ - '--config-file', - '/tmp/foo.yaml', - '--config-file', - '/tmp/bar.yaml', - '--kolla-config-file', - '/tmp/kolla.conf', - '--work-dir', - '/tmp/testing', - '--exclude', - 'foo', - '--exclude', - 'bar' - ] - verifylist = [] - mock_builder.return_value.build_images.return_value = 'done' - mock_uuid.return_value = '123' - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - f, path = tempfile.mkstemp(dir=self.temp_dir) - with mock.patch('tempfile.mkdtemp') as mock_mkd: - mock_mkd.return_value = '/tmp/testing' - with mock.patch('tempfile.mkstemp') as mock_mkstemp: - with mock.patch('os.chdir'): - mock_mkstemp.return_value = f, path - self.cmd.take_action(parsed_args) - - mock_builder.assert_called_once_with([ - '/tmp/foo.yaml', '/tmp/bar.yaml']) - mock_builder.return_value.build_images.assert_called_once_with([ - self.default_kolla_conf, '/tmp/kolla.conf', - path - ], ['foo', 'bar'], False, '/tmp/testing/123') - - @mock.patch('tripleo_common.image.kolla_builder.KollaImageBuilder', - autospec=True) - @mock.patch('os.remove') - def test_container_image_build_list_images(self, mock_remove, - mock_builder): - arglist = [ - '--list-images', - '--config-file', - '/tmp/bar.yaml', - '--work-dir', - '/tmp/testing', - '--kolla-config-file', - '/tmp/kolla.conf' - ] - parsed_args = self.check_parser(self.cmd, arglist, []) - deps = '{"base": ["qrouterd"]}' - mock_builder.return_value.build_images.return_value = deps - - f, path = tempfile.mkstemp(dir=self.temp_dir) - with mock.patch('tempfile.mkstemp') as mock_mkstemp: - mock_mkstemp.return_value = f, path - self.cmd.take_action(parsed_args) - with open(path, 'r') as conf_file: - self.assertEqual( - conf_file.readlines(), - ['[DEFAULT]\n', 'list_dependencies=true']) - self.assertEqual('- base\n- qrouterd\n', - self.cmd.app.stdout.getvalue()) - - @mock.patch('tripleo_common.image.kolla_builder.KollaImageBuilder', - autospec=True) - @mock.patch('os.remove') - @mock.patch('os.makedirs') - def test_container_image_build_list_deps(self, mock_mkdirs, mock_remove, - mock_builder): - arglist = [ - '--config-file', - '/tmp/bar.yaml', - '--kolla-config-file', - '/tmp/kolla.conf', - '--list-dependencies', - ] - parsed_args = self.check_parser(self.cmd, arglist, []) - deps = '{"base": ["qrouterd"]}' - mock_builder.return_value.build_images.return_value = deps - - f, path = tempfile.mkstemp(dir=self.temp_dir) - with mock.patch('tempfile.mkstemp') as mock_mkstemp: - mock_mkstemp.return_value = f, path - self.cmd.take_action(parsed_args) - with open(path, 'r') as conf_file: - self.assertEqual( - conf_file.readlines(), - ['[DEFAULT]\n', 'list_dependencies=true']) - self.assertEqual('base:\n- qrouterd\n', - self.cmd.app.stdout.getvalue()) - - def test_images_from_deps(self): - deps = yaml.safe_load('''base: -- qdrouterd -- cron -- ceph-base: - - ceph-osd - - ceph-rgw - - ceph-mon - - cephfs-fuse - - ceph-mds -- redis -- etcd -- kubernetes-entrypoint -- kolla-toolbox -- telegraf -- openstack-base: - - swift-base: - - swift-proxy-server - - swift-account - - swift-container - - swift-object-expirer - - swift-rsyncd - - swift-object''') - - images_yaml = '''- base -- qdrouterd -- cron -- ceph-base -- ceph-osd -- ceph-rgw -- ceph-mon -- cephfs-fuse -- ceph-mds -- redis -- etcd -- kubernetes-entrypoint -- kolla-toolbox -- telegraf -- openstack-base -- swift-base -- swift-proxy-server -- swift-account -- swift-container -- swift-object-expirer -- swift-rsyncd -- swift-object -''' - images = [] - self.cmd.images_from_deps(images, deps) - self.assertEqual(yaml.safe_load(images_yaml), images) diff --git a/tripleoclient/v1/container_image.py b/tripleoclient/v1/container_image.py index e3a7abb2a..a73f82739 100644 --- a/tripleoclient/v1/container_image.py +++ b/tripleoclient/v1/container_image.py @@ -17,21 +17,15 @@ import copy import datetime import errno from io import StringIO -import json import logging import os import shutil -import sys -import tempfile -import time -import uuid from osc_lib import exceptions as oscexc from osc_lib.i18n import _ from urllib import parse import yaml -from tripleo_common.image.builder import buildah from tripleo_common.image import image_uploader from tripleo_common.image import kolla_builder from tripleo_common.utils.locks import processlock @@ -56,501 +50,6 @@ def build_env_file(params, command_options): return f.getvalue() -class UploadImage(command.Command): - """Push overcloud container images to registries.""" - - auth_required = False - log = logging.getLogger(__name__ + ".UploadImage") - - def get_parser(self, prog_name): - parser = super(UploadImage, self).get_parser(prog_name) - parser.add_argument( - "--config-file", - dest="config_files", - metavar='', - default=[], - action="append", - required=True, - help=_("YAML config file specifying the image build. May be " - "specified multiple times. Order is preserved, and later " - "files will override some options in previous files. " - "Other options will append."), - ) - parser.add_argument( - "--cleanup", - dest="cleanup", - metavar='', - default=image_uploader.CLEANUP_FULL, - help=_("Cleanup behavior for local images left after upload. " - "The default 'full' will attempt to delete all local " - "images. 'partial' will leave images required for " - "deployment on this host. 'none' will do no cleanup.") - ) - - return parser - - def take_action(self, parsed_args): - self.log.debug("take_action(%s)" % parsed_args) - if parsed_args.cleanup not in image_uploader.CLEANUP: - raise oscexc.CommandError('--cleanup must be one of: %s' % - ', '.join(image_uploader.CLEANUP)) - lock = processlock.ProcessLock() - uploader = image_uploader.ImageUploadManager( - parsed_args.config_files, cleanup=parsed_args.cleanup, lock=lock) - try: - uploader.upload() - except KeyboardInterrupt: # ctrl-c - self.log.warning('Upload was interrupted by ctrl-c.') - - -class BuildImage(command.Command): - """Build overcloud container images with kolla-build.""" - - auth_required = False - log = logging.getLogger(__name__ + ".BuildImage") - - @staticmethod - def images_from_deps(images, dep): - '''Builds a list from the dependencies depth-first. ''' - if isinstance(dep, list): - for v in dep: - BuildImage.images_from_deps(images, v) - elif isinstance(dep, dict): - for k, v in dep.items(): - images.append(k) - BuildImage.images_from_deps(images, v) - else: - images.append(dep) - - def get_parser(self, prog_name): - default_kolla_conf = os.path.join( - sys.prefix, 'share', 'tripleo-common', 'container-images', - 'tripleo_kolla_config_overrides.conf') - parser = super(BuildImage, self).get_parser(prog_name) - parser.add_argument( - "--config-file", - dest="config_files", - metavar='', - default=[], - action="append", - help=_("YAML config file specifying the images to build. May be " - "specified multiple times. Order is preserved, and later " - "files will override some options in previous files. " - "Other options will append. If not specified, the default " - "set of containers will be built."), - ) - parser.add_argument( - "--kolla-config-file", - dest="kolla_config_files", - metavar='', - default=[default_kolla_conf], - action="append", - required=True, - help=_("Path to a Kolla config file to use. Multiple config files " - "can be specified, with values in later files taking " - "precedence. By default, tripleo kolla conf file {conf} " - "is added.").format(conf=default_kolla_conf), - ) - parser.add_argument( - '--list-images', - dest='list_images', - action='store_true', - default=False, - help=_('Show the images which would be built instead of ' - 'building them.') - ) - parser.add_argument( - '--list-dependencies', - dest='list_dependencies', - action='store_true', - default=False, - help=_('Show the image build dependencies instead of ' - 'building them.') - ) - parser.add_argument( - "--exclude", - dest="excludes", - metavar='', - default=[], - action="append", - help=_("Name of a container to match against the list of " - "containers to be built to skip. Can be specified multiple " - "times."), - ) - parser.add_argument( - '--use-buildah', - dest='use_buildah', - action='store_true', - default=False, - help=_('Use Buildah instead of Docker to build the images ' - 'with Kolla.') - ) - parser.add_argument( - "--work-dir", - dest="work_dir", - default='/tmp/container-builds', - metavar='', - help=_("TripleO container builds directory, storing configs and " - "logs for each image and its dependencies.") - ) - parser.add_argument( - "--build-timeout", - dest="build_timeout", - default=None, - type=int, - metavar="", - help=_("Build timeout in seconds.") - ) - return parser - - def take_action(self, parsed_args): - self.log.debug("take_action(%s)" % parsed_args) - self.log.warning('This command is deprecated. Please use "openstack ' - 'tripleo container image build" instead.') - - fd, path = tempfile.mkstemp(prefix='kolla_conf_') - with os.fdopen(fd, 'w') as tmp: - tmp.write('[DEFAULT]\n') - if parsed_args.list_images or parsed_args.list_dependencies: - tmp.write('list_dependencies=true') - kolla_config_files = list(parsed_args.kolla_config_files) - kolla_config_files.append(path) - # Generate an unique work directory so we can keep configs and logs - # each time we run the command; they'll be stored in work_dir. - kolla_work_dir = os.path.join(parsed_args.work_dir, str(uuid.uuid4())) - - # Make sure the unique work directory exists - if not os.path.exists(kolla_work_dir): - self.log.debug("Creating container builds " - "workspace in: %s" % kolla_work_dir) - os.makedirs(kolla_work_dir) - - builder = kolla_builder.KollaImageBuilder(parsed_args.config_files) - result = builder.build_images(kolla_config_files, - parsed_args.excludes, - parsed_args.use_buildah, - kolla_work_dir) - - if parsed_args.use_buildah: - deps = json.loads(result) - kolla_cfg = utils.get_read_config(kolla_config_files) - bb = buildah.BuildahBuilder( - kolla_work_dir, deps, - utils.get_from_cfg(kolla_cfg, "base"), - utils.get_from_cfg(kolla_cfg, "type"), - utils.get_from_cfg(kolla_cfg, "tag"), - utils.get_from_cfg(kolla_cfg, "namespace"), - utils.get_from_cfg(kolla_cfg, "registry"), - utils.getboolean_from_cfg(kolla_cfg, "push"), - parsed_args.build_timeout, - self.app.options.debug) - bb.build_all() - elif parsed_args.list_dependencies: - deps = json.loads(result) - yaml.safe_dump( - deps, - self.app.stdout, - indent=2, - default_flow_style=False - ) - elif parsed_args.list_images: - deps = json.loads(result) - images = [] - BuildImage.images_from_deps(images, deps) - yaml.safe_dump( - images, - self.app.stdout, - default_flow_style=False - ) - elif result: - self.app.stdout.write(result) - - -class PrepareImageFiles(command.Command): - """Generate files defining the images, tags and registry.""" - - auth_required = False - log = logging.getLogger(__name__ + ".PrepareImageFiles") - - def get_parser(self, prog_name): - parser = super(PrepareImageFiles, self).get_parser(prog_name) - try: - roles_file = utils.rel_or_abs_path( - constants.OVERCLOUD_ROLES_FILE, - constants.TRIPLEO_HEAT_TEMPLATES) - except exceptions.DeploymentError: - roles_file = None - defaults = kolla_builder.container_images_prepare_defaults() - - parser.add_argument( - "--template-file", - dest="template_file", - default=kolla_builder.DEFAULT_TEMPLATE_FILE, - metavar='', - help=_("YAML template file which the images config file will be " - "built from.\n" - "Default: %s") % kolla_builder.DEFAULT_TEMPLATE_FILE, - ) - parser.add_argument( - "--push-destination", - dest="push_destination", - metavar='', - help=_("Location of image registry to push images to. " - "If specified, a push_destination will be set for every " - "image entry."), - ) - parser.add_argument( - "--tag", - dest="tag", - default=defaults['tag'], - metavar='', - help=_("Override the default tag substitution. " - "If --tag-from-label is specified, " - "start discovery with this tag.\n" - "Default: %s") % defaults['tag'], - ) - parser.add_argument( - "--tag-from-label", - dest="tag_from_label", - metavar='', - help=_("Use the value of the specified label(s) to discover the " - "tag. Labels can be combined in a template format, " - "for example: {version}-{release}"), - ) - parser.add_argument( - "--namespace", - dest="namespace", - default=defaults['namespace'], - metavar='', - help=_("Override the default namespace substitution.\n" - "Default: %s") % defaults['namespace'], - ) - parser.add_argument( - "--prefix", - dest="prefix", - default=defaults['name_prefix'], - metavar='', - help=_("Override the default name prefix substitution.\n" - "Default: %s") % defaults['name_prefix'], - ) - parser.add_argument( - "--suffix", - dest="suffix", - default=defaults['name_suffix'], - metavar='', - help=_("Override the default name suffix substitution.\n" - "Default: %s") % defaults['name_suffix'], - ) - parser.add_argument( - '--set', - metavar='', - action='append', - help=_('Set the value of a variable in the template, even if it ' - 'has no dedicated argument such as "--suffix".') - ) - parser.add_argument( - "--exclude", - dest="excludes", - metavar='', - default=[], - action="append", - help=_("Pattern to match against resulting imagename entries to " - "exclude from the final output. Can be specified multiple " - "times."), - ) - parser.add_argument( - "--include", - dest="includes", - metavar='', - default=[], - action="append", - help=_("Pattern to match against resulting imagename entries to " - "include in final output. Can be specified multiple " - "times, entries not matching any --include will be " - "excluded. --exclude is ignored if --include is used."), - ) - parser.add_argument( - "--output-images-file", - dest="output_images_file", - metavar='', - help=_("File to write resulting image entries to, as well as " - "stdout. Any existing file will be overwritten."), - ) - parser.add_argument( - '--environment-file', '-e', metavar='', - action='append', dest='environment_files', - help=_('Environment files specifying which services are ' - 'containerized. Entries will be filtered to only contain ' - 'images used by containerized services. (Can be specified ' - 'more than once.)') - ) - parser.add_argument( - '--environment-directory', metavar='', - action='append', dest='environment_directories', - default=[os.path.expanduser(constants.DEFAULT_ENV_DIRECTORY)], - help=_('Environment file directories that are automatically ' - 'added to the update command. Entries will be filtered ' - 'to only contain images used by containerized services. ' - 'Can be specified more than once. Files in directories are ' - 'loaded in ascending sort order.') - ) - parser.add_argument( - "--output-env-file", - dest="output_env_file", - metavar='', - help=_("File to write heat environment file which specifies all " - "image parameters. Any existing file will be overwritten."), - ) - parser.add_argument( - '--roles-file', '-r', dest='roles_file', - default=roles_file, - help=_( - 'Roles file, overrides the default %s in the t-h-t templates ' - 'directory used for deployment. May be an ' - 'absolute path or the path relative to the templates dir.' - ) % constants.OVERCLOUD_ROLES_FILE - ) - parser.add_argument( - '--modify-role', - dest='modify_role', - help=_('Name of ansible role to run between every image upload ' - 'pull and push.') - ) - parser.add_argument( - '--modify-vars', - dest='modify_vars', - help=_('Ansible variable file containing variables to use when ' - 'invoking the role --modify-role.') - ) - return parser - - def parse_set_values(self, subs, set_values): - if not set_values: - return - for s in set_values: - try: - (n, v) = s.split(('='), 1) - subs[n] = v - except ValueError: - msg = _('Malformed --set(%s). ' - 'Use the variable=value format.') % s - raise oscexc.CommandError(msg) - - def take_action(self, parsed_args): - self.log.debug("take_action(%s)" % parsed_args) - self.log.warning("[DEPRECATED] This command has been deprecated and " - "replaced by the 'openstack tripleo container image " - "prepare' command.") - - roles_data = utils.fetch_roles_file(parsed_args.roles_file) or set() - - env = utils.build_prepare_env( - parsed_args.environment_files, - parsed_args.environment_directories - ) - - if roles_data: - service_filter = kolla_builder.build_service_filter( - env, roles_data) - else: - service_filter = None - mapping_args = { - 'tag': parsed_args.tag, - 'namespace': parsed_args.namespace, - 'name_prefix': parsed_args.prefix, - 'name_suffix': parsed_args.suffix, - } - self.parse_set_values(mapping_args, parsed_args.set) - pd = env.get('parameter_defaults', {}) - kolla_builder.set_neutron_driver(pd, mapping_args) - - output_images_file = (parsed_args.output_images_file - or 'container_images.yaml') - modify_role = None - modify_vars = None - append_tag = None - if parsed_args.modify_role: - modify_role = parsed_args.modify_role - append_tag = time.strftime('-modified-%Y%m%d%H%M%S') - if parsed_args.modify_vars: - with open(parsed_args.modify_vars) as m: - modify_vars = yaml.safe_load(m.read()) - - prepare_data = kolla_builder.container_images_prepare( - excludes=parsed_args.excludes, - includes=parsed_args.includes, - service_filter=service_filter, - push_destination=parsed_args.push_destination, - mapping_args=mapping_args, - output_env_file=parsed_args.output_env_file, - output_images_file=output_images_file, - tag_from_label=parsed_args.tag_from_label, - modify_role=modify_role, - modify_vars=modify_vars, - append_tag=append_tag, - template_file=parsed_args.template_file - ) - if parsed_args.output_env_file: - params = prepare_data[parsed_args.output_env_file] - output_env_file_expanded = os.path.expanduser( - parsed_args.output_env_file) - if os.path.exists(output_env_file_expanded): - self.log.warning("Output env file exists, " - "moving it to backup.") - shutil.move(output_env_file_expanded, - output_env_file_expanded + ".backup") - utils.safe_write(output_env_file_expanded, - build_env_file(params, self.app.command_options)) - - result = prepare_data[output_images_file] - result_str = yaml.safe_dump({'container_images': result}, - default_flow_style=False) - sys.stdout.write(result_str) - - if parsed_args.output_images_file: - utils.safe_write(parsed_args.output_images_file, result_str) - - -class DiscoverImageTag(command.Command): - """Discover the versioned tag for an image.""" - - auth_required = False - log = logging.getLogger(__name__ + ".DiscoverImageTag") - - def get_parser(self, prog_name): - parser = super(DiscoverImageTag, self).get_parser(prog_name) - parser.add_argument( - "--image", - dest="image", - metavar='', - required=True, - help=_("Fully qualified name of the image to discover the tag for " - "(Including registry and stable tag)."), - ) - parser.add_argument( - "--tag-from-label", - dest="tag_from_label", - metavar='', - help=_("Use the value of the specified label(s) to discover the " - "tag. Labels can be combined in a template format, " - "for example: {version}-{release}"), - ) - return parser - - def take_action(self, parsed_args): - self.log.debug("take_action(%s)" % parsed_args) - self.log.warning("[DEPRECATED] This command has been deprecated and " - "replaced by the 'openstack tripleo container image " - "prepare' command.") - - lock = processlock.ProcessLock() - uploader = image_uploader.ImageUploadManager([], lock=lock) - print(uploader.discover_image_tag( - image=parsed_args.image, - tag_from_label=parsed_args.tag_from_label - )) - - class TripleOContainerImagePush(command.Command): """Push specified image to registry."""