diff --git a/toscaparser/functions.py b/toscaparser/functions.py index f143e67..8261b21 100644 --- a/toscaparser/functions.py +++ b/toscaparser/functions.py @@ -120,15 +120,31 @@ class GetAttribute(Function): * { get_attribute: [ server, private_address ] } * { get_attribute: [ HOST, private_address ] } + * { get_attribute: [ HOST, private_address, 0 ] } """ def validate(self): - if len(self.args) != 2: + if len(self.args) != 2 and len(self.args) != 3: ExceptionCollector.appendException( ValueError(_('Illegal arguments for function "{0}". Expected ' 'arguments: "node-template-name", ' '"attribute-name"').format(GET_ATTRIBUTE))) - self._find_node_template_containing_attribute() + node_tpl = self._find_node_template_containing_attribute() + if len(self.args) > 2: + # Currently we only check the first level + attrs_def = node_tpl.type_definition.get_attributes_def() + attr_def = attrs_def[self.attribute_name] + if attr_def.schema['type'] == "list": + if not isinstance(self.args[2], int): + ExceptionCollector.appendException( + ValueError(_('Illegal arguments for function "{0}". ' + 'Third argument must be a positive' + ' integer') .format(GET_ATTRIBUTE))) + elif attr_def.schema['type'] != "map": + ExceptionCollector.appendException( + ValueError(_('Illegal arguments for function "{0}". ' + 'Expected arguments: "node-template-name", ' + '"attribute-name"').format(GET_ATTRIBUTE))) def result(self): return self diff --git a/toscaparser/tests/data/custom_types/compute_with_attribute_list.yaml b/toscaparser/tests/data/custom_types/compute_with_attribute_list.yaml new file mode 100644 index 0000000..3487433 --- /dev/null +++ b/toscaparser/tests/data/custom_types/compute_with_attribute_list.yaml @@ -0,0 +1,13 @@ +tosca_definitions_version: tosca_simple_yaml_1_0 + +description: Compute node type with a list attribute + +node_types: + tosca.nodes.ComputeWithAttrList: + derived_from: tosca.nodes.Compute + attributes: + attr_list: + type: map + entry_schema: + type: string + diff --git a/toscaparser/tests/data/functions/test_get_attribute_with_index.yaml b/toscaparser/tests/data/functions/test_get_attribute_with_index.yaml new file mode 100644 index 0000000..5766490 --- /dev/null +++ b/toscaparser/tests/data/functions/test_get_attribute_with_index.yaml @@ -0,0 +1,19 @@ +tosca_definitions_version: tosca_simple_yaml_1_0 + +description: > + TOSCA template for testing get_attribute with a list attribute and an index + +imports: + - ../custom_types/compute_with_attribute_list.yaml + +topology_template: + node_templates: + server: + type: tosca.nodes.ComputeWithAttrList + interfaces: + Standard: + configure: + implementation: configure.sh + inputs: + ip_address: { get_attribute: [ SELF, attr_list, 0 ] } + diff --git a/toscaparser/tests/data/functions/test_get_attribute_with_index_error.yaml b/toscaparser/tests/data/functions/test_get_attribute_with_index_error.yaml new file mode 100644 index 0000000..88a2721 --- /dev/null +++ b/toscaparser/tests/data/functions/test_get_attribute_with_index_error.yaml @@ -0,0 +1,19 @@ +tosca_definitions_version: tosca_simple_yaml_1_0 + +description: > + TOSCA template for testing get_attribute with a list attribute and an index + +imports: + - ../custom_types/compute_with_attribute_list.yaml + +topology_template: + node_templates: + server: + type: tosca.nodes.ComputeWithAttrList + interfaces: + Standard: + configure: + implementation: configure.sh + inputs: + ip_address: { get_attribute: [ SELF, private_address, 0 ] } + diff --git a/toscaparser/tests/test_functions.py b/toscaparser/tests/test_functions.py index 182d8e1..d5671c0 100644 --- a/toscaparser/tests/test_functions.py +++ b/toscaparser/tests/test_functions.py @@ -188,7 +188,7 @@ class GetAttributeTest(TestCase): self.assertIn(expected_msg, six.text_type(err)) err = self.assertRaises(ValueError, functions.get_function, None, None, - {'get_attribute': ['x', 'y', 'z']}) + {'get_attribute': ['x', 'y', 'z', 'k']}) self.assertIn(expected_msg, six.text_type(err)) def test_get_attribute_unknown_node_template_name(self): @@ -243,3 +243,16 @@ class GetAttributeTest(TestCase): ValueError, _('"get_attribute: [ HOST, ... ]" is not allowed in "outputs" ' 'section of the TOSCA template.')) + + def test_get_attribute_with_index(self): + self._load_template( + 'functions/test_get_attribute_with_index.yaml') + + def test_get_attribute_with_index_error(self): + self.assertRaises( + exception.ValidationError, self._load_template, + 'functions/test_get_attribute_with_index_error.yaml') + exception.ExceptionCollector.assertExceptionMessage( + ValueError, + _('Illegal arguments for function "get_attribute". ' + 'Expected arguments: "node-template-name", "attribute-name"'))