toscaparser: Avoid exception when creating our own
[parser.git] / tosca2heat / tosca-parser / toscaparser / tests / test_toscatplvalidation.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
16 from toscaparser.common import exception
17 from toscaparser.imports import ImportsLoader
18 from toscaparser.nodetemplate import NodeTemplate
19 from toscaparser.parameters import Input
20 from toscaparser.parameters import Output
21 from toscaparser.policy import Policy
22 from toscaparser.relationship_template import RelationshipTemplate
23 from toscaparser.repositories import Repository
24 from toscaparser.tests.base import TestCase
25 from toscaparser.topology_template import TopologyTemplate
26 from toscaparser.tosca_template import ToscaTemplate
27 from toscaparser.triggers import Triggers
28 from toscaparser.utils.gettextutils import _
29 import toscaparser.utils.yamlparser
30
31
32 class ToscaTemplateValidationTest(TestCase):
33
34     def test_well_defined_template(self):
35         tpl_path = os.path.join(
36             os.path.dirname(os.path.abspath(__file__)),
37             "data/tosca_single_instance_wordpress.yaml")
38         params = {'db_name': 'my_wordpress', 'db_user': 'my_db_user',
39                   'db_root_pwd': '12345678'}
40         self.assertIsNotNone(ToscaTemplate(tpl_path, params))
41
42     def test_custom_interface_allowed(self):
43         tpl_path = os.path.join(
44             os.path.dirname(os.path.abspath(__file__)),
45             "data/interfaces/test_custom_interface_in_template.yaml")
46         self.assertIsNotNone(ToscaTemplate(tpl_path))
47
48     def test_custom_interface_invalid_operation(self):
49         tpl_path = os.path.join(
50             os.path.dirname(os.path.abspath(__file__)),
51             "data/interfaces/test_custom_interface_invalid_operation.yaml")
52         self.assertRaises(exception.ValidationError,
53                           ToscaTemplate, tpl_path)
54         exception.ExceptionCollector.assertExceptionMessage(
55             exception.UnknownFieldError,
56             _('"interfaces" of template "customInterfaceTest" '
57               'contains unknown field "CustomOp4". '
58               'Refer to the definition to verify valid values.'))
59
60     def test_first_level_sections(self):
61         tpl_path = os.path.join(
62             os.path.dirname(os.path.abspath(__file__)),
63             "data/test_tosca_top_level_error1.yaml")
64         self.assertRaises(exception.ValidationError, ToscaTemplate, tpl_path)
65         exception.ExceptionCollector.assertExceptionMessage(
66             exception.MissingRequiredFieldError,
67             _('Template is missing required field '
68               '"tosca_definitions_version".'))
69
70         tpl_path = os.path.join(
71             os.path.dirname(os.path.abspath(__file__)),
72             "data/test_tosca_top_level_error2.yaml")
73         self.assertRaises(exception.ValidationError, ToscaTemplate, tpl_path)
74         exception.ExceptionCollector.assertExceptionMessage(
75             exception.UnknownFieldError,
76             _('Template contains unknown field "node_template". Refer to the '
77               'definition to verify valid values.'))
78
79     def test_template_with_imports_validation(self):
80         tpl_path = os.path.join(
81             os.path.dirname(os.path.abspath(__file__)),
82             "data/tosca_imports_validation.yaml")
83         self.assertRaises(exception.ValidationError, ToscaTemplate, tpl_path)
84         exception.ExceptionCollector.assertExceptionMessage(
85             exception.UnknownFieldError,
86             _('Template custom_types/imported_sample.yaml contains unknown '
87               'field "descriptions". Refer to the definition'
88               ' to verify valid values.'))
89         exception.ExceptionCollector.assertExceptionMessage(
90             exception.UnknownFieldError,
91             _('Template custom_types/imported_sample.yaml contains unknown '
92               'field "node_typess". Refer to the definition to '
93               'verify valid values.'))
94         exception.ExceptionCollector.assertExceptionMessage(
95             exception.UnknownFieldError,
96             _('Template custom_types/imported_sample.yaml contains unknown '
97               'field "tosca1_definitions_version". Refer to the definition'
98               ' to verify valid values.'))
99         exception.ExceptionCollector.assertExceptionMessage(
100             exception.InvalidTemplateVersion,
101             _('The template version "tosca_simple_yaml_1_10 in '
102               'custom_types/imported_sample.yaml" is invalid. '
103               'Valid versions are "tosca_simple_yaml_1_0, '
104               'tosca_simple_yaml_1_1, '
105               'tosca_simple_profile_for_nfv_1_0_0".'))
106         exception.ExceptionCollector.assertExceptionMessage(
107             exception.UnknownFieldError,
108             _('Template custom_types/imported_sample.yaml contains unknown '
109               'field "policy_types1". Refer to the definition to '
110               'verify valid values.'))
111         exception.ExceptionCollector.assertExceptionMessage(
112             exception.UnknownFieldError,
113             _('Nodetype"tosca.nodes.SoftwareComponent.Logstash" contains '
114               'unknown field "capabilities1". Refer to the definition '
115               'to verify valid values.'))
116         exception.ExceptionCollector.assertExceptionMessage(
117             exception.UnknownFieldError,
118             _('Policy "mycompany.mytypes.myScalingPolicy" contains unknown '
119               'field "derived1_from". Refer to the definition to '
120               'verify valid values.'))
121         exception.ExceptionCollector.assertExceptionMessage(
122             exception.UnknownFieldError,
123             _('Relationshiptype "test.relation.connects" contains unknown '
124               'field "derived_from4". Refer to the definition to '
125               'verify valid values.'))
126
127     def test_getoperation_IncorrectValue(self):
128         # test case 1
129         tpl_snippet = '''
130         node_templates:
131              front_end:
132                type: tosca.nodes.Compute
133                interfaces:
134                  Standard:
135                    create:
136                      implementation: scripts/frontend/create.sh
137                    configure:
138                      implementation: scripts/frontend/configure.sh
139                      inputs:
140                        data_dir: {get_operation_output: [front_end,Standard1,
141                                                             create,data_dir]}
142         '''
143         tpl = (toscaparser.utils.yamlparser.simple_parse(tpl_snippet))
144         err = self.assertRaises(ValueError,
145                                 TopologyTemplate, tpl, None)
146         expectedmessage = _('Enter a valid interface name')
147         self.assertEqual(expectedmessage, err.__str__())
148         # test case 2
149         tpl_snippet2 = '''
150         node_templates:
151              front_end:
152                type: tosca.nodes.Compute
153                interfaces:
154                  Standard:
155                    create:
156                      implementation: scripts/frontend/create.sh
157                    configure:
158                      implementation: scripts/frontend/configure.sh
159                      inputs:
160                        data_dir: {get_operation_output: [front_end1,Standard,
161                                                             create,data_dir]}
162         '''
163         tpl2 = (toscaparser.utils.yamlparser.simple_parse(tpl_snippet2))
164         err2 = self.assertRaises(KeyError,
165                                  TopologyTemplate, tpl2, None)
166         expectedmessage2 = _('\'Node template "front_end1" was not found.\'')
167         self.assertEqual(expectedmessage2, err2.__str__())
168         # test case 3
169         tpl_snippet3 = '''
170         node_templates:
171              front_end:
172                type: tosca.nodes.Compute
173                interfaces:
174                  Standard:
175                    create:
176                      implementation: scripts/frontend/create.sh
177                    configure:
178                      implementation: scripts/frontend/configure.sh
179                      inputs:
180                        data_dir: {get_operation_output: [front_end,Standard,
181                                                       get_target,data_dir]}
182         '''
183         tpl3 = (toscaparser.utils.yamlparser.simple_parse(tpl_snippet3))
184         err3 = self.assertRaises(ValueError,
185                                  TopologyTemplate, tpl3, None)
186         expectedmessage3 = _('Enter an operation of Standard interface')
187         self.assertEqual(expectedmessage3, err3.__str__())
188         # test case 4
189         tpl_snippet4 = '''
190         node_templates:
191              front_end:
192                type: tosca.nodes.Compute
193                interfaces:
194                  Standard:
195                    create:
196                      implementation: scripts/frontend/create.sh
197                    configure:
198                      implementation: scripts/frontend/configure.sh
199                      inputs:
200                        data_dir: {get_operation_output: [front_end,Configure,
201                                                         create,data_dir]}
202         '''
203         tpl4 = (toscaparser.utils.yamlparser.simple_parse(tpl_snippet4))
204         err4 = self.assertRaises(ValueError,
205                                  TopologyTemplate, tpl4, None)
206         expectedmessage4 = _('Enter an operation of Configure interface')
207         self.assertEqual(expectedmessage4, err4.__str__())
208         # test case 5
209         tpl_snippet5 = '''
210         node_templates:
211              front_end:
212                type: tosca.nodes.Compute
213                interfaces:
214                  Standard:
215                    create:
216                      implementation: scripts/frontend/create.sh
217                    configure:
218                      implementation: scripts/frontend/configure.sh
219                      inputs:
220                        data_dir: {get_operation_output: [front_end,Standard,
221                                                                     create]}
222         '''
223         tpl5 = (toscaparser.utils.yamlparser.simple_parse(tpl_snippet5))
224         err5 = self.assertRaises(ValueError,
225                                  TopologyTemplate, tpl5, None)
226         expectedmessage5 = _('Illegal arguments for function'
227                              ' "get_operation_output".'
228                              ' Expected arguments: "template_name",'
229                              '"interface_name",'
230                              '"operation_name","output_variable_name"')
231         self.assertEqual(expectedmessage5, err5.__str__())
232
233     def test_unsupported_type(self):
234         tpl_snippet = '''
235         node_templates:
236           invalid_type:
237             type: tosca.test.invalidtype
238             properties:
239               size: { get_input: storage_size }
240               snapshot_id: { get_input: storage_snapshot_id }
241         '''
242         tpl = (toscaparser.utils.yamlparser.simple_parse(tpl_snippet))
243         err = self.assertRaises(exception.UnsupportedTypeError,
244                                 TopologyTemplate, tpl, None)
245         expectedmessage = _('Type "tosca.test.invalidtype" is valid'
246                             ' TOSCA type but not supported at this time.')
247         self.assertEqual(expectedmessage, err.__str__())
248
249     def test_inputs(self):
250         tpl_snippet1 = '''
251         inputs:
252           cpus:
253             type: integer
254             description: Number of CPUs for the server.
255             constraint:
256               - valid_values: [ 1, 2, 4 ]
257             required: yes
258             status: supported
259         '''
260         tpl_snippet2 = '''
261         inputs:
262           cpus:
263             type: integer
264             description: Number of CPUs for the server.
265             constraints:
266               - valid_values: [ 1, 2, 4 ]
267             required: yes
268             status: supported
269         '''
270         tpl_snippet3 = '''
271         inputs:
272           some_list:
273             type: list
274             description: List of items
275             entry_schema:
276               type: string
277             default: []
278         '''
279         inputs1 = (toscaparser.utils.yamlparser.
280                    simple_parse(tpl_snippet1)['inputs'])
281         name1, attrs1 = list(inputs1.items())[0]
282         inputs2 = (toscaparser.utils.yamlparser.
283                    simple_parse(tpl_snippet2)['inputs'])
284         name2, attrs2 = list(inputs2.items())[0]
285         try:
286             Input(name1, attrs1)
287         except Exception as err:
288             self.assertEqual(_('Input "cpus" contains unknown field '
289                                '"constraint". Refer to the definition to '
290                                'verify valid values.'),
291                              err.__str__())
292         input2 = Input(name2, attrs2)
293         self.assertTrue(input2.required)
294         toscaparser.utils.yamlparser.simple_parse(tpl_snippet3)['inputs']
295
296     def _imports_content_test(self, tpl_snippet, path, custom_type_def):
297         imports = (toscaparser.utils.yamlparser.
298                    simple_parse(tpl_snippet)['imports'])
299         loader = ImportsLoader(imports, path, custom_type_def)
300         return loader.get_custom_defs()
301
302     def test_imports_without_templates(self):
303         tpl_snippet = '''
304         imports:
305           # omitted here for brevity
306         '''
307         path = 'toscaparser/tests/data/tosca_elk.yaml'
308         errormsg = _('"imports" keyname is defined without including '
309                      'templates.')
310         err = self.assertRaises(exception.ValidationError,
311                                 self._imports_content_test,
312                                 tpl_snippet,
313                                 path,
314                                 "node_types")
315         self.assertEqual(errormsg, err.__str__())
316
317     def test_imports_with_name_without_templates(self):
318         tpl_snippet = '''
319         imports:
320           - some_definitions:
321         '''
322         path = 'toscaparser/tests/data/tosca_elk.yaml'
323         errormsg = _('A template file name is not provided with import '
324                      'definition "some_definitions".')
325         err = self.assertRaises(exception.ValidationError,
326                                 self._imports_content_test,
327                                 tpl_snippet, path, None)
328         self.assertEqual(errormsg, err.__str__())
329
330     def test_imports_without_import_name(self):
331         tpl_snippet = '''
332         imports:
333           - custom_types/paypalpizzastore_nodejs_app.yaml
334           - https://raw.githubusercontent.com/openstack/\
335 tosca-parser/master/toscaparser/tests/data/custom_types/wordpress.yaml
336         '''
337         path = 'toscaparser/tests/data/tosca_elk.yaml'
338         custom_defs = self._imports_content_test(tpl_snippet,
339                                                  path,
340                                                  "node_types")
341         self.assertTrue(custom_defs)
342
343     def test_imports_wth_import_name(self):
344         tpl_snippet = '''
345         imports:
346           - some_definitions: custom_types/paypalpizzastore_nodejs_app.yaml
347           - more_definitions:
348               file: 'https://raw.githubusercontent.com/openstack/tosca-parser\
349 /master/toscaparser/tests/data/custom_types/wordpress.yaml'
350               namespace_prefix: single_instance_wordpress
351         '''
352         path = 'toscaparser/tests/data/tosca_elk.yaml'
353         custom_defs = self._imports_content_test(tpl_snippet,
354                                                  path,
355                                                  "node_types")
356         self.assertTrue(custom_defs.get("single_instance_wordpress.tosca."
357                                         "nodes.WebApplication.WordPress"))
358
359     def test_imports_wth_namespace_prefix(self):
360         tpl_snippet = '''
361         imports:
362           - more_definitions:
363               file: custom_types/nested_rsyslog.yaml
364               namespace_prefix: testprefix
365         '''
366         path = 'toscaparser/tests/data/tosca_elk.yaml'
367         custom_defs = self._imports_content_test(tpl_snippet,
368                                                  path,
369                                                  "node_types")
370         self.assertTrue(custom_defs.get("testprefix.Rsyslog"))
371
372     def test_imports_with_no_main_template(self):
373         tpl_snippet = '''
374         imports:
375           - some_definitions: https://raw.githubusercontent.com/openstack/\
376 tosca-parser/master/toscaparser/tests/data/custom_types/wordpress.yaml
377           - some_definitions:
378               file: my_defns/my_typesdefs_n.yaml
379         '''
380         errormsg = _('Input tosca template is not provided.')
381         err = self.assertRaises(exception.ValidationError,
382                                 self._imports_content_test,
383                                 tpl_snippet, None, None)
384         self.assertEqual(errormsg, err.__str__())
385
386     def test_imports_duplicate_name(self):
387         tpl_snippet = '''
388         imports:
389           - some_definitions: https://raw.githubusercontent.com/openstack/\
390 tosca-parser/master/toscaparser/tests/data/custom_types/wordpress.yaml
391           - some_definitions:
392               file: my_defns/my_typesdefs_n.yaml
393         '''
394         errormsg = _('Duplicate import name "some_definitions" was found.')
395         path = 'toscaparser/tests/data/tosca_elk.yaml'
396         err = self.assertRaises(exception.ValidationError,
397                                 self._imports_content_test,
398                                 tpl_snippet, path, None)
399         self.assertEqual(errormsg, err.__str__())
400
401     def test_imports_missing_req_field_in_def(self):
402         tpl_snippet = '''
403         imports:
404           - more_definitions:
405               file1: my_defns/my_typesdefs_n.yaml
406               repository: my_company_repo
407               namespace_uri: http://mycompany.com/ns/tosca/2.0
408               namespace_prefix: mycompany
409         '''
410         errormsg = _('Import of template "more_definitions" is missing '
411                      'required field "file".')
412         path = 'toscaparser/tests/data/tosca_elk.yaml'
413         err = self.assertRaises(exception.MissingRequiredFieldError,
414                                 self._imports_content_test,
415                                 tpl_snippet, path, None)
416         self.assertEqual(errormsg, err.__str__())
417
418     def test_imports_file_with_uri(self):
419         tpl_snippet = '''
420         imports:
421           - more_definitions:
422               file: https://raw.githubusercontent.com/openstack/\
423 tosca-parser/master/toscaparser/tests/data/custom_types/wordpress.yaml
424         '''
425         path = 'https://raw.githubusercontent.com/openstack/\
426 tosca-parser/master/toscaparser/tests/data/\
427 tosca_single_instance_wordpress_with_url_import.yaml'
428         custom_defs = self._imports_content_test(tpl_snippet,
429                                                  path,
430                                                  "node_types")
431         self.assertTrue(custom_defs.get("tosca.nodes."
432                                         "WebApplication.WordPress"))
433
434     def test_imports_file_namespace_fields(self):
435         tpl_snippet = '''
436         imports:
437           - more_definitions:
438              file: https://raw.githubusercontent.com/openstack/\
439 heat-translator/master/translator/tests/data/custom_types/wordpress.yaml
440              namespace_prefix: mycompany
441              namespace_uri: http://docs.oasis-open.org/tosca/ns/simple/yaml/1.0
442         '''
443         path = 'toscaparser/tests/data/tosca_elk.yaml'
444         custom_defs = self._imports_content_test(tpl_snippet,
445                                                  path,
446                                                  "node_types")
447         self.assertTrue(custom_defs.get("mycompany.tosca.nodes."
448                                         "WebApplication.WordPress"))
449
450     def test_imports_file_with_suffix_yml(self):
451             tpl_snippet = '''
452             imports:
453               - custom_types/wordpress.yml
454             '''
455             path = 'toscaparser/tests/data/tosca_elk.yaml'
456             custom_defs = self._imports_content_test(tpl_snippet,
457                                                      path,
458                                                      "node_types")
459             self.assertTrue(custom_defs.get("tosca.nodes."
460                                             "WebApplication.WordPress"))
461
462     def test_import_error_file_uri(self):
463         tpl_snippet = '''
464         imports:
465           - more_definitions:
466              file: mycompany.com/ns/tosca/2.0/toscaparser/tests/data\
467 /tosca_elk.yaml
468              namespace_prefix: mycompany
469              namespace_uri: http://docs.oasis-open.org/tosca/ns/simple/yaml/1.0
470         '''
471         path = 'toscaparser/tests/data/tosca_elk.yaml'
472         self.assertRaises(ImportError,
473                           self._imports_content_test,
474                           tpl_snippet, path, None)
475
476     def test_import_single_line_error(self):
477         tpl_snippet = '''
478         imports:
479           - some_definitions: abc.com/tests/data/tosca_elk.yaml
480         '''
481         errormsg = _('Import "abc.com/tests/data/tosca_elk.yaml" is not '
482                      'valid.')
483         path = 'toscaparser/tests/data/tosca_elk.yaml'
484         err = self.assertRaises(ImportError,
485                                 self._imports_content_test,
486                                 tpl_snippet, path, None)
487         self.assertEqual(errormsg, err.__str__())
488
489     def test_outputs(self):
490         tpl_snippet = '''
491         outputs:
492           server_address:
493             description: IP address of server instance.
494             values: { get_property: [server, private_address] }
495         '''
496         outputs = (toscaparser.utils.yamlparser.
497                    simple_parse(tpl_snippet)['outputs'])
498         name, attrs = list(outputs.items())[0]
499         output = Output(name, attrs)
500         try:
501             output.validate()
502         except Exception as err:
503             self.assertTrue(
504                 isinstance(err, exception.MissingRequiredFieldError))
505             self.assertEqual(_('Output "server_address" is missing required '
506                                'field "value".'), err.__str__())
507
508         tpl_snippet = '''
509         outputs:
510           server_address:
511             descriptions: IP address of server instance.
512             value: { get_property: [server, private_address] }
513         '''
514         outputs = (toscaparser.utils.yamlparser.
515                    simple_parse(tpl_snippet)['outputs'])
516         name, attrs = list(outputs.items())[0]
517         output = Output(name, attrs)
518         try:
519             output.validate()
520         except Exception as err:
521             self.assertIsInstance(err, exception.UnknownFieldError)
522             self.assertEqual(_('Output "server_address" contains unknown '
523                                'field "descriptions". Refer to the definition '
524                                'to verify valid values.'),
525                              err.__str__())
526
527     def _repo_content(self, path):
528         repositories = path['repositories']
529         reposit = []
530         for name, val in repositories.items():
531             reposits = Repository(name, val)
532             reposit.append(reposits)
533         return reposit
534
535     def test_repositories(self):
536         tpl_snippet = '''
537         repositories:
538            repo_code0: https://raw.githubusercontent.com/nandinivemula/intern
539            repo_code1:
540               description: My project's code Repository in github usercontent.
541               url: https://github.com/nandinivemula/intern
542               credential:
543                  user: nandini
544                  password: tcs@12345
545            repo_code2:
546               description: My Project's code Repository in github.
547               url: https://github.com/nandinivemula/intern
548               credential:
549                  user: xyzw
550                  password: xyz@123
551         '''
552         tpl = (toscaparser.utils.yamlparser.simple_parse(tpl_snippet))
553         repoobject = self._repo_content(tpl)
554         actualrepo_names = []
555         for repo in repoobject:
556             repos = repo.name
557             actualrepo_names.append(repos)
558         reposname = list(tpl.values())
559         reposnames = reposname[0]
560         expected_reponames = list(reposnames.keys())
561         self.assertEqual(expected_reponames, actualrepo_names)
562
563     def test_repositories_with_missing_required_field(self):
564         tpl_snippet = '''
565         repositories:
566            repo_code0: https://raw.githubusercontent.com/nandinivemula/intern
567            repo_code1:
568               description: My project's code Repository in github usercontent.
569               credential:
570                  user: nandini
571                  password: tcs@12345
572            repo_code2:
573               description: My Project's code Repository in github.
574               url: https://github.com/nandinivemula/intern
575               credential:
576                  user: xyzw
577                  password: xyz@123
578         '''
579         tpl = (toscaparser.utils.yamlparser.simple_parse(tpl_snippet))
580         err = self.assertRaises(exception.MissingRequiredFieldError,
581                                 self._repo_content, tpl)
582         expectedmessage = _('Repository "repo_code1" is missing '
583                             'required field "url".')
584         self.assertEqual(expectedmessage, err.__str__())
585
586     def test_repositories_with_unknown_field(self):
587         tpl_snippet = '''
588         repositories:
589            repo_code0: https://raw.githubusercontent.com/nandinivemula/intern
590            repo_code1:
591               description: My project's code Repository in github usercontent.
592               url: https://github.com/nandinivemula/intern
593               credential:
594                  user: nandini
595                  password: tcs@12345
596            repo_code2:
597               descripton: My Project's code Repository in github.
598               url: https://github.com/nandinivemula/intern
599               credential:
600                  user: xyzw
601                  password: xyz@123
602         '''
603         tpl = (toscaparser.utils.yamlparser.simple_parse(tpl_snippet))
604         err = self.assertRaises(exception.UnknownFieldError,
605                                 self._repo_content, tpl)
606         expectedmessage = _('repositories "repo_code2" contains unknown field'
607                             ' "descripton". Refer to the definition to verify'
608                             ' valid values.')
609         self.assertEqual(expectedmessage, err.__str__())
610
611     def test_repositories_with_invalid_url(self):
612         tpl_snippet = '''
613         repositories:
614            repo_code0: https://raw.githubusercontent.com/nandinivemula/intern
615            repo_code1:
616               description: My project's code Repository in github usercontent.
617               url: h
618               credential:
619                  user: nandini
620                  password: tcs@12345
621            repo_code2:
622               description: My Project's code Repository in github.
623               url: https://github.com/nandinivemula/intern
624               credential:
625                  user: xyzw
626                  password: xyz@123
627         '''
628         tpl = (toscaparser.utils.yamlparser.simple_parse(tpl_snippet))
629         err = self.assertRaises(exception.URLException,
630                                 self._repo_content, tpl)
631         expectedmessage = _('repsositories "repo_code1" Invalid Url')
632         self.assertEqual(expectedmessage, err.__str__())
633
634     def test_groups(self):
635         tpl_snippet = '''
636         node_templates:
637           server:
638             type: tosca.nodes.Compute
639             requirements:
640               - log_endpoint:
641                   capability: log_endpoint
642
643           mysql_dbms:
644             type: tosca.nodes.DBMS
645             properties:
646               root_password: aaa
647               port: 3376
648
649         groups:
650           webserver_group:
651             type: tosca.groups.Root
652             members: [ server, mysql_dbms ]
653         '''
654         tpl = (toscaparser.utils.yamlparser.simple_parse(tpl_snippet))
655         TopologyTemplate(tpl, None)
656
657     def test_groups_with_missing_required_field(self):
658         tpl_snippet = '''
659         node_templates:
660           server:
661             type: tosca.nodes.Compute
662             requirements:
663               - log_endpoint:
664                   capability: log_endpoint
665
666           mysql_dbms:
667             type: tosca.nodes.DBMS
668             properties:
669               root_password: aaa
670               port: 3376
671
672         groups:
673           webserver_group:
674               members: ['server', 'mysql_dbms']
675         '''
676         tpl = (toscaparser.utils.yamlparser.simple_parse(tpl_snippet))
677         err = self.assertRaises(exception.MissingRequiredFieldError,
678                                 TopologyTemplate, tpl, None)
679         expectedmessage = _('Template "webserver_group" is missing '
680                             'required field "type".')
681         self.assertEqual(expectedmessage, err.__str__())
682
683     def test_groups_with_unknown_target(self):
684         tpl_snippet = '''
685         node_templates:
686           server:
687             type: tosca.nodes.Compute
688             requirements:
689               - log_endpoint:
690                   capability: log_endpoint
691
692           mysql_dbms:
693             type: tosca.nodes.DBMS
694             properties:
695               root_password: aaa
696               port: 3376
697
698         groups:
699           webserver_group:
700             type: tosca.groups.Root
701             members: [ serv, mysql_dbms ]
702         '''
703         tpl = (toscaparser.utils.yamlparser.simple_parse(tpl_snippet))
704         expectedmessage = _('"Target member "serv" is not found in '
705                             'node_templates"')
706         err = self.assertRaises(exception.InvalidGroupTargetException,
707                                 TopologyTemplate, tpl, None)
708         self.assertEqual(expectedmessage, err.__str__())
709
710     def test_groups_with_repeated_targets(self):
711         tpl_snippet = '''
712         node_templates:
713           server:
714             type: tosca.nodes.Compute
715             requirements:
716               - log_endpoint:
717                   capability: log_endpoint
718
719           mysql_dbms:
720             type: tosca.nodes.DBMS
721             properties:
722               root_password: aaa
723               port: 3376
724
725         groups:
726           webserver_group:
727             type: tosca.groups.Root
728             members: [ server, server, mysql_dbms ]
729         '''
730         tpl = (toscaparser.utils.yamlparser.simple_parse(tpl_snippet))
731         expectedmessage = _('"Member nodes '
732                             '"[\'server\', \'server\', \'mysql_dbms\']" '
733                             'should be >= 1 and not repeated"')
734         err = self.assertRaises(exception.InvalidGroupTargetException,
735                                 TopologyTemplate, tpl, None)
736         self.assertEqual(expectedmessage, err.__str__())
737
738     def test_groups_with_only_one_target(self):
739         tpl_snippet = '''
740         node_templates:
741           server:
742             type: tosca.nodes.Compute
743             requirements:
744               - log_endpoint:
745                   capability: log_endpoint
746
747           mysql_dbms:
748             type: tosca.nodes.DBMS
749             properties:
750               root_password: aaa
751               port: 3376
752
753         groups:
754           webserver_group:
755             type: tosca.groups.Root
756             members: []
757         '''
758         tpl = (toscaparser.utils.yamlparser.simple_parse(tpl_snippet))
759         expectedmessage = _('"Member nodes "[]" should be >= 1 '
760                             'and not repeated"')
761         err = self.assertRaises(exception.InvalidGroupTargetException,
762                                 TopologyTemplate, tpl, None)
763         self.assertEqual(expectedmessage, err.__str__())
764
765     def _custom_types(self):
766         custom_types = {}
767         def_file = os.path.join(
768             os.path.dirname(os.path.abspath(__file__)),
769             "data/custom_types/wordpress.yaml")
770         custom_type = toscaparser.utils.yamlparser.load_yaml(def_file)
771         node_types = custom_type['node_types']
772         for name in node_types:
773             defintion = node_types[name]
774             custom_types[name] = defintion
775         return custom_types
776
777     def _single_node_template_content_test(self, tpl_snippet):
778         nodetemplates = (toscaparser.utils.yamlparser.
779                          simple_ordered_parse(tpl_snippet))['node_templates']
780         name = list(nodetemplates.keys())[0]
781         nodetemplate = NodeTemplate(name, nodetemplates,
782                                     self._custom_types())
783         nodetemplate.validate()
784         nodetemplate.requirements
785         nodetemplate.get_capabilities_objects()
786         nodetemplate.get_properties_objects()
787         nodetemplate.interfaces
788
789     def test_node_templates(self):
790         tpl_snippet = '''
791         node_templates:
792           server:
793             capabilities:
794               host:
795                 properties:
796                   disk_size: 10
797                   num_cpus: 4
798                   mem_size: 4096
799               os:
800                 properties:
801                   architecture: x86_64
802                   type: Linux
803                   distribution: Fedora
804                   version: 18.0
805         '''
806         expectedmessage = _('Template "server" is missing required field '
807                             '"type".')
808         err = self.assertRaises(
809             exception.MissingRequiredFieldError,
810             lambda: self._single_node_template_content_test(tpl_snippet))
811         self.assertEqual(expectedmessage, err.__str__())
812
813     def test_node_template_with_wrong_properties_keyname(self):
814         """Node template keyname 'properties' given as 'propertiessss'."""
815         tpl_snippet = '''
816         node_templates:
817           mysql_dbms:
818             type: tosca.nodes.DBMS
819             propertiessss:
820               root_password: aaa
821               port: 3376
822         '''
823         expectedmessage = _('Node template "mysql_dbms" contains unknown '
824                             'field "propertiessss". Refer to the definition '
825                             'to verify valid values.')
826         err = self.assertRaises(
827             exception.UnknownFieldError,
828             lambda: self._single_node_template_content_test(tpl_snippet))
829         self.assertEqual(expectedmessage, err.__str__())
830
831     def test_node_template_with_wrong_requirements_keyname(self):
832         """Node template keyname 'requirements' given as 'requirement'."""
833         tpl_snippet = '''
834         node_templates:
835           mysql_dbms:
836             type: tosca.nodes.DBMS
837             properties:
838               root_password: aaa
839               port: 3376
840             requirement:
841               - host: server
842         '''
843         expectedmessage = _('Node template "mysql_dbms" contains unknown '
844                             'field "requirement". Refer to the definition to '
845                             'verify valid values.')
846         err = self.assertRaises(
847             exception.UnknownFieldError,
848             lambda: self._single_node_template_content_test(tpl_snippet))
849         self.assertEqual(expectedmessage, err.__str__())
850
851     def test_node_template_with_wrong_interfaces_keyname(self):
852         """Node template keyname 'interfaces' given as 'interfac'."""
853         tpl_snippet = '''
854         node_templates:
855           mysql_dbms:
856             type: tosca.nodes.DBMS
857             properties:
858               root_password: aaa
859               port: 3376
860             requirements:
861               - host: server
862             interfac:
863               Standard:
864                 configure: mysql_database_configure.sh
865         '''
866         expectedmessage = _('Node template "mysql_dbms" contains unknown '
867                             'field "interfac". Refer to the definition to '
868                             'verify valid values.')
869         err = self.assertRaises(
870             exception.UnknownFieldError,
871             lambda: self._single_node_template_content_test(tpl_snippet))
872         self.assertEqual(expectedmessage, err.__str__())
873
874     def test_node_template_with_wrong_capabilities_keyname(self):
875         """Node template keyname 'capabilities' given as 'capabilitiis'."""
876         tpl_snippet = '''
877         node_templates:
878           mysql_database:
879             type: tosca.nodes.Database
880             properties:
881               db_name: { get_input: db_name }
882               db_user: { get_input: db_user }
883               db_password: { get_input: db_pwd }
884             capabilitiis:
885               database_endpoint:
886                 properties:
887                   port: { get_input: db_port }
888         '''
889         expectedmessage = _('Node template "mysql_database" contains unknown '
890                             'field "capabilitiis". Refer to the definition to '
891                             'verify valid values.')
892         err = self.assertRaises(
893             exception.UnknownFieldError,
894             lambda: self._single_node_template_content_test(tpl_snippet))
895         self.assertEqual(expectedmessage, err.__str__())
896
897     def test_node_template_with_wrong_artifacts_keyname(self):
898         """Node template keyname 'artifacts' given as 'artifactsss'."""
899         tpl_snippet = '''
900         node_templates:
901           mysql_database:
902             type: tosca.nodes.Database
903             artifactsss:
904               db_content:
905                 implementation: files/my_db_content.txt
906                 type: tosca.artifacts.File
907         '''
908         expectedmessage = _('Node template "mysql_database" contains unknown '
909                             'field "artifactsss". Refer to the definition to '
910                             'verify valid values.')
911         err = self.assertRaises(
912             exception.UnknownFieldError,
913             lambda: self._single_node_template_content_test(tpl_snippet))
914         self.assertEqual(expectedmessage, err.__str__())
915
916     def test_node_template_with_multiple_wrong_keynames(self):
917         """Node templates given with multiple wrong keynames."""
918         tpl_snippet = '''
919         node_templates:
920           mysql_dbms:
921             type: tosca.nodes.DBMS
922             propertieees:
923               root_password: aaa
924               port: 3376
925             requirements:
926               - host: server
927             interfacs:
928               Standard:
929                 configure: mysql_database_configure.sh
930         '''
931         expectedmessage = _('Node template "mysql_dbms" contains unknown '
932                             'field "propertieees". Refer to the definition to '
933                             'verify valid values.')
934         err = self.assertRaises(
935             exception.UnknownFieldError,
936             lambda: self._single_node_template_content_test(tpl_snippet))
937         self.assertEqual(expectedmessage, err.__str__())
938
939         tpl_snippet = '''
940         node_templates:
941           mysql_database:
942             type: tosca.nodes.Database
943             properties:
944               name: { get_input: db_name }
945               user: { get_input: db_user }
946               password: { get_input: db_pwd }
947             capabilitiiiies:
948               database_endpoint:
949               properties:
950                 port: { get_input: db_port }
951             requirementsss:
952               - host:
953                   node: mysql_dbms
954             interfac:
955               Standard:
956                  configure: mysql_database_configure.sh
957
958         '''
959         expectedmessage = _('Node template "mysql_database" contains unknown '
960                             'field "capabilitiiiies". Refer to the definition '
961                             'to verify valid values.')
962         err = self.assertRaises(
963             exception.UnknownFieldError,
964             lambda: self._single_node_template_content_test(tpl_snippet))
965         self.assertEqual(expectedmessage, err.__str__())
966
967     def test_node_template_type(self):
968         tpl_snippet = '''
969         node_templates:
970           mysql_database:
971             type: tosca.nodes.Databases
972             properties:
973               db_name: { get_input: db_name }
974               db_user: { get_input: db_user }
975               db_password: { get_input: db_pwd }
976             capabilities:
977               database_endpoint:
978                 properties:
979                   port: { get_input: db_port }
980             requirements:
981               - host: mysql_dbms
982             interfaces:
983               Standard:
984                  configure: mysql_database_configure.sh
985         '''
986         expectedmessage = _('Type "tosca.nodes.Databases" is not '
987                             'a valid type.')
988         err = self.assertRaises(
989             exception.InvalidTypeError,
990             lambda: self._single_node_template_content_test(tpl_snippet))
991         self.assertEqual(expectedmessage, err.__str__())
992
993     def test_node_template_requirements(self):
994         tpl_snippet = '''
995         node_templates:
996           webserver:
997             type: tosca.nodes.WebServer
998             requirements:
999               host: server
1000             interfaces:
1001               Standard:
1002                 create: webserver_install.sh
1003                 start: d.sh
1004         '''
1005         expectedmessage = _('"requirements" of template "webserver" must be '
1006                             'of type "list".')
1007         err = self.assertRaises(
1008             exception.TypeMismatchError,
1009             lambda: self._single_node_template_content_test(tpl_snippet))
1010         self.assertEqual(expectedmessage, err.__str__())
1011
1012         tpl_snippet = '''
1013         node_templates:
1014           mysql_database:
1015             type: tosca.nodes.Database
1016             properties:
1017               db_name: { get_input: db_name }
1018               db_user: { get_input: db_user }
1019               db_password: { get_input: db_pwd }
1020             capabilities:
1021               database_endpoint:
1022                 properties:
1023                   port: { get_input: db_port }
1024             requirements:
1025               - host: mysql_dbms
1026               - database_endpoint: mysql_database
1027             interfaces:
1028               Standard:
1029                  configure: mysql_database_configure.sh
1030         '''
1031         expectedmessage = _('"requirements" of template "mysql_database" '
1032                             'contains unknown field "database_endpoint". '
1033                             'Refer to the definition to verify valid values.')
1034         err = self.assertRaises(
1035             exception.UnknownFieldError,
1036             lambda: self._single_node_template_content_test(tpl_snippet))
1037         self.assertEqual(expectedmessage, err.__str__())
1038
1039     def test_node_template_requirements_with_wrong_node_keyname(self):
1040         """Node template requirements keyname 'node' given as 'nodes'."""
1041         tpl_snippet = '''
1042         node_templates:
1043           mysql_database:
1044             type: tosca.nodes.Database
1045             requirements:
1046               - host:
1047                   nodes: mysql_dbms
1048
1049         '''
1050         expectedmessage = _('"requirements" of template "mysql_database" '
1051                             'contains unknown field "nodes". Refer to the '
1052                             'definition to verify valid values.')
1053         err = self.assertRaises(
1054             exception.UnknownFieldError,
1055             lambda: self._single_node_template_content_test(tpl_snippet))
1056         self.assertEqual(expectedmessage, err.__str__())
1057
1058     def test_node_template_requirements_with_wrong_capability_keyname(self):
1059         """Incorrect node template requirements keyname
1060
1061         Node template requirements keyname 'capability' given as
1062         'capabilityy'.
1063         """
1064         tpl_snippet = '''
1065         node_templates:
1066           mysql_database:
1067             type: tosca.nodes.Database
1068             requirements:
1069               - host:
1070                   node: mysql_dbms
1071               - log_endpoint:
1072                   node: logstash
1073                   capabilityy: log_endpoint
1074                   relationship:
1075                     type: tosca.relationships.ConnectsTo
1076
1077         '''
1078         expectedmessage = _('"requirements" of template "mysql_database" '
1079                             'contains unknown field "capabilityy". Refer to '
1080                             'the definition to verify valid values.')
1081         err = self.assertRaises(
1082             exception.UnknownFieldError,
1083             lambda: self._single_node_template_content_test(tpl_snippet))
1084         self.assertEqual(expectedmessage, err.__str__())
1085
1086     def test_node_template_requirements_with_wrong_relationship_keyname(self):
1087         """Incorrect node template requirements keyname
1088
1089         Node template requirements keyname 'relationship' given as
1090         'relationshipppp'.
1091         """
1092         tpl_snippet = '''
1093         node_templates:
1094           mysql_database:
1095             type: tosca.nodes.Database
1096             requirements:
1097               - host:
1098                   node: mysql_dbms
1099               - log_endpoint:
1100                   node: logstash
1101                   capability: log_endpoint
1102                   relationshipppp:
1103                     type: tosca.relationships.ConnectsTo
1104
1105         '''
1106         expectedmessage = _('"requirements" of template "mysql_database" '
1107                             'contains unknown field "relationshipppp". Refer '
1108                             'to the definition to verify valid values.')
1109         err = self.assertRaises(
1110             exception.UnknownFieldError,
1111             lambda: self._single_node_template_content_test(tpl_snippet))
1112         self.assertEqual(expectedmessage, err.__str__())
1113
1114     def test_node_template_requirements_with_wrong_occurrences_keyname(self):
1115         """Incorrect node template requirements keyname
1116
1117         Node template requirements keyname 'occurrences' given as
1118         'occurences'.
1119         """
1120         tpl_snippet = '''
1121         node_templates:
1122           mysql_database:
1123             type: tosca.nodes.Database
1124             requirements:
1125               - host:
1126                   node: mysql_dbms
1127               - log_endpoint:
1128                   node: logstash
1129                   capability: log_endpoint
1130                   relationship:
1131                     type: tosca.relationships.ConnectsTo
1132                   occurences: [0, UNBOUNDED]
1133         '''
1134         expectedmessage = _('"requirements" of template "mysql_database" '
1135                             'contains unknown field "occurences". Refer to '
1136                             'the definition to verify valid values.')
1137         err = self.assertRaises(
1138             exception.UnknownFieldError,
1139             lambda: self._single_node_template_content_test(tpl_snippet))
1140         self.assertEqual(expectedmessage, err.__str__())
1141
1142     def test_node_template_requirements_with_multiple_wrong_keynames(self):
1143         """Node templates given with multiple wrong requirements keynames."""
1144         tpl_snippet = '''
1145         node_templates:
1146           mysql_database:
1147             type: tosca.nodes.Database
1148             requirements:
1149               - host:
1150                   node: mysql_dbms
1151               - log_endpoint:
1152                   nod: logstash
1153                   capabilit: log_endpoint
1154                   relationshipppp:
1155                     type: tosca.relationships.ConnectsTo
1156
1157         '''
1158         expectedmessage = _('"requirements" of template "mysql_database" '
1159                             'contains unknown field "nod". Refer to the '
1160                             'definition to verify valid values.')
1161         err = self.assertRaises(
1162             exception.UnknownFieldError,
1163             lambda: self._single_node_template_content_test(tpl_snippet))
1164         self.assertEqual(expectedmessage, err.__str__())
1165
1166         tpl_snippet = '''
1167         node_templates:
1168           mysql_database:
1169             type: tosca.nodes.Database
1170             requirements:
1171               - host:
1172                   node: mysql_dbms
1173               - log_endpoint:
1174                   node: logstash
1175                   capabilit: log_endpoint
1176                   relationshipppp:
1177                     type: tosca.relationships.ConnectsTo
1178
1179         '''
1180         expectedmessage = _('"requirements" of template "mysql_database" '
1181                             'contains unknown field "capabilit". Refer to the '
1182                             'definition to verify valid values.')
1183         err = self.assertRaises(
1184             exception.UnknownFieldError,
1185             lambda: self._single_node_template_content_test(tpl_snippet))
1186         self.assertEqual(expectedmessage, err.__str__())
1187
1188     def test_node_template_requirements_invalid_occurrences(self):
1189         tpl_snippet = '''
1190         node_templates:
1191           server:
1192             type: tosca.nodes.Compute
1193             requirements:
1194               - log_endpoint:
1195                   capability: log_endpoint
1196                   occurrences: [0, -1]
1197         '''
1198         expectedmessage = _('Value of property "[0, -1]" is invalid.')
1199         err = self.assertRaises(
1200             exception.InvalidPropertyValueError,
1201             lambda: self._single_node_template_content_test(tpl_snippet))
1202         self.assertEqual(expectedmessage, err.__str__())
1203
1204         tpl_snippet = '''
1205         node_templates:
1206           server:
1207             type: tosca.nodes.Compute
1208             requirements:
1209               - log_endpoint:
1210                   capability: log_endpoint
1211                   occurrences: [a, w]
1212         '''
1213         expectedmessage = _('"a" is not an integer.')
1214         err = self.assertRaises(
1215             ValueError,
1216             lambda: self._single_node_template_content_test(tpl_snippet))
1217         self.assertEqual(expectedmessage, err.__str__())
1218
1219         tpl_snippet = '''
1220         node_templates:
1221           server:
1222             type: tosca.nodes.Compute
1223             requirements:
1224               - log_endpoint:
1225                   capability: log_endpoint
1226                   occurrences: -1
1227         '''
1228         expectedmessage = _('"-1" is not a list.')
1229         err = self.assertRaises(
1230             ValueError,
1231             lambda: self._single_node_template_content_test(tpl_snippet))
1232         self.assertEqual(expectedmessage, err.__str__())
1233
1234         tpl_snippet = '''
1235         node_templates:
1236           server:
1237             type: tosca.nodes.Compute
1238             requirements:
1239               - log_endpoint:
1240                   capability: log_endpoint
1241                   occurrences: [5, 1]
1242         '''
1243         expectedmessage = _('Value of property "[5, 1]" is invalid.')
1244         err = self.assertRaises(
1245             exception.InvalidPropertyValueError,
1246             lambda: self._single_node_template_content_test(tpl_snippet))
1247         self.assertEqual(expectedmessage, err.__str__())
1248
1249         tpl_snippet = '''
1250         node_templates:
1251           server:
1252             type: tosca.nodes.Compute
1253             requirements:
1254               - log_endpoint:
1255                   capability: log_endpoint
1256                   occurrences: [0, 0]
1257         '''
1258         expectedmessage = _('Value of property "[0, 0]" is invalid.')
1259         err = self.assertRaises(
1260             exception.InvalidPropertyValueError,
1261             lambda: self._single_node_template_content_test(tpl_snippet))
1262         self.assertEqual(expectedmessage, err.__str__())
1263
1264     def test_node_template_requirements_valid_occurrences(self):
1265         tpl_snippet = '''
1266         node_templates:
1267           server:
1268             type: tosca.nodes.Compute
1269             requirements:
1270               - log_endpoint:
1271                   capability: log_endpoint
1272                   occurrences: [2, 2]
1273         '''
1274         self._single_node_template_content_test(tpl_snippet)
1275
1276     def test_node_template_capabilities(self):
1277         tpl_snippet = '''
1278         node_templates:
1279           mysql_database:
1280             type: tosca.nodes.Database
1281             properties:
1282               db_name: { get_input: db_name }
1283               db_user: { get_input: db_user }
1284               db_password: { get_input: db_pwd }
1285             capabilities:
1286               http_endpoint:
1287                 properties:
1288                   port: { get_input: db_port }
1289             requirements:
1290               - host: mysql_dbms
1291             interfaces:
1292               Standard:
1293                  configure: mysql_database_configure.sh
1294         '''
1295         expectedmessage = _('"capabilities" of template "mysql_database" '
1296                             'contains unknown field "http_endpoint". Refer to '
1297                             'the definition to verify valid values.')
1298         err = self.assertRaises(
1299             exception.UnknownFieldError,
1300             lambda: self._single_node_template_content_test(tpl_snippet))
1301         self.assertEqual(expectedmessage, err.__str__())
1302
1303     def test_node_template_properties(self):
1304         tpl_snippet = '''
1305         node_templates:
1306           server:
1307             type: tosca.nodes.Compute
1308             properties:
1309               os_image: F18_x86_64
1310             capabilities:
1311               host:
1312                 properties:
1313                   disk_size: 10 GB
1314                   num_cpus: { get_input: cpus }
1315                   mem_size: 4096 MB
1316               os:
1317                 properties:
1318                   architecture: x86_64
1319                   type: Linux
1320                   distribution: Fedora
1321                   version: 18.0
1322         '''
1323         expectedmessage = _('"properties" of template "server" contains '
1324                             'unknown field "os_image". Refer to the '
1325                             'definition to verify valid values.')
1326         err = self.assertRaises(
1327             exception.UnknownFieldError,
1328             lambda: self._single_node_template_content_test(tpl_snippet))
1329         self.assertEqual(expectedmessage, err.__str__())
1330
1331     def test_node_template_interfaces(self):
1332         tpl_snippet = '''
1333         node_templates:
1334           wordpress:
1335             type: tosca.nodes.WebApplication.WordPress
1336             requirements:
1337               - host: webserver
1338               - database_endpoint: mysql_database
1339             interfaces:
1340               Standards:
1341                  create: wordpress_install.sh
1342                  configure:
1343                    implementation: wordpress_configure.sh
1344                    inputs:
1345                      wp_db_name: { get_property: [ mysql_database, db_name ] }
1346                      wp_db_user: { get_property: [ mysql_database, db_user ] }
1347                      wp_db_password: { get_property: [ mysql_database, \
1348                      db_password ] }
1349                      wp_db_port: { get_property: [ SELF, \
1350                      database_endpoint, port ] }
1351         '''
1352         expectedmessage = _('"interfaces" of template "wordpress" contains '
1353                             'unknown field "Standards". Refer to the '
1354                             'definition to verify valid values.')
1355         err = self.assertRaises(
1356             exception.UnknownFieldError,
1357             lambda: self._single_node_template_content_test(tpl_snippet))
1358         self.assertEqual(expectedmessage, err.__str__())
1359
1360         tpl_snippet = '''
1361         node_templates:
1362           wordpress:
1363             type: tosca.nodes.WebApplication.WordPress
1364             requirements:
1365               - host: webserver
1366               - database_endpoint: mysql_database
1367             interfaces:
1368               Standard:
1369                  create: wordpress_install.sh
1370                  config:
1371                    implementation: wordpress_configure.sh
1372                    inputs:
1373                      wp_db_name: { get_property: [ mysql_database, db_name ] }
1374                      wp_db_user: { get_property: [ mysql_database, db_user ] }
1375                      wp_db_password: { get_property: [ mysql_database, \
1376                      db_password ] }
1377                      wp_db_port: { get_property: [ SELF, \
1378                      database_endpoint, port ] }
1379         '''
1380         expectedmessage = _('"interfaces" of template "wordpress" contains '
1381                             'unknown field "config". Refer to the definition '
1382                             'to verify valid values.')
1383         err = self.assertRaises(
1384             exception.UnknownFieldError,
1385             lambda: self._single_node_template_content_test(tpl_snippet))
1386         self.assertEqual(expectedmessage, err.__str__())
1387
1388         tpl_snippet = '''
1389         node_templates:
1390           wordpress:
1391             type: tosca.nodes.WebApplication.WordPress
1392             requirements:
1393               - host: webserver
1394               - database_endpoint: mysql_database
1395             interfaces:
1396               Standard:
1397                  create: wordpress_install.sh
1398                  configure:
1399                    implementation: wordpress_configure.sh
1400                    input:
1401                      wp_db_name: { get_property: [ mysql_database, db_name ] }
1402                      wp_db_user: { get_property: [ mysql_database, db_user ] }
1403                      wp_db_password: { get_property: [ mysql_database, \
1404                      db_password ] }
1405                      wp_db_port: { get_ref_property: [ database_endpoint, \
1406                      database_endpoint, port ] }
1407         '''
1408         expectedmessage = _('"interfaces" of template "wordpress" contains '
1409                             'unknown field "input". Refer to the definition '
1410                             'to verify valid values.')
1411         err = self.assertRaises(
1412             exception.UnknownFieldError,
1413             lambda: self._single_node_template_content_test(tpl_snippet))
1414         self.assertEqual(expectedmessage, err.__str__())
1415
1416     def test_relationship_template_properties(self):
1417         tpl_snippet = '''
1418         relationship_templates:
1419             storage_attachto:
1420                 type: AttachesTo
1421                 properties:
1422                   device: test_device
1423         '''
1424         expectedmessage = _('"properties" of template "storage_attachto" is '
1425                             'missing required field "[\'location\']".')
1426         rel_template = (toscaparser.utils.yamlparser.
1427                         simple_parse(tpl_snippet))['relationship_templates']
1428         name = list(rel_template.keys())[0]
1429         rel_template = RelationshipTemplate(rel_template[name], name)
1430         err = self.assertRaises(exception.MissingRequiredFieldError,
1431                                 rel_template.validate)
1432         self.assertEqual(expectedmessage, six.text_type(err))
1433
1434     def test_invalid_template_version(self):
1435         tosca_tpl = os.path.join(
1436             os.path.dirname(os.path.abspath(__file__)),
1437             "data/test_invalid_template_version.yaml")
1438         self.assertRaises(exception.ValidationError, ToscaTemplate, tosca_tpl)
1439         valid_versions = ', '.join(ToscaTemplate.VALID_TEMPLATE_VERSIONS)
1440         exception.ExceptionCollector.assertExceptionMessage(
1441             exception.InvalidTemplateVersion,
1442             (_('The template version "tosca_xyz" is invalid. Valid versions '
1443                'are "%s".') % valid_versions))
1444
1445     def test_import_invalid_type(self):
1446         tosca_tpl = os.path.join(
1447             os.path.dirname(os.path.abspath(__file__)),
1448             "data/test_import_invalid_type.yaml")
1449         self.assertRaises(exception.ValidationError, ToscaTemplate, tosca_tpl)
1450         exception.ExceptionCollector.assertExceptionMessage(
1451             exception.UnknownFieldError,
1452             (_("Template {'invalid': 'custom_types/invalid_type.yaml'} "
1453                'contains unknown field "annotation_types". Refer to the '
1454                'definition to verify valid values.')))
1455
1456     def test_node_template_capabilities_properties(self):
1457         # validating capability property values
1458         tpl_snippet = '''
1459         node_templates:
1460           server:
1461             type: tosca.nodes.WebServer
1462             capabilities:
1463               data_endpoint:
1464                 properties:
1465                   initiator: test
1466         '''
1467         expectedmessage = _('The value "test" of property "initiator" is '
1468                             'not valid. Expected a value from "[source, '
1469                             'target, peer]".')
1470
1471         err = self.assertRaises(
1472             exception.ValidationError,
1473             lambda: self._single_node_template_content_test(tpl_snippet))
1474         self.assertEqual(expectedmessage, err.__str__())
1475
1476         tpl_snippet = '''
1477         node_templates:
1478           server:
1479             type: tosca.nodes.Compute
1480             capabilities:
1481               host:
1482                 properties:
1483                   disk_size: 10 GB
1484                   num_cpus: { get_input: cpus }
1485                   mem_size: 4096 MB
1486               os:
1487                 properties:
1488                   architecture: x86_64
1489                   type: Linux
1490                   distribution: Fedora
1491                   version: 18.0
1492               scalable:
1493                 properties:
1494                   min_instances: 1
1495                   max_instances: 3
1496                   default_instances: 5
1497         '''
1498         expectedmessage = _('"properties" of template "server": '
1499                             '"default_instances" value is not between '
1500                             '"min_instances" and "max_instances".')
1501         err = self.assertRaises(
1502             exception.ValidationError,
1503             lambda: self._single_node_template_content_test(tpl_snippet))
1504         self.assertEqual(expectedmessage, err.__str__())
1505
1506     def test_node_template_objectstorage_without_required_property(self):
1507         tpl_snippet = '''
1508         node_templates:
1509           server:
1510             type: tosca.nodes.ObjectStorage
1511             properties:
1512               maxsize: 1 GB
1513         '''
1514         expectedmessage = _('"properties" of template "server" is missing '
1515                             'required field "[\'name\']".')
1516         err = self.assertRaises(
1517             exception.MissingRequiredFieldError,
1518             lambda: self._single_node_template_content_test(tpl_snippet))
1519         self.assertEqual(expectedmessage, err.__str__())
1520
1521     def test_node_template_objectstorage_with_invalid_scalar_unit(self):
1522         tpl_snippet = '''
1523         node_templates:
1524           server:
1525             type: tosca.nodes.ObjectStorage
1526             properties:
1527               name: test
1528               maxsize: -1
1529         '''
1530         expectedmessage = _('"-1" is not a valid scalar-unit.')
1531         err = self.assertRaises(
1532             ValueError,
1533             lambda: self._single_node_template_content_test(tpl_snippet))
1534         self.assertEqual(expectedmessage, err.__str__())
1535
1536     def test_node_template_objectstorage_with_invalid_scalar_type(self):
1537         tpl_snippet = '''
1538         node_templates:
1539           server:
1540             type: tosca.nodes.ObjectStorage
1541             properties:
1542               name: test
1543               maxsize: 1 XB
1544         '''
1545         expectedmessage = _('"1 XB" is not a valid scalar-unit.')
1546         err = self.assertRaises(
1547             ValueError,
1548             lambda: self._single_node_template_content_test(tpl_snippet))
1549         self.assertEqual(expectedmessage, err.__str__())
1550
1551     def test_special_keywords(self):
1552         """Test special keywords
1553
1554            Test that special keywords, e.g. metadata, which are not part
1555            of specification do not throw any validation error.
1556         """
1557         tpl_snippet_metadata_map = '''
1558         node_templates:
1559           server:
1560             type: tosca.nodes.Compute
1561             metadata:
1562               name: server A
1563               role: master
1564         '''
1565         self._single_node_template_content_test(tpl_snippet_metadata_map)
1566
1567         tpl_snippet_metadata_inline = '''
1568         node_templates:
1569           server:
1570             type: tosca.nodes.Compute
1571             metadata: none
1572         '''
1573         self._single_node_template_content_test(tpl_snippet_metadata_inline)
1574
1575     def test_policy_valid_keynames(self):
1576         tpl_snippet = '''
1577         policies:
1578           - servers_placement:
1579               type: tosca.policies.Placement
1580               description: Apply placement policy to servers
1581               metadata: { user1: 1001, user2: 1002 }
1582               targets: [ serv1, serv2 ]
1583         '''
1584         policies = (toscaparser.utils.yamlparser.
1585                     simple_parse(tpl_snippet))['policies'][0]
1586         name = list(policies.keys())[0]
1587         Policy(name, policies[name], None, None)
1588
1589     def test_policy_invalid_keyname(self):
1590         tpl_snippet = '''
1591         policies:
1592           - servers_placement:
1593               type: tosca.policies.Placement
1594               testkey: testvalue
1595         '''
1596         policies = (toscaparser.utils.yamlparser.
1597                     simple_parse(tpl_snippet))['policies'][0]
1598         name = list(policies.keys())[0]
1599
1600         expectedmessage = _('Policy "servers_placement" contains '
1601                             'unknown field "testkey". Refer to the '
1602                             'definition to verify valid values.')
1603         err = self.assertRaises(
1604             exception.UnknownFieldError,
1605             lambda: Policy(name, policies[name], None, None))
1606         self.assertEqual(expectedmessage, err.__str__())
1607
1608     def test_policy_trigger_valid_keyname_senlin_resources(self):
1609         tpl_snippet = '''
1610         triggers:
1611          - resize_compute:
1612              description: trigger
1613              event_type: tosca.events.resource.utilization
1614              schedule:
1615                start_time: "2015-05-07T07:00:00Z"
1616                end_time: "2015-06-07T07:00:00Z"
1617              target_filter:
1618                node: master-container
1619                requirement: host
1620                capability: Container
1621              condition:
1622                constraint: { greater_than: 50 }
1623                period: 60
1624                evaluations: 1
1625                method : average
1626              action:
1627                resize: # Operation name
1628                 inputs:
1629                  strategy: LEAST_USED
1630                  implementation: Senlin.webhook()
1631         '''
1632         triggers = (toscaparser.utils.yamlparser.
1633                     simple_parse(tpl_snippet))['triggers'][0]
1634         name = list(triggers.keys())[0]
1635         Triggers(name, triggers[name])
1636
1637     def test_policy_trigger_valid_keyname_heat_resources(self):
1638         tpl_snippet = '''
1639         triggers:
1640          - high_cpu_usage:
1641              description: trigger
1642              meter_name: cpu_util
1643              condition:
1644                constraint: utilization greater_than 60%
1645                threshold: 60
1646                period: 600
1647                evaluations: 1
1648                method: average
1649                comparison_operator: gt
1650              metadata: SG1
1651              action: [SP1]
1652         '''
1653         triggers = (toscaparser.utils.yamlparser.
1654                     simple_parse(tpl_snippet))['triggers'][0]
1655         name = list(triggers.keys())[0]
1656         Triggers(name, triggers[name])
1657
1658     def test_policy_trigger_invalid_keyname_senlin_resources(self):
1659         tpl_snippet = '''
1660         triggers:
1661          - resize_compute:
1662              description: trigger
1663              event_type: tosca.events.resource.utilization
1664              schedule:
1665                start_time: "2015-05-07T07:00:00Z"
1666                end_time: "2015-06-07T07:00:00Z"
1667              target_filter1:
1668                node: master-container
1669                requirement: host
1670                capability: Container
1671              condition:
1672                constraint: utilization greater_than 50%
1673                period1: 60
1674                evaluations: 1
1675                method: average
1676              action:
1677                resize: # Operation name
1678                 inputs:
1679                  strategy: LEAST_USED
1680                  implementation: Senlin.webhook()
1681         '''
1682         triggers = (toscaparser.utils.yamlparser.
1683                     simple_parse(tpl_snippet))['triggers'][0]
1684         name = list(triggers.keys())[0]
1685         expectedmessage = _(
1686             'Triggers "resize_compute" contains unknown field '
1687             '"target_filter1". Refer to the definition '
1688             'to verify valid values.')
1689         err = self.assertRaises(
1690             exception.UnknownFieldError,
1691             lambda: Triggers(name, triggers[name]))
1692         self.assertEqual(expectedmessage, err.__str__())
1693
1694     def test_policy_trigger_invalid_keyname_heat_resources(self):
1695         tpl_snippet = '''
1696         triggers:
1697          - high_cpu_usage:
1698              description: trigger
1699              meter_name: cpu_util
1700              condition:
1701                constraint: utilization greater_than 60%
1702                threshold: 60
1703                period: 600
1704                evaluations: 1
1705                method: average
1706                comparison_operator: gt
1707              metadata1: SG1
1708              action: [SP1]
1709         '''
1710         triggers = (toscaparser.utils.yamlparser.
1711                     simple_parse(tpl_snippet))['triggers'][0]
1712         name = list(triggers.keys())[0]
1713         expectedmessage = _(
1714             'Triggers "high_cpu_usage" contains unknown field '
1715             '"metadata1". Refer to the definition '
1716             'to verify valid values.')
1717         err = self.assertRaises(
1718             exception.UnknownFieldError,
1719             lambda: Triggers(name, triggers[name]))
1720         self.assertEqual(expectedmessage, err.__str__())
1721
1722     def test_policy_missing_required_keyname(self):
1723         tpl_snippet = '''
1724         policies:
1725           - servers_placement:
1726               description: test description
1727         '''
1728         policies = (toscaparser.utils.yamlparser.
1729                     simple_parse(tpl_snippet))['policies'][0]
1730         name = list(policies.keys())[0]
1731
1732         expectedmessage = _('Template "servers_placement" is missing '
1733                             'required field "type".')
1734         err = self.assertRaises(
1735             exception.MissingRequiredFieldError,
1736             lambda: Policy(name, policies[name], None, None))
1737         self.assertEqual(expectedmessage, err.__str__())
1738
1739     def test_credential_datatype(self):
1740         tosca_tpl = os.path.join(
1741             os.path.dirname(os.path.abspath(__file__)),
1742             "data/test_credential_datatype.yaml")
1743         self.assertIsNotNone(ToscaTemplate(tosca_tpl))
1744
1745     def test_invalid_default_value(self):
1746         tpl_path = os.path.join(
1747             os.path.dirname(os.path.abspath(__file__)),
1748             "data/test_invalid_input_defaults.yaml")
1749         self.assertRaises(exception.ValidationError, ToscaTemplate, tpl_path)
1750         exception.ExceptionCollector.assertExceptionMessage(
1751             ValueError, _('"two" is not an integer.'))
1752
1753     def test_invalid_capability(self):
1754         tpl_snippet = '''
1755         node_templates:
1756           server:
1757             type: tosca.nodes.Compute
1758             capabilities:
1759                 oss:
1760                     properties:
1761                         architecture: x86_64
1762         '''
1763         tpl = (toscaparser.utils.yamlparser.simple_parse(tpl_snippet))
1764         err = self.assertRaises(exception.UnknownFieldError,
1765                                 TopologyTemplate, tpl, None)
1766         expectedmessage = _('"capabilities" of template "server" contains '
1767                             'unknown field "oss". Refer to the definition '
1768                             'to verify valid values.')
1769         self.assertEqual(expectedmessage, err.__str__())
1770
1771     def test_qualified_name(self):
1772         tpl_snippet_full_name = '''
1773         node_templates:
1774           supported_type:
1775             type: tosca.nodes.Compute
1776         '''
1777         tpl = (
1778             toscaparser.utils.yamlparser.simple_parse(
1779                 tpl_snippet_full_name))
1780         TopologyTemplate(tpl, None)
1781
1782         tpl_snippet_short_name = '''
1783         node_templates:
1784           supported_type:
1785             type: Compute
1786         '''
1787         tpl = (
1788             toscaparser.utils.yamlparser.simple_parse(
1789                 tpl_snippet_short_name))
1790         TopologyTemplate(tpl, None)
1791
1792         tpl_snippet_qualified_name = '''
1793         node_templates:
1794           supported_type:
1795             type: tosca:Compute
1796         '''
1797         tpl = (
1798             toscaparser.utils.yamlparser.simple_parse(
1799                 tpl_snippet_qualified_name))
1800         TopologyTemplate(tpl, None)
1801
1802     def test_requirements_as_list(self):
1803         """Node template with requirements provided with or without list
1804
1805         Node template requirements are required to be provided as list.
1806         """
1807
1808         expectedmessage = _('"requirements" of template "my_webserver"'
1809                             ' must be of type "list".')
1810
1811         # requirements provided as dictionary
1812         tpl_snippet1 = '''
1813         node_templates:
1814           my_webserver:
1815             type: tosca.nodes.WebServer
1816             requirements:
1817               host: server
1818           server:
1819             type: tosca.nodes.Compute
1820         '''
1821         err1 = self.assertRaises(
1822             exception.TypeMismatchError,
1823             lambda: self._single_node_template_content_test(tpl_snippet1))
1824         self.assertEqual(expectedmessage, err1.__str__())
1825
1826         # requirements provided as string
1827         tpl_snippet2 = '''
1828         node_templates:
1829           my_webserver:
1830             type: tosca.nodes.WebServer
1831             requirements: server
1832           server:
1833             type: tosca.nodes.Compute
1834         '''
1835         err2 = self.assertRaises(
1836             exception.TypeMismatchError,
1837             lambda: self._single_node_template_content_test(tpl_snippet2))
1838         self.assertEqual(expectedmessage, err2.__str__())
1839
1840         # requirements provided as list
1841         tpl_snippet3 = '''
1842         node_templates:
1843           my_webserver:
1844             type: tosca.nodes.WebServer
1845             requirements:
1846               - host: server
1847           server:
1848             type: tosca.nodes.Compute
1849         '''
1850         self.assertIsNone(
1851             self._single_node_template_content_test(tpl_snippet3))
1852
1853     def test_properties_override_with_flavor_and_image(self):
1854         tpl_path = os.path.join(
1855             os.path.dirname(os.path.abspath(__file__)),
1856             "data/test_normative_type_properties_override.yaml")
1857         self.assertIsNotNone(ToscaTemplate(tpl_path))