diff --git a/toscaparser/functions.py b/toscaparser/functions.py index 37cdd045..a0df4f39 100644 --- a/toscaparser/functions.py +++ b/toscaparser/functions.py @@ -18,6 +18,7 @@ import six from toscaparser.common.exception import ExceptionCollector from toscaparser.common.exception import UnknownInputError from toscaparser.dataentity import DataEntity +from toscaparser.elements.entity_type import EntityType from toscaparser.utils.gettextutils import _ @@ -179,7 +180,6 @@ class GetAttribute(Function): def _find_host_containing_attribute(self, node_template_name=SELF): node_template = self._find_node_template(node_template_name) if node_template: - from toscaparser.elements.entity_type import EntityType hosted_on_rel = EntityType.TOSCA_DEF[HOSTED_ON] for r in node_template.requirements: for requirement, target_name in r.items(): @@ -328,6 +328,9 @@ class GetProperty(Function): def _find_node_template(self, node_template_name): if node_template_name == SELF: return self.context + # enable the HOST value in the function + if node_template_name == HOST: + return self._find_host_containing_property() if not hasattr(self.tosca_tpl, 'nodetemplates'): return for node_template in self.tosca_tpl.nodetemplates: @@ -338,6 +341,28 @@ class GetProperty(Function): 'Node template "{0}" was not found.' ).format(node_template_name))) + # Add this functions similar to get_attribute case + def _find_host_containing_property(self, node_template_name=SELF): + node_template = self._find_node_template(node_template_name) + hosted_on_rel = EntityType.TOSCA_DEF[HOSTED_ON] + for r in node_template.requirements: + for requirement, target_name in r.items(): + 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 self._property_exists_in_type(target_type): + return target_node + return self._find_host_containing_property( + target_name) + return None + + def _property_exists_in_type(self, type_definition): + props_def = type_definition.get_properties_def() + found = [props_def[self.args[1]]] \ + if self.args[1] in props_def else [] + return len(found) == 1 + def result(self): if len(self.args) == 3: property_value = self._find_req_or_cap_property(self.args[1], diff --git a/toscaparser/tests/data/custom_types/compute_with_prop.yaml b/toscaparser/tests/data/custom_types/compute_with_prop.yaml new file mode 100644 index 00000000..93a82aff --- /dev/null +++ b/toscaparser/tests/data/custom_types/compute_with_prop.yaml @@ -0,0 +1,13 @@ +tosca_definitions_version: tosca_simple_yaml_1_0 + +description: > + Compute node type with a parameter for the get property with host test + +node_types: + tosca.nodes.ComputeWithProp: + derived_from: tosca.nodes.Compute + properties: + test: + required: false + type: integer + diff --git a/toscaparser/tests/data/functions/test_get_property_with_host.yaml b/toscaparser/tests/data/functions/test_get_property_with_host.yaml new file mode 100644 index 00000000..1ca69caf --- /dev/null +++ b/toscaparser/tests/data/functions/test_get_property_with_host.yaml @@ -0,0 +1,65 @@ +tosca_definitions_version: tosca_simple_yaml_1_0 + +description: > + TOSCA simple profile to test the get property function with HOST parameter + +imports: + - ../custom_types/compute_with_prop.yaml + +topology_template: + inputs: + db_name: + type: string + description: The name of the database. + default: wordpress + db_user: + type: string + description: The user name of the DB user. + default: wp_user + db_pwd: + type: string + description: The WordPress database admin account password. + default: wp_pass + db_root_pwd: + type: string + description: Root password for MySQL. + db_port: + type: PortDef + description: Port for the MySQL database. + default: 3306 + + node_templates: + + mysql_database: + type: tosca.nodes.Database + properties: + name: { get_input: db_name } + user: { get_input: db_user } + password: { get_input: db_pwd } + capabilities: + database_endpoint: + properties: + port: { get_input: db_port } + requirements: + - host: mysql_dbms + interfaces: + Standard: + configure: + implementation: mysql/mysql_database_configure.sh + inputs: + db_port: { get_property: [ HOST, port ] } + test: { get_property: [ HOST, test ] } + + mysql_dbms: + type: tosca.nodes.DBMS + properties: + root_password: { get_input: db_root_pwd } + port: { get_input: db_port } + requirements: + - host: server + + server: + type: tosca.nodes.ComputeWithProp + properties: + test: 1 + diff --git a/toscaparser/tests/test_functions.py b/toscaparser/tests/test_functions.py index ccc6f8b4..b21c02c0 100644 --- a/toscaparser/tests/test_functions.py +++ b/toscaparser/tests/test_functions.py @@ -27,9 +27,11 @@ class IntrinsicFunctionsTest(TestCase): params = {'db_name': 'my_wordpress', 'db_user': 'my_db_user'} tosca = ToscaTemplate(tosca_tpl, parsed_params=params) - def _get_node(self, node_name): + def _get_node(self, node_name, tosca=None): + if tosca is None: + tosca = self.tosca return [ - node for node in self.tosca.nodetemplates + node for node in tosca.nodetemplates if node.name == node_name][0] def _get_operation(self, interfaces, operation): @@ -116,6 +118,22 @@ class IntrinsicFunctionsTest(TestCase): 'root_password') self.assertIsNone(dbms_root_password.result()) + def test_get_property_with_host(self): + tosca_tpl = os.path.join( + os.path.dirname(os.path.abspath(__file__)), + "data/functions/test_get_property_with_host.yaml") + mysql_database = self._get_node('mysql_database', + ToscaTemplate(tosca_tpl)) + operation = self._get_operation(mysql_database.interfaces, 'configure') + db_port = operation.inputs['db_port'] + self.assertTrue(isinstance(db_port, functions.GetProperty)) + result = db_port.result() + self.assertEqual(3306, result) + test = operation.inputs['test'] + self.assertTrue(isinstance(test, functions.GetProperty)) + result = test.result() + self.assertEqual(1, result) + class GetAttributeTest(TestCase):