diff --git a/toscaparser/elements/constraints.py b/toscaparser/elements/constraints.py index 3fe1976..c4d862f 100644 --- a/toscaparser/elements/constraints.py +++ b/toscaparser/elements/constraints.py @@ -14,10 +14,10 @@ import collections import datetime import re +import toscaparser from toscaparser.common.exception import InvalidSchemaError from toscaparser.common.exception import ValidationError from toscaparser.elements import scalarunit -from toscaparser.functions import is_function from toscaparser.utils.gettextutils import _ @@ -262,7 +262,8 @@ class GreaterOrEqual(Constraint): 'be comparable.')) def _is_valid(self, value): - if is_function(value) or value >= self.constraint_value: + if toscaparser.functions.is_function(value) or \ + value >= self.constraint_value: return True return False @@ -417,8 +418,8 @@ class ValidValues(Constraint): def _err_msg(self, value): allowed = '[%s]' % ', '.join(str(a) for a in self.constraint_value) - return (_('%(pname)s: %(pvalue)s is not an valid ' - 'value "%(cvalue)s".') % + return (_('%(pname)s: %(pvalue)s is not a valid value. Expected a ' + 'value from "%(cvalue)s".') % dict(pname=self.property_name, pvalue=value, cvalue=allowed)) diff --git a/toscaparser/functions.py b/toscaparser/functions.py index 9ac2ce8..4028aab 100644 --- a/toscaparser/functions.py +++ b/toscaparser/functions.py @@ -16,6 +16,7 @@ import abc import six from toscaparser.common.exception import UnknownInputError +from toscaparser.dataentity import DataEntity from toscaparser.utils.gettextutils import _ @@ -80,9 +81,15 @@ class GetInput(Function): raise UnknownInputError(input_name=self.args[0]) def result(self): - found_input = [input_def for input_def in self.tosca_tpl.inputs - if self.input_name == input_def.name][0] - return found_input.default + if self.tosca_tpl.parsed_params and \ + self.input_name in self.tosca_tpl.parsed_params: + return DataEntity.validate_datatype( + self.tosca_tpl.tpl['inputs'][self.input_name]['type'], + self.tosca_tpl.parsed_params[self.input_name]) + + input = [input_def for input_def in self.tosca_tpl.inputs + if self.input_name == input_def.name][0] + return input.default @property def input_name(self): @@ -307,7 +314,7 @@ class GetProperty(Function): else: property_value = self._find_property(self.args[1]).value if isinstance(property_value, Function): - return property_value + return property_value.result() return get_function(self.tosca_tpl, self.context, property_value) diff --git a/toscaparser/tests/data/CSAR/tosca_elk/Definitions/tosca_elk.yaml b/toscaparser/tests/data/CSAR/tosca_elk/Definitions/tosca_elk.yaml index 66cc04b..932f131 100644 --- a/toscaparser/tests/data/CSAR/tosca_elk/Definitions/tosca_elk.yaml +++ b/toscaparser/tests/data/CSAR/tosca_elk/Definitions/tosca_elk.yaml @@ -43,16 +43,14 @@ topology_template: properties: github_url: { get_input: github_url } requirements: - - host: - node: nodejs - - database_connection: - node: mongo_db + - host: nodejs + - database_connection: mongo_db interfaces: Standard: configure: implementation: ../Scripts/nodejs/config.sh inputs: - github_url: http://github.com/paypal/rest-api-sample-app-nodejs.git + github_url: { get_property: [ SELF, github_url ] } mongodb_ip: { get_attribute: [mongo_server, private_address] } start: ../Scripts/nodejs/start.sh nodejs: @@ -66,16 +64,14 @@ topology_template: mongo_db: type: tosca.nodes.Database requirements: - - host: - node: mongo_dbms + - host: mongo_dbms interfaces: Standard: create: ../Scripts/mongodb/create_database.sh mongo_dbms: type: tosca.nodes.DBMS requirements: - - host: - node: mongo_server + - host: mongo_server interfaces: Standard: create: ../Scripts/mongodb/create.sh @@ -87,8 +83,7 @@ topology_template: elasticsearch: type: tosca.nodes.SoftwareComponent.Elasticsearch requirements: - - host: - node: elasticsearch_server + - host: elasticsearch_server interfaces: Standard: create: ../Scripts/elasticsearch/create.sh @@ -96,8 +91,7 @@ topology_template: logstash: type: tosca.nodes.SoftwareComponent.Logstash requirements: - - host: - node: logstash_server + - host: logstash_server - search_endpoint: node: elasticsearch capability: search_endpoint @@ -116,11 +110,8 @@ topology_template: kibana: type: tosca.nodes.SoftwareComponent.Kibana requirements: - - host: - node: kibana_server - - search_endpoint: - node: elasticsearch - capability: search_endpoint + - host: kibana_server + - search_endpoint: elasticsearch interfaces: Standard: create: ../Scripts/kibana/create.sh @@ -133,8 +124,7 @@ topology_template: app_collectd: type: tosca.nodes.SoftwareComponent.Collectd requirements: - - host: - node: app_server + - host: app_server - log_endpoint: node: logstash capability: log_endpoint @@ -155,8 +145,7 @@ topology_template: app_rsyslog: type: tosca.nodes.SoftwareComponent.Rsyslog requirements: - - host: - node: app_server + - host: app_server - log_endpoint: node: logstash capability: log_endpoint diff --git a/toscaparser/tests/data/CSAR/tosca_single_instance_wordpress/Definitions/tosca_single_instance_wordpress.yaml b/toscaparser/tests/data/CSAR/tosca_single_instance_wordpress/Definitions/tosca_single_instance_wordpress.yaml index 1edee26..96b7db6 100644 --- a/toscaparser/tests/data/CSAR/tosca_single_instance_wordpress/Definitions/tosca_single_instance_wordpress.yaml +++ b/toscaparser/tests/data/CSAR/tosca_single_instance_wordpress/Definitions/tosca_single_instance_wordpress.yaml @@ -33,10 +33,8 @@ topology_template: wordpress: type: tosca.nodes.WebApplication.WordPress requirements: - - host: - node: webserver - - database_endpoint: - node: mysql_database + - host: webserver + - database_endpoint: mysql_database interfaces: Standard: create: Scripts/WordPress/install.sh @@ -54,8 +52,7 @@ topology_template: user: { get_input: db_user } password: { get_input: db_pwd } requirements: - - host: - node: mysql_dbms + - host: mysql_dbms interfaces: Standard: configure: @@ -72,8 +69,7 @@ topology_template: root_password: { get_input: db_root_pwd } port: { get_input: db_port } requirements: - - host: - node: server + - host: server interfaces: Standard: create: Scripts/MYSQLDBMS/install.sh @@ -86,8 +82,7 @@ topology_template: webserver: type: tosca.nodes.WebServer requirements: - - host: - node: server + - host: server interfaces: Standard: create: Scripts/WebServer/install.sh diff --git a/toscaparser/tests/data/tosca_elk.yaml b/toscaparser/tests/data/tosca_elk.yaml index 2576d6e..6fc1756 100644 --- a/toscaparser/tests/data/tosca_elk.yaml +++ b/toscaparser/tests/data/tosca_elk.yaml @@ -51,7 +51,7 @@ topology_template: configure: implementation: nodejs/config.sh inputs: - github_url: http://github.com/paypal/rest-api-sample-app-nodejs.git + github_url: { get_property: [ SELF, github_url ] } mongodb_ip: { get_attribute: [mongo_server, private_address] } start: nodejs/start.sh nodejs: @@ -111,9 +111,7 @@ topology_template: type: tosca.nodes.SoftwareComponent.Kibana requirements: - host: kibana_server - - search_endpoint: - node: elasticsearch - capability: search_endpoint + - search_endpoint: elasticsearch interfaces: Standard: create: kibana/create.sh diff --git a/toscaparser/tests/data/tosca_single_instance_wordpress.yaml b/toscaparser/tests/data/tosca_single_instance_wordpress.yaml index f657034..9e686ab 100644 --- a/toscaparser/tests/data/tosca_single_instance_wordpress.yaml +++ b/toscaparser/tests/data/tosca_single_instance_wordpress.yaml @@ -46,9 +46,9 @@ topology_template: configure: implementation: wordpress/wordpress_configure.sh inputs: - wp_db_name: wordpress - wp_db_user: wp_user - wp_db_password: wp_pass + wp_db_name: { get_property: [ mysql_database, name ] } + wp_db_user: { get_property: [ mysql_database, user ] } + wp_db_password: { get_property: [ mysql_database, password ] } mysql_database: type: tosca.nodes.Database @@ -61,17 +61,17 @@ topology_template: properties: port: { get_input: db_port } requirements: - - host: - node: mysql_dbms + - host: mysql_dbms interfaces: Standard: configure: implementation: mysql/mysql_database_configure.sh inputs: - db_name: wordpress - db_user: wp_user - db_password: wp_pass - db_root_password: passw0rd + db_name: { get_property: [ SELF, name ] } + db_user: { get_property: [ SELF, user ] } + db_password: { get_property: [ SELF, password ] } + db_root_password: { get_property: [ mysql_dbms, root_password ] } + mysql_dbms: type: tosca.nodes.DBMS properties: @@ -84,12 +84,12 @@ topology_template: create: implementation: mysql/mysql_dbms_install.sh inputs: - db_root_password: passw0rd + db_root_password: { get_property: [ mysql_dbms, root_password ] } start: mysql/mysql_dbms_start.sh configure: implementation: mysql/mysql_dbms_configure.sh inputs: - db_port: 3366 + db_port: { get_property: [ mysql_dbms, port ] } webserver: type: tosca.nodes.WebServer @@ -99,6 +99,7 @@ topology_template: Standard: create: webserver/webserver_install.sh start: webserver/webserver_start.sh + server: type: tosca.nodes.Compute capabilities: diff --git a/toscaparser/tests/test_constraints.py b/toscaparser/tests/test_constraints.py index 784ff5b..10cec09 100644 --- a/toscaparser/tests/test_constraints.py +++ b/toscaparser/tests/test_constraints.py @@ -100,8 +100,8 @@ class ConstraintTest(TestCase): constraint = Constraint('prop', Schema.INTEGER, schema) error = self.assertRaises(exception.ValidationError, constraint.validate, 5) - self.assertEqual('prop: 5 is not an valid value "[2, 4, 6, 8]".', - str(error)) + self.assertEqual('prop: 5 is not a valid value. Expected a value from ' + '"[2, 4, 6, 8]".', str(error)) def test_invalid_in_range(self): snippet = 'in_range: {2, 6}' diff --git a/toscaparser/tests/test_datatypes.py b/toscaparser/tests/test_datatypes.py index f5dcd9b..bfc1765 100644 --- a/toscaparser/tests/test_datatypes.py +++ b/toscaparser/tests/test_datatypes.py @@ -221,7 +221,7 @@ class DataTypeTest(TestCase): data = DataEntity('tosca.my.datatypes.PeopleBase', value, DataTypeTest.custom_type_def) error = self.assertRaises(ValueError, data.validate) - self.assertEqual('"123" is not a string', error.__str__()) + self.assertEqual('"123" is not a string.', error.__str__()) # the value of name doesn't meet the defined constraint def test_value_error_in_dataentity(self): @@ -247,7 +247,7 @@ class DataTypeTest(TestCase): data = DataEntity('tosca.my.datatypes.People', value, DataTypeTest.custom_type_def) error = self.assertRaises(ValueError, data.validate) - self.assertEqual('"1" is not a string', error.__str__()) + self.assertEqual('"1" is not a string.', error.__str__()) # contact_pone is an invalid field name in nested datatype def test_validation_in_nested_datatype(self): @@ -289,11 +289,11 @@ class DataTypeTest(TestCase): "data/datatypes/test_custom_datatypes_value_error.yaml") error = self.assertRaises(ValueError, ToscaTemplate, tpl_path) self.assertEqual('"[\'1 foo street\', \'9 bar avenue\']" ' - 'is not a map', error.__str__()) + 'is not a map.', error.__str__()) def test_datatype_in_template_nested_datatype_error(self): tpl_path = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/datatypes/test_custom_datatypes_nested_datatype_error.yaml") error = self.assertRaises(ValueError, ToscaTemplate, tpl_path) - self.assertEqual('"123456789" is not a string', error.__str__()) + self.assertEqual('"123456789" is not a string.', error.__str__()) diff --git a/toscaparser/tests/test_functions.py b/toscaparser/tests/test_functions.py index 268d54b..d66a5b8 100644 --- a/toscaparser/tests/test_functions.py +++ b/toscaparser/tests/test_functions.py @@ -23,7 +23,8 @@ class IntrinsicFunctionsTest(TestCase): tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/tosca_single_instance_wordpress.yaml") - tosca = ToscaTemplate(tosca_tpl) + params = {'db_name': 'my_wordpress', 'db_user': 'my_db_user'} + tosca = ToscaTemplate(tosca_tpl, parsed_params=params) def _get_node(self, node_name): return [ @@ -39,34 +40,30 @@ class IntrinsicFunctionsTest(TestCase): return [prop.value for prop in node_template.get_properties_objects() if prop.name == property_name][0] - def test_get_property(self): - TestCase.skip(self, 'bug #1440247') - mysql_dbms = self._get_node('mysql_dbms') - operation = self._get_operation(mysql_dbms.interfaces, 'configure') - db_root_password = operation.inputs['db_root_password'] - self.assertTrue(isinstance(db_root_password, functions.GetProperty)) - result = db_root_password.result() - self.assertTrue(isinstance(result, functions.GetInput)) + def _get_inputs_dict(self): + inputs = {} + for input in self.tosca.inputs: + inputs[input.name] = input.default + return inputs - def test_get_requirement_property(self): - TestCase.skip(self, 'bug #1440247') + def _get_input(self, name): + self._get_inputs_dict()[name] + + def test_get_property(self): wordpress = self._get_node('wordpress') operation = self._get_operation(wordpress.interfaces, 'configure') - wp_db_port = operation.inputs['wp_db_port'] - self.assertTrue(isinstance(wp_db_port, functions.GetProperty)) - result = wp_db_port.result() - self.assertTrue(isinstance(result, functions.GetInput)) - self.assertEqual('db_port', result.input_name) + wp_db_password = operation.inputs['wp_db_password'] + self.assertTrue(isinstance(wp_db_password, functions.GetProperty)) + result = wp_db_password.result() + self.assertEqual('wp_pass', result) - def test_get_capability_property(self): - TestCase.skip(self, 'bug #1440247') - mysql_database = self._get_node('mysql_database') - 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.assertTrue(isinstance(result, functions.GetInput)) - self.assertEqual('db_port', result.input_name) + def test_get_property_with_input_param(self): + wordpress = self._get_node('wordpress') + operation = self._get_operation(wordpress.interfaces, 'configure') + wp_db_user = operation.inputs['wp_db_user'] + self.assertTrue(isinstance(wp_db_user, functions.GetProperty)) + result = wp_db_user.result() + self.assertEqual('my_db_user', result) def test_unknown_capability_property(self): err = self.assertRaises( @@ -87,13 +84,6 @@ class IntrinsicFunctionsTest(TestCase): expected_inputs.remove(prop.value.input_name) self.assertListEqual(expected_inputs, []) - def test_get_input_in_interface(self): - TestCase.skip(self, 'bug #1440247') - mysql_dbms = self._get_node('mysql_dbms') - operation = self._get_operation(mysql_dbms.interfaces, 'configure') - db_user = operation.inputs['db_user'] - self.assertTrue(isinstance(db_user, functions.GetInput)) - def test_get_input_validation(self): self.assertRaises(exception.UnknownInputError, self._load_template, diff --git a/toscaparser/tests/test_properties.py b/toscaparser/tests/test_properties.py index 8e3ba9d..8eb44ff 100644 --- a/toscaparser/tests/test_properties.py +++ b/toscaparser/tests/test_properties.py @@ -44,7 +44,7 @@ class PropertyTest(TestCase): propertyInstance = Property('test_property', 'a', test_property_schema) error = self.assertRaises(ValueError, propertyInstance.validate) - self.assertEqual('"a" is not a list', str(error)) + self.assertEqual('"a" is not a list.', str(error)) def test_list_entry_schema(self): test_property_schema = {'type': 'list', @@ -73,8 +73,7 @@ class PropertyTest(TestCase): propertyInstance = Property('test_property', [1, 'b'], test_property_schema) error = self.assertRaises(ValueError, propertyInstance.validate) - self.assertEqual('"b" is not an integer', - str(error)) + self.assertEqual('"b" is not an integer.', str(error)) def test_map(self): test_property_schema = {'type': 'map'} @@ -88,7 +87,7 @@ class PropertyTest(TestCase): propertyInstance = Property('test_property', 12, test_property_schema) error = self.assertRaises(ValueError, propertyInstance.validate) - self.assertEqual('"12" is not a map', str(error)) + self.assertEqual('"12" is not a map.', str(error)) def test_map_entry_schema(self): test_property_schema = {'type': 'map', @@ -107,7 +106,7 @@ class PropertyTest(TestCase): {'valid': True, 'contact_name': 123}, test_property_schema) error = self.assertRaises(ValueError, propertyInstance.validate) - self.assertEqual('"123" is not a boolean', str(error)) + self.assertEqual('"123" is not a boolean.', str(error)) def test_boolean(self): test_property_schema = {'type': 'boolean'} @@ -124,7 +123,7 @@ class PropertyTest(TestCase): propertyInstance = Property('test_property', 12, test_property_schema) error = self.assertRaises(ValueError, propertyInstance.validate) - self.assertEqual('"12" is not a boolean', str(error)) + self.assertEqual('"12" is not a boolean.', str(error)) def test_float(self): test_property_schema = {'type': 'float'} @@ -138,7 +137,7 @@ class PropertyTest(TestCase): propertyInstance = Property('test_property', 12, test_property_schema) error = self.assertRaises(ValueError, propertyInstance.validate) - self.assertEqual('"12" is not a float', str(error)) + self.assertEqual('"12" is not a float.', str(error)) def test_timestamp(self): test_property_schema = {'type': 'timestamp'} diff --git a/toscaparser/tests/test_toscatpl.py b/toscaparser/tests/test_toscatpl.py index 5f90124..ae1dbd2 100644 --- a/toscaparser/tests/test_toscatpl.py +++ b/toscaparser/tests/test_toscatpl.py @@ -68,7 +68,7 @@ class ToscaTemplateTest(TestCase): expected_type = "tosca.nodes.Database" expected_properties = ['name', 'password', 'user'] expected_capabilities = ['database_endpoint'] - expected_requirements = [{'host': {'node': 'mysql_dbms'}}] + expected_requirements = [{'host': 'mysql_dbms'}] ''' TODO: needs enhancement in tosca_elk.yaml.. expected_relationshp = ['tosca.relationships.HostedOn'] expected_host = ['mysql_dbms'] diff --git a/toscaparser/tests/test_toscatplvalidation.py b/toscaparser/tests/test_toscatplvalidation.py index 97e3a98..9043052 100644 --- a/toscaparser/tests/test_toscatplvalidation.py +++ b/toscaparser/tests/test_toscatplvalidation.py @@ -730,7 +730,7 @@ custom_types/wordpress.yaml capability: log_endpoint occurrences: [a, w] ''' - expectedmessage = ('"a" is not an integer') + expectedmessage = ('"a" is not an integer.') err = self.assertRaises( ValueError, lambda: self._single_node_template_content_test(tpl_snippet)) @@ -745,7 +745,7 @@ custom_types/wordpress.yaml capability: log_endpoint occurrences: -1 ''' - expectedmessage = ('"-1" is not a list') + expectedmessage = ('"-1" is not a list.') err = self.assertRaises( ValueError, lambda: self._single_node_template_content_test(tpl_snippet)) @@ -1000,7 +1000,7 @@ custom_types/wordpress.yaml lambda: self._single_node_template_content_test(tpl_snippet)) self.assertEqual(expectedmessage, err.__str__()) - # validatating capability property values + # validating capability property values tpl_snippet = ''' node_templates: server: @@ -1010,8 +1010,8 @@ custom_types/wordpress.yaml properties: initiator: test ''' - expectedmessage = ('initiator: test is not an valid value ' - '"[source, target, peer]".') + expectedmessage = ('initiator: test is not a valid value. Expected a ' + 'value from "[source, target, peer]".') err = self.assertRaises( exception.ValidationError, diff --git a/toscaparser/utils/validateutils.py b/toscaparser/utils/validateutils.py index f24e4d4..19f93b0 100644 --- a/toscaparser/utils/validateutils.py +++ b/toscaparser/utils/validateutils.py @@ -42,31 +42,31 @@ def validate_integer(value): try: value = int(value) except Exception: - raise ValueError(_('"%s" is not an integer') % value) + raise ValueError(_('"%s" is not an integer.') % value) return value def validate_float(value): if not isinstance(value, float): - raise ValueError(_('"%s" is not a float') % value) + raise ValueError(_('"%s" is not a float.') % value) return validate_number(value) def validate_string(value): if not isinstance(value, six.string_types): - raise ValueError(_('"%s" is not a string') % value) + raise ValueError(_('"%s" is not a string.') % value) return value def validate_list(value): if not isinstance(value, list): - raise ValueError(_('"%s" is not a list') % value) + raise ValueError(_('"%s" is not a list.') % value) return value def validate_map(value): if not isinstance(value, collections.Mapping): - raise ValueError(_('"%s" is not a map') % value) + raise ValueError(_('"%s" is not a map.') % value) return value @@ -78,7 +78,7 @@ def validate_boolean(value): normalised = value.lower() if normalised in ['true', 'false']: return normalised == 'true' - raise ValueError(_('"%s" is not a boolean') % value) + raise ValueError(_('"%s" is not a boolean.') % value) def validate_timestamp(value):