Load all templates for generating parameter schema

To be able to handle parameter defaults properly, we need to load all
possible templates when merging the environments, to generate an
approximate schema.

Closes-Bug: #1669571
Change-Id: Idab781d3e6af92990c357a727aa60ec0aa8f5f05
This commit is contained in:
Thomas Herve 2017-05-02 16:05:05 +02:00
parent 37625840df
commit 7221cd2eba
3 changed files with 41 additions and 4 deletions

View File

@ -696,7 +696,7 @@ class EngineService(service.ServiceBase):
else:
tmpl = templatem.Template(template, files=files)
env_util.merge_environments(environment_files, files, params,
tmpl.param_schemata())
tmpl.all_param_schemata(files))
tmpl.env = environment.Environment(params)
self._validate_new_stack(cnxt, stack_name, tmpl)
@ -891,7 +891,7 @@ class EngineService(service.ServiceBase):
new_files.update(files or {})
tmpl = templatem.Template(new_template, files=new_files)
env_util.merge_environments(environment_files, files, params,
tmpl.param_schemata())
tmpl.all_param_schemata(files))
existing_env = current_stack.env.env_as_dict()
existing_params = existing_env[env_fmt.PARAMETERS]
clear_params = set(args.get(rpc_api.PARAM_CLEAR_PARAMETERS, []))
@ -912,7 +912,7 @@ class EngineService(service.ServiceBase):
else:
tmpl = templatem.Template(template, files=files)
env_util.merge_environments(environment_files, files, params,
tmpl.param_schemata())
tmpl.all_param_schemata(files))
tmpl.env = environment.Environment(params)
max_resources = cfg.CONF.max_resources_per_stack
@ -1221,7 +1221,7 @@ class EngineService(service.ServiceBase):
tmpl = templatem.Template(template, files=files)
env_util.merge_environments(environment_files, files, params,
tmpl.param_schemata())
tmpl.all_param_schemata(files))
tmpl.env = environment.Environment(params)
try:
self._validate_template(cnxt, tmpl)

View File

@ -23,6 +23,7 @@ from stevedore import extension
from heat.common import exception
from heat.common.i18n import _
from heat.common import template_format
from heat.engine import conditions
from heat.engine import environment
from heat.engine import function
@ -197,6 +198,21 @@ class Template(collections.Mapping):
"""Return a dict of parameters.Schema objects for the parameters."""
pass
def all_param_schemata(self, files):
schema = {}
files = files if files is not None else {}
for f in files.values():
try:
data = template_format.parse(f)
except ValueError:
continue
else:
sub_tmpl = Template(data)
schema.update(sub_tmpl.param_schemata())
# Parent template has precedence, so update the schema last.
schema.update(self.param_schemata())
return schema
@abc.abstractmethod
def get_section_name(self, section):
"""Return a correct section name."""

View File

@ -1016,6 +1016,27 @@ class ValidateTest(common.HeatTestCase):
res['Parameters']['net_name']['Value'])
self.assertNotIn('Default', res['Parameters']['net_name'])
def test_validate_parameters_nested(self):
t = template_format.parse(test_template_allowed_integers)
other_template = test_template_no_default.replace(
'net_name', 'net_name2')
files = {'env1': 'parameter_defaults:\n net_name: net1',
'env2': 'parameter_defaults:'
'\n net_name: net2'
'\n net_name2: net3',
'tmpl1.yaml': test_template_no_default,
'tmpl2.yaml': other_template}
params = {'parameters': {}, 'parameter_defaults': {}}
self.engine.validate_template(
self.ctx, t,
params=params,
files=files, environment_files=['env1', 'env2'])
self.assertEqual('net2', params['parameter_defaults']['net_name'])
self.assertEqual('net3', params['parameter_defaults']['net_name2'])
def test_validate_hot_empty_parameters_valid(self):
t = template_format.parse(
"""