Fix stack preview
Don't execute translation rule for property that contains a GetParam function that can't be resolved at the moment. Such situation happens when we try to resolve get_param function that refer to parameter with None value. We receive parameter value from parent stack, where this value is a reference to some resource without resource_id, so this situation is legal for stack preview and we shouldn't fail. Note, that we can reproduce this behaviour only with resources with hidden parameters and overrided get_resource_id method, that returns None if resoruce creation has not been started yet. Change-Id: Ia1097940db983721c8b5116db7ee0a2c4c45339d Closes-Bug: #1548802
This commit is contained in:
parent
73fc655d1c
commit
a7d63111a3
@ -11,6 +11,9 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_utils import encodeutils
|
||||
|
||||
from heat.common import exception
|
||||
from heat.common.i18n import _
|
||||
from heat.engine.cfn import functions as cfn_funcs
|
||||
from heat.engine import function
|
||||
@ -154,7 +157,14 @@ class TranslationRule(object):
|
||||
if isinstance(param, hot_funcs.Removed):
|
||||
raise AttributeError(_('Property uses removed function.'))
|
||||
if isinstance(param, (hot_funcs.GetParam, cfn_funcs.ParamRef)):
|
||||
return function.resolve(param)
|
||||
try:
|
||||
return function.resolve(param)
|
||||
except exception.UserParameterMissing as ex:
|
||||
# We can't resolve parameter now. Abort translation.
|
||||
err_msg = encodeutils.exception_to_unicode(ex)
|
||||
raise AttributeError(
|
||||
_('Can not resolve parameter '
|
||||
'due to: %s') % err_msg)
|
||||
elif isinstance(param, list):
|
||||
return [resolve_param(param_item) for param_item in param]
|
||||
else:
|
||||
|
@ -16,6 +16,7 @@ import six
|
||||
|
||||
from heat.common import exception
|
||||
from heat.engine.cfn import functions as cfn_funcs
|
||||
from heat.engine import function
|
||||
from heat.engine.hot import functions as hot_funcs
|
||||
from heat.engine import parameters
|
||||
from heat.engine import properties
|
||||
@ -797,3 +798,40 @@ class TestTranslationRule(common.HeatTestCase):
|
||||
rule.execute_rule()
|
||||
|
||||
self.assertEqual([param], props.data.get('far'))
|
||||
|
||||
def test_property_no_translation_if_user_parameter_missing(self):
|
||||
"""Test translation in the case of missing parameter"""
|
||||
schema = {
|
||||
'source': properties.Schema(
|
||||
properties.Schema.STRING
|
||||
),
|
||||
'destination': properties.Schema(
|
||||
properties.Schema.STRING
|
||||
)}
|
||||
|
||||
class DummyStack(dict):
|
||||
@property
|
||||
def parameters(self):
|
||||
return mock.Mock()
|
||||
|
||||
param = hot_funcs.GetParam(DummyStack(),
|
||||
'get_param',
|
||||
'source_param')
|
||||
|
||||
param.parameters = {}
|
||||
|
||||
data = {'source': param, 'destination': ''}
|
||||
props = properties.Properties(schema, data,
|
||||
resolver=function.resolve)
|
||||
|
||||
rule = translation.TranslationRule(
|
||||
props,
|
||||
translation.TranslationRule.REPLACE,
|
||||
['destination'],
|
||||
value_path=['source'])
|
||||
|
||||
rule.execute_rule()
|
||||
|
||||
# ensure that translation rule was not applied
|
||||
self.assertEqual({'source': param, 'destination': ''},
|
||||
data)
|
||||
|
@ -186,3 +186,44 @@ outputs:
|
||||
|
||||
self.assertEqual('abc', res['properties']['value'])
|
||||
self.assertEqual([], res['required_by'])
|
||||
|
||||
def test_res_group_with_nested_template(self):
|
||||
main_template = '''
|
||||
heat_template_version: 2015-04-30
|
||||
resources:
|
||||
fixed_network:
|
||||
type: "OS::Neutron::Net"
|
||||
rg:
|
||||
type: "OS::Heat::ResourceGroup"
|
||||
properties:
|
||||
count: 1
|
||||
resource_def:
|
||||
type: nested.yaml
|
||||
properties:
|
||||
fixed_network_id: {get_resource: fixed_network}
|
||||
'''
|
||||
nested_template = '''
|
||||
heat_template_version: 2015-04-30
|
||||
|
||||
parameters:
|
||||
fixed_network_id:
|
||||
type: string
|
||||
resources:
|
||||
port:
|
||||
type: "OS::Neutron::Port"
|
||||
properties:
|
||||
network_id:
|
||||
get_param: fixed_network_id
|
||||
|
||||
'''
|
||||
stack_name = self._stack_rand_name()
|
||||
result = self.client.stacks.preview(
|
||||
disable_rollback=True,
|
||||
stack_name=stack_name,
|
||||
template=main_template,
|
||||
files={'nested.yaml': nested_template}).to_dict()
|
||||
# ensure that fixed network and port here
|
||||
self.assertEqual('fixed_network',
|
||||
result['resources'][0]['resource_name'])
|
||||
self.assertEqual('port',
|
||||
result['resources'][1][0][0]['resource_name'])
|
||||
|
Loading…
Reference in New Issue
Block a user