Merge "Make cfn functions inherit from HOT"
This commit is contained in:
commit
54feba728b
|
@ -12,7 +12,6 @@
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import collections
|
import collections
|
||||||
import itertools
|
|
||||||
|
|
||||||
from oslo_serialization import jsonutils
|
from oslo_serialization import jsonutils
|
||||||
import six
|
import six
|
||||||
|
@ -21,6 +20,7 @@ from heat.api.aws import utils as aws_utils
|
||||||
from heat.common import exception
|
from heat.common import exception
|
||||||
from heat.common.i18n import _
|
from heat.common.i18n import _
|
||||||
from heat.engine import function
|
from heat.engine import function
|
||||||
|
from heat.engine.hot import functions as hot_funcs
|
||||||
|
|
||||||
|
|
||||||
class FindInMap(function.Function):
|
class FindInMap(function.Function):
|
||||||
|
@ -88,31 +88,6 @@ class ParamRef(function.Function):
|
||||||
key='unknown')
|
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):
|
def Ref(stack, fn_name, args):
|
||||||
"""A function for resolving parameters or resource references.
|
"""A function for resolving parameters or resource references.
|
||||||
|
|
||||||
|
@ -125,26 +100,21 @@ def Ref(stack, fn_name, args):
|
||||||
{ "Ref" : "<resource_name>" }
|
{ "Ref" : "<resource_name>" }
|
||||||
"""
|
"""
|
||||||
if args in stack:
|
if args in stack:
|
||||||
RefClass = ResourceRef
|
RefClass = hot_funcs.GetResource
|
||||||
else:
|
else:
|
||||||
RefClass = ParamRef
|
RefClass = ParamRef
|
||||||
return RefClass(stack, fn_name, args)
|
return RefClass(stack, fn_name, args)
|
||||||
|
|
||||||
|
|
||||||
class GetAtt(function.Function):
|
class GetAtt(hot_funcs.GetAttThenSelect):
|
||||||
"""A function for resolving resource attributes.
|
"""A function for resolving resource attributes.
|
||||||
|
|
||||||
Takes the form::
|
Takes the form::
|
||||||
|
|
||||||
{ "Fn::GetAtt" : [ "<resource_name>",
|
{ "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):
|
def _parse_args(self):
|
||||||
try:
|
try:
|
||||||
resource_name, attribute = self.args
|
resource_name, attribute = self.args
|
||||||
|
@ -152,62 +122,7 @@ class GetAtt(function.Function):
|
||||||
raise ValueError(_('Arguments to "%s" must be of the form '
|
raise ValueError(_('Arguments to "%s" must be of the form '
|
||||||
'[resource_name, attribute]') % self.fn_name)
|
'[resource_name, attribute]') % self.fn_name)
|
||||||
|
|
||||||
return resource_name, attribute
|
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
|
|
||||||
|
|
||||||
|
|
||||||
class Select(function.Function):
|
class Select(function.Function):
|
||||||
|
@ -217,7 +132,7 @@ class Select(function.Function):
|
||||||
|
|
||||||
{ "Fn::Select" : [ "<index>", [ "<value_1>", "<value_2>", ... ] ] }
|
{ "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>", ... } ] }
|
{ "Fn::Select" : [ "<index>", { "<key_1>": "<value_1>", ... } ] }
|
||||||
|
|
||||||
|
@ -283,7 +198,7 @@ class Select(function.Function):
|
||||||
self.fn_name)
|
self.fn_name)
|
||||||
|
|
||||||
|
|
||||||
class Join(function.Function):
|
class Join(hot_funcs.Join):
|
||||||
"""A function for joining strings.
|
"""A function for joining strings.
|
||||||
|
|
||||||
Takes the form::
|
Takes the form::
|
||||||
|
@ -295,47 +210,6 @@ class Join(function.Function):
|
||||||
"<string_1><delim><string_2><delim>..."
|
"<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):
|
class Split(function.Function):
|
||||||
"""A function for splitting strings.
|
"""A function for splitting strings.
|
||||||
|
@ -379,7 +253,7 @@ class Split(function.Function):
|
||||||
return strings.split(self._delim)
|
return strings.split(self._delim)
|
||||||
|
|
||||||
|
|
||||||
class Replace(function.Function):
|
class Replace(hot_funcs.Replace):
|
||||||
"""A function for performing string substitutions.
|
"""A function for performing string substitutions.
|
||||||
|
|
||||||
Takes the form::
|
Takes the form::
|
||||||
|
@ -398,15 +272,6 @@ class Replace(function.Function):
|
||||||
performed is otherwise undefined.
|
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):
|
def _parse_args(self):
|
||||||
|
|
||||||
example = ('{"%s": '
|
example = ('{"%s": '
|
||||||
|
@ -427,39 +292,6 @@ class Replace(function.Function):
|
||||||
else:
|
else:
|
||||||
return mapping, string
|
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):
|
class Base64(function.Function):
|
||||||
"""A placeholder function for converting to base64.
|
"""A placeholder function for converting to base64.
|
||||||
|
@ -535,7 +367,7 @@ class MemberListToMap(function.Function):
|
||||||
valuename=self._valuename)
|
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 retrieving data in a parent provider template.
|
||||||
|
|
||||||
A function for obtaining data from the facade resource from within the
|
A function for obtaining data from the facade resource from within the
|
||||||
|
@ -555,40 +387,46 @@ class ResourceFacade(function.Function):
|
||||||
'Metadata', 'DeletionPolicy', 'UpdatePolicy'
|
'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:
|
class If(hot_funcs.If):
|
||||||
fmt_data = {'fn_name': self.fn_name,
|
"""A function to return corresponding value based on condition evaluation.
|
||||||
'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.
|
|
||||||
|
|
||||||
Takes the form::
|
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 true for a condition that evaluates to false or
|
||||||
returns false for a condition that evaluates to true.
|
returns false for a condition that evaluates to true.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, stack, fn_name, args):
|
def _get_condition(self):
|
||||||
super(Not, self).__init__(stack, fn_name, args)
|
|
||||||
try:
|
try:
|
||||||
if (not self.args or
|
if (not self.args or
|
||||||
not isinstance(self.args, collections.Sequence) or
|
not isinstance(self.args, collections.Sequence) or
|
||||||
|
@ -596,7 +434,7 @@ class Not(function.Function):
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
if len(self.args) != 1:
|
if len(self.args) != 1:
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
self.condition = self.args[0]
|
return self.args[0]
|
||||||
except ValueError:
|
except ValueError:
|
||||||
msg = _('Arguments to "%s" must be of the form: '
|
msg = _('Arguments to "%s" must be of the form: '
|
||||||
'[condition]')
|
'[condition]')
|
||||||
|
@ -609,3 +447,29 @@ class Not(function.Function):
|
||||||
'after resolved the value is: %s')
|
'after resolved the value is: %s')
|
||||||
raise ValueError(msg % resolved_value)
|
raise ValueError(msg % resolved_value)
|
||||||
return not 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.
|
||||||
|
"""
|
||||||
|
|
|
@ -17,7 +17,6 @@ from heat.common import exception
|
||||||
from heat.common.i18n import _
|
from heat.common.i18n import _
|
||||||
from heat.engine.cfn import functions as cfn_funcs
|
from heat.engine.cfn import functions as cfn_funcs
|
||||||
from heat.engine import function
|
from heat.engine import function
|
||||||
from heat.engine.hot import functions as hot_funcs
|
|
||||||
from heat.engine import parameters
|
from heat.engine import parameters
|
||||||
from heat.engine import rsrc_defn
|
from heat.engine import rsrc_defn
|
||||||
from heat.engine import template_common
|
from heat.engine import template_common
|
||||||
|
@ -212,16 +211,16 @@ class CfnTemplate(CfnTemplateBase):
|
||||||
'Fn::Base64': cfn_funcs.Base64,
|
'Fn::Base64': cfn_funcs.Base64,
|
||||||
'Fn::MemberListToMap': cfn_funcs.MemberListToMap,
|
'Fn::MemberListToMap': cfn_funcs.MemberListToMap,
|
||||||
'Fn::ResourceFacade': cfn_funcs.ResourceFacade,
|
'Fn::ResourceFacade': cfn_funcs.ResourceFacade,
|
||||||
'Fn::If': hot_funcs.If,
|
'Fn::If': cfn_funcs.If,
|
||||||
}
|
}
|
||||||
|
|
||||||
condition_functions = {
|
condition_functions = {
|
||||||
'Fn::Equals': hot_funcs.Equals,
|
'Fn::Equals': cfn_funcs.Equals,
|
||||||
'Ref': cfn_funcs.ParamRef,
|
'Ref': cfn_funcs.ParamRef,
|
||||||
'Fn::FindInMap': cfn_funcs.FindInMap,
|
'Fn::FindInMap': cfn_funcs.FindInMap,
|
||||||
'Fn::Not': cfn_funcs.Not,
|
'Fn::Not': cfn_funcs.Not,
|
||||||
'Fn::And': hot_funcs.And,
|
'Fn::And': cfn_funcs.And,
|
||||||
'Fn::Or': hot_funcs.Or
|
'Fn::Or': cfn_funcs.Or
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, tmpl, template_id=None, files=None, env=None):
|
def __init__(self, tmpl, template_id=None, files=None, env=None):
|
||||||
|
|
|
@ -24,7 +24,6 @@ from yaql.language import exceptions
|
||||||
from heat.common import exception
|
from heat.common import exception
|
||||||
from heat.common.i18n import _
|
from heat.common.i18n import _
|
||||||
from heat.engine import attributes
|
from heat.engine import attributes
|
||||||
from heat.engine.cfn import functions as cfn_funcs
|
|
||||||
from heat.engine import function
|
from heat.engine import function
|
||||||
|
|
||||||
opts = [
|
opts = [
|
||||||
|
@ -113,7 +112,32 @@ class GetParam(function.Function):
|
||||||
return ''
|
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.
|
"""A function for resolving resource attributes.
|
||||||
|
|
||||||
Takes the form::
|
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):
|
def _parse_args(self):
|
||||||
if (not isinstance(self.args, collections.Sequence) or
|
if (not isinstance(self.args, collections.Sequence) or
|
||||||
isinstance(self.args, six.string_types)):
|
isinstance(self.args, six.string_types)):
|
||||||
|
@ -136,12 +167,65 @@ class GetAttThenSelect(cfn_funcs.GetAtt):
|
||||||
'[resource_name, attribute, (path), ...]') %
|
'[resource_name, attribute, (path), ...]') %
|
||||||
self.fn_name)
|
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):
|
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:
|
if attribute is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -213,7 +297,7 @@ class GetAttAllAttributes(GetAtt):
|
||||||
if len(self.args) > 1:
|
if len(self.args) > 1:
|
||||||
return super(GetAttAllAttributes, self)._parse_args()
|
return super(GetAttAllAttributes, self)._parse_args()
|
||||||
else:
|
else:
|
||||||
return self.args[0], None
|
return self.args[0], None, []
|
||||||
else:
|
else:
|
||||||
raise TypeError(_('Argument to "%s" must be a list') %
|
raise TypeError(_('Argument to "%s" must be a list') %
|
||||||
self.fn_name)
|
self.fn_name)
|
||||||
|
@ -246,7 +330,7 @@ class GetAttAllAttributes(GetAtt):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
class Replace(cfn_funcs.Replace):
|
class Replace(function.Function):
|
||||||
"""A function for performing string substitutions.
|
"""A function for performing string substitutions.
|
||||||
|
|
||||||
Takes the form::
|
Takes the form::
|
||||||
|
@ -267,6 +351,15 @@ class Replace(cfn_funcs.Replace):
|
||||||
performed is otherwise undefined.
|
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):
|
def _parse_args(self):
|
||||||
if not isinstance(self.args, collections.Mapping):
|
if not isinstance(self.args, collections.Mapping):
|
||||||
raise TypeError(_('Arguments to "%s" must be a map') %
|
raise TypeError(_('Arguments to "%s" must be a map') %
|
||||||
|
@ -286,6 +379,39 @@ class Replace(cfn_funcs.Replace):
|
||||||
else:
|
else:
|
||||||
return mapping, string
|
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):
|
class ReplaceJson(Replace):
|
||||||
"""A function for performing string substitutions.
|
"""A function for performing string substitutions.
|
||||||
|
@ -387,25 +513,75 @@ class GetFile(function.Function):
|
||||||
return f
|
return f
|
||||||
|
|
||||||
|
|
||||||
class Join(cfn_funcs.Join):
|
class Join(function.Function):
|
||||||
"""A function for joining strings.
|
"""A function for joining strings.
|
||||||
|
|
||||||
Takes the form::
|
Takes the form::
|
||||||
|
|
||||||
{ "list_join" : [ "<delim>", [ "<string_1>", "<string_2>", ... ] ] }
|
list_join:
|
||||||
|
- <delim>
|
||||||
|
- - <string_1>
|
||||||
|
- <string_2>
|
||||||
|
- ...
|
||||||
|
|
||||||
And resolves to::
|
And resolves to::
|
||||||
|
|
||||||
"<string_1><delim><string_2><delim>..."
|
"<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):
|
class JoinMultiple(function.Function):
|
||||||
"""A function for joining one or more lists of strings.
|
"""A function for joining one or more lists of strings.
|
||||||
|
|
||||||
Takes the form::
|
Takes the form::
|
||||||
|
|
||||||
{ "list_join" : [ "<delim>", [ "<string_1>", "<string_2>", ... ] ] }
|
list_join:
|
||||||
|
- <delim>
|
||||||
|
- - <string_1>
|
||||||
|
- <string_2>
|
||||||
|
- ...
|
||||||
|
- - ...
|
||||||
|
|
||||||
And resolves to::
|
And resolves to::
|
||||||
|
|
||||||
|
@ -476,11 +652,14 @@ class MapMerge(function.Function):
|
||||||
|
|
||||||
Takes the form::
|
Takes the form::
|
||||||
|
|
||||||
{ "map_merge" : [{'k1': 'v1', 'k2': 'v2'}, {'k1': 'v2'}] }
|
map_merge:
|
||||||
|
- <k1>: <v1>
|
||||||
|
<k2>: <v2>
|
||||||
|
- <k1>: <v3>
|
||||||
|
|
||||||
And resolves to::
|
And resolves to::
|
||||||
|
|
||||||
{'k1': 'v2', 'k2': 'v2'}
|
{"<k1>": "<v2>", "<k2>": "<v3>"}
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -517,13 +696,17 @@ class MapReplace(function.Function):
|
||||||
|
|
||||||
Takes the form::
|
Takes the form::
|
||||||
|
|
||||||
{"map_replace" : [{'k1': 'v1', 'k2': 'v2'},
|
map_replace:
|
||||||
{'keys': {'k1': 'K1'},
|
- <k1>: <v1>
|
||||||
'values': {'v2': 'V2'}}]}
|
<k2>: <v2>
|
||||||
|
- keys:
|
||||||
|
<k1>: <K1>
|
||||||
|
values:
|
||||||
|
<v2>: <V2>
|
||||||
|
|
||||||
And resolves to::
|
And resolves to::
|
||||||
|
|
||||||
{'K1': 'v1', 'k2': 'V2'}
|
{"<K1>": "<v1>", "<k2>": "<V2>"}
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -588,7 +771,7 @@ class MapReplace(function.Function):
|
||||||
return ret_map
|
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 retrieving data in a parent provider template.
|
||||||
|
|
||||||
A function for obtaining data from the facade resource from within the
|
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'
|
'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):
|
class Removed(function.Function):
|
||||||
"""This function existed in previous versions of HOT, but has been removed.
|
"""This function existed in previous versions of HOT, but has been removed.
|
||||||
|
@ -767,14 +970,11 @@ class StrSplit(function.Function):
|
||||||
|
|
||||||
Takes the form::
|
Takes the form::
|
||||||
|
|
||||||
str_split: [delimiter, string, <index> ]
|
|
||||||
|
|
||||||
or::
|
|
||||||
|
|
||||||
str_split:
|
str_split:
|
||||||
- delimiter
|
- <delimiter>
|
||||||
- string
|
- <string>
|
||||||
- <index>
|
- <index>
|
||||||
|
|
||||||
If <index> is specified, the specified list item will be returned
|
If <index> is specified, the specified list item will be returned
|
||||||
otherwise, the whole list is returned, similar to get_attr with
|
otherwise, the whole list is returned, similar to get_attr with
|
||||||
path based attributes accessing lists.
|
path based attributes accessing lists.
|
||||||
|
@ -901,7 +1101,9 @@ class Equals(function.Function):
|
||||||
|
|
||||||
Takes the form::
|
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
|
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.
|
if the two values are equal or false if they aren't.
|
||||||
|
@ -931,7 +1133,10 @@ class If(function.Macro):
|
||||||
|
|
||||||
Takes the form::
|
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
|
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
|
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):
|
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::
|
Takes the form::
|
||||||
|
|
||||||
{ "not" : condition }
|
not: <condition>
|
||||||
|
|
||||||
Returns true for a condition that evaluates to false or
|
Returns true for a condition that evaluates to false or
|
||||||
returns false for a condition that evaluates to true.
|
returns false for a condition that evaluates to true.
|
||||||
|
@ -970,10 +1175,13 @@ class Not(function.Function):
|
||||||
|
|
||||||
def __init__(self, stack, fn_name, args):
|
def __init__(self, stack, fn_name, args):
|
||||||
super(Not, self).__init__(stack, fn_name, args)
|
super(Not, self).__init__(stack, fn_name, args)
|
||||||
|
self.condition = self._get_condition()
|
||||||
|
|
||||||
|
def _get_condition(self):
|
||||||
try:
|
try:
|
||||||
if not self.args:
|
if not self.args:
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
self.condition = self.args
|
return self.args
|
||||||
except ValueError:
|
except ValueError:
|
||||||
msg = _('Arguments to "%s" must be of the form: '
|
msg = _('Arguments to "%s" must be of the form: '
|
||||||
'condition')
|
'condition')
|
||||||
|
@ -989,11 +1197,14 @@ class Not(function.Function):
|
||||||
|
|
||||||
|
|
||||||
class And(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::
|
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
|
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
|
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):
|
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::
|
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,
|
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
|
or returns false if all of the conditions evaluates to false. The minimum
|
||||||
|
|
|
@ -73,7 +73,7 @@ class HOTemplate20130523(template_common.CommonTemplate):
|
||||||
functions = {
|
functions = {
|
||||||
'Fn::GetAZs': cfn_funcs.GetAZs,
|
'Fn::GetAZs': cfn_funcs.GetAZs,
|
||||||
'get_param': hot_funcs.GetParam,
|
'get_param': hot_funcs.GetParam,
|
||||||
'get_resource': cfn_funcs.ResourceRef,
|
'get_resource': hot_funcs.GetResource,
|
||||||
'Ref': cfn_funcs.Ref,
|
'Ref': cfn_funcs.Ref,
|
||||||
'get_attr': hot_funcs.GetAttThenSelect,
|
'get_attr': hot_funcs.GetAttThenSelect,
|
||||||
'Fn::Select': cfn_funcs.Select,
|
'Fn::Select': cfn_funcs.Select,
|
||||||
|
@ -302,7 +302,7 @@ class HOTemplate20141016(HOTemplate20130523):
|
||||||
'get_attr': hot_funcs.GetAtt,
|
'get_attr': hot_funcs.GetAtt,
|
||||||
'get_file': hot_funcs.GetFile,
|
'get_file': hot_funcs.GetFile,
|
||||||
'get_param': hot_funcs.GetParam,
|
'get_param': hot_funcs.GetParam,
|
||||||
'get_resource': cfn_funcs.ResourceRef,
|
'get_resource': hot_funcs.GetResource,
|
||||||
'list_join': hot_funcs.Join,
|
'list_join': hot_funcs.Join,
|
||||||
'resource_facade': hot_funcs.ResourceFacade,
|
'resource_facade': hot_funcs.ResourceFacade,
|
||||||
'str_replace': hot_funcs.Replace,
|
'str_replace': hot_funcs.Replace,
|
||||||
|
@ -326,7 +326,7 @@ class HOTemplate20150430(HOTemplate20141016):
|
||||||
'get_attr': hot_funcs.GetAtt,
|
'get_attr': hot_funcs.GetAtt,
|
||||||
'get_file': hot_funcs.GetFile,
|
'get_file': hot_funcs.GetFile,
|
||||||
'get_param': hot_funcs.GetParam,
|
'get_param': hot_funcs.GetParam,
|
||||||
'get_resource': cfn_funcs.ResourceRef,
|
'get_resource': hot_funcs.GetResource,
|
||||||
'list_join': hot_funcs.Join,
|
'list_join': hot_funcs.Join,
|
||||||
'repeat': hot_funcs.Repeat,
|
'repeat': hot_funcs.Repeat,
|
||||||
'resource_facade': hot_funcs.ResourceFacade,
|
'resource_facade': hot_funcs.ResourceFacade,
|
||||||
|
@ -354,7 +354,7 @@ class HOTemplate20151015(HOTemplate20150430):
|
||||||
'get_attr': hot_funcs.GetAttAllAttributes,
|
'get_attr': hot_funcs.GetAttAllAttributes,
|
||||||
'get_file': hot_funcs.GetFile,
|
'get_file': hot_funcs.GetFile,
|
||||||
'get_param': hot_funcs.GetParam,
|
'get_param': hot_funcs.GetParam,
|
||||||
'get_resource': cfn_funcs.ResourceRef,
|
'get_resource': hot_funcs.GetResource,
|
||||||
'list_join': hot_funcs.JoinMultiple,
|
'list_join': hot_funcs.JoinMultiple,
|
||||||
'repeat': hot_funcs.Repeat,
|
'repeat': hot_funcs.Repeat,
|
||||||
'resource_facade': hot_funcs.ResourceFacade,
|
'resource_facade': hot_funcs.ResourceFacade,
|
||||||
|
@ -386,7 +386,7 @@ class HOTemplate20160408(HOTemplate20151015):
|
||||||
'get_attr': hot_funcs.GetAttAllAttributes,
|
'get_attr': hot_funcs.GetAttAllAttributes,
|
||||||
'get_file': hot_funcs.GetFile,
|
'get_file': hot_funcs.GetFile,
|
||||||
'get_param': hot_funcs.GetParam,
|
'get_param': hot_funcs.GetParam,
|
||||||
'get_resource': cfn_funcs.ResourceRef,
|
'get_resource': hot_funcs.GetResource,
|
||||||
'list_join': hot_funcs.JoinMultiple,
|
'list_join': hot_funcs.JoinMultiple,
|
||||||
'repeat': hot_funcs.Repeat,
|
'repeat': hot_funcs.Repeat,
|
||||||
'resource_facade': hot_funcs.ResourceFacade,
|
'resource_facade': hot_funcs.ResourceFacade,
|
||||||
|
@ -459,7 +459,7 @@ class HOTemplate20161014(HOTemplate20160408):
|
||||||
'get_attr': hot_funcs.GetAttAllAttributes,
|
'get_attr': hot_funcs.GetAttAllAttributes,
|
||||||
'get_file': hot_funcs.GetFile,
|
'get_file': hot_funcs.GetFile,
|
||||||
'get_param': hot_funcs.GetParam,
|
'get_param': hot_funcs.GetParam,
|
||||||
'get_resource': cfn_funcs.ResourceRef,
|
'get_resource': hot_funcs.GetResource,
|
||||||
'list_join': hot_funcs.JoinMultiple,
|
'list_join': hot_funcs.JoinMultiple,
|
||||||
'repeat': hot_funcs.RepeatWithMap,
|
'repeat': hot_funcs.RepeatWithMap,
|
||||||
'resource_facade': hot_funcs.ResourceFacade,
|
'resource_facade': hot_funcs.ResourceFacade,
|
||||||
|
|
|
@ -321,7 +321,7 @@ class TranslationRule(object):
|
||||||
def _exec_resolve(self, translation_key, translation_data):
|
def _exec_resolve(self, translation_key, translation_data):
|
||||||
|
|
||||||
def resolve_and_find(translation_value):
|
def resolve_and_find(translation_value):
|
||||||
if isinstance(translation_value, cfn_funcs.ResourceRef):
|
if isinstance(translation_value, hot_funcs.GetResource):
|
||||||
return
|
return
|
||||||
if isinstance(translation_value, function.Function):
|
if isinstance(translation_value, function.Function):
|
||||||
translation_value = function.resolve(translation_value)
|
translation_value = function.resolve(translation_value)
|
||||||
|
|
|
@ -22,8 +22,8 @@ from neutronclient.v2_0 import client as neutronclient
|
||||||
from heat.common import exception
|
from heat.common import exception
|
||||||
from heat.common import template_format
|
from heat.common import template_format
|
||||||
from heat.common import timeutils
|
from heat.common import timeutils
|
||||||
from heat.engine.cfn import functions as cfn_funcs
|
|
||||||
from heat.engine.clients.os import neutron
|
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 rsrc_defn
|
||||||
from heat.engine import scheduler
|
from heat.engine import scheduler
|
||||||
from heat.engine import stack as parser
|
from heat.engine import stack as parser
|
||||||
|
@ -498,7 +498,7 @@ class NeutronFloatingIPTest(common.HeatTestCase):
|
||||||
t = template_format.parse(neutron_floating_no_assoc_template)
|
t = template_format.parse(neutron_floating_no_assoc_template)
|
||||||
stack = utils.parse_stack(t)
|
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'
|
p_result.return_value = 'subnet_uuid'
|
||||||
# check dependencies for fip resource
|
# check dependencies for fip resource
|
||||||
required_by = set(stack.dependencies.required_by(
|
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 = self.patchobject(neutronclient.Client, 'show_network')
|
||||||
p_show.return_value = {'network': {'subnets': ['subnet_uuid']}}
|
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)
|
autospec=True)
|
||||||
|
|
||||||
def return_uuid(self):
|
def return_uuid(self):
|
||||||
|
|
|
@ -20,8 +20,8 @@ import six
|
||||||
|
|
||||||
from heat.common import exception
|
from heat.common import exception
|
||||||
from heat.common import template_format
|
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.clients.os import neutron
|
||||||
|
from heat.engine.hot import functions as hot_funcs
|
||||||
from heat.engine.resources.openstack.neutron import subnet
|
from heat.engine.resources.openstack.neutron import subnet
|
||||||
from heat.engine import rsrc_defn
|
from heat.engine import rsrc_defn
|
||||||
from heat.engine import scheduler
|
from heat.engine import scheduler
|
||||||
|
@ -710,6 +710,6 @@ class NeutronSubnetTest(common.HeatTestCase):
|
||||||
rsrc = stack['subnet']
|
rsrc = stack['subnet']
|
||||||
stack.create()
|
stack.create()
|
||||||
|
|
||||||
self.assertEqual(cfn_funcs.ResourceRef(stack, 'get_resource', 'net'),
|
self.assertEqual(hot_funcs.GetResource(stack, 'get_resource', 'net'),
|
||||||
rsrc.properties.get('network'))
|
rsrc.properties.get('network'))
|
||||||
self.assertIsNone(rsrc.properties.get('network_id'))
|
self.assertIsNone(rsrc.properties.get('network_id'))
|
||||||
|
|
|
@ -15,8 +15,8 @@ from oslo_serialization import jsonutils
|
||||||
import six
|
import six
|
||||||
|
|
||||||
from heat.common import exception
|
from heat.common import exception
|
||||||
from heat.engine.cfn import functions as cfn_funcs
|
|
||||||
from heat.engine import constraints
|
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.hot import parameters as hot_param
|
||||||
from heat.engine import parameters
|
from heat.engine import parameters
|
||||||
from heat.engine import plugin_manager
|
from heat.engine import plugin_manager
|
||||||
|
@ -1235,7 +1235,7 @@ class PropertiesTest(common.HeatTestCase):
|
||||||
# define properties with function and constraint
|
# define properties with function and constraint
|
||||||
props = properties.Properties(
|
props = properties.Properties(
|
||||||
schema,
|
schema,
|
||||||
{'foo': cfn_funcs.ResourceRef(
|
{'foo': hot_funcs.GetResource(
|
||||||
stack, 'get_resource', 'another_res')},
|
stack, 'get_resource', 'another_res')},
|
||||||
test_resolver)
|
test_resolver)
|
||||||
|
|
||||||
|
|
|
@ -530,7 +530,7 @@ class TestTranslationRule(common.HeatTestCase):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
stack = DummyStack(another_res=rsrc())
|
stack = DummyStack(another_res=rsrc())
|
||||||
ref = cfn_funcs.ResourceRef(stack, 'get_resource',
|
ref = hot_funcs.GetResource(stack, 'get_resource',
|
||||||
'another_res')
|
'another_res')
|
||||||
data = {
|
data = {
|
||||||
'far': [{'red': ref}],
|
'far': [{'red': ref}],
|
||||||
|
@ -608,7 +608,7 @@ class TestTranslationRule(common.HeatTestCase):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
stack = DummyStack(another_res=rsrc())
|
stack = DummyStack(another_res=rsrc())
|
||||||
ref = cfn_funcs.ResourceRef(stack, 'get_resource',
|
ref = hot_funcs.GetResource(stack, 'get_resource',
|
||||||
'another_res')
|
'another_res')
|
||||||
data = {'far': ref}
|
data = {'far': ref}
|
||||||
props = properties.Properties(schema, data)
|
props = properties.Properties(schema, data)
|
||||||
|
|
Loading…
Reference in New Issue