Merge "Filter container images by deployed services"

This commit is contained in:
Jenkins 2017-08-21 09:13:07 +00:00 committed by Gerrit Code Review
commit 930f64cbe7
3 changed files with 65 additions and 5 deletions

View File

@ -0,0 +1,5 @@
---
features:
- The "openstack overcloud container image prepare" command can now filter
the image list by the containerized services being deployed. This is done by
specifying the heat environment files which enable containerized services.

View File

@ -97,13 +97,23 @@ class TestContainerImagePrepare(TestPluginV1):
) )
@mock.patch('tripleo_common.image.kolla_builder.KollaImageBuilder') @mock.patch('tripleo_common.image.kolla_builder.KollaImageBuilder')
def test_container_image_prepare(self, mock_builder): @mock.patch('heatclient.common.template_utils.'
'process_multiple_environments_and_files')
def test_container_image_prepare(self, pmef, mock_builder):
temp = tempfile.mkdtemp() temp = tempfile.mkdtemp()
self.addCleanup(shutil.rmtree, temp) self.addCleanup(shutil.rmtree, temp)
images_file = os.path.join(temp, 'overcloud_containers.yaml') images_file = os.path.join(temp, 'overcloud_containers.yaml')
env_file = os.path.join(temp, 'containers_env.yaml') env_file = os.path.join(temp, 'containers_env.yaml')
tmpl_file = os.path.join(temp, 'overcloud_containers.yaml.j2') tmpl_file = os.path.join(temp, 'overcloud_containers.yaml.j2')
aodh_file = os.path.join(temp, 'docker', 'services',
'overcloud_containers.yaml.j2')
resource_registry = {'resource_registry': {
'OS::TripleO::Services::AodhEvaluator': aodh_file,
'OS::TripleO::Services::AodhApi': aodh_file
}}
pmef.return_value = None, resource_registry
arglist = [ arglist = [
'--template-file', '--template-file',
@ -126,6 +136,8 @@ class TestContainerImagePrepare(TestPluginV1):
'ceph_image=mydaemon', 'ceph_image=mydaemon',
'--set', '--set',
'ceph_tag=mytag', 'ceph_tag=mytag',
'-e',
'environment/docker.yaml'
] ]
self.cmd.app.command_options = arglist self.cmd.app.command_options = arglist
verifylist = [] verifylist = []
@ -133,9 +145,16 @@ class TestContainerImagePrepare(TestPluginV1):
cift.return_value = [{ cift.return_value = [{
'imagename': 'tripleo/os-aodh-apifoo:passed-ci', 'imagename': 'tripleo/os-aodh-apifoo:passed-ci',
'params': ['DockerAodhApiImage', 'DockerAodhConfigImage'], 'params': ['DockerAodhApiImage', 'DockerAodhConfigImage'],
'services': [
'OS::TripleO::Services::AodhApi',
'OS::TripleO::Services::AodhEvaluator',
],
}, { }, {
'imagename': 'tripleo/os-heat-apifoo:passed-ci', 'imagename': 'tripleo/os-aodh-evaluatorfoo:passed-ci',
'params': ['DockerHeatApiImage'], 'params': ['DockerAodhEvaluatorImage'],
'services': [
'OS::TripleO::Services::AodhEvaluator',
],
}] }]
mock_builder.return_value.container_images_from_template = cift mock_builder.return_value.container_images_from_template = cift
@ -145,6 +164,7 @@ class TestContainerImagePrepare(TestPluginV1):
self.cmd.take_action(parsed_args) self.cmd.take_action(parsed_args)
mock_builder.assert_called_once_with([tmpl_file]) mock_builder.assert_called_once_with([tmpl_file])
pmef.assert_called_once_with(['environment/docker.yaml'])
cift.assert_called_once_with( cift.assert_called_once_with(
filter=mock.ANY, filter=mock.ANY,
name_prefix='os-', name_prefix='os-',
@ -159,14 +179,15 @@ class TestContainerImagePrepare(TestPluginV1):
'container_images': [{ 'container_images': [{
'imagename': 'tripleo/os-aodh-apifoo:passed-ci', 'imagename': 'tripleo/os-aodh-apifoo:passed-ci',
}, { }, {
'imagename': 'tripleo/os-heat-apifoo:passed-ci', 'imagename': 'tripleo/os-aodh-evaluatorfoo:passed-ci',
}] }]
} }
env_data = { env_data = {
'parameter_defaults': { 'parameter_defaults': {
'DockerAodhApiImage': 'tripleo/os-aodh-apifoo:passed-ci', 'DockerAodhApiImage': 'tripleo/os-aodh-apifoo:passed-ci',
'DockerAodhConfigImage': 'tripleo/os-aodh-apifoo:passed-ci', 'DockerAodhConfigImage': 'tripleo/os-aodh-apifoo:passed-ci',
'DockerHeatApiImage': 'tripleo/os-heat-apifoo:passed-ci', 'DockerAodhEvaluatorImage':
'tripleo/os-aodh-evaluatorfoo:passed-ci'
} }
} }
with open(images_file) as f: with open(images_file) as f:

View File

@ -21,6 +21,7 @@ import re
import sys import sys
import tempfile import tempfile
from heatclient.common import template_utils
from osc_lib.command import command from osc_lib.command import command
from osc_lib import exceptions as oscexc from osc_lib import exceptions as oscexc
from osc_lib.i18n import _ from osc_lib.i18n import _
@ -243,6 +244,14 @@ class PrepareImageFiles(command.Command):
help=_("File to write resulting image entries to, as well as " help=_("File to write resulting image entries to, as well as "
"stdout. Any existing file will be overwritten."), "stdout. Any existing file will be overwritten."),
) )
parser.add_argument(
'--service-environment-file', '-e', metavar='<file path>',
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( parser.add_argument(
"--env-file", "--env-file",
dest="env_file", dest="env_file",
@ -277,6 +286,21 @@ class PrepareImageFiles(command.Command):
yaml.safe_dump({'parameter_defaults': params}, f, yaml.safe_dump({'parameter_defaults': params}, f,
default_flow_style=False) default_flow_style=False)
def build_service_filter(self, environment_files):
if not environment_files:
return None
service_filter = set()
env_files, env = (
template_utils.process_multiple_environments_and_files(
environment_files))
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
def take_action(self, parsed_args): def take_action(self, parsed_args):
self.log.debug("take_action(%s)" % parsed_args) self.log.debug("take_action(%s)" % parsed_args)
subs = { subs = {
@ -287,11 +311,19 @@ class PrepareImageFiles(command.Command):
} }
self.parse_set_values(subs, parsed_args.set) self.parse_set_values(subs, parsed_args.set)
service_filter = self.build_service_filter(
parsed_args.environment_files)
def ffunc(entry): def ffunc(entry):
imagename = entry.get('imagename', '') imagename = entry.get('imagename', '')
for p in parsed_args.excludes: for p in parsed_args.excludes:
if re.search(p, imagename): if re.search(p, imagename):
return None return None
if service_filter is not None:
# check the entry is for a service being deployed
image_services = set(entry.get('services', []))
if not service_filter.intersection(image_services):
return None
if parsed_args.pull_source: if parsed_args.pull_source:
entry['pull_source'] = parsed_args.pull_source entry['pull_source'] = parsed_args.pull_source
if parsed_args.push_destination: if parsed_args.push_destination:
@ -307,6 +339,8 @@ class PrepareImageFiles(command.Command):
if 'params' in entry: if 'params' in entry:
for p in entry.pop('params'): for p in entry.pop('params'):
params[p] = imagename params[p] = imagename
if 'services' in entry:
del(entry['services'])
if parsed_args.env_file: if parsed_args.env_file:
self.write_env_file(params, parsed_args.env_file) self.write_env_file(params, parsed_args.env_file)