summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorshangxdy <shang.xiaodong@zte.com.cn>2016-12-05 14:23:25 +0800
committershangxdy <shang.xiaodong@zte.com.cn>2016-12-09 23:40:40 +0800
commitd098a14d69bf78b7674ec5d75003c21250e640bc (patch)
treef2ecde70b315149ecbc78d71a135fe0e5cd391a0
parentc72383042c976022d8b49b3fc77a4c1a1b735ec0 (diff)
Add output validation for substitution mappings
1. The outputs defined by the topology template have to match the attributes of the node type or the substituted node template, 2.The observable attributes of the substituted node template have to be defined as attributes of the node type or outputs in the topology template. The patch will be submitted to openstack too. JIRA: PARSER-115 Change-Id: Ifa62be9d5c1be79ceacfa1ae6e3835b2de446f88 Signed-off-by: shangxdy <shang.xiaodong@zte.com.cn>
-rw-r--r--tosca2heat/tosca-parser/toscaparser/common/exception.py9
-rw-r--r--tosca2heat/tosca-parser/toscaparser/substitution_mappings.py58
-rw-r--r--tosca2heat/tosca-parser/toscaparser/tests/data/topology_template/databasesubsystem.yaml8
-rw-r--r--tosca2heat/tosca-parser/toscaparser/tests/data/topology_template/queuingsubsystem.yaml15
-rw-r--r--tosca2heat/tosca-parser/toscaparser/tests/data/topology_template/transactionsubsystem.yaml6
-rw-r--r--tosca2heat/tosca-parser/toscaparser/tests/test_topology_template.py2
6 files changed, 73 insertions, 25 deletions
diff --git a/tosca2heat/tosca-parser/toscaparser/common/exception.py b/tosca2heat/tosca-parser/toscaparser/common/exception.py
index 724844b..13ccabd 100644
--- a/tosca2heat/tosca-parser/toscaparser/common/exception.py
+++ b/tosca2heat/tosca-parser/toscaparser/common/exception.py
@@ -114,6 +114,10 @@ class UnknownInputError(TOSCAException):
msg_fmt = _('Unknown input "%(input_name)s".')
+class UnknownOutputError(TOSCAException):
+ msg_fmt = _('Unknown output "%(output_name)s" in %(where)s.')
+
+
class MissingRequiredInputError(TOSCAException):
msg_fmt = _('%(what)s is missing required input definition '
'of input "%(input_name)s".')
@@ -129,6 +133,11 @@ class MissingDefaultValueError(TOSCAException):
'of input "%(input_name)s".')
+class MissingRequiredOutputError(TOSCAException):
+ msg_fmt = _('%(what)s is missing required output definition '
+ 'of output "%(output_name)s".')
+
+
class InvalidPropertyValueError(TOSCAException):
msg_fmt = _('Value of property "%(what)s" is invalid.')
diff --git a/tosca2heat/tosca-parser/toscaparser/substitution_mappings.py b/tosca2heat/tosca-parser/toscaparser/substitution_mappings.py
index d4653c3..dea5de7 100644
--- a/tosca2heat/tosca-parser/toscaparser/substitution_mappings.py
+++ b/tosca2heat/tosca-parser/toscaparser/substitution_mappings.py
@@ -17,7 +17,9 @@ from toscaparser.common.exception import InvalidNodeTypeError
from toscaparser.common.exception import MissingDefaultValueError
from toscaparser.common.exception import MissingRequiredFieldError
from toscaparser.common.exception import MissingRequiredInputError
+from toscaparser.common.exception import MissingRequiredOutputError
from toscaparser.common.exception import UnknownFieldError
+from toscaparser.common.exception import UnknownOutputError
from toscaparser.elements.nodetype import NodeType
from toscaparser.utils.gettextutils import _
@@ -34,6 +36,8 @@ class SubstitutionMappings(object):
SECTIONS = (NODE_TYPE, REQUIREMENTS, CAPABILITIES) = \
('node_type', 'requirements', 'capabilities')
+ OPTIONAL_OUTPUTS = ['tosca_id', 'tosca_name', 'state']
+
def __init__(self, sub_mapping_def, nodetemplates, inputs, outputs,
sub_mapped_node_template, custom_defs):
self.nodetemplates = nodetemplates
@@ -110,9 +114,9 @@ class SubstitutionMappings(object):
"""validate the inputs of substitution mappings.
The inputs defined by the topology template have to match the
- properties of the node type or the substituted node. If there are
- more inputs than the substituted node has properties, default values
- must be defined for those inputs.
+ properties of the node type or the substituted node template. If
+ there are more inputs than the substituted node has properties,
+ default values must be defined for those inputs.
"""
all_inputs = set([input.name for input in self.inputs])
@@ -136,9 +140,7 @@ class SubstitutionMappings(object):
customized_parameters = set(self.sub_mapped_node_template
.get_properties().keys()
if self.sub_mapped_node_template else [])
- all_properties = set([p.name for p in
- self.node_definition.
- get_properties_def_objects()])
+ all_properties = set(self.node_definition.get_properties_def())
for parameter in customized_parameters - all_inputs:
if parameter in all_properties:
ExceptionCollector.appendException(
@@ -191,14 +193,36 @@ class SubstitutionMappings(object):
# field=req))
def _validate_outputs(self):
- """validate the outputs of substitution mappings."""
- pass
- # The outputs in service template which defines substutition mappings
- # must be in atrributes of node template wchich be mapped.
- # outputs_names = self.sub_mapped_node_template.get_properties().
- # keys() if self.sub_mapped_node_template else None
- # for name in outputs_names:
- # if name not in [output.name for input in self.outputs]:
- # ExceptionCollector.appendException(
- # UnknownFieldError(what='SubstitutionMappings',
- # field=name))
+ """validate the outputs of substitution mappings.
+
+ The outputs defined by the topology template have to match the
+ attributes of the node type or the substituted node template,
+ and the observable attributes of the substituted node template
+ have to be defined as attributes of the node type or outputs in
+ the topology template.
+ """
+
+ # The outputs defined by the topology template have to match the
+ # attributes of the node type according to the specification, but
+ # it's reasonable that there are more inputs than the node type
+ # has properties, the specification will be amended?
+ for output in self.outputs:
+ if output.name not in self.node_definition.get_attributes_def():
+ ExceptionCollector.appendException(
+ UnknownOutputError(
+ where=_('SubstitutionMappings with node_type ')
+ + self.node_type,
+ output_name=output.name))
+
+ # The observable attributes of the substituted node template
+ # have to be defined as attributes of the node type or outputs in
+ # the topology template, the attributes in tosca.node.root are
+ # optional.
+ for attribute in self.node_definition.get_attributes_def():
+ if attribute not in [output.name for output in self.outputs] \
+ and attribute not in self.OPTIONAL_OUTPUTS:
+ ExceptionCollector.appendException(
+ MissingRequiredOutputError(
+ what=_('SubstitutionMappings with node_type ')
+ + self.node_type,
+ output_name=attribute))
diff --git a/tosca2heat/tosca-parser/toscaparser/tests/data/topology_template/databasesubsystem.yaml b/tosca2heat/tosca-parser/toscaparser/tests/data/topology_template/databasesubsystem.yaml
index ebf1856..6990679 100644
--- a/tosca2heat/tosca-parser/toscaparser/tests/data/topology_template/databasesubsystem.yaml
+++ b/tosca2heat/tosca-parser/toscaparser/tests/data/topology_template/databasesubsystem.yaml
@@ -75,10 +75,10 @@ topology_template:
distribution: Ubuntu
version: 14.04
- outputs:
- receiver_ip:
- description: private IP address of the database application
- value: { get_attribute: [ server, private_address ] }
+# outputs:
+# receiver_ip:
+# description: private IP address of the database application
+# value: { get_attribute: [ server, private_address ] }
# It seems current _process_intrisic_function can not handle more than 2 arguments, save it for later
# receiver_port:
# description: Port of the message receiver endpoint
diff --git a/tosca2heat/tosca-parser/toscaparser/tests/data/topology_template/queuingsubsystem.yaml b/tosca2heat/tosca-parser/toscaparser/tests/data/topology_template/queuingsubsystem.yaml
index 76fa7e2..8c4cc76 100644
--- a/tosca2heat/tosca-parser/toscaparser/tests/data/topology_template/queuingsubsystem.yaml
+++ b/tosca2heat/tosca-parser/toscaparser/tests/data/topology_template/queuingsubsystem.yaml
@@ -61,9 +61,18 @@ topology_template:
version: 14.04
outputs:
- receiver_ip:
- description: private IP address of the message receiver application
- value: { get_attribute: [ server, private_address ] }
+# receiver_ip:
+# description: private IP address of the message receiver application
+# value: { get_attribute: [ server, private_address ] }
+
+ server_ip:
+ description: server_ip of the message receiver application
+ value: { get_input: server_ip }
+
+ server_port:
+ description: server_port of the message receiver application
+ value: { get_input: server_port }
+
# It seems current _process_intrisic_function can not handle more than 2 arguments, save it for later
# receiver_port:
# description: Port of the message receiver endpoint
diff --git a/tosca2heat/tosca-parser/toscaparser/tests/data/topology_template/transactionsubsystem.yaml b/tosca2heat/tosca-parser/toscaparser/tests/data/topology_template/transactionsubsystem.yaml
index 0f145a3..7b839d7 100644
--- a/tosca2heat/tosca-parser/toscaparser/tests/data/topology_template/transactionsubsystem.yaml
+++ b/tosca2heat/tosca-parser/toscaparser/tests/data/topology_template/transactionsubsystem.yaml
@@ -77,6 +77,12 @@ topology_template:
receiver_ip:
description: private IP address of the message receiver application
value: { get_attribute: [ server, private_address ] }
+
+ receiver_port:
+ description: receiver_port of the message receiver application
+ value: { get_input: receiver_port }
+
+
# It seems current _process_intrisic_function can not handle more than 2 arguments, save it for later
# receiver_port:
# description: Port of the message receiver endpoint
diff --git a/tosca2heat/tosca-parser/toscaparser/tests/test_topology_template.py b/tosca2heat/tosca-parser/toscaparser/tests/test_topology_template.py
index 6974d52..eb8d589 100644
--- a/tosca2heat/tosca-parser/toscaparser/tests/test_topology_template.py
+++ b/tosca2heat/tosca-parser/toscaparser/tests/test_topology_template.py
@@ -154,7 +154,7 @@ class TopologyTemplateTest(TestCase):
def test_outputs(self):
self.assertEqual(
- ['receiver_ip'],
+ sorted(['receiver_ip', 'receiver_port']),
sorted([output.name for output in self.topo.outputs]))
def test_groups(self):