Make cfn functions inherit from HOT

HOT is our canonical native format, so define the cfn intrinsic functions
in terms of the HOT functions instead of the other way around. Ensure each
function has a consistently-formatted docstring appropriate to its template
type.

Change-Id: I743446bdef3fd7472537db75bf9e0fbfb164e36a
This commit is contained in:
Zane Bitter 2016-09-08 17:00:48 -04:00
parent 0327c339f5
commit 8262265292
9 changed files with 333 additions and 256 deletions

View File

@ -12,7 +12,6 @@
# under the License.
import collections
import itertools
from oslo_serialization import jsonutils
import six
@ -21,6 +20,7 @@ from heat.api.aws import utils as aws_utils
from heat.common import exception
from heat.common.i18n import _
from heat.engine import function
from heat.engine.hot import functions as hot_funcs
class FindInMap(function.Function):
@ -88,31 +88,6 @@ class ParamRef(function.Function):
key='unknown')
class ResourceRef(function.Function):
"""A function for resolving resource references.
Takes the form::
{ "Ref" : "<resource_name>" }
"""
def _resource(self, path='unknown'):
resource_name = function.resolve(self.args)
try:
return self.stack[resource_name]
except KeyError:
raise exception.InvalidTemplateReference(resource=resource_name,
key=path)
def dependencies(self, path):
return itertools.chain(super(ResourceRef, self).dependencies(path),
[self._resource(path)])
def result(self):
return self._resource().FnGetRefId()
def Ref(stack, fn_name, args):
"""A function for resolving parameters or resource references.
@ -125,26 +100,21 @@ def Ref(stack, fn_name, args):
{ "Ref" : "<resource_name>" }
"""
if args in stack:
RefClass = ResourceRef
RefClass = hot_funcs.GetResource
else:
RefClass = ParamRef
return RefClass(stack, fn_name, args)
class GetAtt(function.Function):
class GetAtt(hot_funcs.GetAttThenSelect):
"""A function for resolving resource attributes.
Takes the form::
{ "Fn::GetAtt" : [ "<resource_name>",
"<attribute_name" ] }
"<attribute_name>" ] }
"""
def __init__(self, stack, fn_name, args):
super(GetAtt, self).__init__(stack, fn_name, args)
self._resource_name, self._attribute = self._parse_args()
def _parse_args(self):
try:
resource_name, attribute = self.args
@ -152,62 +122,7 @@ class GetAtt(function.Function):
raise ValueError(_('Arguments to "%s" must be of the form '
'[resource_name, attribute]') % self.fn_name)
return resource_name, attribute
def _resource(self, path='unknown'):
resource_name = function.resolve(self._resource_name)
try:
return self.stack[resource_name]
except KeyError:
raise exception.InvalidTemplateReference(resource=resource_name,
key=path)
def dep_attrs(self, resource_name):
if self._resource().name == resource_name:
attrs = [function.resolve(self._attribute)]
else:
attrs = []
return itertools.chain(super(GetAtt, self).dep_attrs(resource_name),
attrs)
def dependencies(self, path):
return itertools.chain(super(GetAtt, self).dependencies(path),
[self._resource(path)])
def _allow_without_attribute_name(self):
return False
def validate(self):
super(GetAtt, self).validate()
res = self._resource()
if self._allow_without_attribute_name():
# if allow without attribute_name, then don't check
# when attribute_name is None
if self._attribute is None:
return
attr = function.resolve(self._attribute)
from heat.engine import resource
if (type(res).get_attribute == resource.Resource.get_attribute and
attr not in res.attributes_schema):
raise exception.InvalidTemplateAttribute(
resource=self._resource_name, key=attr)
def result(self):
attribute = function.resolve(self._attribute)
r = self._resource()
if r.action in (r.CREATE, r.ADOPT, r.SUSPEND, r.RESUME,
r.UPDATE, r.ROLLBACK, r.SNAPSHOT, r.CHECK):
return r.FnGetAtt(attribute)
# NOTE(sirushtim): Add r.INIT to states above once convergence
# is the default.
elif r.stack.has_cache_data(r.name) and r.action == r.INIT:
return r.FnGetAtt(attribute)
else:
return None
return resource_name, attribute, []
class Select(function.Function):
@ -217,7 +132,7 @@ class Select(function.Function):
{ "Fn::Select" : [ "<index>", [ "<value_1>", "<value_2>", ... ] ] }
Takes the form (for a map lookup)::
or (for a map lookup)::
{ "Fn::Select" : [ "<index>", { "<key_1>": "<value_1>", ... } ] }
@ -283,7 +198,7 @@ class Select(function.Function):
self.fn_name)
class Join(function.Function):
class Join(hot_funcs.Join):
"""A function for joining strings.
Takes the form::
@ -295,47 +210,6 @@ class Join(function.Function):
"<string_1><delim><string_2><delim>..."
"""
def __init__(self, stack, fn_name, args):
super(Join, self).__init__(stack, fn_name, args)
example = '"%s" : [ " ", [ "str1", "str2"]]' % self.fn_name
fmt_data = {'fn_name': self.fn_name,
'example': example}
if not isinstance(self.args, list):
raise TypeError(_('Incorrect arguments to "%(fn_name)s" '
'should be: %(example)s') % fmt_data)
try:
self._delim, self._strings = self.args
except ValueError:
raise ValueError(_('Incorrect arguments to "%(fn_name)s" '
'should be: %(example)s') % fmt_data)
def result(self):
strings = function.resolve(self._strings)
if strings is None:
strings = []
if (isinstance(strings, six.string_types) or
not isinstance(strings, collections.Sequence)):
raise TypeError(_('"%s" must operate on a list') % self.fn_name)
delim = function.resolve(self._delim)
if not isinstance(delim, six.string_types):
raise TypeError(_('"%s" delimiter must be a string') %
self.fn_name)
def ensure_string(s):
if s is None:
return ''
if not isinstance(s, six.string_types):
raise TypeError(
_('Items to join must be strings not %s'
) % (repr(s)[:200]))
return s
return delim.join(ensure_string(s) for s in strings)
class Split(function.Function):
"""A function for splitting strings.
@ -379,7 +253,7 @@ class Split(function.Function):
return strings.split(self._delim)
class Replace(function.Function):
class Replace(hot_funcs.Replace):
"""A function for performing string substitutions.
Takes the form::
@ -398,15 +272,6 @@ class Replace(function.Function):
performed is otherwise undefined.
"""
def __init__(self, stack, fn_name, args):
super(Replace, self).__init__(stack, fn_name, args)
self._mapping, self._string = self._parse_args()
if not isinstance(self._mapping,
(collections.Mapping, function.Function)):
raise TypeError(_('"%s" parameters must be a mapping') %
self.fn_name)
def _parse_args(self):
example = ('{"%s": '
@ -427,39 +292,6 @@ class Replace(function.Function):
else:
return mapping, string
def result(self):
template = function.resolve(self._string)
mapping = function.resolve(self._mapping)
if not isinstance(template, six.string_types):
raise TypeError(_('"%s" template must be a string') % self.fn_name)
if not isinstance(mapping, collections.Mapping):
raise TypeError(_('"%s" params must be a map') % self.fn_name)
def replace(string, change):
placeholder, value = change
if not isinstance(placeholder, six.string_types):
raise TypeError(_('"%s" param placeholders must be strings') %
self.fn_name)
if value is None:
value = ''
if not isinstance(value,
(six.string_types, six.integer_types,
float, bool)):
raise TypeError(_('"%s" params must be strings or numbers') %
self.fn_name)
return string.replace(placeholder, six.text_type(value))
mapping = collections.OrderedDict(sorted(mapping.items(),
key=lambda t: len(t[0]),
reverse=True))
return six.moves.reduce(replace, six.iteritems(mapping), template)
class Base64(function.Function):
"""A placeholder function for converting to base64.
@ -535,7 +367,7 @@ class MemberListToMap(function.Function):
valuename=self._valuename)
class ResourceFacade(function.Function):
class ResourceFacade(hot_funcs.ResourceFacade):
"""A function for retrieving data in a parent provider template.
A function for obtaining data from the facade resource from within the
@ -555,40 +387,46 @@ class ResourceFacade(function.Function):
'Metadata', 'DeletionPolicy', 'UpdatePolicy'
)
def __init__(self, stack, fn_name, args):
super(ResourceFacade, self).__init__(stack, fn_name, args)
if self.args not in self._RESOURCE_ATTRIBUTES:
fmt_data = {'fn_name': self.fn_name,
'allowed': ', '.join(self._RESOURCE_ATTRIBUTES)}
raise ValueError(_('Incorrect arguments to "%(fn_name)s" '
'should be one of: %(allowed)s') % fmt_data)
def result(self):
attr = function.resolve(self.args)
if attr == self.METADATA:
return self.stack.parent_resource.metadata_get()
elif attr == self.UPDATE_POLICY:
up = self.stack.parent_resource.t._update_policy or {}
return function.resolve(up)
elif attr == self.DELETION_POLICY:
return self.stack.parent_resource.t.deletion_policy()
class Not(function.Function):
"""A function acts as a NOT operator.
class If(hot_funcs.If):
"""A function to return corresponding value based on condition evaluation.
Takes the form::
{ "Fn::Not" : [condition] }
{ "Fn::If" : [ "<condition_name>",
"<value_if_true>",
"<value_if_false>" ] }
The value_if_true to be returned if the specified condition evaluates
to true, the value_if_false to be returned if the specified condition
evaluates to false.
"""
class Equals(hot_funcs.Equals):
"""A function for comparing whether two values are equal.
Takes the form::
{ "Fn::Equals" : [ "<value_1>", "<value_2>" ] }
The value can be any type that you want to compare. Returns true
if the two values are equal or false if they aren't.
"""
class Not(hot_funcs.Not):
"""A function that acts as a NOT operator on a condition.
Takes the form::
{ "Fn::Not" : [ "<condition>" ] }
Returns true for a condition that evaluates to false or
returns false for a condition that evaluates to true.
"""
def __init__(self, stack, fn_name, args):
super(Not, self).__init__(stack, fn_name, args)
def _get_condition(self):
try:
if (not self.args or
not isinstance(self.args, collections.Sequence) or
@ -596,7 +434,7 @@ class Not(function.Function):
raise ValueError()
if len(self.args) != 1:
raise ValueError()
self.condition = self.args[0]
return self.args[0]
except ValueError:
msg = _('Arguments to "%s" must be of the form: '
'[condition]')
@ -609,3 +447,29 @@ class Not(function.Function):
'after resolved the value is: %s')
raise ValueError(msg % resolved_value)
return not resolved_value
class And(hot_funcs.And):
"""A function that acts as an AND operator on conditions.
Takes the form::
{ "Fn::And" : [ "<condition_1>", "<condition_2>", ... ] }
Returns true if all the specified conditions evaluate to true, or returns
false if any one of the conditions evaluates to false. The minimum number
of conditions that you can include is 2.
"""
class Or(hot_funcs.Or):
"""A function that acts as an OR operator on conditions.
Takes the form::
{ "Fn::Or" : [ "<condition_1>", "<condition_2>", ... ] }
Returns true if any one of the specified conditions evaluate to true,
or returns false if all of the conditions evaluates to false. The minimum
number of conditions that you can include is 2.
"""

View File

@ -17,7 +17,6 @@ from heat.common import exception
from heat.common.i18n import _
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 rsrc_defn
from heat.engine import template_common
@ -212,16 +211,16 @@ class CfnTemplate(CfnTemplateBase):
'Fn::Base64': cfn_funcs.Base64,
'Fn::MemberListToMap': cfn_funcs.MemberListToMap,
'Fn::ResourceFacade': cfn_funcs.ResourceFacade,
'Fn::If': hot_funcs.If,
'Fn::If': cfn_funcs.If,
}
condition_functions = {
'Fn::Equals': hot_funcs.Equals,
'Fn::Equals': cfn_funcs.Equals,
'Ref': cfn_funcs.ParamRef,
'Fn::FindInMap': cfn_funcs.FindInMap,
'Fn::Not': cfn_funcs.Not,
'Fn::And': hot_funcs.And,
'Fn::Or': hot_funcs.Or
'Fn::And': cfn_funcs.And,
'Fn::Or': cfn_funcs.Or
}
def __init__(self, tmpl, template_id=None, files=None, env=None):

View File

@ -24,7 +24,6 @@ from yaql.language import exceptions
from heat.common import exception
from heat.common.i18n import _
from heat.engine import attributes
from heat.engine.cfn import functions as cfn_funcs
from heat.engine import function
opts = [
@ -113,7 +112,32 @@ class GetParam(function.Function):
return ''
class GetAttThenSelect(cfn_funcs.GetAtt):
class GetResource(function.Function):
"""A function for resolving resource references.
Takes the form::
get_resource: <resource_name>
"""
def _resource(self, path='unknown'):
resource_name = function.resolve(self.args)
try:
return self.stack[resource_name]
except KeyError:
raise exception.InvalidTemplateReference(resource=resource_name,
key=path)
def dependencies(self, path):
return itertools.chain(super(GetResource, self).dependencies(path),
[self._resource(path)])
def result(self):
return self._resource().FnGetRefId()
class GetAttThenSelect(function.Function):
"""A function for resolving resource attributes.
Takes the form::
@ -125,6 +149,13 @@ class GetAttThenSelect(cfn_funcs.GetAtt):
- ...
"""
def __init__(self, stack, fn_name, args):
super(GetAttThenSelect, self).__init__(stack, fn_name, args)
(self._resource_name,
self._attribute,
self._path_components) = self._parse_args()
def _parse_args(self):
if (not isinstance(self.args, collections.Sequence) or
isinstance(self.args, six.string_types)):
@ -136,12 +167,65 @@ class GetAttThenSelect(cfn_funcs.GetAtt):
'[resource_name, attribute, (path), ...]') %
self.fn_name)
self._path_components = self.args[2:]
return self.args[0], self.args[1], self.args[2:]
return tuple(self.args[:2])
def _resource(self, path='unknown'):
resource_name = function.resolve(self._resource_name)
try:
return self.stack[resource_name]
except KeyError:
raise exception.InvalidTemplateReference(resource=resource_name,
key=path)
def dep_attrs(self, resource_name):
if self._resource().name == resource_name:
attrs = [function.resolve(self._attribute)]
else:
attrs = []
return itertools.chain(super(GetAttThenSelect,
self).dep_attrs(resource_name),
attrs)
def dependencies(self, path):
return itertools.chain(super(GetAttThenSelect,
self).dependencies(path),
[self._resource(path)])
def _allow_without_attribute_name(self):
return False
def validate(self):
super(GetAttThenSelect, self).validate()
res = self._resource()
if self._allow_without_attribute_name():
# if allow without attribute_name, then don't check
# when attribute_name is None
if self._attribute is None:
return
attr = function.resolve(self._attribute)
from heat.engine import resource
if (type(res).get_attribute == resource.Resource.get_attribute and
attr not in res.attributes_schema):
raise exception.InvalidTemplateAttribute(
resource=self._resource_name, key=attr)
def result(self):
attribute = super(GetAttThenSelect, self).result()
attr_name = function.resolve(self._attribute)
r = self._resource()
if r.action in (r.CREATE, r.ADOPT, r.SUSPEND, r.RESUME,
r.UPDATE, r.ROLLBACK, r.SNAPSHOT, r.CHECK):
attribute = r.FnGetAtt(attr_name)
# NOTE(sirushtim): Add r.INIT to states above once convergence
# is the default.
elif r.stack.has_cache_data(r.name) and r.action == r.INIT:
attribute = r.FnGetAtt(attr_name)
else:
attribute = None
if attribute is None:
return None
@ -213,7 +297,7 @@ class GetAttAllAttributes(GetAtt):
if len(self.args) > 1:
return super(GetAttAllAttributes, self)._parse_args()
else:
return self.args[0], None
return self.args[0], None, []
else:
raise TypeError(_('Argument to "%s" must be a list') %
self.fn_name)
@ -246,7 +330,7 @@ class GetAttAllAttributes(GetAtt):
return True
class Replace(cfn_funcs.Replace):
class Replace(function.Function):
"""A function for performing string substitutions.
Takes the form::
@ -267,6 +351,15 @@ class Replace(cfn_funcs.Replace):
performed is otherwise undefined.
"""
def __init__(self, stack, fn_name, args):
super(Replace, self).__init__(stack, fn_name, args)
self._mapping, self._string = self._parse_args()
if not isinstance(self._mapping,
(collections.Mapping, function.Function)):
raise TypeError(_('"%s" parameters must be a mapping') %
self.fn_name)
def _parse_args(self):
if not isinstance(self.args, collections.Mapping):
raise TypeError(_('Arguments to "%s" must be a map') %
@ -286,6 +379,39 @@ class Replace(cfn_funcs.Replace):
else:
return mapping, string
def result(self):
template = function.resolve(self._string)
mapping = function.resolve(self._mapping)
if not isinstance(template, six.string_types):
raise TypeError(_('"%s" template must be a string') % self.fn_name)
if not isinstance(mapping, collections.Mapping):
raise TypeError(_('"%s" params must be a map') % self.fn_name)
def replace(string, change):
placeholder, value = change
if not isinstance(placeholder, six.string_types):
raise TypeError(_('"%s" param placeholders must be strings') %
self.fn_name)
if value is None:
value = ''
if not isinstance(value,
(six.string_types, six.integer_types,
float, bool)):
raise TypeError(_('"%s" params must be strings or numbers') %
self.fn_name)
return string.replace(placeholder, six.text_type(value))
mapping = collections.OrderedDict(sorted(mapping.items(),
key=lambda t: len(t[0]),
reverse=True))
return six.moves.reduce(replace, six.iteritems(mapping), template)
class ReplaceJson(Replace):
"""A function for performing string substitutions.
@ -387,25 +513,75 @@ class GetFile(function.Function):
return f
class Join(cfn_funcs.Join):
class Join(function.Function):
"""A function for joining strings.
Takes the form::
{ "list_join" : [ "<delim>", [ "<string_1>", "<string_2>", ... ] ] }
list_join:
- <delim>
- - <string_1>
- <string_2>
- ...
And resolves to::
"<string_1><delim><string_2><delim>..."
"""
def __init__(self, stack, fn_name, args):
super(Join, self).__init__(stack, fn_name, args)
example = '"%s" : [ " ", [ "str1", "str2"]]' % self.fn_name
fmt_data = {'fn_name': self.fn_name,
'example': example}
if not isinstance(self.args, list):
raise TypeError(_('Incorrect arguments to "%(fn_name)s" '
'should be: %(example)s') % fmt_data)
try:
self._delim, self._strings = self.args
except ValueError:
raise ValueError(_('Incorrect arguments to "%(fn_name)s" '
'should be: %(example)s') % fmt_data)
def result(self):
strings = function.resolve(self._strings)
if strings is None:
strings = []
if (isinstance(strings, six.string_types) or
not isinstance(strings, collections.Sequence)):
raise TypeError(_('"%s" must operate on a list') % self.fn_name)
delim = function.resolve(self._delim)
if not isinstance(delim, six.string_types):
raise TypeError(_('"%s" delimiter must be a string') %
self.fn_name)
def ensure_string(s):
if s is None:
return ''
if not isinstance(s, six.string_types):
raise TypeError(
_('Items to join must be strings not %s'
) % (repr(s)[:200]))
return s
return delim.join(ensure_string(s) for s in strings)
class JoinMultiple(function.Function):
"""A function for joining one or more lists of strings.
Takes the form::
{ "list_join" : [ "<delim>", [ "<string_1>", "<string_2>", ... ] ] }
list_join:
- <delim>
- - <string_1>
- <string_2>
- ...
- - ...
And resolves to::
@ -476,11 +652,14 @@ class MapMerge(function.Function):
Takes the form::
{ "map_merge" : [{'k1': 'v1', 'k2': 'v2'}, {'k1': 'v2'}] }
map_merge:
- <k1>: <v1>
<k2>: <v2>
- <k1>: <v3>
And resolves to::
{'k1': 'v2', 'k2': 'v2'}
{"<k1>": "<v2>", "<k2>": "<v3>"}
"""
@ -517,13 +696,17 @@ class MapReplace(function.Function):
Takes the form::
{"map_replace" : [{'k1': 'v1', 'k2': 'v2'},
{'keys': {'k1': 'K1'},
'values': {'v2': 'V2'}}]}
map_replace:
- <k1>: <v1>
<k2>: <v2>
- keys:
<k1>: <K1>
values:
<v2>: <V2>
And resolves to::
{'K1': 'v1', 'k2': 'V2'}
{"<K1>": "<v1>", "<k2>": "<V2>"}
"""
@ -588,7 +771,7 @@ class MapReplace(function.Function):
return ret_map
class ResourceFacade(cfn_funcs.ResourceFacade):
class ResourceFacade(function.Function):
"""A function for retrieving data in a parent provider template.
A function for obtaining data from the facade resource from within the
@ -608,6 +791,26 @@ class ResourceFacade(cfn_funcs.ResourceFacade):
'metadata', 'deletion_policy', 'update_policy'
)
def __init__(self, stack, fn_name, args):
super(ResourceFacade, self).__init__(stack, fn_name, args)
if self.args not in self._RESOURCE_ATTRIBUTES:
fmt_data = {'fn_name': self.fn_name,
'allowed': ', '.join(self._RESOURCE_ATTRIBUTES)}
raise ValueError(_('Incorrect arguments to "%(fn_name)s" '
'should be one of: %(allowed)s') % fmt_data)
def result(self):
attr = function.resolve(self.args)
if attr == self.METADATA:
return self.stack.parent_resource.metadata_get()
elif attr == self.UPDATE_POLICY:
up = self.stack.parent_resource.t._update_policy or {}
return function.resolve(up)
elif attr == self.DELETION_POLICY:
return self.stack.parent_resource.t.deletion_policy()
class Removed(function.Function):
"""This function existed in previous versions of HOT, but has been removed.
@ -767,14 +970,11 @@ class StrSplit(function.Function):
Takes the form::
str_split: [delimiter, string, <index> ]
or::
str_split:
- delimiter
- string
- <delimiter>
- <string>
- <index>
If <index> is specified, the specified list item will be returned
otherwise, the whole list is returned, similar to get_attr with
path based attributes accessing lists.
@ -901,7 +1101,9 @@ class Equals(function.Function):
Takes the form::
{ "equals" : ["value_1", "value_2"] }
equals:
- <value_1>
- <value_2>
The value can be any type that you want to compare. Returns true
if the two values are equal or false if they aren't.
@ -931,7 +1133,10 @@ class If(function.Macro):
Takes the form::
{ "if" : [condition_name, value_if_true, value_if_false] }
if:
- <condition_name>
- <value_if_true>
- <value_if_false>
The value_if_true to be returned if the specified condition evaluates
to true, the value_if_false to be returned if the specified condition
@ -958,11 +1163,11 @@ class If(function.Macro):
class Not(function.Function):
"""A function acts as a NOT operator.
"""A function that acts as a NOT operator on a condition.
Takes the form::
{ "not" : condition }
not: <condition>
Returns true for a condition that evaluates to false or
returns false for a condition that evaluates to true.
@ -970,10 +1175,13 @@ class Not(function.Function):
def __init__(self, stack, fn_name, args):
super(Not, self).__init__(stack, fn_name, args)
self.condition = self._get_condition()
def _get_condition(self):
try:
if not self.args:
raise ValueError()
self.condition = self.args
return self.args
except ValueError:
msg = _('Arguments to "%s" must be of the form: '
'condition')
@ -989,11 +1197,14 @@ class Not(function.Function):
class And(function.Function):
"""A function acts as an AND operator.
"""A function that acts as an AND operator on conditions.
Takes the form::
{ "and" : [{condition_1}, {condition_2}, {...}, {condition_n}] }
and:
- <condition_1>
- <condition_2>
- ...
Returns true if all the specified conditions evaluate to true, or returns
false if any one of the conditions evaluates to false. The minimum number
@ -1025,11 +1236,14 @@ class And(function.Function):
class Or(function.Function):
"""A function acts as an OR operator to evaluate all the conditions.
"""A function that acts as an OR operator on conditions.
Takes the form::
{ "or" : [{condition_1}, {condition_2}, {...}, {condition_n}] }
or:
- <condition_1>
- <condition_2>
- ...
Returns true if any one of the specified conditions evaluate to true,
or returns false if all of the conditions evaluates to false. The minimum

View File

@ -73,7 +73,7 @@ class HOTemplate20130523(template_common.CommonTemplate):
functions = {
'Fn::GetAZs': cfn_funcs.GetAZs,
'get_param': hot_funcs.GetParam,
'get_resource': cfn_funcs.ResourceRef,
'get_resource': hot_funcs.GetResource,
'Ref': cfn_funcs.Ref,
'get_attr': hot_funcs.GetAttThenSelect,
'Fn::Select': cfn_funcs.Select,
@ -302,7 +302,7 @@ class HOTemplate20141016(HOTemplate20130523):
'get_attr': hot_funcs.GetAtt,
'get_file': hot_funcs.GetFile,
'get_param': hot_funcs.GetParam,
'get_resource': cfn_funcs.ResourceRef,
'get_resource': hot_funcs.GetResource,
'list_join': hot_funcs.Join,
'resource_facade': hot_funcs.ResourceFacade,
'str_replace': hot_funcs.Replace,
@ -326,7 +326,7 @@ class HOTemplate20150430(HOTemplate20141016):
'get_attr': hot_funcs.GetAtt,
'get_file': hot_funcs.GetFile,
'get_param': hot_funcs.GetParam,
'get_resource': cfn_funcs.ResourceRef,
'get_resource': hot_funcs.GetResource,
'list_join': hot_funcs.Join,
'repeat': hot_funcs.Repeat,
'resource_facade': hot_funcs.ResourceFacade,
@ -354,7 +354,7 @@ class HOTemplate20151015(HOTemplate20150430):
'get_attr': hot_funcs.GetAttAllAttributes,
'get_file': hot_funcs.GetFile,
'get_param': hot_funcs.GetParam,
'get_resource': cfn_funcs.ResourceRef,
'get_resource': hot_funcs.GetResource,
'list_join': hot_funcs.JoinMultiple,
'repeat': hot_funcs.Repeat,
'resource_facade': hot_funcs.ResourceFacade,
@ -386,7 +386,7 @@ class HOTemplate20160408(HOTemplate20151015):
'get_attr': hot_funcs.GetAttAllAttributes,
'get_file': hot_funcs.GetFile,
'get_param': hot_funcs.GetParam,
'get_resource': cfn_funcs.ResourceRef,
'get_resource': hot_funcs.GetResource,
'list_join': hot_funcs.JoinMultiple,
'repeat': hot_funcs.Repeat,
'resource_facade': hot_funcs.ResourceFacade,
@ -459,7 +459,7 @@ class HOTemplate20161014(HOTemplate20160408):
'get_attr': hot_funcs.GetAttAllAttributes,
'get_file': hot_funcs.GetFile,
'get_param': hot_funcs.GetParam,
'get_resource': cfn_funcs.ResourceRef,
'get_resource': hot_funcs.GetResource,
'list_join': hot_funcs.JoinMultiple,
'repeat': hot_funcs.RepeatWithMap,
'resource_facade': hot_funcs.ResourceFacade,

View File

@ -276,7 +276,7 @@ class TranslationRule(object):
def _exec_resolve(self, translation_key, translation_data):
def resolve_and_find(translation_value):
if isinstance(translation_value, cfn_funcs.ResourceRef):
if isinstance(translation_value, hot_funcs.GetResource):
return
if isinstance(translation_value, function.Function):
translation_value = function.resolve(translation_value)

View File

@ -22,8 +22,8 @@ from neutronclient.v2_0 import client as neutronclient
from heat.common import exception
from heat.common import template_format
from heat.common import timeutils
from heat.engine.cfn import functions as cfn_funcs
from heat.engine.clients.os import neutron
from heat.engine.hot import functions as hot_funcs
from heat.engine import rsrc_defn
from heat.engine import scheduler
from heat.engine import stack as parser
@ -498,7 +498,7 @@ class NeutronFloatingIPTest(common.HeatTestCase):
t = template_format.parse(neutron_floating_no_assoc_template)
stack = utils.parse_stack(t)
p_result = self.patchobject(cfn_funcs.ResourceRef, 'result')
p_result = self.patchobject(hot_funcs.GetResource, 'result')
p_result.return_value = 'subnet_uuid'
# check dependencies for fip resource
required_by = set(stack.dependencies.required_by(
@ -515,7 +515,7 @@ class NeutronFloatingIPTest(common.HeatTestCase):
p_show = self.patchobject(neutronclient.Client, 'show_network')
p_show.return_value = {'network': {'subnets': ['subnet_uuid']}}
p_result = self.patchobject(cfn_funcs.ResourceRef, 'result',
p_result = self.patchobject(hot_funcs.GetResource, 'result',
autospec=True)
def return_uuid(self):

View File

@ -20,8 +20,8 @@ import six
from heat.common import exception
from heat.common import template_format
from heat.engine.cfn import functions as cfn_funcs
from heat.engine.clients.os import neutron
from heat.engine.hot import functions as hot_funcs
from heat.engine.resources.openstack.neutron import subnet
from heat.engine import rsrc_defn
from heat.engine import scheduler
@ -710,6 +710,6 @@ class NeutronSubnetTest(common.HeatTestCase):
rsrc = stack['subnet']
stack.create()
self.assertEqual(cfn_funcs.ResourceRef(stack, 'get_resource', 'net'),
self.assertEqual(hot_funcs.GetResource(stack, 'get_resource', 'net'),
rsrc.properties.get('network'))
self.assertIsNone(rsrc.properties.get('network_id'))

View File

@ -15,8 +15,8 @@ from oslo_serialization import jsonutils
import six
from heat.common import exception
from heat.engine.cfn import functions as cfn_funcs
from heat.engine import constraints
from heat.engine.hot import functions as hot_funcs
from heat.engine.hot import parameters as hot_param
from heat.engine import parameters
from heat.engine import plugin_manager
@ -1235,7 +1235,7 @@ class PropertiesTest(common.HeatTestCase):
# define properties with function and constraint
props = properties.Properties(
schema,
{'foo': cfn_funcs.ResourceRef(
{'foo': hot_funcs.GetResource(
stack, 'get_resource', 'another_res')},
test_resolver)

View File

@ -530,7 +530,7 @@ class TestTranslationRule(common.HeatTestCase):
pass
stack = DummyStack(another_res=rsrc())
ref = cfn_funcs.ResourceRef(stack, 'get_resource',
ref = hot_funcs.GetResource(stack, 'get_resource',
'another_res')
data = {
'far': [{'red': ref}],
@ -608,7 +608,7 @@ class TestTranslationRule(common.HeatTestCase):
pass
stack = DummyStack(another_res=rsrc())
ref = cfn_funcs.ResourceRef(stack, 'get_resource',
ref = hot_funcs.GetResource(stack, 'get_resource',
'another_res')
data = {'far': ref}
props = properties.Properties(schema, data)