diff --git a/tripleoclient/tests/v1/overcloud_image/test_container_image.py b/tripleoclient/tests/v1/overcloud_image/test_container_image.py index c95187bad..4d294ffdc 100644 --- a/tripleoclient/tests/v1/overcloud_image/test_container_image.py +++ b/tripleoclient/tests/v1/overcloud_image/test_container_image.py @@ -74,6 +74,43 @@ class TestContainerImagePrepare(TestPluginV1): # Get the command object to test self.cmd = container_image.PrepareImageFiles(self.app, None) + def test_get_enabled_services(self): + temp = tempfile.mkdtemp() + self.addCleanup(shutil.rmtree, temp) + resource_registry = {'parameter_defaults': { + 'RoleDisabledViaEnvironmentCount': 0, + 'RoleOverwrittenViaEnvironmentServices': [ + 'OS::TripleO::Services::FromResourceRegistry' + ] + }} + roles_file = '/foo/roles_data.yaml' + 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_open_context = mock.mock_open(read_data=roles_yaml) + with mock.patch('six.moves.builtins.open', mock_open_context): + enabled_services = self.cmd.get_enabled_services(resource_registry, + roles_file) + mock_open_context.assert_called_once_with(roles_file) + self.assertEqual(set(['OS::TripleO::Services::AodhEvaluator', + 'OS::TripleO::Services::FromResourceRegistry']), + enabled_services) + @mock.patch('tripleo_common.image.kolla_builder.KollaImageBuilder') def test_container_image_prepare_noargs(self, mock_builder): arglist = [] @@ -106,8 +143,7 @@ class TestContainerImagePrepare(TestPluginV1): 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', - 'overcloud_containers.yaml.j2') + aodh_file = os.path.join(temp, 'docker', 'services', 'aodh.yaml') resource_registry = {'resource_registry': { 'OS::TripleO::Services::AodhEvaluator': aodh_file, diff --git a/tripleoclient/v1/container_image.py b/tripleoclient/v1/container_image.py index bcbffdd22..fc9f27e19 100644 --- a/tripleoclient/v1/container_image.py +++ b/tripleoclient/v1/container_image.py @@ -30,6 +30,8 @@ import yaml from tripleo_common.image import image_uploader from tripleo_common.image import kolla_builder +from tripleoclient import constants + class UploadImage(command.Command): """Push overcloud container images to registries.""" @@ -163,6 +165,8 @@ class PrepareImageFiles(command.Command): template_file = os.path.join(sys.prefix, 'share', 'tripleo-common', 'container-images', 'overcloud_containers.yaml.j2') + roles_file = os.path.join(constants.TRIPLEO_HEAT_TEMPLATES, + constants.OVERCLOUD_ROLES_FILE) parser.add_argument( "--template-file", dest="template_file", @@ -258,6 +262,12 @@ class PrepareImageFiles(command.Command): 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' + ) % constants.OVERCLOUD_ROLES_FILE + ) return parser def parse_set_values(self, subs, set_values): @@ -285,20 +295,42 @@ class PrepareImageFiles(command.Command): yaml.safe_dump({'parameter_defaults': params}, f, default_flow_style=False) - def build_service_filter(self, environment_files): + def get_enabled_services(self, environment, roles_file): + enabled_services = set() + try: + roles_data = yaml.safe_load(open(roles_file).read()) + except IOError: + return enabled_services + + parameter_defaults = environment.get('parameter_defaults', {}) + + for role in roles_data: + count = parameter_defaults.get('%sCount' % role['name'], + role.get('CountDefault', 0)) + if count > 0: + enabled_services.update( + parameter_defaults.get('%sServices' % role['name'], + role.get('ServicesDefault', []))) + + return enabled_services + + def build_service_filter(self, environment_files, roles_file): + # Do not filter unless asked for it if not environment_files: return None - service_filter = set() env_files, env = ( template_utils.process_multiple_environments_and_files( environment_files)) + enabled_services = self.get_enabled_services(env, roles_file) + containerized_services = set() for service, env_path in env.get('resource_registry', {}).items(): # Use the template path to determine if it represents a # containerized service if '/docker/services/' in env_path: - service_filter.add(service) - return service_filter + containerized_services.add(service) + + return containerized_services.intersection(enabled_services) def take_action(self, parsed_args): self.log.debug("take_action(%s)" % parsed_args) @@ -311,7 +343,7 @@ class PrepareImageFiles(command.Command): self.parse_set_values(subs, parsed_args.set) service_filter = self.build_service_filter( - parsed_args.environment_files) + parsed_args.environment_files, parsed_args.roles_file) def ffunc(entry): imagename = entry.get('imagename', '')