Support version of tosca_simple_yaml_1_1
[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_node_template_capabilities_properties(self):
1446         # validating capability property values
1447         tpl_snippet = '''
1448         node_templates:
1449           server:
1450             type: tosca.nodes.WebServer
1451             capabilities:
1452               data_endpoint:
1453                 properties:
1454                   initiator: test
1455         '''
1456         expectedmessage = _('The value "test" of property "initiator" is '
1457                             'not valid. Expected a value from "[source, '
1458                             'target, peer]".')
1459
1460         err = self.assertRaises(
1461             exception.ValidationError,
1462             lambda: self._single_node_template_content_test(tpl_snippet))
1463         self.assertEqual(expectedmessage, err.__str__())
1464
1465         tpl_snippet = '''
1466         node_templates:
1467           server:
1468             type: tosca.nodes.Compute
1469             capabilities:
1470               host:
1471                 properties:
1472                   disk_size: 10 GB
1473                   num_cpus: { get_input: cpus }
1474                   mem_size: 4096 MB
1475               os:
1476                 properties:
1477                   architecture: x86_64
1478                   type: Linux
1479                   distribution: Fedora
1480                   version: 18.0
1481               scalable:
1482                 properties:
1483                   min_instances: 1
1484                   max_instances: 3
1485                   default_instances: 5
1486         '''
1487         expectedmessage = _('"properties" of template "server": '
1488                             '"default_instances" value is not between '
1489                             '"min_instances" and "max_instances".')
1490         err = self.assertRaises(
1491             exception.ValidationError,
1492             lambda: self._single_node_template_content_test(tpl_snippet))
1493         self.assertEqual(expectedmessage, err.__str__())
1494
1495     def test_node_template_objectstorage_without_required_property(self):
1496         tpl_snippet = '''
1497         node_templates:
1498           server:
1499             type: tosca.nodes.ObjectStorage
1500             properties:
1501               maxsize: 1 GB
1502         '''
1503         expectedmessage = _('"properties" of template "server" is missing '
1504                             'required field "[\'name\']".')
1505         err = self.assertRaises(
1506             exception.MissingRequiredFieldError,
1507             lambda: self._single_node_template_content_test(tpl_snippet))
1508         self.assertEqual(expectedmessage, err.__str__())
1509
1510     def test_node_template_objectstorage_with_invalid_scalar_unit(self):
1511         tpl_snippet = '''
1512         node_templates:
1513           server:
1514             type: tosca.nodes.ObjectStorage
1515             properties:
1516               name: test
1517               maxsize: -1
1518         '''
1519         expectedmessage = _('"-1" is not a valid scalar-unit.')
1520         err = self.assertRaises(
1521             ValueError,
1522             lambda: self._single_node_template_content_test(tpl_snippet))
1523         self.assertEqual(expectedmessage, err.__str__())
1524
1525     def test_node_template_objectstorage_with_invalid_scalar_type(self):
1526         tpl_snippet = '''
1527         node_templates:
1528           server:
1529             type: tosca.nodes.ObjectStorage
1530             properties:
1531               name: test
1532               maxsize: 1 XB
1533         '''
1534         expectedmessage = _('"1 XB" is not a valid scalar-unit.')
1535         err = self.assertRaises(
1536             ValueError,
1537             lambda: self._single_node_template_content_test(tpl_snippet))
1538         self.assertEqual(expectedmessage, err.__str__())
1539
1540     def test_special_keywords(self):
1541         """Test special keywords
1542
1543            Test that special keywords, e.g. metadata, which are not part
1544            of specification do not throw any validation error.
1545         """
1546         tpl_snippet_metadata_map = '''
1547         node_templates:
1548           server:
1549             type: tosca.nodes.Compute
1550             metadata:
1551               name: server A
1552               role: master
1553         '''
1554         self._single_node_template_content_test(tpl_snippet_metadata_map)
1555
1556         tpl_snippet_metadata_inline = '''
1557         node_templates:
1558           server:
1559             type: tosca.nodes.Compute
1560             metadata: none
1561         '''
1562         self._single_node_template_content_test(tpl_snippet_metadata_inline)
1563
1564     def test_policy_valid_keynames(self):
1565         tpl_snippet = '''
1566         policies:
1567           - servers_placement:
1568               type: tosca.policies.Placement
1569               description: Apply placement policy to servers
1570               metadata: { user1: 1001, user2: 1002 }
1571               targets: [ serv1, serv2 ]
1572         '''
1573         policies = (toscaparser.utils.yamlparser.
1574                     simple_parse(tpl_snippet))['policies'][0]
1575         name = list(policies.keys())[0]
1576         Policy(name, policies[name], None, None)
1577
1578     def test_policy_invalid_keyname(self):
1579         tpl_snippet = '''
1580         policies:
1581           - servers_placement:
1582               type: tosca.policies.Placement
1583               testkey: testvalue
1584         '''
1585         policies = (toscaparser.utils.yamlparser.
1586                     simple_parse(tpl_snippet))['policies'][0]
1587         name = list(policies.keys())[0]
1588
1589         expectedmessage = _('Policy "servers_placement" contains '
1590                             'unknown field "testkey". Refer to the '
1591                             'definition to verify valid values.')
1592         err = self.assertRaises(
1593             exception.UnknownFieldError,
1594             lambda: Policy(name, policies[name], None, None))
1595         self.assertEqual(expectedmessage, err.__str__())
1596
1597     def test_policy_trigger_valid_keyname_senlin_resources(self):
1598         tpl_snippet = '''
1599         triggers:
1600          - resize_compute:
1601              description: trigger
1602              event_type: tosca.events.resource.utilization
1603              schedule:
1604                start_time: "2015-05-07T07:00:00Z"
1605                end_time: "2015-06-07T07:00:00Z"
1606              target_filter:
1607                node: master-container
1608                requirement: host
1609                capability: Container
1610              condition:
1611                constraint: { greater_than: 50 }
1612                period: 60
1613                evaluations: 1
1614                method : average
1615              action:
1616                resize: # Operation name
1617                 inputs:
1618                  strategy: LEAST_USED
1619                  implementation: Senlin.webhook()
1620         '''
1621         triggers = (toscaparser.utils.yamlparser.
1622                     simple_parse(tpl_snippet))['triggers'][0]
1623         name = list(triggers.keys())[0]
1624         Triggers(name, triggers[name])
1625
1626     def test_policy_trigger_valid_keyname_heat_resources(self):
1627         tpl_snippet = '''
1628         triggers:
1629          - high_cpu_usage:
1630              description: trigger
1631              meter_name: cpu_util
1632              condition:
1633                constraint: utilization greater_than 60%
1634                threshold: 60
1635                period: 600
1636                evaluations: 1
1637                method: average
1638                comparison_operator: gt
1639              metadata: SG1
1640              action: [SP1]
1641         '''
1642         triggers = (toscaparser.utils.yamlparser.
1643                     simple_parse(tpl_snippet))['triggers'][0]
1644         name = list(triggers.keys())[0]
1645         Triggers(name, triggers[name])
1646
1647     def test_policy_trigger_invalid_keyname_senlin_resources(self):
1648         tpl_snippet = '''
1649         triggers:
1650          - resize_compute:
1651              description: trigger
1652              event_type: tosca.events.resource.utilization
1653              schedule:
1654                start_time: "2015-05-07T07:00:00Z"
1655                end_time: "2015-06-07T07:00:00Z"
1656              target_filter1:
1657                node: master-container
1658                requirement: host
1659                capability: Container
1660              condition:
1661                constraint: utilization greater_than 50%
1662                period1: 60
1663                evaluations: 1
1664                method: average
1665              action:
1666                resize: # Operation name
1667                 inputs:
1668                  strategy: LEAST_USED
1669                  implementation: Senlin.webhook()
1670         '''
1671         triggers = (toscaparser.utils.yamlparser.
1672                     simple_parse(tpl_snippet))['triggers'][0]
1673         name = list(triggers.keys())[0]
1674         expectedmessage = _(
1675             'Triggers "resize_compute" contains unknown field '
1676             '"target_filter1". Refer to the definition '
1677             'to verify valid values.')
1678         err = self.assertRaises(
1679             exception.UnknownFieldError,
1680             lambda: Triggers(name, triggers[name]))
1681         self.assertEqual(expectedmessage, err.__str__())
1682
1683     def test_policy_trigger_invalid_keyname_heat_resources(self):
1684         tpl_snippet = '''
1685         triggers:
1686          - high_cpu_usage:
1687              description: trigger
1688              meter_name: cpu_util
1689              condition:
1690                constraint: utilization greater_than 60%
1691                threshold: 60
1692                period: 600
1693                evaluations: 1
1694                method: average
1695                comparison_operator: gt
1696              metadata1: SG1
1697              action: [SP1]
1698         '''
1699         triggers = (toscaparser.utils.yamlparser.
1700                     simple_parse(tpl_snippet))['triggers'][0]
1701         name = list(triggers.keys())[0]
1702         expectedmessage = _(
1703             'Triggers "high_cpu_usage" contains unknown field '
1704             '"metadata1". Refer to the definition '
1705             'to verify valid values.')
1706         err = self.assertRaises(
1707             exception.UnknownFieldError,
1708             lambda: Triggers(name, triggers[name]))
1709         self.assertEqual(expectedmessage, err.__str__())
1710
1711     def test_policy_missing_required_keyname(self):
1712         tpl_snippet = '''
1713         policies:
1714           - servers_placement:
1715               description: test description
1716         '''
1717         policies = (toscaparser.utils.yamlparser.
1718                     simple_parse(tpl_snippet))['policies'][0]
1719         name = list(policies.keys())[0]
1720
1721         expectedmessage = _('Template "servers_placement" is missing '
1722                             'required field "type".')
1723         err = self.assertRaises(
1724             exception.MissingRequiredFieldError,
1725             lambda: Policy(name, policies[name], None, None))
1726         self.assertEqual(expectedmessage, err.__str__())
1727
1728     def test_credential_datatype(self):
1729         tosca_tpl = os.path.join(
1730             os.path.dirname(os.path.abspath(__file__)),
1731             "data/test_credential_datatype.yaml")
1732         self.assertIsNotNone(ToscaTemplate(tosca_tpl))
1733
1734     def test_invalid_default_value(self):
1735         tpl_path = os.path.join(
1736             os.path.dirname(os.path.abspath(__file__)),
1737             "data/test_invalid_input_defaults.yaml")
1738         self.assertRaises(exception.ValidationError, ToscaTemplate, tpl_path)
1739         exception.ExceptionCollector.assertExceptionMessage(
1740             ValueError, _('"two" is not an integer.'))
1741
1742     def test_invalid_capability(self):
1743         tpl_snippet = '''
1744         node_templates:
1745           server:
1746             type: tosca.nodes.Compute
1747             capabilities:
1748                 oss:
1749                     properties:
1750                         architecture: x86_64
1751         '''
1752         tpl = (toscaparser.utils.yamlparser.simple_parse(tpl_snippet))
1753         err = self.assertRaises(exception.UnknownFieldError,
1754                                 TopologyTemplate, tpl, None)
1755         expectedmessage = _('"capabilities" of template "server" contains '
1756                             'unknown field "oss". Refer to the definition '
1757                             'to verify valid values.')
1758         self.assertEqual(expectedmessage, err.__str__())
1759
1760     def test_qualified_name(self):
1761         tpl_snippet_full_name = '''
1762         node_templates:
1763           supported_type:
1764             type: tosca.nodes.Compute
1765         '''
1766         tpl = (
1767             toscaparser.utils.yamlparser.simple_parse(
1768                 tpl_snippet_full_name))
1769         TopologyTemplate(tpl, None)
1770
1771         tpl_snippet_short_name = '''
1772         node_templates:
1773           supported_type:
1774             type: Compute
1775         '''
1776         tpl = (
1777             toscaparser.utils.yamlparser.simple_parse(
1778                 tpl_snippet_short_name))
1779         TopologyTemplate(tpl, None)
1780
1781         tpl_snippet_qualified_name = '''
1782         node_templates:
1783           supported_type:
1784             type: tosca:Compute
1785         '''
1786         tpl = (
1787             toscaparser.utils.yamlparser.simple_parse(
1788                 tpl_snippet_qualified_name))
1789         TopologyTemplate(tpl, None)
1790
1791     def test_requirements_as_list(self):
1792         """Node template with requirements provided with or without list
1793
1794         Node template requirements are required to be provided as list.
1795         """
1796
1797         expectedmessage = _('"requirements" of template "my_webserver"'
1798                             ' must be of type "list".')
1799
1800         # requirements provided as dictionary
1801         tpl_snippet1 = '''
1802         node_templates:
1803           my_webserver:
1804             type: tosca.nodes.WebServer
1805             requirements:
1806               host: server
1807           server:
1808             type: tosca.nodes.Compute
1809         '''
1810         err1 = self.assertRaises(
1811             exception.TypeMismatchError,
1812             lambda: self._single_node_template_content_test(tpl_snippet1))
1813         self.assertEqual(expectedmessage, err1.__str__())
1814
1815         # requirements provided as string
1816         tpl_snippet2 = '''
1817         node_templates:
1818           my_webserver:
1819             type: tosca.nodes.WebServer
1820             requirements: server
1821           server:
1822             type: tosca.nodes.Compute
1823         '''
1824         err2 = self.assertRaises(
1825             exception.TypeMismatchError,
1826             lambda: self._single_node_template_content_test(tpl_snippet2))
1827         self.assertEqual(expectedmessage, err2.__str__())
1828
1829         # requirements provided as list
1830         tpl_snippet3 = '''
1831         node_templates:
1832           my_webserver:
1833             type: tosca.nodes.WebServer
1834             requirements:
1835               - host: server
1836           server:
1837             type: tosca.nodes.Compute
1838         '''
1839         self.assertIsNone(
1840             self._single_node_template_content_test(tpl_snippet3))
1841
1842     def test_properties_override_with_flavor_and_image(self):
1843         tpl_path = os.path.join(
1844             os.path.dirname(os.path.abspath(__file__)),
1845             "data/test_normative_type_properties_override.yaml")
1846         self.assertIsNotNone(ToscaTemplate(tpl_path))