af35cfb2580e7a7f160d28739341f89b95dc2531
[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_relationship_interface(self):
220         template = ToscaTemplate(self.tosca_elk_tpl)
221         for node_tpl in template.nodetemplates:
222             if node_tpl.name == 'logstash':
223                 config_interface = 'Configure'
224                 artifact = 'logstash/configure_elasticsearch.py'
225                 relation = node_tpl.relationships
226                 for key in relation.keys():
227                     rel_tpl = relation.get(key).get_relationship_template()
228                     if rel_tpl:
229                         self.assertTrue(rel_tpl[0].is_derived_from(
230                             "tosca.relationships.Root"))
231                         interfaces = rel_tpl[0].interfaces
232                         for interface in interfaces:
233                             self.assertEqual(config_interface,
234                                              interface.type)
235                             self.assertEqual('pre_configure_source',
236                                              interface.name)
237                             self.assertEqual(artifact,
238                                              interface.implementation)
239
240     def test_relationship(self):
241         template = ToscaTemplate(self.tosca_elk_tpl)
242         for node_tpl in template.nodetemplates:
243             if node_tpl.name == 'paypal_pizzastore':
244                 expected_relationships = ['tosca.relationships.ConnectsTo',
245                                           'tosca.relationships.HostedOn']
246                 expected_hosts = ['tosca.nodes.Database',
247                                   'tosca.nodes.WebServer']
248                 self.assertEqual(len(node_tpl.relationships), 2)
249                 self.assertEqual(
250                     expected_relationships,
251                     sorted([k.type for k in node_tpl.relationships.keys()]))
252                 self.assertEqual(
253                     expected_hosts,
254                     sorted([v.type for v in node_tpl.relationships.values()]))
255
256     def test_repositories(self):
257         template = ToscaTemplate(self.tosca_repo_tpl)
258         self.assertEqual(
259             ['repo_code0', 'repo_code1', 'repo_code2'],
260             sorted([input.name for input in template.repositories]))
261
262         input_name = "repo_code2"
263         expected_url = "https://github.com/nandinivemula/intern/master"
264         for input in template.repositories:
265             if input.name == input_name:
266                 self.assertEqual(input.url, expected_url)
267
268     def test_template_macro(self):
269         template = ToscaTemplate(self.tosca_elk_tpl)
270         for node_tpl in template.nodetemplates:
271             if node_tpl.name == 'mongo_server':
272                 self.assertEqual(
273                     ['disk_size', 'mem_size', 'num_cpus'],
274                     sorted(node_tpl.get_capability('host').
275                            get_properties().keys()))
276
277     def test_template_requirements(self):
278         """Test different formats of requirements
279
280         The requirements can be defined in few different ways,
281         1. Requirement expressed as a capability with an implicit relationship.
282         2. Requirement expressed with explicit relationship.
283         3. Requirement expressed with a relationship template.
284         4. Requirement expressed via TOSCA types to provision a node
285            with explicit relationship.
286         5. Requirement expressed via TOSCA types with a filter.
287         """
288         tosca_tpl = os.path.join(
289             os.path.dirname(os.path.abspath(__file__)),
290             "data/requirements/test_requirements.yaml")
291         tosca = ToscaTemplate(tosca_tpl)
292         for node_tpl in tosca.nodetemplates:
293             if node_tpl.name == 'my_app':
294                 expected_relationship = [
295                     ('tosca.relationships.ConnectsTo', 'mysql_database'),
296                     ('tosca.relationships.HostedOn', 'my_webserver')]
297                 actual_relationship = sorted([
298                     (relation.type, node.name) for
299                     relation, node in node_tpl.relationships.items()])
300                 self.assertEqual(expected_relationship, actual_relationship)
301             if node_tpl.name == 'mysql_database':
302                     self.assertEqual(
303                         [('tosca.relationships.HostedOn', 'my_dbms')],
304                         [(relation.type, node.name) for
305                          relation,
306                          node in node_tpl.relationships.items()])
307             if node_tpl.name == 'my_server':
308                     self.assertEqual(
309                         [('tosca.relationships.AttachesTo', 'my_storage')],
310                         [(relation.type, node.name) for
311                          relation,
312                          node in node_tpl.relationships.items()])
313
314     def test_template_requirements_not_implemented(self):
315         # TODO(spzala): replace this test with new one once TOSCA types look up
316         # support is implemented.
317         """Requirements that yet need to be implemented
318
319         The following requirement formats are not yet implemented,
320         due to look up dependency:
321         1. Requirement expressed via TOSCA types to provision a node
322            with explicit relationship.
323         2. Requirement expressed via TOSCA types with a filter.
324         """
325         tpl_snippet_1 = '''
326         node_templates:
327           mysql_database:
328             type: tosca.nodes.Database
329             description: Requires a particular node type and relationship.
330                         To be full-filled via lookup into node repository.
331             requirements:
332               - req1:
333                   node: tosca.nodes.DBMS
334                   relationship: tosca.relationships.HostedOn
335         '''
336
337         tpl_snippet_2 = '''
338         node_templates:
339           my_webserver:
340             type: tosca.nodes.WebServer
341             description: Requires a particular node type with a filter.
342                          To be full-filled via lookup into node repository.
343             requirements:
344               - req1:
345                   node: tosca.nodes.Compute
346                   target_filter:
347                     properties:
348                       num_cpus: { in_range: [ 1, 4 ] }
349                       mem_size: { greater_or_equal: 2 }
350                     capabilities:
351                       - tosca.capabilities.OS:
352                           properties:
353                             architecture: x86_64
354                             type: linux
355         '''
356
357         tpl_snippet_3 = '''
358         node_templates:
359           my_webserver2:
360             type: tosca.nodes.WebServer
361             description: Requires a node type with a particular capability.
362                          To be full-filled via lookup into node repository.
363             requirements:
364               - req1:
365                   node: tosca.nodes.Compute
366                   relationship: tosca.relationships.HostedOn
367                   capability: tosca.capabilities.Container
368         '''
369         self._requirements_not_implemented(tpl_snippet_1, 'mysql_database')
370         self._requirements_not_implemented(tpl_snippet_2, 'my_webserver')
371         self._requirements_not_implemented(tpl_snippet_3, 'my_webserver2')
372
373     def _requirements_not_implemented(self, tpl_snippet, tpl_name):
374         nodetemplates = (toscaparser.utils.yamlparser.
375                          simple_parse(tpl_snippet))['node_templates']
376         self.assertRaises(
377             NotImplementedError,
378             lambda: NodeTemplate(tpl_name, nodetemplates).relationships)
379
380     # Test the following:
381     # 1. Custom node type derived from 'WebApplication' named 'TestApp'
382     #    with a custom Capability Type 'TestCapability'
383     # 2. Same as #1, but referencing a custom 'TestCapability' Capability Type
384     #    that is not defined
385     def test_custom_capability_type_definition(self):
386         tpl_snippet = '''
387         node_templates:
388           test_app:
389             type: tosca.nodes.WebApplication.TestApp
390             capabilities:
391               test_cap:
392                 properties:
393                   test: 1
394         '''
395         # custom node type definition with custom capability type definition
396         custom_def = '''
397         tosca.nodes.WebApplication.TestApp:
398           derived_from: tosca.nodes.WebApplication
399           capabilities:
400             test_cap:
401                type: tosca.capabilities.TestCapability
402         tosca.capabilities.TestCapability:
403           derived_from: tosca.capabilities.Root
404           properties:
405             test:
406               type: integer
407               required: false
408         '''
409         expected_capabilities = ['app_endpoint', 'feature', 'test_cap']
410         nodetemplates = (toscaparser.utils.yamlparser.
411                          simple_parse(tpl_snippet))['node_templates']
412         custom_def = (toscaparser.utils.yamlparser.
413                       simple_parse(custom_def))
414         name = list(nodetemplates.keys())[0]
415         tpl = NodeTemplate(name, nodetemplates, custom_def)
416         self.assertEqual(
417             expected_capabilities,
418             sorted(tpl.get_capabilities().keys()))
419
420         # custom definition without valid capability type definition
421         custom_def = '''
422         tosca.nodes.WebApplication.TestApp:
423           derived_from: tosca.nodes.WebApplication
424           capabilities:
425             test_cap:
426                type: tosca.capabilities.TestCapability
427         '''
428         custom_def = (toscaparser.utils.yamlparser.
429                       simple_parse(custom_def))
430         tpl = NodeTemplate(name, nodetemplates, custom_def)
431         err = self.assertRaises(
432             exception.InvalidTypeError,
433             lambda: NodeTemplate(name, nodetemplates,
434                                  custom_def).get_capabilities_objects())
435         self.assertEqual('Type "tosca.capabilities.TestCapability" is not '
436                          'a valid type.', six.text_type(err))
437
438     def test_local_template_with_local_relpath_import(self):
439         tosca_tpl = os.path.join(
440             os.path.dirname(os.path.abspath(__file__)),
441             "data/tosca_single_instance_wordpress.yaml")
442         params = {'db_name': 'my_wordpress', 'db_user': 'my_db_user',
443                   'db_root_pwd': '12345678'}
444         tosca = ToscaTemplate(tosca_tpl, parsed_params=params)
445         self.assertTrue(tosca.topology_template.custom_defs)
446
447     def test_local_template_with_url_import(self):
448         tosca_tpl = os.path.join(
449             os.path.dirname(os.path.abspath(__file__)),
450             "data/tosca_single_instance_wordpress_with_url_import.yaml")
451         tosca = ToscaTemplate(tosca_tpl,
452                               parsed_params={'db_root_pwd': '123456'})
453         self.assertTrue(tosca.topology_template.custom_defs)
454
455     def test_url_template_with_local_relpath_import(self):
456         tosca_tpl = ('https://raw.githubusercontent.com/openstack/'
457                      'tosca-parser/master/toscaparser/tests/data/'
458                      'tosca_single_instance_wordpress.yaml')
459         tosca = ToscaTemplate(tosca_tpl, a_file=False,
460                               parsed_params={"db_name": "mysql",
461                                              "db_user": "mysql",
462                                              "db_root_pwd": "1234",
463                                              "db_pwd": "5678",
464                                              "db_port": 3306,
465                                              "cpus": 4})
466         self.assertTrue(tosca.topology_template.custom_defs)
467
468     def test_url_template_with_local_abspath_import(self):
469         tosca_tpl = ('https://raw.githubusercontent.com/openstack/'
470                      'tosca-parser/master/toscaparser/tests/data/'
471                      'tosca_single_instance_wordpress_with_local_abspath_'
472                      'import.yaml')
473         self.assertRaises(exception.ValidationError, ToscaTemplate, tosca_tpl,
474                           None, False)
475         err_msg = (_('Absolute file name "/tmp/tosca-parser/toscaparser/tests'
476                      '/data/custom_types/wordpress.yaml" cannot be used in a '
477                      'URL-based input template "%(tpl)s".')
478                    % {'tpl': tosca_tpl})
479         exception.ExceptionCollector.assertExceptionMessage(ImportError,
480                                                             err_msg)
481
482     def test_url_template_with_url_import(self):
483         tosca_tpl = ('https://raw.githubusercontent.com/openstack/'
484                      'tosca-parser/master/toscaparser/tests/data/'
485                      'tosca_single_instance_wordpress_with_url_import.yaml')
486         tosca = ToscaTemplate(tosca_tpl, a_file=False,
487                               parsed_params={"db_root_pwd": "1234"})
488         self.assertTrue(tosca.topology_template.custom_defs)
489
490     def test_csar_parsing_wordpress(self):
491         csar_archive = os.path.join(
492             os.path.dirname(os.path.abspath(__file__)),
493             'data/CSAR/csar_wordpress.zip')
494         self.assertTrue(ToscaTemplate(csar_archive,
495                                       parsed_params={"db_name": "mysql",
496                                                      "db_user": "mysql",
497                                                      "db_root_pwd": "1234",
498                                                      "db_pwd": "5678",
499                                                      "db_port": 3306,
500                                                      "cpus": 4}))
501
502     def test_csar_parsing_elk_url_based(self):
503         csar_archive = ('https://github.com/openstack/tosca-parser/raw/master/'
504                         'toscaparser/tests/data/CSAR/csar_elk.zip')
505         self.assertTrue(ToscaTemplate(csar_archive, a_file=False,
506                                       parsed_params={"my_cpus": 4}))
507
508     def test_nested_imports_in_templates(self):
509         tosca_tpl = os.path.join(
510             os.path.dirname(os.path.abspath(__file__)),
511             "data/test_instance_nested_imports.yaml")
512         tosca = ToscaTemplate(tosca_tpl)
513         expected_custom_types = ['tosca.nodes.SoftwareComponent.Kibana',
514                                  'tosca.nodes.WebApplication.WordPress',
515                                  'test_namespace_prefix.Rsyslog',
516                                  'Test2ndRsyslogType',
517                                  'test_2nd_namespace_prefix.Rsyslog',
518                                  'tosca.nodes.SoftwareComponent.Logstash',
519                                  'tosca.nodes.SoftwareComponent.Rsyslog.'
520                                  'TestRsyslogType']
521         self.assertItemsEqual(tosca.topology_template.custom_defs.keys(),
522                               expected_custom_types)
523
524     def test_invalid_template_file(self):
525         template_file = 'invalid template file'
526         expected_msg = (_('"%s" is not a valid file.') % template_file)
527         self.assertRaises(
528             exception.ValidationError,
529             ToscaTemplate, template_file, None, False)
530         exception.ExceptionCollector.assertExceptionMessage(ValueError,
531                                                             expected_msg)
532
533     def test_multiple_validation_errors(self):
534         tosca_tpl = os.path.join(
535             os.path.dirname(os.path.abspath(__file__)),
536             "data/test_multiple_validation_errors.yaml")
537         self.assertRaises(exception.ValidationError, ToscaTemplate, tosca_tpl,
538                           None)
539         valid_versions = ', '.join(ToscaTemplate.VALID_TEMPLATE_VERSIONS)
540         err1_msg = (_('The template version "tosca_simple_yaml_1" is invalid. '
541                       'Valid versions are "%s".') % valid_versions)
542         exception.ExceptionCollector.assertExceptionMessage(
543             exception.InvalidTemplateVersion, err1_msg)
544
545         err2_msg = _('Import "custom_types/not_there.yaml" is not valid.')
546         exception.ExceptionCollector.assertExceptionMessage(
547             ImportError, err2_msg)
548
549         err3_msg = _('Type "tosca.nodes.WebApplication.WordPress" is not a '
550                      'valid type.')
551         exception.ExceptionCollector.assertExceptionMessage(
552             exception.InvalidTypeError, err3_msg)
553
554         err4_msg = _('Node template "wordpress" contains unknown field '
555                      '"requirement". Refer to the definition to verify valid '
556                      'values.')
557         exception.ExceptionCollector.assertExceptionMessage(
558             exception.UnknownFieldError, err4_msg)
559
560         err5_msg = _('\'Property "passwords" was not found in node template '
561                      '"mysql_database".\'')
562         exception.ExceptionCollector.assertExceptionMessage(
563             KeyError, err5_msg)
564
565         err6_msg = _('Template "mysql_dbms" is missing required field "type".')
566         exception.ExceptionCollector.assertExceptionMessage(
567             exception.MissingRequiredFieldError, err6_msg)
568
569         err7_msg = _('Node template "mysql_dbms" contains unknown field '
570                      '"type1". Refer to the definition to verify valid '
571                      'values.')
572         exception.ExceptionCollector.assertExceptionMessage(
573             exception.UnknownFieldError, err7_msg)
574
575         err8_msg = _('\'Node template "server1" was not found in '
576                      '"webserver".\'')
577         exception.ExceptionCollector.assertExceptionMessage(
578             KeyError, err8_msg)
579
580         err9_msg = _('"relationship" used in template "webserver" is missing '
581                      'required field "type".')
582         exception.ExceptionCollector.assertExceptionMessage(
583             exception.MissingRequiredFieldError, err9_msg)
584
585         err10_msg = _('Type "tosca.nodes.XYZ" is not a valid type.')
586         exception.ExceptionCollector.assertExceptionMessage(
587             exception.InvalidTypeError, err10_msg)
588
589     def test_invalid_section_names(self):
590         tosca_tpl = os.path.join(
591             os.path.dirname(os.path.abspath(__file__)),
592             "data/test_invalid_section_names.yaml")
593         self.assertRaises(exception.ValidationError, ToscaTemplate, tosca_tpl,
594                           None)
595         err1_msg = _('Template contains unknown field '
596                      '"tosca_definitions_versions". Refer to the definition '
597                      'to verify valid values.')
598         exception.ExceptionCollector.assertExceptionMessage(
599             exception.UnknownFieldError, err1_msg)
600
601         err2_msg = _('Template contains unknown field "descriptions". '
602                      'Refer to the definition to verify valid values.')
603         exception.ExceptionCollector.assertExceptionMessage(
604             exception.UnknownFieldError, err2_msg)
605
606         err3_msg = _('Template contains unknown field "import". Refer to '
607                      'the definition to verify valid values.')
608         exception.ExceptionCollector.assertExceptionMessage(
609             exception.UnknownFieldError, err3_msg)
610
611         err4_msg = _('Template contains unknown field "topology_templates". '
612                      'Refer to the definition to verify valid values.')
613         exception.ExceptionCollector.assertExceptionMessage(
614             exception.UnknownFieldError, err4_msg)
615
616     def test_csar_with_alternate_extenstion(self):
617         tosca_tpl = os.path.join(
618             os.path.dirname(os.path.abspath(__file__)),
619             "data/CSAR/csar_elk.csar")
620         tosca = ToscaTemplate(tosca_tpl, parsed_params={"my_cpus": 2})
621         self.assertTrue(tosca.topology_template.custom_defs)
622
623     def test_available_rel_tpls(self):
624         tosca_tpl = os.path.join(
625             os.path.dirname(os.path.abspath(__file__)),
626             "data/test_available_rel_tpls.yaml")
627         tosca = ToscaTemplate(tosca_tpl)
628         for node in tosca.nodetemplates:
629             for relationship, target in node.relationships.items():
630                 try:
631                     target.relationships
632                 except TypeError as error:
633                     self.fail(error)
634
635     def test_no_input(self):
636         self.assertRaises(exception.ValidationError, ToscaTemplate, None,
637                           None, False, None)
638         err_msg = (('No path or yaml_dict_tpl was provided. '
639                     'There is nothing to parse.'))
640         exception.ExceptionCollector.assertExceptionMessage(ValueError,
641                                                             err_msg)
642
643     def test_path_and_yaml_dict_tpl_input(self):
644         test_tpl = os.path.join(
645             os.path.dirname(os.path.abspath(__file__)),
646             "data/tosca_helloworld.yaml")
647
648         yaml_dict_tpl = toscaparser.utils.yamlparser.load_yaml(test_tpl)
649
650         tosca = ToscaTemplate(test_tpl, yaml_dict_tpl=yaml_dict_tpl)
651
652         self.assertEqual(tosca.version, "tosca_simple_yaml_1_0")
653
654     def test_yaml_dict_tpl_input(self):
655         test_tpl = os.path.join(
656             os.path.dirname(os.path.abspath(__file__)),
657             "data/tosca_helloworld.yaml")
658
659         yaml_dict_tpl = toscaparser.utils.yamlparser.load_yaml(test_tpl)
660
661         tosca = ToscaTemplate(yaml_dict_tpl=yaml_dict_tpl)
662
663         self.assertEqual(tosca.version, "tosca_simple_yaml_1_0")
664
665     def test_yaml_dict_tpl_with_params_and_url_import(self):
666         test_tpl = os.path.join(
667             os.path.dirname(os.path.abspath(__file__)),
668             "data/tosca_single_instance_wordpress_with_url_import.yaml")
669
670         yaml_dict_tpl = toscaparser.utils.yamlparser.load_yaml(test_tpl)
671
672         params = {'db_name': 'my_wordpress', 'db_user': 'my_db_user',
673                   'db_root_pwd': 'mypasswd'}
674
675         tosca = ToscaTemplate(parsed_params=params,
676                               yaml_dict_tpl=yaml_dict_tpl)
677
678         self.assertEqual(tosca.version, "tosca_simple_yaml_1_0")
679
680     def test_yaml_dict_tpl_with_rel_import(self):
681         test_tpl = os.path.join(
682             os.path.dirname(os.path.abspath(__file__)),
683             "data/tosca_single_instance_wordpress.yaml")
684
685         yaml_dict_tpl = toscaparser.utils.yamlparser.load_yaml(test_tpl)
686         params = {'db_name': 'my_wordpress', 'db_user': 'my_db_user',
687                   'db_root_pwd': '12345678'}
688         self.assertRaises(exception.ValidationError, ToscaTemplate, None,
689                           params, False, yaml_dict_tpl)
690         err_msg = (_('Relative file name "custom_types/wordpress.yaml" '
691                      'cannot be used in a pre-parsed input template.'))
692         exception.ExceptionCollector.assertExceptionMessage(ImportError,
693                                                             err_msg)
694
695     def test_yaml_dict_tpl_with_fullpath_import(self):
696         test_tpl = os.path.join(
697             os.path.dirname(os.path.abspath(__file__)),
698             "data/tosca_single_instance_wordpress.yaml")
699
700         yaml_dict_tpl = toscaparser.utils.yamlparser.load_yaml(test_tpl)
701
702         yaml_dict_tpl['imports'] = [os.path.join(os.path.dirname(
703             os.path.abspath(__file__)), "data/custom_types/wordpress.yaml")]
704
705         params = {'db_name': 'my_wordpress', 'db_user': 'my_db_user',
706                   'db_root_pwd': 'mypasswd'}
707
708         tosca = ToscaTemplate(parsed_params=params,
709                               yaml_dict_tpl=yaml_dict_tpl)
710
711         self.assertEqual(tosca.version, "tosca_simple_yaml_1_0")
712
713     def test_policies_for_node_templates(self):
714         tosca_tpl = os.path.join(
715             os.path.dirname(os.path.abspath(__file__)),
716             "data/policies/tosca_policy_template.yaml")
717         tosca = ToscaTemplate(tosca_tpl)
718
719         for policy in tosca.topology_template.policies:
720             self.assertTrue(
721                 policy.is_derived_from("tosca.policies.Root"))
722             if policy.name == 'my_compute_placement_policy':
723                 self.assertEqual('tosca.policies.Placement', policy.type)
724                 self.assertEqual(['my_server_1', 'my_server_2'],
725                                  policy.targets)
726                 self.assertEqual('node_templates', policy.get_targets_type())
727                 for node in policy.targets_list:
728                     if node.name == 'my_server_1':
729                         '''Test property value'''
730                         props = node.get_properties()
731                         if props and 'mem_size' in props.keys():
732                             self.assertEqual(props['mem_size'].value,
733                                              '4096 MB')
734
735     def test_policies_for_groups(self):
736         tosca_tpl = os.path.join(
737             os.path.dirname(os.path.abspath(__file__)),
738             "data/policies/tosca_policy_template.yaml")
739         tosca = ToscaTemplate(tosca_tpl)
740
741         for policy in tosca.topology_template.policies:
742             self.assertTrue(
743                 policy.is_derived_from("tosca.policies.Root"))
744             if policy.name == 'my_groups_placement':
745                 self.assertEqual('mycompany.mytypes.myScalingPolicy',
746                                  policy.type)
747                 self.assertEqual(['webserver_group'], policy.targets)
748                 self.assertEqual('groups', policy.get_targets_type())
749                 group = policy.get_targets_list()[0]
750                 for node in group.get_member_nodes():
751                     if node.name == 'my_server_2':
752                         '''Test property value'''
753                         props = node.get_properties()
754                         if props and 'mem_size' in props.keys():
755                             self.assertEqual(props['mem_size'].value,
756                                              '4096 MB')
757
758     def test_node_filter(self):
759         tosca_tpl = os.path.join(
760             os.path.dirname(os.path.abspath(__file__)),
761             "data/node_filter/test_node_filter.yaml")
762         ToscaTemplate(tosca_tpl)
763
764     def test_attributes_inheritance(self):
765         tosca_tpl = os.path.join(
766             os.path.dirname(os.path.abspath(__file__)),
767             "data/test_attributes_inheritance.yaml")
768         ToscaTemplate(tosca_tpl)
769
770     def test_repositories_definition(self):
771         tosca_tpl = os.path.join(
772             os.path.dirname(os.path.abspath(__file__)),
773             "data/repositories/test_repositories_definition.yaml")
774         ToscaTemplate(tosca_tpl)
775
776     def test_custom_caps_def(self):
777         tosca_tpl = os.path.join(
778             os.path.dirname(os.path.abspath(__file__)),
779             "data/test_custom_caps_def.yaml")
780         ToscaTemplate(tosca_tpl)
781
782     def test_custom_rel_with_script(self):
783         tosca_tpl = os.path.join(
784             os.path.dirname(os.path.abspath(__file__)),
785             "data/test_tosca_custom_rel_with_script.yaml")
786         tosca = ToscaTemplate(tosca_tpl)
787         rel = tosca.relationship_templates[0]
788         self.assertEqual(rel.type, "tosca.relationships.HostedOn")
789         self.assertTrue(rel.is_derived_from("tosca.relationships.Root"))
790         self.assertEqual(len(rel.interfaces), 1)
791         self.assertEqual(rel.interfaces[0].type, "Configure")
792
793     def test_various_portspec_errors(self):
794         tosca_tpl = os.path.join(
795             os.path.dirname(os.path.abspath(__file__)),
796             "data/datatypes/test_datatype_portspec_add_req.yaml")
797         self.assertRaises(exception.ValidationError, ToscaTemplate, tosca_tpl,
798                           None)
799
800         # TODO(TBD) find way to reuse error messages from constraints.py
801         msg = (_('The value "%(pvalue)s" of property "%(pname)s" is out of '
802                  'range "(min:%(vmin)s, max:%(vmax)s)".') %
803                dict(pname=PortSpec.SOURCE,
804                     pvalue='0',
805                     vmin='1',
806                     vmax='65535'))
807         exception.ExceptionCollector.assertExceptionMessage(
808             exception.ValidationError, msg)
809
810         # Test value below range min.
811         msg = (_('The value "%(pvalue)s" of property "%(pname)s" is out of '
812                  'range "(min:%(vmin)s, max:%(vmax)s)".') %
813                dict(pname=PortSpec.SOURCE,
814                     pvalue='1',
815                     vmin='2',
816                     vmax='65534'))
817         exception.ExceptionCollector.assertExceptionMessage(
818             exception.RangeValueError, msg)
819
820         # Test value above range max.
821         msg = (_('The value "%(pvalue)s" of property "%(pname)s" is out of '
822                  'range "(min:%(vmin)s, max:%(vmax)s)".') %
823                dict(pname=PortSpec.SOURCE,
824                     pvalue='65535',
825                     vmin='2',
826                     vmax='65534'))
827         exception.ExceptionCollector.assertExceptionMessage(
828             exception.RangeValueError, msg)
829
830     def test_containers(self):
831         tosca_tpl = os.path.join(
832             os.path.dirname(os.path.abspath(__file__)),
833             "data/containers/test_container_docker_mysql.yaml")
834         ToscaTemplate(tosca_tpl, parsed_params={"mysql_root_pwd": "12345678"})
835
836     def test_endpoint_on_compute(self):
837         tosca_tpl = os.path.join(
838             os.path.dirname(os.path.abspath(__file__)),
839             "data/test_endpoint_on_compute.yaml")
840         ToscaTemplate(tosca_tpl)
841
842     def test_nested_dsl_def(self):
843         tosca_tpl = os.path.join(
844             os.path.dirname(os.path.abspath(__file__)),
845             "data/dsl_definitions/test_nested_dsl_def.yaml")
846         self.assertIsNotNone(ToscaTemplate(tosca_tpl))
847
848     def test_multiple_policies(self):
849         tosca_tpl = os.path.join(
850             os.path.dirname(os.path.abspath(__file__)),
851             "data/policies/test_tosca_nfv_multiple_policies.yaml")
852         tosca = ToscaTemplate(tosca_tpl)
853         self.assertEqual(
854             ['ALRM1', 'SP1', 'SP2'],
855             sorted([policy.name for policy in tosca.policies]))