Merge "Return nested parameters for resource group."
This commit is contained in:
commit
03832aedee
|
@ -576,6 +576,13 @@ class Resource(status.ResourceStatus):
|
|||
"""
|
||||
return False
|
||||
|
||||
def get_nested_parameters_stack(self):
|
||||
"""Return the nested stack for schema validation.
|
||||
|
||||
Regular resources don't have such a thing.
|
||||
"""
|
||||
return
|
||||
|
||||
def has_hook(self, hook):
|
||||
# Clear the cache to make sure the data is up to date:
|
||||
self._data = None
|
||||
|
|
|
@ -454,6 +454,13 @@ class InstanceGroup(stack_resource.StackResource):
|
|||
},
|
||||
}
|
||||
|
||||
def get_nested_parameters_stack(self):
|
||||
"""Return a nested group of size 1 for validation."""
|
||||
child_template = self._create_template(1)
|
||||
params = self.child_params()
|
||||
name = "%s-%s" % (self.stack.name, self.name)
|
||||
return self._parse_nested_stack(name, child_template, params)
|
||||
|
||||
|
||||
def resource_mapping():
|
||||
return {
|
||||
|
|
|
@ -790,6 +790,14 @@ class ResourceGroup(stack_resource.StackResource):
|
|||
{},
|
||||
adopt_data=resource_data)
|
||||
|
||||
def get_nested_parameters_stack(self):
|
||||
"""Return a nested group of size 1 for validation."""
|
||||
names = self._resource_names(1)
|
||||
child_template = self._assemble_nested(names)
|
||||
params = self.child_params()
|
||||
name = "%s-%s" % (self.stack.name, self.name)
|
||||
return self._parse_nested_stack(name, child_template, params)
|
||||
|
||||
|
||||
def resource_mapping():
|
||||
return {
|
||||
|
|
|
@ -199,6 +199,24 @@ class StackResource(resource.Resource):
|
|||
|
||||
return self.nested().preview_resources()
|
||||
|
||||
def get_nested_parameters_stack(self):
|
||||
"""Return a stack for schema validation.
|
||||
|
||||
This returns a stack to be introspected for building parameters schema.
|
||||
It can be customized by subclass to return a restricted version of what
|
||||
will be running.
|
||||
"""
|
||||
try:
|
||||
child_template = self.child_template()
|
||||
params = self.child_params()
|
||||
except NotImplementedError:
|
||||
class_name = reflection.get_class_name(self, fully_qualified=False)
|
||||
LOG.warning("Nested parameters of '%s' not yet "
|
||||
"implemented", class_name)
|
||||
return
|
||||
name = "%s-%s" % (self.stack.name, self.name)
|
||||
return self._parse_nested_stack(name, child_template, params)
|
||||
|
||||
def _parse_child_template(self, child_template, child_env):
|
||||
parsed_child_template = child_template
|
||||
if isinstance(parsed_child_template, template.Template):
|
||||
|
|
|
@ -1238,36 +1238,7 @@ class EngineService(service.ServiceBase):
|
|||
result['ParameterGroups'] = param_groups.parameter_groups
|
||||
|
||||
if show_nested:
|
||||
# Note preview_resources is needed here to build the tree
|
||||
# of nested resources/stacks in memory, otherwise the
|
||||
# nested/has_nested() tests below won't work
|
||||
stack.preview_resources()
|
||||
|
||||
def nested_params(stk):
|
||||
n_result = {}
|
||||
for r in stk:
|
||||
if stk[r].has_nested():
|
||||
n_params = stk[r].nested().parameters.map(
|
||||
api.format_validate_parameter,
|
||||
filter_func=filter_parameter)
|
||||
n_result[r] = {
|
||||
'Type': stk[r].type(),
|
||||
'Description': stk[r].nested().t.get(
|
||||
'Description', ''),
|
||||
'Parameters': n_params
|
||||
}
|
||||
|
||||
# Add parameter_groups if it is present in nested stack
|
||||
nested_pg = parameter_groups.ParameterGroups(
|
||||
stk[r].nested().t)
|
||||
if nested_pg.parameter_groups:
|
||||
n_result[r].update({'ParameterGroups':
|
||||
nested_pg.parameter_groups})
|
||||
|
||||
n_result[r].update(nested_params(stk[r].nested()))
|
||||
return {'NestedParameters': n_result} if n_result else {}
|
||||
|
||||
result.update(nested_params(stack))
|
||||
result.update(stack.get_nested_parameters(filter_parameter))
|
||||
|
||||
result['Environment'] = tmpl.env.user_env_as_dict()
|
||||
return result
|
||||
|
|
|
@ -32,6 +32,7 @@ from heat.common import exception
|
|||
from heat.common.i18n import _
|
||||
from heat.common import identifier
|
||||
from heat.common import lifecycle_plugin_utils
|
||||
from heat.engine import api
|
||||
from heat.engine import dependencies
|
||||
from heat.engine import environment
|
||||
from heat.engine import event
|
||||
|
@ -1051,6 +1052,36 @@ class Stack(collections.Mapping):
|
|||
return [resource.preview()
|
||||
for resource in six.itervalues(self.resources)]
|
||||
|
||||
def get_nested_parameters(self, filter_func):
|
||||
"""Return nested parameters schema, if any.
|
||||
|
||||
This introspects the resources to return the parameters of the nested
|
||||
stacks. It uses the `get_nested_parameters_stack` API to build the
|
||||
stack.
|
||||
"""
|
||||
result = {}
|
||||
for name, rsrc in six.iteritems(self.resources):
|
||||
nested = rsrc.get_nested_parameters_stack()
|
||||
if nested is None:
|
||||
continue
|
||||
nested_params = nested.parameters.map(
|
||||
api.format_validate_parameter,
|
||||
filter_func=filter_func)
|
||||
params = {
|
||||
'Type': rsrc.type(),
|
||||
'Description': nested.t.get('Description', ''),
|
||||
'Parameters': nested_params
|
||||
}
|
||||
|
||||
# Add parameter_groups if it is present in nested stack
|
||||
nested_pg = param_groups.ParameterGroups(nested.t)
|
||||
if nested_pg.parameter_groups:
|
||||
params.update({'ParameterGroups': nested_pg.parameter_groups})
|
||||
|
||||
params.update(nested.get_nested_parameters(filter_func))
|
||||
result[name] = params
|
||||
return {'NestedParameters': result} if result else {}
|
||||
|
||||
def _store_resources(self):
|
||||
for r in reversed(self.dependencies):
|
||||
if r.action == r.INIT:
|
||||
|
|
|
@ -2039,3 +2039,69 @@ parameter_groups:
|
|||
self.ctx, t, {})
|
||||
self.assertEqual(exception.InvalidSchemaError,
|
||||
exc.exc_info[0])
|
||||
|
||||
def test_validate_empty_resource_group(self):
|
||||
engine = service.EngineService('a', 't')
|
||||
params = {
|
||||
"resource_registry": {
|
||||
"OS::Test::TestResource": "https://server.test/nested.template"
|
||||
}
|
||||
}
|
||||
root_template_str = '''
|
||||
heat_template_version: 2015-10-15
|
||||
parameters:
|
||||
test_root_param:
|
||||
type: string
|
||||
resources:
|
||||
Group:
|
||||
type: OS::Heat::ResourceGroup
|
||||
properties:
|
||||
count: 0
|
||||
resource_def:
|
||||
type: OS::Test::TestResource
|
||||
'''
|
||||
nested_template_str = '''
|
||||
heat_template_version: 2015-10-15
|
||||
parameters:
|
||||
test_param:
|
||||
type: string
|
||||
'''
|
||||
root_template = template_format.parse(root_template_str)
|
||||
|
||||
self.patchobject(urlfetch, 'get')
|
||||
urlfetch.get.return_value = nested_template_str
|
||||
|
||||
res = dict(engine.validate_template(self.ctx, root_template,
|
||||
params, show_nested=True))
|
||||
expected = {
|
||||
'Description': 'No description',
|
||||
'Environment': {
|
||||
'event_sinks': [],
|
||||
'parameter_defaults': {},
|
||||
'parameters': {},
|
||||
'resource_registry': {
|
||||
'OS::Test::TestResource':
|
||||
'https://server.test/nested.template',
|
||||
'resources': {}}},
|
||||
'NestedParameters': {
|
||||
'Group': {
|
||||
'Description': 'No description',
|
||||
'Parameters': {},
|
||||
'Type': 'OS::Heat::ResourceGroup',
|
||||
'NestedParameters': {
|
||||
'0': {
|
||||
'Description': 'No description',
|
||||
'Parameters': {
|
||||
'test_param': {
|
||||
'Description': '',
|
||||
'Label': 'test_param',
|
||||
'NoEcho': 'false',
|
||||
'Type': 'String'}},
|
||||
'Type': 'OS::Test::TestResource'}}}},
|
||||
'Parameters': {
|
||||
'test_root_param': {
|
||||
'Description': '',
|
||||
'Label': 'test_root_param',
|
||||
'NoEcho': 'false',
|
||||
'Type': 'String'}}}
|
||||
self.assertEqual(expected, res)
|
||||
|
|
|
@ -322,6 +322,37 @@ outputs:
|
|||
updated_rand = self._stack_output(stack1, 'random1')
|
||||
self.assertNotEqual(initial_rand, updated_rand)
|
||||
|
||||
def test_validation(self):
|
||||
resource_group = '''
|
||||
heat_template_version: 2016-10-14
|
||||
|
||||
parameters:
|
||||
the_count:
|
||||
type: number
|
||||
|
||||
resources:
|
||||
|
||||
the_group:
|
||||
type: OS::Heat::ResourceGroup
|
||||
properties:
|
||||
count: {get_param: the_count}
|
||||
resource_def:
|
||||
type: OS::Heat::RandomString
|
||||
'''
|
||||
ret = self.client.stacks.validate(template=resource_group)
|
||||
expected = {'Description': 'No description',
|
||||
'Environment': {'event_sinks': [],
|
||||
'parameter_defaults': {},
|
||||
'parameters': {},
|
||||
'resource_registry': {u'resources': {}}},
|
||||
'Parameters': {
|
||||
'the_count': {'Description': '',
|
||||
'Label': 'the_count',
|
||||
'NoEcho': 'false',
|
||||
'Type': 'Number'}}}
|
||||
|
||||
self.assertEqual(expected, ret)
|
||||
|
||||
|
||||
class ResourceGroupTestNullParams(functional_base.FunctionalTestsBase):
|
||||
template = '''
|
||||
|
|
Loading…
Reference in New Issue