summaryrefslogtreecommitdiffstats
path: root/tosca2heat/tosca-parser/toscaparser
diff options
context:
space:
mode:
authorjulien zhang <zhang.jun3g@zte.com.cn>2017-07-17 12:42:12 +0000
committerGerrit Code Review <gerrit@opnfv.org>2017-07-17 12:42:12 +0000
commit30149ea784b60fc12de3e8a70aca23a16011ca70 (patch)
tree819c4ee6241f8323b517c371256c3c6d1247b5a5 /tosca2heat/tosca-parser/toscaparser
parentc7491340551cdd9d757d63b4bbe79132506e386a (diff)
parent040e0718bcfac3cd01cf4ccae82bef2c0d01087b (diff)
Merge "synchronize upstream about tosca-parser"
Diffstat (limited to 'tosca2heat/tosca-parser/toscaparser')
-rw-r--r--tosca2heat/tosca-parser/toscaparser/elements/TOSCA_definition_1_0.yaml25
-rw-r--r--tosca2heat/tosca-parser/toscaparser/elements/nodetype.py2
-rw-r--r--tosca2heat/tosca-parser/toscaparser/elements/policytype.py2
-rw-r--r--tosca2heat/tosca-parser/toscaparser/functions.py57
-rw-r--r--tosca2heat/tosca-parser/toscaparser/tests/data/custom_types/container_cap_child.yaml33
-rw-r--r--tosca2heat/tosca-parser/toscaparser/tests/data/custom_types/custom_cap.yaml22
-rw-r--r--tosca2heat/tosca-parser/toscaparser/tests/data/custom_types/node_with_cap.yaml7
-rw-r--r--tosca2heat/tosca-parser/toscaparser/tests/data/functions/test_container_cap_child.yaml28
-rw-r--r--tosca2heat/tosca-parser/toscaparser/tests/data/functions/test_get_prop_cap_bool.yaml37
-rw-r--r--tosca2heat/tosca-parser/toscaparser/tests/data/functions/test_get_prop_cap_host.yaml25
-rw-r--r--tosca2heat/tosca-parser/toscaparser/tests/data/policies/tosca_policy_template.yaml26
-rw-r--r--tosca2heat/tosca-parser/toscaparser/tests/data/test_custom_capabilty.yaml23
-rw-r--r--tosca2heat/tosca-parser/toscaparser/tests/data/topology_template/definitions.yaml2
-rw-r--r--tosca2heat/tosca-parser/toscaparser/tests/test_functions.py24
-rw-r--r--tosca2heat/tosca-parser/toscaparser/tests/test_topology_template.py2
-rw-r--r--tosca2heat/tosca-parser/toscaparser/tests/test_toscatplvalidation.py53
-rw-r--r--tosca2heat/tosca-parser/toscaparser/triggers.py26
17 files changed, 367 insertions, 27 deletions
diff --git a/tosca2heat/tosca-parser/toscaparser/elements/TOSCA_definition_1_0.yaml b/tosca2heat/tosca-parser/toscaparser/elements/TOSCA_definition_1_0.yaml
index 9f3369e..57c9bf9 100644
--- a/tosca2heat/tosca-parser/toscaparser/elements/TOSCA_definition_1_0.yaml
+++ b/tosca2heat/tosca-parser/toscaparser/elements/TOSCA_definition_1_0.yaml
@@ -339,6 +339,26 @@ node_types:
relationship: tosca.relationships.network.LinksTo
node: tosca.nodes.network.Network
+ tosca.nodes.network.FloatingIP:
+ derived_from: tosca.nodes.Root
+ description: >
+ The TOSCA FloatingIP node represents a floating IP that can associate to a Port.
+ properties:
+ floating_network:
+ type: string
+ required: true
+ floating_ip_address:
+ type: string
+ required: false
+ port_id:
+ type: string
+ required: false
+ requirements:
+ - link:
+ capability: tosca.capabilities.network.Linkable
+ relationship: tosca.relationships.network.LinksTo
+ node: tosca.nodes.network.Port
+
tosca.nodes.ObjectStorage:
derived_from: tosca.nodes.Root
description: >
@@ -928,6 +948,11 @@ policy_types:
description: The TOSCA Policy Type definition that is used to govern
scaling of TOSCA nodes or groups of nodes.
+ tosca.policies.Monitoring:
+ derived_from: tosca.policies.Root
+ description: The TOSCA Policy Type definition that is used to govern
+ monitoring of TOSCA nodes or groups of nodes.
+
tosca.policies.Update:
derived_from: tosca.policies.Root
description: The TOSCA Policy Type definition that is used to govern
diff --git a/tosca2heat/tosca-parser/toscaparser/elements/nodetype.py b/tosca2heat/tosca-parser/toscaparser/elements/nodetype.py
index 7f3da2d..4889ed8 100644
--- a/tosca2heat/tosca-parser/toscaparser/elements/nodetype.py
+++ b/tosca2heat/tosca-parser/toscaparser/elements/nodetype.py
@@ -83,8 +83,6 @@ class NodeType(StatefulEntityType):
captype = value['capability']
value = (self.
_get_node_type_by_cap(captype))
- # _get_node_type_by_cap(key, captype))
- # relation = self._get_relation(key, value)
keyword = key
node_type = value
rtype = RelationshipType(relation, keyword, self.custom_def)
diff --git a/tosca2heat/tosca-parser/toscaparser/elements/policytype.py b/tosca2heat/tosca-parser/toscaparser/elements/policytype.py
index a922d26..82aed0a 100644
--- a/tosca2heat/tosca-parser/toscaparser/elements/policytype.py
+++ b/tosca2heat/tosca-parser/toscaparser/elements/policytype.py
@@ -113,7 +113,7 @@ class PolicyType(StatefulEntityType):
for entry_schema, entry_schema_type in meta_data.items():
if isinstance(entry_schema_type, dict) and not \
- entry_schema_type.get('type') == 'string':
+ entry_schema_type.get('type') == 'string':
ExceptionCollector.appendException(
InvalidTypeError(what='"%s" defined in policy for '
'metadata "%s"'
diff --git a/tosca2heat/tosca-parser/toscaparser/functions.py b/tosca2heat/tosca-parser/toscaparser/functions.py
index d498229..b64f1bc 100644
--- a/tosca2heat/tosca-parser/toscaparser/functions.py
+++ b/tosca2heat/tosca-parser/toscaparser/functions.py
@@ -158,6 +158,8 @@ class GetAttribute(Function):
# then check the req or caps
attr = self._find_req_or_cap_attribute(self.args[1],
self.args[2])
+ if not attr:
+ return
value_type = attr.schema['type']
if len(self.args) > index:
@@ -236,8 +238,8 @@ class GetAttribute(Function):
target_node = self._find_node_template(target_name)
target_type = target_node.type_definition
for capability in target_type.get_capabilities_objects():
- if capability.type in \
- hosted_on_rel['valid_target_types']:
+ if capability.inherits_from(
+ hosted_on_rel['valid_target_types']):
if self._attribute_exists_in_type(target_type):
return target_node
return self._find_host_containing_attribute(
@@ -412,6 +414,8 @@ class GetProperty(Function):
def _find_req_or_cap_property(self, req_or_cap, property_name):
node_tpl = self._find_node_template(self.args[0])
+ if node_tpl is None:
+ return None
# Find property in node template's requirements
for r in node_tpl.requirements:
for req, node_name in r.items():
@@ -429,7 +433,8 @@ class GetProperty(Function):
def _get_capability_property(self,
node_template,
capability_name,
- property_name):
+ property_name,
+ throw_errors=True):
"""Gets a node template capability property."""
caps = node_template.get_capabilities()
if caps and capability_name in caps.keys():
@@ -438,7 +443,7 @@ class GetProperty(Function):
props = cap.get_properties()
if props and property_name in props.keys():
property = props[property_name].value
- if not property:
+ if property is None and throw_errors:
ExceptionCollector.appendException(
KeyError(_('Property "%(prop)s" was not found in '
'capability "%(cap)s" of node template '
@@ -448,12 +453,15 @@ class GetProperty(Function):
'ntpl1': node_template.name,
'ntpl2': self.context.name}))
return property
- msg = _('Requirement/Capability "{0}" referenced from node template '
- '"{1}" was not found in node template "{2}".').format(
- capability_name,
- self.context.name,
- node_template.name)
- ExceptionCollector.appendException(KeyError(msg))
+ if throw_errors:
+ msg = _('Requirement/Capability "{0}" referenced from '
+ 'node template "{1}" was not found in node template'
+ ' "{2}".').format(capability_name,
+ self.context.name,
+ node_template.name)
+ ExceptionCollector.appendException(KeyError(msg))
+ else:
+ return None
def _find_property(self, property_name):
node_tpl = self._find_node_template(self.args[0])
@@ -475,7 +483,18 @@ class GetProperty(Function):
return self.context
# enable the HOST value in the function
if node_template_name == HOST:
- return self._find_host_containing_property()
+ node = self._find_host_containing_property()
+ if node is None:
+ ExceptionCollector.appendException(
+ KeyError(_(
+ "Property '{0}' not found in capability/requirement"
+ " '{1}' referenced from node template {2}").
+ format(self.args[2],
+ self.args[1],
+ self.context.name)))
+ return None
+ else:
+ return node
if node_template_name == TARGET:
if not isinstance(self.context.type_definition, RelationshipType):
ExceptionCollector.appendException(
@@ -498,7 +517,9 @@ class GetProperty(Function):
ExceptionCollector.appendException(
KeyError(_(
'Node template "{0}" was not found.'
- ).format(node_template_name)))
+ ' referenced from node template {1}'
+ ).format(node_template_name,
+ self.context.name)))
def _get_index_value(self, value, index):
if isinstance(value, list):
@@ -555,9 +576,19 @@ class GetProperty(Function):
target_node = self._find_node_template(target_name)
target_type = target_node.type_definition
for capability in target_type.get_capabilities_objects():
- if capability.type in hosted_on_rel['valid_target_types']:
+ if capability.inherits_from(
+ hosted_on_rel['valid_target_types']):
if self._property_exists_in_type(target_type):
return target_node
+ # If requirement was not found, look in node
+ # template's capabilities
+ if (len(self.args) > 2 and
+ self._get_capability_property(target_node,
+ self.args[1],
+ self.args[2],
+ False)
+ is not None):
+ return target_node
return self._find_host_containing_property(
target_name)
return None
diff --git a/tosca2heat/tosca-parser/toscaparser/tests/data/custom_types/container_cap_child.yaml b/tosca2heat/tosca-parser/toscaparser/tests/data/custom_types/container_cap_child.yaml
new file mode 100644
index 0000000..1df09dd
--- /dev/null
+++ b/tosca2heat/tosca-parser/toscaparser/tests/data/custom_types/container_cap_child.yaml
@@ -0,0 +1,33 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: >
+ Define a capability class that inherits from tosca.capabilities.Container
+
+capability_types:
+
+ tosca.capabilities.ContainerChild:
+ derived_from: tosca.capabilities.Container
+
+node_types:
+
+ tosca.nodes.SomeNode:
+ derived_from: tosca.nodes.Root
+ properties:
+ some_prop:
+ type: string
+ requirements:
+ - host_child:
+ capability: tosca.capabilities.ContainerChild
+ node: tosca.nodes.SomeNode2
+ relationship: tosca.relationships.HostedOn
+
+ tosca.nodes.SomeNode2:
+ derived_from: tosca.nodes.Root
+ capabilities:
+ host_child:
+ type: tosca.capabilities.ContainerChild
+ requirements:
+ - host:
+ capability: tosca.capabilities.Container
+ node: tosca.nodes.Compute
+ relationship: tosca.relationships.HostedOn
diff --git a/tosca2heat/tosca-parser/toscaparser/tests/data/custom_types/custom_cap.yaml b/tosca2heat/tosca-parser/toscaparser/tests/data/custom_types/custom_cap.yaml
new file mode 100644
index 0000000..018bcf6
--- /dev/null
+++ b/tosca2heat/tosca-parser/toscaparser/tests/data/custom_types/custom_cap.yaml
@@ -0,0 +1,22 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+capability_types:
+
+ tosca.capabilities.SomeCap:
+ derived_from: tosca.capabilities.Container
+
+node_types:
+
+ tosca.nodes.NodeWithReq:
+ derived_from: tosca.nodes.SoftwareComponent
+ requirements:
+ - host:
+ capability: tosca.capabilities.SomeCap
+ relationship: tosca.relationships.HostedOn
+ occurrences: [1, 1]
+
+ tosca.nodes.NodeWithCap:
+ derived_from: tosca.nodes.SoftwareComponent
+ capabilities:
+ host:
+ type: tosca.capabilities.SomeCap
diff --git a/tosca2heat/tosca-parser/toscaparser/tests/data/custom_types/node_with_cap.yaml b/tosca2heat/tosca-parser/toscaparser/tests/data/custom_types/node_with_cap.yaml
index b17513f..332f830 100644
--- a/tosca2heat/tosca-parser/toscaparser/tests/data/custom_types/node_with_cap.yaml
+++ b/tosca2heat/tosca-parser/toscaparser/tests/data/custom_types/node_with_cap.yaml
@@ -6,7 +6,7 @@ description: >
capability_types:
tosca.capabilities.SomeCap:
- derived_from: tosca.capabilities.Root
+ derived_from: tosca.capabilities.Container
properties:
type:
type: string
@@ -19,6 +19,11 @@ node_types:
tosca.nodes.SomeNode:
derived_from: tosca.nodes.Root
+ properties:
+ some_prop:
+ type: string
+ required: false
+ default: some
requirements:
- some_req:
capability: tosca.capabilities.SomeCap
diff --git a/tosca2heat/tosca-parser/toscaparser/tests/data/functions/test_container_cap_child.yaml b/tosca2heat/tosca-parser/toscaparser/tests/data/functions/test_container_cap_child.yaml
new file mode 100644
index 0000000..84118c8
--- /dev/null
+++ b/tosca2heat/tosca-parser/toscaparser/tests/data/functions/test_container_cap_child.yaml
@@ -0,0 +1,28 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: >
+ TOSCA simple profile to test the get attribute function with HOST parameter
+ using a node that has as capability a child class of Container
+
+imports:
+ - ../custom_types/container_cap_child.yaml
+
+topology_template:
+
+ node_templates:
+
+ test_node:
+ type: tosca.nodes.SomeNode
+ properties:
+ some_prop: { get_attribute: [ HOST, public_address ] }
+ requirements:
+ - host_child: test_node2
+
+ test_node2:
+ type: tosca.nodes.SomeNode2
+ requirements:
+ - host: server
+
+ server:
+ type: tosca.nodes.Compute
+
diff --git a/tosca2heat/tosca-parser/toscaparser/tests/data/functions/test_get_prop_cap_bool.yaml b/tosca2heat/tosca-parser/toscaparser/tests/data/functions/test_get_prop_cap_bool.yaml
new file mode 100644
index 0000000..d9c4c1c
--- /dev/null
+++ b/tosca2heat/tosca-parser/toscaparser/tests/data/functions/test_get_prop_cap_bool.yaml
@@ -0,0 +1,37 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: TOSCA test for boolean properties
+
+node_types:
+
+ tosca.nodes.SoftwareComponentTest:
+ derived_from: tosca.nodes.SoftwareComponent
+ properties:
+ some_prop:
+ type: boolean
+
+ tosca.nodes.ComputeTest:
+ derived_from: tosca.nodes.Compute
+ capabilities:
+ endpoint:
+ type: tosca.capabilities.Endpoint
+
+topology_template:
+
+ node_templates:
+
+ software:
+ type: tosca.nodes.SoftwareComponentTest
+ properties:
+ some_prop: { get_property: [ HOST, endpoint, secure ] }
+ requirements:
+ - host: server
+
+ server:
+ type: tosca.nodes.ComputeTest
+ capabilities:
+ endpoint:
+ properties:
+ network_name: PUBLIC
+ secure: false
+
diff --git a/tosca2heat/tosca-parser/toscaparser/tests/data/functions/test_get_prop_cap_host.yaml b/tosca2heat/tosca-parser/toscaparser/tests/data/functions/test_get_prop_cap_host.yaml
new file mode 100644
index 0000000..7fcb4a7
--- /dev/null
+++ b/tosca2heat/tosca-parser/toscaparser/tests/data/functions/test_get_prop_cap_host.yaml
@@ -0,0 +1,25 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: TOSCA test for the IM
+
+imports:
+ - test: ../custom_types/node_with_cap.yaml
+
+topology_template:
+
+ node_templates:
+
+ some_node:
+ type: tosca.nodes.SomeNode
+ properties:
+ some_prop: { get_property: [ HOST, some_req, type ] }
+ requirements:
+ - some_req: server
+
+ server:
+ type: tosca.nodes.NodeWithCap
+ capabilities:
+ some_req:
+ properties:
+ type: someval
+
diff --git a/tosca2heat/tosca-parser/toscaparser/tests/data/policies/tosca_policy_template.yaml b/tosca2heat/tosca-parser/toscaparser/tests/data/policies/tosca_policy_template.yaml
index 47f7870..4c18d9d 100644
--- a/tosca2heat/tosca-parser/toscaparser/tests/data/policies/tosca_policy_template.yaml
+++ b/tosca2heat/tosca-parser/toscaparser/tests/data/policies/tosca_policy_template.yaml
@@ -75,6 +75,32 @@ topology_template:
inputs:
strategy: LEAST_USED
implementation: Senlin.webhook()
+ high_cpu_usage:
+ description: trigger
+ meter_name: cpu_util
+ condition:
+ constraint: utilization greater_than 60%
+ threshold: 60
+ period: 600
+ evaluations: 1
+ method: average
+ comparison_operator: gt
+ metadata: SG1
+ action: [SP1]
+
+ low_cpu_usage:
+ description: trigger
+ meter_name: cpu_util
+ condition:
+ constraint: utilization less_than 20%
+ threshold: 20
+ period: 600
+ evaluations: 1
+ method: average
+ comparison_operator: gt
+ metadata: SG1
+ action: [SP1]
+
- my_groups_placement:
type: mycompany.mytypes.myScalingPolicy
targets: [ webserver_group ]
diff --git a/tosca2heat/tosca-parser/toscaparser/tests/data/test_custom_capabilty.yaml b/tosca2heat/tosca-parser/toscaparser/tests/data/test_custom_capabilty.yaml
new file mode 100644
index 0000000..03a8a07
--- /dev/null
+++ b/tosca2heat/tosca-parser/toscaparser/tests/data/test_custom_capabilty.yaml
@@ -0,0 +1,23 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: TOSCA simple profile to test a custom defined capability
+
+imports:
+ - custom_types/custom_cap.yaml
+
+topology_template:
+
+ node_templates:
+
+ node_req:
+ type: tosca.nodes.NodeWithReq
+ requirements:
+ - host: node_cap
+
+ node_cap:
+ type: tosca.nodes.NodeWithCap
+ requirements:
+ - host: server
+
+ server:
+ type: tosca.nodes.Compute
diff --git a/tosca2heat/tosca-parser/toscaparser/tests/data/topology_template/definitions.yaml b/tosca2heat/tosca-parser/toscaparser/tests/data/topology_template/definitions.yaml
index ba5eac1..300bb8a 100644
--- a/tosca2heat/tosca-parser/toscaparser/tests/data/topology_template/definitions.yaml
+++ b/tosca2heat/tosca-parser/toscaparser/tests/data/topology_template/definitions.yaml
@@ -49,7 +49,7 @@ node_types:
derived_from: tosca.nodes.Database
example.SomeApp:
- derived_from: tosca.nodes.SoftwareComponent
+ derived_from: tosca.nodes.WebApplication
properties:
admin_user:
type: string
diff --git a/tosca2heat/tosca-parser/toscaparser/tests/test_functions.py b/tosca2heat/tosca-parser/toscaparser/tests/test_functions.py
index fa60140..2e1d71e 100644
--- a/tosca2heat/tosca-parser/toscaparser/tests/test_functions.py
+++ b/tosca2heat/tosca-parser/toscaparser/tests/test_functions.py
@@ -188,6 +188,26 @@ class IntrinsicFunctionsTest(TestCase):
self.assertIsInstance(source_port, functions.GetProperty)
self.assertEqual(3306, source_port.result())
+ def test_get_prop_cap_host(self):
+ tosca_tpl = os.path.join(
+ os.path.dirname(os.path.abspath(__file__)),
+ "data/functions/test_get_prop_cap_host.yaml")
+ some_node = self._get_node('some_node',
+ ToscaTemplate(tosca_tpl))
+ some_prop = some_node.get_properties()['some_prop']
+ self.assertIsInstance(some_prop.value, functions.GetProperty)
+ self.assertEqual('someval', some_prop.value.result())
+
+ def test_get_prop_cap_bool(self):
+ tosca_tpl = os.path.join(
+ os.path.dirname(os.path.abspath(__file__)),
+ "data/functions/test_get_prop_cap_bool.yaml")
+ some_node = self._get_node('software',
+ ToscaTemplate(tosca_tpl))
+ some_prop = some_node.get_properties()['some_prop']
+ self.assertIsInstance(some_prop.value, functions.GetProperty)
+ self.assertEqual(False, some_prop.value.result())
+
class GetAttributeTest(TestCase):
@@ -318,6 +338,10 @@ class GetAttributeTest(TestCase):
self.assertIsNotNone(self._load_template(
'functions/test_get_implicit_attribute.yaml'))
+ def test_get_attribute_capability_inheritance(self):
+ self.assertIsNotNone(self._load_template(
+ 'functions/test_container_cap_child.yaml'))
+
class ConcatTest(TestCase):
diff --git a/tosca2heat/tosca-parser/toscaparser/tests/test_topology_template.py b/tosca2heat/tosca-parser/toscaparser/tests/test_topology_template.py
index 3aabc9b..a0d6dc3 100644
--- a/tosca2heat/tosca-parser/toscaparser/tests/test_topology_template.py
+++ b/tosca2heat/tosca-parser/toscaparser/tests/test_topology_template.py
@@ -91,7 +91,7 @@ class TopologyTemplateTest(TestCase):
tpl_name = "app"
expected_type = "example.SomeApp"
expected_properties = ['admin_user', 'pool_size']
- expected_capabilities = ['feature', 'message_receiver']
+ expected_capabilities = ['app_endpoint', 'feature', 'message_receiver']
expected_requirements = [{'host': {'node': 'websrv'}}]
expected_relationshp = ['tosca.relationships.HostedOn']
expected_host = ['websrv']
diff --git a/tosca2heat/tosca-parser/toscaparser/tests/test_toscatplvalidation.py b/tosca2heat/tosca-parser/toscaparser/tests/test_toscatplvalidation.py
index 911867f..f7c22ab 100644
--- a/tosca2heat/tosca-parser/toscaparser/tests/test_toscatplvalidation.py
+++ b/tosca2heat/tosca-parser/toscaparser/tests/test_toscatplvalidation.py
@@ -1581,7 +1581,7 @@ heat-translator/master/translator/tests/data/custom_types/wordpress.yaml
lambda: Policy(name, policies[name], None, None))
self.assertEqual(expectedmessage, err.__str__())
- def test_policy_trigger_valid_keyname(self):
+ def test_policy_trigger_valid_keyname_senlin_resources(self):
tpl_snippet = '''
triggers:
- resize_compute:
@@ -1610,7 +1610,28 @@ heat-translator/master/translator/tests/data/custom_types/wordpress.yaml
name = list(triggers.keys())[0]
Triggers(name, triggers[name])
- def test_policy_trigger_invalid_keyname(self):
+ def test_policy_trigger_valid_keyname_heat_resources(self):
+ tpl_snippet = '''
+ triggers:
+ - high_cpu_usage:
+ description: trigger
+ meter_name: cpu_util
+ condition:
+ constraint: utilization greater_than 60%
+ threshold: 60
+ period: 600
+ evaluations: 1
+ method: average
+ comparison_operator: gt
+ metadata: SG1
+ action: [SP1]
+ '''
+ triggers = (toscaparser.utils.yamlparser.
+ simple_parse(tpl_snippet))['triggers'][0]
+ name = list(triggers.keys())[0]
+ Triggers(name, triggers[name])
+
+ def test_policy_trigger_invalid_keyname_senlin_resources(self):
tpl_snippet = '''
triggers:
- resize_compute:
@@ -1646,6 +1667,34 @@ heat-translator/master/translator/tests/data/custom_types/wordpress.yaml
lambda: Triggers(name, triggers[name]))
self.assertEqual(expectedmessage, err.__str__())
+ def test_policy_trigger_invalid_keyname_heat_resources(self):
+ tpl_snippet = '''
+ triggers:
+ - high_cpu_usage:
+ description: trigger
+ meter_name: cpu_util
+ condition:
+ constraint: utilization greater_than 60%
+ threshold: 60
+ period: 600
+ evaluations: 1
+ method: average
+ comparison_operator: gt
+ metadata1: SG1
+ action: [SP1]
+ '''
+ triggers = (toscaparser.utils.yamlparser.
+ simple_parse(tpl_snippet))['triggers'][0]
+ name = list(triggers.keys())[0]
+ expectedmessage = _(
+ 'Triggers "high_cpu_usage" contains unknown field '
+ '"metadata1". Refer to the definition '
+ 'to verify valid values.')
+ err = self.assertRaises(
+ exception.UnknownFieldError,
+ lambda: Triggers(name, triggers[name]))
+ self.assertEqual(expectedmessage, err.__str__())
+
def test_policy_missing_required_keyname(self):
tpl_snippet = '''
policies:
diff --git a/tosca2heat/tosca-parser/toscaparser/triggers.py b/tosca2heat/tosca-parser/toscaparser/triggers.py
index 9edeef4..8e47eee 100644
--- a/tosca2heat/tosca-parser/toscaparser/triggers.py
+++ b/tosca2heat/tosca-parser/toscaparser/triggers.py
@@ -16,12 +16,16 @@ import logging
from toscaparser.common.exception import ExceptionCollector
from toscaparser.common.exception import UnknownFieldError
from toscaparser.entity_template import EntityTemplate
-
-SECTIONS = (DESCRIPTION, EVENT, SCHEDULE, TARGET_FILTER, CONDITION, ACTION) = \
- ('description', 'event_type', 'schedule',
- 'target_filter', 'condition', 'action')
-CONDITION_KEYNAMES = (CONTRAINT, PERIOD, EVALUATIONS, METHOD) = \
- ('constraint', 'period', 'evaluations', 'method')
+from toscaparser.utils import validateutils
+
+SECTIONS = (DESCRIPTION, EVENT, SCHEDULE, METER_NAME, METADATA,
+ TARGET_FILTER, CONDITION, ACTION) = \
+ ('description', 'event_type', 'schedule', 'meter_name',
+ 'metadata', 'target_filter', 'condition', 'action')
+CONDITION_KEYNAMES = (CONSTRAINT, PERIOD, EVALUATIONS, METHOD,
+ THRESHOLD, COMPARISON_OPERATOR) = \
+ ('constraint', 'period', 'evaluations',
+ 'method', 'threshold', 'comparison_operator')
log = logging.getLogger('tosca')
@@ -34,6 +38,7 @@ class Triggers(EntityTemplate):
self.trigger_tpl = trigger_tpl
self._validate_keys()
self._validate_condition()
+ self._validate_input()
def get_description(self):
return self.trigger_tpl['description']
@@ -66,3 +71,12 @@ class Triggers(EntityTemplate):
ExceptionCollector.appendException(
UnknownFieldError(what='Triggers "%s"' % self.name,
field=key))
+
+ def _validate_input(self):
+ for key, value in self.get_condition().items():
+ if key in [PERIOD, EVALUATIONS]:
+ validateutils.validate_integer(value)
+ elif key == THRESHOLD:
+ validateutils.validate_numeric(value)
+ elif key in [METER_NAME, METHOD]:
+ validateutils.validate_string(value)