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