From f52871b8f5ed66924ae8c715788d0bc09c1518ac Mon Sep 17 00:00:00 2001 From: shangxdy Date: Mon, 15 Aug 2016 15:43:07 +0800 Subject: Add required definition in class of Input. As a template designer; I want to know if the parameters is missed when deploy a template, but currently there is not validation about the required parameters; So i add property in class of Input, and validate the require parameter. Note: the patch will submit to Openstack community too. JIRA:PARSER-88 Change-Id: I5763a18da4037b0f81a55b8c8d83414e685b03d2 Signed-off-by: shangxdy --- tosca2heat/tosca-parser/toscaparser/parameters.py | 9 ++++-- .../functions/test_get_property_with_host.yaml | 1 + .../test_tosca_normative_type_by_shortname.yaml | 1 + .../tests/data/topology_template/system.yaml | 2 +- .../data/tosca_single_instance_wordpress.yaml | 1 + ...stance_wordpress_with_local_abspath_import.yaml | 1 + ..._single_instance_wordpress_with_url_import.yaml | 1 + .../toscaparser/tests/test_functions.py | 2 +- .../toscaparser/tests/test_toscatpl.py | 26 +++++++++++---- .../toscaparser/tests/test_toscatplvalidation.py | 37 ++++++++++++++++------ .../tosca-parser/toscaparser/topology_template.py | 9 +++++- 11 files changed, 70 insertions(+), 20 deletions(-) diff --git a/tosca2heat/tosca-parser/toscaparser/parameters.py b/tosca2heat/tosca-parser/toscaparser/parameters.py index 1d2cb29..ca8e697 100644 --- a/tosca2heat/tosca-parser/toscaparser/parameters.py +++ b/tosca2heat/tosca-parser/toscaparser/parameters.py @@ -35,10 +35,17 @@ class Input(object): self.name = name self.schema = Schema(name, schema_dict) + self._validate_field() + self.validate_type(self.type) + @property def type(self): return self.schema.type + @property + def required(self): + return self.schema.required + @property def description(self): return self.schema.description @@ -52,8 +59,6 @@ class Input(object): return self.schema.constraints def validate(self, value=None): - self._validate_field() - self.validate_type(self.type) if value is not None: self._validate_value(value) diff --git a/tosca2heat/tosca-parser/toscaparser/tests/data/functions/test_get_property_with_host.yaml b/tosca2heat/tosca-parser/toscaparser/tests/data/functions/test_get_property_with_host.yaml index 1ca69ca..1e5f5e6 100644 --- a/tosca2heat/tosca-parser/toscaparser/tests/data/functions/test_get_property_with_host.yaml +++ b/tosca2heat/tosca-parser/toscaparser/tests/data/functions/test_get_property_with_host.yaml @@ -23,6 +23,7 @@ topology_template: db_root_pwd: type: string description: Root password for MySQL. + default: '12345678' db_port: type: PortDef description: Port for the MySQL database. diff --git a/tosca2heat/tosca-parser/toscaparser/tests/data/test_tosca_normative_type_by_shortname.yaml b/tosca2heat/tosca-parser/toscaparser/tests/data/test_tosca_normative_type_by_shortname.yaml index 8a702fb..c0653e7 100644 --- a/tosca2heat/tosca-parser/toscaparser/tests/data/test_tosca_normative_type_by_shortname.yaml +++ b/tosca2heat/tosca-parser/toscaparser/tests/data/test_tosca_normative_type_by_shortname.yaml @@ -10,6 +10,7 @@ topology_template: description: Number of CPUs for the server. constraints: - valid_values: [ 1, 2, 4, 8 ] + default: 2 node_templates: server: diff --git a/tosca2heat/tosca-parser/toscaparser/tests/data/topology_template/system.yaml b/tosca2heat/tosca-parser/toscaparser/tests/data/topology_template/system.yaml index 3c946f3..00fb486 100644 --- a/tosca2heat/tosca-parser/toscaparser/tests/data/topology_template/system.yaml +++ b/tosca2heat/tosca-parser/toscaparser/tests/data/topology_template/system.yaml @@ -15,7 +15,7 @@ topology_template: description: IP address of the message queuing server to receive messages from. mq_server_port: type: integer - default1: 8080 + default: 8080 description: Port to be used for receiving messages. node_templates: diff --git a/tosca2heat/tosca-parser/toscaparser/tests/data/tosca_single_instance_wordpress.yaml b/tosca2heat/tosca-parser/toscaparser/tests/data/tosca_single_instance_wordpress.yaml index 9e686ab..f605b05 100644 --- a/tosca2heat/tosca-parser/toscaparser/tests/data/tosca_single_instance_wordpress.yaml +++ b/tosca2heat/tosca-parser/toscaparser/tests/data/tosca_single_instance_wordpress.yaml @@ -29,6 +29,7 @@ topology_template: db_root_pwd: type: string description: Root password for MySQL. + default: '12345678' db_port: type: PortDef description: Port for the MySQL database. diff --git a/tosca2heat/tosca-parser/toscaparser/tests/data/tosca_single_instance_wordpress_with_local_abspath_import.yaml b/tosca2heat/tosca-parser/toscaparser/tests/data/tosca_single_instance_wordpress_with_local_abspath_import.yaml index 6caac11..9a57eb0 100644 --- a/tosca2heat/tosca-parser/toscaparser/tests/data/tosca_single_instance_wordpress_with_local_abspath_import.yaml +++ b/tosca2heat/tosca-parser/toscaparser/tests/data/tosca_single_instance_wordpress_with_local_abspath_import.yaml @@ -31,6 +31,7 @@ topology_template: db_root_pwd: type: string description: Root password for MySQL. + default: '12345678' db_port: type: PortDef description: Port for the MySQL database. diff --git a/tosca2heat/tosca-parser/toscaparser/tests/data/tosca_single_instance_wordpress_with_url_import.yaml b/tosca2heat/tosca-parser/toscaparser/tests/data/tosca_single_instance_wordpress_with_url_import.yaml index e5f1580..5d41749 100644 --- a/tosca2heat/tosca-parser/toscaparser/tests/data/tosca_single_instance_wordpress_with_url_import.yaml +++ b/tosca2heat/tosca-parser/toscaparser/tests/data/tosca_single_instance_wordpress_with_url_import.yaml @@ -29,6 +29,7 @@ topology_template: db_root_pwd: type: string description: Root password for MySQL. + default: '12345678' db_port: type: PortDef description: Port for the MySQL database. diff --git a/tosca2heat/tosca-parser/toscaparser/tests/test_functions.py b/tosca2heat/tosca-parser/toscaparser/tests/test_functions.py index 4d063e5..81de909 100644 --- a/tosca2heat/tosca-parser/toscaparser/tests/test_functions.py +++ b/tosca2heat/tosca-parser/toscaparser/tests/test_functions.py @@ -116,7 +116,7 @@ class IntrinsicFunctionsTest(TestCase): self.assertEqual(3306, dbms_port.result()) dbms_root_password = self._get_property(mysql_dbms, 'root_password') - self.assertIsNone(dbms_root_password.result()) + self.assertEqual(dbms_root_password.result(), "12345678") def test_get_property_with_host(self): tosca_tpl = os.path.join( diff --git a/tosca2heat/tosca-parser/toscaparser/tests/test_toscatpl.py b/tosca2heat/tosca-parser/toscaparser/tests/test_toscatpl.py index 2488b65..e229d2f 100644 --- a/tosca2heat/tosca-parser/toscaparser/tests/test_toscatpl.py +++ b/tosca2heat/tosca-parser/toscaparser/tests/test_toscatpl.py @@ -452,7 +452,13 @@ class ToscaTemplateTest(TestCase): tosca_tpl = ('https://raw.githubusercontent.com/openstack/' 'tosca-parser/master/toscaparser/tests/data/' 'tosca_single_instance_wordpress.yaml') - tosca = ToscaTemplate(tosca_tpl, None, False) + tosca = ToscaTemplate(tosca_tpl, a_file=False, + parsed_params={"db_name": "mysql", + "db_user": "mysql", + "db_root_pwd": "1234", + "db_pwd": "5678", + "db_port": 3306, + "cpus": 4}) self.assertTrue(tosca.topology_template.custom_defs) def test_url_template_with_local_abspath_import(self): @@ -473,19 +479,27 @@ class ToscaTemplateTest(TestCase): tosca_tpl = ('https://raw.githubusercontent.com/openstack/' 'tosca-parser/master/toscaparser/tests/data/' 'tosca_single_instance_wordpress_with_url_import.yaml') - tosca = ToscaTemplate(tosca_tpl, None, False) + tosca = ToscaTemplate(tosca_tpl, a_file=False, + parsed_params={"db_root_pwd": "1234"}) self.assertTrue(tosca.topology_template.custom_defs) def test_csar_parsing_wordpress(self): csar_archive = os.path.join( os.path.dirname(os.path.abspath(__file__)), 'data/CSAR/csar_wordpress.zip') - self.assertTrue(ToscaTemplate(csar_archive)) + self.assertTrue(ToscaTemplate(csar_archive, + parsed_params={"db_name": "mysql", + "db_user": "mysql", + "db_root_pwd": "1234", + "db_pwd": "5678", + "db_port": 3306, + "cpus": 4})) def test_csar_parsing_elk_url_based(self): csar_archive = ('https://github.com/openstack/tosca-parser/raw/master/' 'toscaparser/tests/data/CSAR/csar_elk.zip') - self.assertTrue(ToscaTemplate(csar_archive, None, False)) + self.assertTrue(ToscaTemplate(csar_archive, a_file=False, + parsed_params={"my_cpus": 4})) def test_nested_imports_in_templates(self): tosca_tpl = os.path.join( @@ -593,7 +607,7 @@ class ToscaTemplateTest(TestCase): tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/CSAR/csar_elk.csar") - tosca = ToscaTemplate(tosca_tpl) + tosca = ToscaTemplate(tosca_tpl, parsed_params={"my_cpus": 2}) self.assertTrue(tosca.topology_template.custom_defs) def test_available_rel_tpls(self): @@ -802,4 +816,4 @@ class ToscaTemplateTest(TestCase): tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/test_containers.yaml") - ToscaTemplate(tosca_tpl) + ToscaTemplate(tosca_tpl, parsed_params={"mysql_root_pwd": "12345678"}) diff --git a/tosca2heat/tosca-parser/toscaparser/tests/test_toscatplvalidation.py b/tosca2heat/tosca-parser/toscaparser/tests/test_toscatplvalidation.py index 986d9e4..57daf7e 100644 --- a/tosca2heat/tosca-parser/toscaparser/tests/test_toscatplvalidation.py +++ b/tosca2heat/tosca-parser/toscaparser/tests/test_toscatplvalidation.py @@ -99,7 +99,7 @@ class ToscaTemplateValidationTest(TestCase): 'verify valid values.')) def test_inputs(self): - tpl_snippet = ''' + tpl_snippet1 = ''' inputs: cpus: type: integer @@ -109,14 +109,33 @@ class ToscaTemplateValidationTest(TestCase): required: yes status: supported ''' - inputs = (toscaparser.utils.yamlparser. - simple_parse(tpl_snippet)['inputs']) - name, attrs = list(inputs.items())[0] - input = Input(name, attrs) - err = self.assertRaises(exception.UnknownFieldError, input.validate) - self.assertEqual(_('Input "cpus" contains unknown field "constraint". ' - 'Refer to the definition to verify valid values.'), - err.__str__()) + tpl_snippet2 = ''' + inputs: + cpus: + type: integer + description: Number of CPUs for the server. + constraints: + - valid_values: [ 1, 2, 4 ] + required: yes + status: supported + ''' + inputs1 = (toscaparser.utils.yamlparser. + simple_parse(tpl_snippet1)['inputs']) + name1, attrs1 = list(inputs1.items())[0] + inputs2 = (toscaparser.utils.yamlparser. + simple_parse(tpl_snippet2)['inputs']) + name2, attrs2 = list(inputs2.items())[0] + try: + Input(name1, attrs1) + except Exception as err: + # err=self.assertRaises(exception.UnknownFieldError, + # input1.validate) + self.assertEqual(_('Input "cpus" contains unknown field ' + '"constraint". Refer to the definition to ' + 'verify valid values.'), + err.__str__()) + input2 = Input(name2, attrs2) + self.assertTrue(input2.required) def _imports_content_test(self, tpl_snippet, path, custom_type_def): imports = (toscaparser.utils.yamlparser. diff --git a/tosca2heat/tosca-parser/toscaparser/topology_template.py b/tosca2heat/tosca-parser/toscaparser/topology_template.py index fe05979..100a06b 100644 --- a/tosca2heat/tosca-parser/toscaparser/topology_template.py +++ b/tosca2heat/tosca-parser/toscaparser/topology_template.py @@ -26,7 +26,6 @@ from toscaparser.substitution_mappings import SubstitutionMappings from toscaparser.tpl_relationship_graph import ToscaGraph from toscaparser.utils.gettextutils import _ - # Topology template key names SECTIONS = (DESCRIPTION, INPUTS, NODE_TEMPLATES, RELATIONSHIP_TEMPLATES, OUTPUTS, GROUPS, @@ -73,6 +72,14 @@ class TopologyTemplate(object): default = input.default if default: input.validate(default) + if (self.parsed_params and input.name not in self.parsed_params + or self.parsed_params is None) and input.required \ + and input.default is None: + exception.ExceptionCollector.appendException( + exception.MissingRequiredParameterError( + what='Template', + input_name=input.name)) + inputs.append(input) return inputs -- cgit 1.2.3-korg