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