Add import file with suffix of yml testcases
[parser.git] / tosca2heat / tosca-parser / toscaparser / tests / test_toscatpl.py
1 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
2 #    not use this file except in compliance with the License. You may obtain
3 #    a copy of the License at
4 #
5 #         http://www.apache.org/licenses/LICENSE-2.0
6 #
7 #    Unless required by applicable law or agreed to in writing, software
8 #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10 #    License for the specific language governing permissions and limitations
11 #    under the License.
12
13 import os
14 import six
15 from toscaparser.common import exception
16 import toscaparser.elements.interfaces as ifaces
17 from toscaparser.elements.nodetype import NodeType
18 from toscaparser.elements.portspectype import PortSpec
19 from toscaparser.functions import GetInput
20 from toscaparser.functions import GetProperty
21 from toscaparser.nodetemplate import NodeTemplate
22 from toscaparser.tests.base import TestCase
23 from toscaparser.tosca_template import ToscaTemplate
24 from toscaparser.utils.gettextutils import _
25 import toscaparser.utils.yamlparser
26
27
28 class ToscaTemplateTest(TestCase):
29     '''TOSCA template.'''
30     tosca_tpl = os.path.join(
31         os.path.dirname(os.path.abspath(__file__)),
32         "data/tosca_single_instance_wordpress.yaml")
33     params = {'db_name': 'my_wordpress', 'db_user': 'my_db_user',
34               'db_root_pwd': '12345678'}
35     tosca = ToscaTemplate(tosca_tpl, parsed_params=params)
36     tosca_elk_tpl = os.path.join(
37         os.path.dirname(os.path.abspath(__file__)),
38         "data/tosca_elk.yaml")
39     tosca_repo_tpl = os.path.join(
40         os.path.dirname(os.path.abspath(__file__)),
41         "data/repositories/tosca_repositories_test_definition.yaml")
42
43     def test_version(self):
44         self.assertEqual(self.tosca.version, "tosca_simple_yaml_1_0")
45
46     def test_description(self):
47         expected_description = "TOSCA simple profile with wordpress, " \
48                                "web server and mysql on the same server."
49         self.assertEqual(self.tosca.description, expected_description)
50
51     def test_inputs(self):
52         self.assertEqual(
53             ['cpus', 'db_name', 'db_port',
54              'db_pwd', 'db_root_pwd', 'db_user'],
55             sorted([input.name for input in self.tosca.inputs]))
56
57         input_name = "db_port"
58         expected_description = "Port for the MySQL database."
59         for input in self.tosca.inputs:
60             if input.name == input_name:
61                 self.assertEqual(input.description, expected_description)
62
63     def test_node_tpls(self):
64         '''Test nodetemplate names.'''
65         self.assertEqual(
66             ['mysql_database', 'mysql_dbms', 'server',
67              'webserver', 'wordpress'],
68             sorted([tpl.name for tpl in self.tosca.nodetemplates]))
69
70         tpl_name = "mysql_database"
71         expected_type = "tosca.nodes.Database"
72         expected_properties = ['name', 'password', 'user']
73         expected_capabilities = ['database_endpoint', 'feature']
74         expected_requirements = [{'host': 'mysql_dbms'}]
75         ''' TODO: needs enhancement in tosca_elk.yaml..
76         expected_relationshp = ['tosca.relationships.HostedOn']
77         expected_host = ['mysql_dbms']
78         '''
79         expected_interface = [ifaces.LIFECYCLE_SHORTNAME]
80
81         for tpl in self.tosca.nodetemplates:
82             if tpl_name == tpl.name:
83                 '''Test node type.'''
84                 self.assertEqual(tpl.type, expected_type)
85
86                 '''Test properties.'''
87                 self.assertEqual(
88                     expected_properties,
89                     sorted(tpl.get_properties().keys()))
90
91                 '''Test capabilities.'''
92                 self.assertEqual(
93                     expected_capabilities,
94                     sorted(tpl.get_capabilities().keys()))
95
96                 '''Test requirements.'''
97                 self.assertEqual(
98                     expected_requirements, tpl.requirements)
99
100                 '''Test relationship.'''
101                 ''' needs enhancements in tosca_elk.yaml
102                 self.assertEqual(
103                     expected_relationshp,
104                     [x.type for x in tpl.relationships.keys()])
105                 self.assertEqual(
106                     expected_host,
107                     [y.name for y in tpl.relationships.values()])
108                 '''
109                 '''Test interfaces.'''
110                 self.assertEqual(
111                     expected_interface,
112                     [x.type for x in tpl.interfaces])
113
114             if tpl.name == 'server':
115                 '''Test property value'''
116                 props = tpl.get_properties()
117                 if props and 'mem_size' in props.keys():
118                     self.assertEqual(props['mem_size'].value, '4096 MB')
119                 '''Test capability'''
120                 caps = tpl.get_capabilities()
121                 self.assertIn('os', caps.keys())
122                 os_props_objs = None
123                 os_props = None
124                 os_type_prop = None
125                 if caps and 'os' in caps.keys():
126                     capability = caps['os']
127                     os_props_objs = capability.get_properties_objects()
128                     os_props = capability.get_properties()
129                     os_type_prop = capability.get_property_value('type')
130                     break
131                 self.assertEqual(
132                     ['Linux'],
133                     [p.value for p in os_props_objs if p.name == 'type'])
134                 self.assertEqual(
135                     'Linux',
136                     os_props['type'].value if 'type' in os_props else '')
137                 self.assertEqual('Linux', os_props['type'].value)
138                 self.assertEqual('Linux', os_type_prop)
139
140     def test_node_inheritance_type(self):
141         wordpress_node = [
142             node for node in self.tosca.nodetemplates
143             if node.name == 'wordpress'][0]
144         self.assertTrue(
145             wordpress_node.is_derived_from("tosca.nodes.WebApplication"))
146         self.assertTrue(
147             wordpress_node.is_derived_from("tosca.nodes.Root"))
148         self.assertFalse(
149             wordpress_node.is_derived_from("tosca.policies.Root"))
150
151     def test_outputs(self):
152         self.assertEqual(
153             ['website_url'],
154             sorted([output.name for output in self.tosca.outputs]))
155
156     def test_interfaces(self):
157         wordpress_node = [
158             node for node in self.tosca.nodetemplates
159             if node.name == 'wordpress'][0]
160         interfaces = wordpress_node.interfaces
161         self.assertEqual(2, len(interfaces))
162         for interface in interfaces:
163             if interface.name == 'create':
164                 self.assertEqual(ifaces.LIFECYCLE_SHORTNAME,
165                                  interface.type)
166                 self.assertEqual('wordpress/wordpress_install.sh',
167                                  interface.implementation)
168                 self.assertIsNone(interface.inputs)
169             elif interface.name == 'configure':
170                 self.assertEqual(ifaces.LIFECYCLE_SHORTNAME,
171                                  interface.type)
172                 self.assertEqual('wordpress/wordpress_configure.sh',
173                                  interface.implementation)
174                 self.assertEqual(3, len(interface.inputs))
175                 TestCase.skip(self, 'bug #1440247')
176                 wp_db_port = interface.inputs['wp_db_port']
177                 self.assertIsInstance(wp_db_port, GetProperty)
178                 self.assertEqual('get_property', wp_db_port.name)
179                 self.assertEqual(['SELF',
180                                   'database_endpoint',
181                                   'port'],
182                                  wp_db_port.args)
183                 result = wp_db_port.result()
184                 self.assertIsInstance(result, GetInput)
185             else:
186                 raise AssertionError(
187                     'Unexpected interface: {0}'.format(interface.name))
188
189     def test_normative_type_by_short_name(self):
190         # test template with a short name Compute
191         template = os.path.join(
192             os.path.dirname(os.path.abspath(__file__)),
193             "data/test_tosca_normative_type_by_shortname.yaml")
194
195         tosca_tpl = ToscaTemplate(template)
196         expected_type = "tosca.nodes.Compute"
197         for tpl in tosca_tpl.nodetemplates:
198             self.assertEqual(tpl.type, expected_type)
199         for tpl in tosca_tpl.nodetemplates:
200             compute_type = NodeType(tpl.type)
201             self.assertEqual(
202                 sorted(['tosca.capabilities.Container',
203                         'tosca.capabilities.Endpoint.Admin',
204                         'tosca.capabilities.Node',
205                         'tosca.capabilities.OperatingSystem',
206                         'tosca.capabilities.network.Bindable',
207                         'tosca.capabilities.Scalable']),
208                 sorted([c.type
209                         for c in compute_type.get_capabilities_objects()]))
210
211     def test_template_with_no_inputs(self):
212         tosca_tpl = self._load_template('test_no_inputs_in_template.yaml')
213         self.assertEqual(0, len(tosca_tpl.inputs))
214
215     def test_template_with_no_outputs(self):
216         tosca_tpl = self._load_template('test_no_outputs_in_template.yaml')
217         self.assertEqual(0, len(tosca_tpl.outputs))
218
219     def test_template_file_with_suffix_yml(self):
220         tosca_tpl = self._load_template('custom_types/wordpress.yml')
221         self.assertIsNotNone(tosca_tpl)
222
223     def test_relationship_interface(self):
224         template = ToscaTemplate(self.tosca_elk_tpl)
225         for node_tpl in template.nodetemplates:
226             if node_tpl.name == 'logstash':
227                 config_interface = 'Configure'
228                 artifact = 'logstash/configure_elasticsearch.py'
229                 relation = node_tpl.relationships
230                 for key in relation.keys():
231                     rel_tpl = relation.get(key).get_relationship_template()
232                     if rel_tpl:
233                         self.assertTrue(rel_tpl[0].is_derived_from(
234                             "tosca.relationships.Root"))
235                         interfaces = rel_tpl[0].interfaces
236                         for interface in interfaces:
237                             self.assertEqual(config_interface,
238                                              interface.type)
239                             self.assertEqual('pre_configure_source',
240                                              interface.name)
241                             self.assertEqual(artifact,
242                                              interface.implementation)
243
244     def test_relationship(self):
245         template = ToscaTemplate(self.tosca_elk_tpl)
246         for node_tpl in template.nodetemplates:
247             if node_tpl.name == 'paypal_pizzastore':
248                 expected_relationships = ['tosca.relationships.ConnectsTo',
249                                           'tosca.relationships.HostedOn']
250                 expected_hosts = ['tosca.nodes.Database',
251                                   'tosca.nodes.WebServer']
252                 self.assertEqual(len(node_tpl.relationships), 2)
253                 self.assertEqual(
254                     expected_relationships,
255                     sorted([k.type for k in node_tpl.relationships.keys()]))
256                 self.assertEqual(
257                     expected_hosts,
258                     sorted([v.type for v in node_tpl.relationships.values()]))
259
260     def test_repositories(self):
261         template = ToscaTemplate(self.tosca_repo_tpl)
262         self.assertEqual(
263             ['repo_code0', 'repo_code1', 'repo_code2'],
264             sorted([input.name for input in template.repositories]))
265
266         input_name = "repo_code2"
267         expected_url = "https://github.com/nandinivemula/intern/master"
268         for input in template.repositories:
269             if input.name == input_name:
270                 self.assertEqual(input.url, expected_url)
271
272     def test_template_macro(self):
273         template = ToscaTemplate(self.tosca_elk_tpl)
274         for node_tpl in template.nodetemplates:
275             if node_tpl.name == 'mongo_server':
276                 self.assertEqual(
277                     ['disk_size', 'mem_size', 'num_cpus'],
278                     sorted(node_tpl.get_capability('host').
279                            get_properties().keys()))
280
281     def test_template_requirements(self):
282         """Test different formats of requirements
283
284         The requirements can be defined in few different ways,
285         1. Requirement expressed as a capability with an implicit relationship.
286         2. Requirement expressed with explicit relationship.
287         3. Requirement expressed with a relationship template.
288         4. Requirement expressed via TOSCA types to provision a node
289            with explicit relationship.
290         5. Requirement expressed via TOSCA types with a filter.
291         """
292         tosca_tpl = os.path.join(
293             os.path.dirname(os.path.abspath(__file__)),
294             "data/requirements/test_requirements.yaml")
295         tosca = ToscaTemplate(tosca_tpl)
296         for node_tpl in tosca.nodetemplates:
297             if node_tpl.name == 'my_app':
298                 expected_relationship = [
299                     ('tosca.relationships.ConnectsTo', 'mysql_database'),
300                     ('tosca.relationships.HostedOn', 'my_webserver')]
301                 actual_relationship = sorted([
302                     (relation.type, node.name) for
303                     relation, node in node_tpl.relationships.items()])
304                 self.assertEqual(expected_relationship, actual_relationship)
305             if node_tpl.name == 'mysql_database':
306                     self.assertEqual(
307                         [('tosca.relationships.HostedOn', 'my_dbms')],
308                         [(relation.type, node.name) for
309                          relation,
310                          node in node_tpl.relationships.items()])
311             if node_tpl.name == 'my_server':
312                     self.assertEqual(
313                         [('tosca.relationships.AttachesTo', 'my_storage')],
314                         [(relation.type, node.name) for
315                          relation,
316                          node in node_tpl.relationships.items()])
317
318     def test_template_requirements_not_implemented(self):
319         # TODO(spzala): replace this test with new one once TOSCA types look up
320         # support is implemented.
321         """Requirements that yet need to be implemented
322
323         The following requirement formats are not yet implemented,
324         due to look up dependency:
325         1. Requirement expressed via TOSCA types to provision a node
326            with explicit relationship.
327         2. Requirement expressed via TOSCA types with a filter.
328         """
329         tpl_snippet_1 = '''
330         node_templates:
331           mysql_database:
332             type: tosca.nodes.Database
333             description: Requires a particular node type and relationship.
334                         To be full-filled via lookup into node repository.
335             requirements:
336               - req1:
337                   node: tosca.nodes.DBMS
338                   relationship: tosca.relationships.HostedOn
339         '''
340
341         tpl_snippet_2 = '''
342         node_templates:
343           my_webserver:
344             type: tosca.nodes.WebServer
345             description: Requires a particular node type with a filter.
346                          To be full-filled via lookup into node repository.
347             requirements:
348               - req1:
349                   node: tosca.nodes.Compute
350                   target_filter:
351                     properties:
352                       num_cpus: { in_range: [ 1, 4 ] }
353                       mem_size: { greater_or_equal: 2 }
354                     capabilities:
355                       - tosca.capabilities.OS:
356                           properties:
357                             architecture: x86_64
358                             type: linux
359         '''
360
361         tpl_snippet_3 = '''
362         node_templates:
363           my_webserver2:
364             type: tosca.nodes.WebServer
365             description: Requires a node type with a particular capability.
366                          To be full-filled via lookup into node repository.
367             requirements:
368               - req1:
369                   node: tosca.nodes.Compute
370                   relationship: tosca.relationships.HostedOn
371                   capability: tosca.capabilities.Container
372         '''
373         self._requirements_not_implemented(tpl_snippet_1, 'mysql_database')
374         self._requirements_not_implemented(tpl_snippet_2, 'my_webserver')
375         self._requirements_not_implemented(tpl_snippet_3, 'my_webserver2')
376
377     def _requirements_not_implemented(self, tpl_snippet, tpl_name):
378         nodetemplates = (toscaparser.utils.yamlparser.
379                          simple_parse(tpl_snippet))['node_templates']
380         self.assertRaises(
381             NotImplementedError,
382             lambda: NodeTemplate(tpl_name, nodetemplates).relationships)
383
384     # Test the following:
385     # 1. Custom node type derived from 'WebApplication' named 'TestApp'
386     #    with a custom Capability Type 'TestCapability'
387     # 2. Same as #1, but referencing a custom 'TestCapability' Capability Type
388     #    that is not defined
389     def test_custom_capability_type_definition(self):
390         tpl_snippet = '''
391         node_templates:
392           test_app:
393             type: tosca.nodes.WebApplication.TestApp
394             capabilities:
395               test_cap:
396                 properties:
397                   test: 1
398         '''
399         # custom node type definition with custom capability type definition
400         custom_def = '''
401         tosca.nodes.WebApplication.TestApp:
402           derived_from: tosca.nodes.WebApplication
403           capabilities:
404             test_cap:
405                type: tosca.capabilities.TestCapability
406         tosca.capabilities.TestCapability:
407           derived_from: tosca.capabilities.Root
408           properties:
409             test:
410               type: integer
411               required: false
412         '''
413         expected_capabilities = ['app_endpoint', 'feature', 'test_cap']
414         nodetemplates = (toscaparser.utils.yamlparser.
415                          simple_parse(tpl_snippet))['node_templates']
416         custom_def = (toscaparser.utils.yamlparser.
417                       simple_parse(custom_def))
418         name = list(nodetemplates.keys())[0]
419         tpl = NodeTemplate(name, nodetemplates, custom_def)
420         self.assertEqual(
421             expected_capabilities,
422             sorted(tpl.get_capabilities().keys()))
423
424         # custom definition without valid capability type definition
425         custom_def = '''
426         tosca.nodes.WebApplication.TestApp:
427           derived_from: tosca.nodes.WebApplication
428           capabilities:
429             test_cap:
430                type: tosca.capabilities.TestCapability
431         '''
432         custom_def = (toscaparser.utils.yamlparser.
433                       simple_parse(custom_def))
434         tpl = NodeTemplate(name, nodetemplates, custom_def)
435         err = self.assertRaises(
436             exception.InvalidTypeError,
437             lambda: NodeTemplate(name, nodetemplates,
438                                  custom_def).get_capabilities_objects())
439         self.assertEqual('Type "tosca.capabilities.TestCapability" is not '
440                          'a valid type.', six.text_type(err))
441
442     def test_local_template_with_local_relpath_import(self):
443         tosca_tpl = os.path.join(
444             os.path.dirname(os.path.abspath(__file__)),
445             "data/tosca_single_instance_wordpress.yaml")
446         params = {'db_name': 'my_wordpress', 'db_user': 'my_db_user',
447                   'db_root_pwd': '12345678'}
448         tosca = ToscaTemplate(tosca_tpl, parsed_params=params)
449         self.assertTrue(tosca.topology_template.custom_defs)
450
451     def test_local_template_with_url_import(self):
452         tosca_tpl = os.path.join(
453             os.path.dirname(os.path.abspath(__file__)),
454             "data/tosca_single_instance_wordpress_with_url_import.yaml")
455         tosca = ToscaTemplate(tosca_tpl,
456                               parsed_params={'db_root_pwd': '123456'})
457         self.assertTrue(tosca.topology_template.custom_defs)
458
459     def test_url_template_with_local_relpath_import(self):
460         tosca_tpl = ('https://raw.githubusercontent.com/openstack/'
461                      'tosca-parser/master/toscaparser/tests/data/'
462                      'tosca_single_instance_wordpress.yaml')
463         tosca = ToscaTemplate(tosca_tpl, a_file=False,
464                               parsed_params={"db_name": "mysql",
465                                              "db_user": "mysql",
466                                              "db_root_pwd": "1234",
467                                              "db_pwd": "5678",
468                                              "db_port": 3306,
469                                              "cpus": 4})
470         self.assertTrue(tosca.topology_template.custom_defs)
471
472     def test_url_template_with_local_abspath_import(self):
473         tosca_tpl = ('https://raw.githubusercontent.com/openstack/'
474                      'tosca-parser/master/toscaparser/tests/data/'
475                      'tosca_single_instance_wordpress_with_local_abspath_'
476                      'import.yaml')
477         self.assertRaises(exception.ValidationError, ToscaTemplate, tosca_tpl,
478                           None, False)
479         err_msg = (_('Absolute file name "/tmp/tosca-parser/toscaparser/tests'
480                      '/data/custom_types/wordpress.yaml" cannot be used in a '
481                      'URL-based input template "%(tpl)s".')
482                    % {'tpl': tosca_tpl})
483         exception.ExceptionCollector.assertExceptionMessage(ImportError,
484                                                             err_msg)
485
486     def test_url_template_with_url_import(self):
487         tosca_tpl = ('https://raw.githubusercontent.com/openstack/'
488                      'tosca-parser/master/toscaparser/tests/data/'
489                      'tosca_single_instance_wordpress_with_url_import.yaml')
490         tosca = ToscaTemplate(tosca_tpl, a_file=False,
491                               parsed_params={"db_root_pwd": "1234"})
492         self.assertTrue(tosca.topology_template.custom_defs)
493
494     def test_csar_parsing_wordpress(self):
495         csar_archive = os.path.join(
496             os.path.dirname(os.path.abspath(__file__)),
497             'data/CSAR/csar_wordpress.zip')
498         self.assertTrue(ToscaTemplate(csar_archive,
499                                       parsed_params={"db_name": "mysql",
500                                                      "db_user": "mysql",
501                                                      "db_root_pwd": "1234",
502                                                      "db_pwd": "5678",
503                                                      "db_port": 3306,
504                                                      "cpus": 4}))
505
506     def test_csar_parsing_elk_url_based(self):
507         csar_archive = ('https://github.com/openstack/tosca-parser/raw/master/'
508                         'toscaparser/tests/data/CSAR/csar_elk.zip')
509         self.assertTrue(ToscaTemplate(csar_archive, a_file=False,
510                                       parsed_params={"my_cpus": 4}))
511
512     def test_nested_imports_in_templates(self):
513         tosca_tpl = os.path.join(
514             os.path.dirname(os.path.abspath(__file__)),
515             "data/test_instance_nested_imports.yaml")
516         tosca = ToscaTemplate(tosca_tpl)
517         expected_custom_types = ['tosca.nodes.SoftwareComponent.Kibana',
518                                  'tosca.nodes.WebApplication.WordPress',
519                                  'test_namespace_prefix.Rsyslog',
520                                  'Test2ndRsyslogType',
521                                  'test_2nd_namespace_prefix.Rsyslog',
522                                  'tosca.nodes.SoftwareComponent.Logstash',
523                                  'tosca.nodes.SoftwareComponent.Rsyslog.'
524                                  'TestRsyslogType']
525         self.assertItemsEqual(tosca.topology_template.custom_defs.keys(),
526                               expected_custom_types)
527
528     def test_invalid_template_file(self):
529         template_file = 'invalid template file'
530         expected_msg = (_('"%s" is not a valid file.') % template_file)
531         self.assertRaises(
532             exception.ValidationError,
533             ToscaTemplate, template_file, None, False)
534         exception.ExceptionCollector.assertExceptionMessage(ValueError,
535                                                             expected_msg)
536
537     def test_multiple_validation_errors(self):
538         tosca_tpl = os.path.join(
539             os.path.dirname(os.path.abspath(__file__)),
540             "data/test_multiple_validation_errors.yaml")
541         self.assertRaises(exception.ValidationError, ToscaTemplate, tosca_tpl,
542                           None)
543         valid_versions = ', '.join(ToscaTemplate.VALID_TEMPLATE_VERSIONS)
544         err1_msg = (_('The template version "tosca_simple_yaml_1" is invalid. '
545                       'Valid versions are "%s".') % valid_versions)
546         exception.ExceptionCollector.assertExceptionMessage(
547             exception.InvalidTemplateVersion, err1_msg)
548
549         err2_msg = _('Import "custom_types/not_there.yaml" is not valid.')
550         exception.ExceptionCollector.assertExceptionMessage(
551             ImportError, err2_msg)
552
553         err3_msg = _('Type "tosca.nodes.WebApplication.WordPress" is not a '
554                      'valid type.')
555         exception.ExceptionCollector.assertExceptionMessage(
556             exception.InvalidTypeError, err3_msg)
557
558         err4_msg = _('Node template "wordpress" contains unknown field '
559                      '"requirement". Refer to the definition to verify valid '
560                      'values.')
561         exception.ExceptionCollector.assertExceptionMessage(
562             exception.UnknownFieldError, err4_msg)
563
564         err5_msg = _('\'Property "passwords" was not found in node template '
565                      '"mysql_database".\'')
566         exception.ExceptionCollector.assertExceptionMessage(
567             KeyError, err5_msg)
568
569         err6_msg = _('Template "mysql_dbms" is missing required field "type".')
570         exception.ExceptionCollector.assertExceptionMessage(
571             exception.MissingRequiredFieldError, err6_msg)
572
573         err7_msg = _('Node template "mysql_dbms" contains unknown field '
574                      '"type1". Refer to the definition to verify valid '
575                      'values.')
576         exception.ExceptionCollector.assertExceptionMessage(
577             exception.UnknownFieldError, err7_msg)
578
579         err8_msg = _('\'Node template "server1" was not found in '
580                      '"webserver".\'')
581         exception.ExceptionCollector.assertExceptionMessage(
582             KeyError, err8_msg)
583
584         err9_msg = _('"relationship" used in template "webserver" is missing '
585                      'required field "type".')
586         exception.ExceptionCollector.assertExceptionMessage(
587             exception.MissingRequiredFieldError, err9_msg)
588
589         err10_msg = _('Type "tosca.nodes.XYZ" is not a valid type.')
590         exception.ExceptionCollector.assertExceptionMessage(
591             exception.InvalidTypeError, err10_msg)
592
593     def test_invalid_section_names(self):
594         tosca_tpl = os.path.join(
595             os.path.dirname(os.path.abspath(__file__)),
596             "data/test_invalid_section_names.yaml")
597         self.assertRaises(exception.ValidationError, ToscaTemplate, tosca_tpl,
598                           None)
599         err1_msg = _('Template contains unknown field '
600                      '"tosca_definitions_versions". Refer to the definition '
601                      'to verify valid values.')
602         exception.ExceptionCollector.assertExceptionMessage(
603             exception.UnknownFieldError, err1_msg)
604
605         err2_msg = _('Template contains unknown field "descriptions". '
606                      'Refer to the definition to verify valid values.')
607         exception.ExceptionCollector.assertExceptionMessage(
608             exception.UnknownFieldError, err2_msg)
609
610         err3_msg = _('Template contains unknown field "import". Refer to '
611                      'the definition to verify valid values.')
612         exception.ExceptionCollector.assertExceptionMessage(
613             exception.UnknownFieldError, err3_msg)
614
615         err4_msg = _('Template contains unknown field "topology_templates". '
616                      'Refer to the definition to verify valid values.')
617         exception.ExceptionCollector.assertExceptionMessage(
618             exception.UnknownFieldError, err4_msg)
619
620     def test_csar_with_alternate_extenstion(self):
621         tosca_tpl = os.path.join(
622             os.path.dirname(os.path.abspath(__file__)),
623             "data/CSAR/csar_elk.csar")
624         tosca = ToscaTemplate(tosca_tpl, parsed_params={"my_cpus": 2})
625         self.assertTrue(tosca.topology_template.custom_defs)
626
627     def test_available_rel_tpls(self):
628         tosca_tpl = os.path.join(
629             os.path.dirname(os.path.abspath(__file__)),
630             "data/test_available_rel_tpls.yaml")
631         tosca = ToscaTemplate(tosca_tpl)
632         for node in tosca.nodetemplates:
633             for relationship, target in node.relationships.items():
634                 try:
635                     target.relationships
636                 except TypeError as error:
637                     self.fail(error)
638
639     def test_no_input(self):
640         self.assertRaises(exception.ValidationError, ToscaTemplate, None,
641                           None, False, None)
642         err_msg = (('No path or yaml_dict_tpl was provided. '
643                     'There is nothing to parse.'))
644         exception.ExceptionCollector.assertExceptionMessage(ValueError,
645                                                             err_msg)
646
647     def test_path_and_yaml_dict_tpl_input(self):
648         test_tpl = os.path.join(
649             os.path.dirname(os.path.abspath(__file__)),
650             "data/tosca_helloworld.yaml")
651
652         yaml_dict_tpl = toscaparser.utils.yamlparser.load_yaml(test_tpl)
653
654         tosca = ToscaTemplate(test_tpl, yaml_dict_tpl=yaml_dict_tpl)
655
656         self.assertEqual(tosca.version, "tosca_simple_yaml_1_0")
657
658     def test_yaml_dict_tpl_input(self):
659         test_tpl = os.path.join(
660             os.path.dirname(os.path.abspath(__file__)),
661             "data/tosca_helloworld.yaml")
662
663         yaml_dict_tpl = toscaparser.utils.yamlparser.load_yaml(test_tpl)
664
665         tosca = ToscaTemplate(yaml_dict_tpl=yaml_dict_tpl)
666
667         self.assertEqual(tosca.version, "tosca_simple_yaml_1_0")
668
669     def test_yaml_dict_tpl_with_params_and_url_import(self):
670         test_tpl = os.path.join(
671             os.path.dirname(os.path.abspath(__file__)),
672             "data/tosca_single_instance_wordpress_with_url_import.yaml")
673
674         yaml_dict_tpl = toscaparser.utils.yamlparser.load_yaml(test_tpl)
675
676         params = {'db_name': 'my_wordpress', 'db_user': 'my_db_user',
677                   'db_root_pwd': 'mypasswd'}
678
679         tosca = ToscaTemplate(parsed_params=params,
680                               yaml_dict_tpl=yaml_dict_tpl)
681
682         self.assertEqual(tosca.version, "tosca_simple_yaml_1_0")
683
684     def test_yaml_dict_tpl_with_rel_import(self):
685         test_tpl = os.path.join(
686             os.path.dirname(os.path.abspath(__file__)),
687             "data/tosca_single_instance_wordpress.yaml")
688
689         yaml_dict_tpl = toscaparser.utils.yamlparser.load_yaml(test_tpl)
690         params = {'db_name': 'my_wordpress', 'db_user': 'my_db_user',
691                   'db_root_pwd': '12345678'}
692         self.assertRaises(exception.ValidationError, ToscaTemplate, None,
693                           params, False, yaml_dict_tpl)
694         err_msg = (_('Relative file name "custom_types/wordpress.yaml" '
695                      'cannot be used in a pre-parsed input template.'))
696         exception.ExceptionCollector.assertExceptionMessage(ImportError,
697                                                             err_msg)
698
699     def test_yaml_dict_tpl_with_fullpath_import(self):
700         test_tpl = os.path.join(
701             os.path.dirname(os.path.abspath(__file__)),
702             "data/tosca_single_instance_wordpress.yaml")
703
704         yaml_dict_tpl = toscaparser.utils.yamlparser.load_yaml(test_tpl)
705
706         yaml_dict_tpl['imports'] = [os.path.join(os.path.dirname(
707             os.path.abspath(__file__)), "data/custom_types/wordpress.yaml")]
708
709         params = {'db_name': 'my_wordpress', 'db_user': 'my_db_user',
710                   'db_root_pwd': 'mypasswd'}
711
712         tosca = ToscaTemplate(parsed_params=params,
713                               yaml_dict_tpl=yaml_dict_tpl)
714
715         self.assertEqual(tosca.version, "tosca_simple_yaml_1_0")
716
717     def test_policies_for_node_templates(self):
718         tosca_tpl = os.path.join(
719             os.path.dirname(os.path.abspath(__file__)),
720             "data/policies/tosca_policy_template.yaml")
721         tosca = ToscaTemplate(tosca_tpl)
722
723         for policy in tosca.topology_template.policies:
724             self.assertTrue(
725                 policy.is_derived_from("tosca.policies.Root"))
726             if policy.name == 'my_compute_placement_policy':
727                 self.assertEqual('tosca.policies.Placement', policy.type)
728                 self.assertEqual(['my_server_1', 'my_server_2'],
729                                  policy.targets)
730                 self.assertEqual('node_templates', policy.get_targets_type())
731                 for node in policy.targets_list:
732                     if node.name == 'my_server_1':
733                         '''Test property value'''
734                         props = node.get_properties()
735                         if props and 'mem_size' in props.keys():
736                             self.assertEqual(props['mem_size'].value,
737                                              '4096 MB')
738
739     def test_policies_for_groups(self):
740         tosca_tpl = os.path.join(
741             os.path.dirname(os.path.abspath(__file__)),
742             "data/policies/tosca_policy_template.yaml")
743         tosca = ToscaTemplate(tosca_tpl)
744
745         for policy in tosca.topology_template.policies:
746             self.assertTrue(
747                 policy.is_derived_from("tosca.policies.Root"))
748             if policy.name == 'my_groups_placement':
749                 self.assertEqual('mycompany.mytypes.myScalingPolicy',
750                                  policy.type)
751                 self.assertEqual(['webserver_group'], policy.targets)
752                 self.assertEqual('groups', policy.get_targets_type())
753                 group = policy.get_targets_list()[0]
754                 for node in group.get_member_nodes():
755                     if node.name == 'my_server_2':
756                         '''Test property value'''
757                         props = node.get_properties()
758                         if props and 'mem_size' in props.keys():
759                             self.assertEqual(props['mem_size'].value,
760                                              '4096 MB')
761
762     def test_node_filter(self):
763         tosca_tpl = os.path.join(
764             os.path.dirname(os.path.abspath(__file__)),
765             "data/node_filter/test_node_filter.yaml")
766         ToscaTemplate(tosca_tpl)
767
768     def test_attributes_inheritance(self):
769         tosca_tpl = os.path.join(
770             os.path.dirname(os.path.abspath(__file__)),
771             "data/test_attributes_inheritance.yaml")
772         ToscaTemplate(tosca_tpl)
773
774     def test_repositories_definition(self):
775         tosca_tpl = os.path.join(
776             os.path.dirname(os.path.abspath(__file__)),
777             "data/repositories/test_repositories_definition.yaml")
778         ToscaTemplate(tosca_tpl)
779
780     def test_custom_caps_def(self):
781         tosca_tpl = os.path.join(
782             os.path.dirname(os.path.abspath(__file__)),
783             "data/test_custom_caps_def.yaml")
784         ToscaTemplate(tosca_tpl)
785
786     def test_custom_rel_with_script(self):
787         tosca_tpl = os.path.join(
788             os.path.dirname(os.path.abspath(__file__)),
789             "data/test_tosca_custom_rel_with_script.yaml")
790         tosca = ToscaTemplate(tosca_tpl)
791         rel = tosca.relationship_templates[0]
792         self.assertEqual(rel.type, "tosca.relationships.HostedOn")
793         self.assertTrue(rel.is_derived_from("tosca.relationships.Root"))
794         self.assertEqual(len(rel.interfaces), 1)
795         self.assertEqual(rel.interfaces[0].type, "Configure")
796
797     def test_various_portspec_errors(self):
798         tosca_tpl = os.path.join(
799             os.path.dirname(os.path.abspath(__file__)),
800             "data/datatypes/test_datatype_portspec_add_req.yaml")
801         self.assertRaises(exception.ValidationError, ToscaTemplate, tosca_tpl,
802                           None)
803
804         # TODO(TBD) find way to reuse error messages from constraints.py
805         msg = (_('The value "%(pvalue)s" of property "%(pname)s" is out of '
806                  'range "(min:%(vmin)s, max:%(vmax)s)".') %
807                dict(pname=PortSpec.SOURCE,
808                     pvalue='0',
809                     vmin='1',
810                     vmax='65535'))
811         exception.ExceptionCollector.assertExceptionMessage(
812             exception.ValidationError, msg)
813
814         # Test value below range min.
815         msg = (_('The value "%(pvalue)s" of property "%(pname)s" is out of '
816                  'range "(min:%(vmin)s, max:%(vmax)s)".') %
817                dict(pname=PortSpec.SOURCE,
818                     pvalue='1',
819                     vmin='2',
820                     vmax='65534'))
821         exception.ExceptionCollector.assertExceptionMessage(
822             exception.RangeValueError, msg)
823
824         # Test value above range max.
825         msg = (_('The value "%(pvalue)s" of property "%(pname)s" is out of '
826                  'range "(min:%(vmin)s, max:%(vmax)s)".') %
827                dict(pname=PortSpec.SOURCE,
828                     pvalue='65535',
829                     vmin='2',
830                     vmax='65534'))
831         exception.ExceptionCollector.assertExceptionMessage(
832             exception.RangeValueError, msg)
833
834     def test_containers(self):
835         tosca_tpl = os.path.join(
836             os.path.dirname(os.path.abspath(__file__)),
837             "data/containers/test_container_docker_mysql.yaml")
838         ToscaTemplate(tosca_tpl, parsed_params={"mysql_root_pwd": "12345678"})
839
840     def test_endpoint_on_compute(self):
841         tosca_tpl = os.path.join(
842             os.path.dirname(os.path.abspath(__file__)),
843             "data/test_endpoint_on_compute.yaml")
844         ToscaTemplate(tosca_tpl)
845
846     def test_nested_dsl_def(self):
847         tosca_tpl = os.path.join(
848             os.path.dirname(os.path.abspath(__file__)),
849             "data/dsl_definitions/test_nested_dsl_def.yaml")
850         self.assertIsNotNone(ToscaTemplate(tosca_tpl))
851
852     def test_multiple_policies(self):
853         tosca_tpl = os.path.join(
854             os.path.dirname(os.path.abspath(__file__)),
855             "data/policies/test_tosca_nfv_multiple_policies.yaml")
856         tosca = ToscaTemplate(tosca_tpl)
857         self.assertEqual(
858             ['ALRM1', 'SP1', 'SP2'],
859             sorted([policy.name for policy in tosca.policies]))