Merge "Release D doc update"
[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_import_error_file_uri(self):
450         tpl_snippet = '''
451         imports:
452           - more_definitions:
453              file: mycompany.com/ns/tosca/2.0/toscaparser/tests/data\
454 /tosca_elk.yaml
455              namespace_prefix: mycompany
456              namespace_uri: http://docs.oasis-open.org/tosca/ns/simple/yaml/1.0
457         '''
458         path = 'toscaparser/tests/data/tosca_elk.yaml'
459         self.assertRaises(ImportError,
460                           self._imports_content_test,
461                           tpl_snippet, path, None)
462
463     def test_import_single_line_error(self):
464         tpl_snippet = '''
465         imports:
466           - some_definitions: abc.com/tests/data/tosca_elk.yaml
467         '''
468         errormsg = _('Import "abc.com/tests/data/tosca_elk.yaml" is not '
469                      'valid.')
470         path = 'toscaparser/tests/data/tosca_elk.yaml'
471         err = self.assertRaises(ImportError,
472                                 self._imports_content_test,
473                                 tpl_snippet, path, None)
474         self.assertEqual(errormsg, err.__str__())
475
476     def test_outputs(self):
477         tpl_snippet = '''
478         outputs:
479           server_address:
480             description: IP address of server instance.
481             values: { get_property: [server, private_address] }
482         '''
483         outputs = (toscaparser.utils.yamlparser.
484                    simple_parse(tpl_snippet)['outputs'])
485         name, attrs = list(outputs.items())[0]
486         output = Output(name, attrs)
487         try:
488             output.validate()
489         except Exception as err:
490             self.assertTrue(
491                 isinstance(err, exception.MissingRequiredFieldError))
492             self.assertEqual(_('Output "server_address" is missing required '
493                                'field "value".'), err.__str__())
494
495         tpl_snippet = '''
496         outputs:
497           server_address:
498             descriptions: IP address of server instance.
499             value: { get_property: [server, private_address] }
500         '''
501         outputs = (toscaparser.utils.yamlparser.
502                    simple_parse(tpl_snippet)['outputs'])
503         name, attrs = list(outputs.items())[0]
504         output = Output(name, attrs)
505         try:
506             output.validate()
507         except Exception as err:
508             self.assertIsInstance(err, exception.UnknownFieldError)
509             self.assertEqual(_('Output "server_address" contains unknown '
510                                'field "descriptions". Refer to the definition '
511                                'to verify valid values.'),
512                              err.__str__())
513
514     def _repo_content(self, path):
515         repositories = path['repositories']
516         reposit = []
517         for name, val in repositories.items():
518             reposits = Repository(name, val)
519             reposit.append(reposits)
520         return reposit
521
522     def test_repositories(self):
523         tpl_snippet = '''
524         repositories:
525            repo_code0: https://raw.githubusercontent.com/nandinivemula/intern
526            repo_code1:
527               description: My project's code Repository in github usercontent.
528               url: https://github.com/nandinivemula/intern
529               credential:
530                  user: nandini
531                  password: tcs@12345
532            repo_code2:
533               description: My Project's code Repository in github.
534               url: https://github.com/nandinivemula/intern
535               credential:
536                  user: xyzw
537                  password: xyz@123
538         '''
539         tpl = (toscaparser.utils.yamlparser.simple_parse(tpl_snippet))
540         repoobject = self._repo_content(tpl)
541         actualrepo_names = []
542         for repo in repoobject:
543             repos = repo.name
544             actualrepo_names.append(repos)
545         reposname = list(tpl.values())
546         reposnames = reposname[0]
547         expected_reponames = list(reposnames.keys())
548         self.assertEqual(expected_reponames, actualrepo_names)
549
550     def test_repositories_with_missing_required_field(self):
551         tpl_snippet = '''
552         repositories:
553            repo_code0: https://raw.githubusercontent.com/nandinivemula/intern
554            repo_code1:
555               description: My project's code Repository in github usercontent.
556               credential:
557                  user: nandini
558                  password: tcs@12345
559            repo_code2:
560               description: My Project's code Repository in github.
561               url: https://github.com/nandinivemula/intern
562               credential:
563                  user: xyzw
564                  password: xyz@123
565         '''
566         tpl = (toscaparser.utils.yamlparser.simple_parse(tpl_snippet))
567         err = self.assertRaises(exception.MissingRequiredFieldError,
568                                 self._repo_content, tpl)
569         expectedmessage = _('Repository "repo_code1" is missing '
570                             'required field "url".')
571         self.assertEqual(expectedmessage, err.__str__())
572
573     def test_repositories_with_unknown_field(self):
574         tpl_snippet = '''
575         repositories:
576            repo_code0: https://raw.githubusercontent.com/nandinivemula/intern
577            repo_code1:
578               description: My project's code Repository in github usercontent.
579               url: https://github.com/nandinivemula/intern
580               credential:
581                  user: nandini
582                  password: tcs@12345
583            repo_code2:
584               descripton: My Project's code Repository in github.
585               url: https://github.com/nandinivemula/intern
586               credential:
587                  user: xyzw
588                  password: xyz@123
589         '''
590         tpl = (toscaparser.utils.yamlparser.simple_parse(tpl_snippet))
591         err = self.assertRaises(exception.UnknownFieldError,
592                                 self._repo_content, tpl)
593         expectedmessage = _('repositories "repo_code2" contains unknown field'
594                             ' "descripton". Refer to the definition to verify'
595                             ' valid values.')
596         self.assertEqual(expectedmessage, err.__str__())
597
598     def test_repositories_with_invalid_url(self):
599         tpl_snippet = '''
600         repositories:
601            repo_code0: https://raw.githubusercontent.com/nandinivemula/intern
602            repo_code1:
603               description: My project's code Repository in github usercontent.
604               url: h
605               credential:
606                  user: nandini
607                  password: tcs@12345
608            repo_code2:
609               description: My Project's code Repository in github.
610               url: https://github.com/nandinivemula/intern
611               credential:
612                  user: xyzw
613                  password: xyz@123
614         '''
615         tpl = (toscaparser.utils.yamlparser.simple_parse(tpl_snippet))
616         err = self.assertRaises(exception.URLException,
617                                 self._repo_content, tpl)
618         expectedmessage = _('repsositories "repo_code1" Invalid Url')
619         self.assertEqual(expectedmessage, err.__str__())
620
621     def test_groups(self):
622         tpl_snippet = '''
623         node_templates:
624           server:
625             type: tosca.nodes.Compute
626             requirements:
627               - log_endpoint:
628                   capability: log_endpoint
629
630           mysql_dbms:
631             type: tosca.nodes.DBMS
632             properties:
633               root_password: aaa
634               port: 3376
635
636         groups:
637           webserver_group:
638             type: tosca.groups.Root
639             members: [ server, mysql_dbms ]
640         '''
641         tpl = (toscaparser.utils.yamlparser.simple_parse(tpl_snippet))
642         TopologyTemplate(tpl, None)
643
644     def test_groups_with_missing_required_field(self):
645         tpl_snippet = '''
646         node_templates:
647           server:
648             type: tosca.nodes.Compute
649             requirements:
650               - log_endpoint:
651                   capability: log_endpoint
652
653           mysql_dbms:
654             type: tosca.nodes.DBMS
655             properties:
656               root_password: aaa
657               port: 3376
658
659         groups:
660           webserver_group:
661               members: ['server', 'mysql_dbms']
662         '''
663         tpl = (toscaparser.utils.yamlparser.simple_parse(tpl_snippet))
664         err = self.assertRaises(exception.MissingRequiredFieldError,
665                                 TopologyTemplate, tpl, None)
666         expectedmessage = _('Template "webserver_group" is missing '
667                             'required field "type".')
668         self.assertEqual(expectedmessage, err.__str__())
669
670     def test_groups_with_unknown_target(self):
671         tpl_snippet = '''
672         node_templates:
673           server:
674             type: tosca.nodes.Compute
675             requirements:
676               - log_endpoint:
677                   capability: log_endpoint
678
679           mysql_dbms:
680             type: tosca.nodes.DBMS
681             properties:
682               root_password: aaa
683               port: 3376
684
685         groups:
686           webserver_group:
687             type: tosca.groups.Root
688             members: [ serv, mysql_dbms ]
689         '''
690         tpl = (toscaparser.utils.yamlparser.simple_parse(tpl_snippet))
691         expectedmessage = _('"Target member "serv" is not found in '
692                             'node_templates"')
693         err = self.assertRaises(exception.InvalidGroupTargetException,
694                                 TopologyTemplate, tpl, None)
695         self.assertEqual(expectedmessage, err.__str__())
696
697     def test_groups_with_repeated_targets(self):
698         tpl_snippet = '''
699         node_templates:
700           server:
701             type: tosca.nodes.Compute
702             requirements:
703               - log_endpoint:
704                   capability: log_endpoint
705
706           mysql_dbms:
707             type: tosca.nodes.DBMS
708             properties:
709               root_password: aaa
710               port: 3376
711
712         groups:
713           webserver_group:
714             type: tosca.groups.Root
715             members: [ server, server, mysql_dbms ]
716         '''
717         tpl = (toscaparser.utils.yamlparser.simple_parse(tpl_snippet))
718         expectedmessage = _('"Member nodes '
719                             '"[\'server\', \'server\', \'mysql_dbms\']" '
720                             'should be >= 1 and not repeated"')
721         err = self.assertRaises(exception.InvalidGroupTargetException,
722                                 TopologyTemplate, tpl, None)
723         self.assertEqual(expectedmessage, err.__str__())
724
725     def test_groups_with_only_one_target(self):
726         tpl_snippet = '''
727         node_templates:
728           server:
729             type: tosca.nodes.Compute
730             requirements:
731               - log_endpoint:
732                   capability: log_endpoint
733
734           mysql_dbms:
735             type: tosca.nodes.DBMS
736             properties:
737               root_password: aaa
738               port: 3376
739
740         groups:
741           webserver_group:
742             type: tosca.groups.Root
743             members: []
744         '''
745         tpl = (toscaparser.utils.yamlparser.simple_parse(tpl_snippet))
746         expectedmessage = _('"Member nodes "[]" should be >= 1 '
747                             'and not repeated"')
748         err = self.assertRaises(exception.InvalidGroupTargetException,
749                                 TopologyTemplate, tpl, None)
750         self.assertEqual(expectedmessage, err.__str__())
751
752     def _custom_types(self):
753         custom_types = {}
754         def_file = os.path.join(
755             os.path.dirname(os.path.abspath(__file__)),
756             "data/custom_types/wordpress.yaml")
757         custom_type = toscaparser.utils.yamlparser.load_yaml(def_file)
758         node_types = custom_type['node_types']
759         for name in node_types:
760             defintion = node_types[name]
761             custom_types[name] = defintion
762         return custom_types
763
764     def _single_node_template_content_test(self, tpl_snippet):
765         nodetemplates = (toscaparser.utils.yamlparser.
766                          simple_ordered_parse(tpl_snippet))['node_templates']
767         name = list(nodetemplates.keys())[0]
768         nodetemplate = NodeTemplate(name, nodetemplates,
769                                     self._custom_types())
770         nodetemplate.validate()
771         nodetemplate.requirements
772         nodetemplate.get_capabilities_objects()
773         nodetemplate.get_properties_objects()
774         nodetemplate.interfaces
775
776     def test_node_templates(self):
777         tpl_snippet = '''
778         node_templates:
779           server:
780             capabilities:
781               host:
782                 properties:
783                   disk_size: 10
784                   num_cpus: 4
785                   mem_size: 4096
786               os:
787                 properties:
788                   architecture: x86_64
789                   type: Linux
790                   distribution: Fedora
791                   version: 18.0
792         '''
793         expectedmessage = _('Template "server" is missing required field '
794                             '"type".')
795         err = self.assertRaises(
796             exception.MissingRequiredFieldError,
797             lambda: self._single_node_template_content_test(tpl_snippet))
798         self.assertEqual(expectedmessage, err.__str__())
799
800     def test_node_template_with_wrong_properties_keyname(self):
801         """Node template keyname 'properties' given as 'propertiessss'."""
802         tpl_snippet = '''
803         node_templates:
804           mysql_dbms:
805             type: tosca.nodes.DBMS
806             propertiessss:
807               root_password: aaa
808               port: 3376
809         '''
810         expectedmessage = _('Node template "mysql_dbms" contains unknown '
811                             'field "propertiessss". Refer to the definition '
812                             'to verify valid values.')
813         err = self.assertRaises(
814             exception.UnknownFieldError,
815             lambda: self._single_node_template_content_test(tpl_snippet))
816         self.assertEqual(expectedmessage, err.__str__())
817
818     def test_node_template_with_wrong_requirements_keyname(self):
819         """Node template keyname 'requirements' given as 'requirement'."""
820         tpl_snippet = '''
821         node_templates:
822           mysql_dbms:
823             type: tosca.nodes.DBMS
824             properties:
825               root_password: aaa
826               port: 3376
827             requirement:
828               - host: server
829         '''
830         expectedmessage = _('Node template "mysql_dbms" contains unknown '
831                             'field "requirement". Refer to the definition to '
832                             'verify valid values.')
833         err = self.assertRaises(
834             exception.UnknownFieldError,
835             lambda: self._single_node_template_content_test(tpl_snippet))
836         self.assertEqual(expectedmessage, err.__str__())
837
838     def test_node_template_with_wrong_interfaces_keyname(self):
839         """Node template keyname 'interfaces' given as 'interfac'."""
840         tpl_snippet = '''
841         node_templates:
842           mysql_dbms:
843             type: tosca.nodes.DBMS
844             properties:
845               root_password: aaa
846               port: 3376
847             requirements:
848               - host: server
849             interfac:
850               Standard:
851                 configure: mysql_database_configure.sh
852         '''
853         expectedmessage = _('Node template "mysql_dbms" contains unknown '
854                             'field "interfac". Refer to the definition to '
855                             'verify valid values.')
856         err = self.assertRaises(
857             exception.UnknownFieldError,
858             lambda: self._single_node_template_content_test(tpl_snippet))
859         self.assertEqual(expectedmessage, err.__str__())
860
861     def test_node_template_with_wrong_capabilities_keyname(self):
862         """Node template keyname 'capabilities' given as 'capabilitiis'."""
863         tpl_snippet = '''
864         node_templates:
865           mysql_database:
866             type: tosca.nodes.Database
867             properties:
868               db_name: { get_input: db_name }
869               db_user: { get_input: db_user }
870               db_password: { get_input: db_pwd }
871             capabilitiis:
872               database_endpoint:
873                 properties:
874                   port: { get_input: db_port }
875         '''
876         expectedmessage = _('Node template "mysql_database" contains unknown '
877                             'field "capabilitiis". Refer to the definition to '
878                             'verify valid values.')
879         err = self.assertRaises(
880             exception.UnknownFieldError,
881             lambda: self._single_node_template_content_test(tpl_snippet))
882         self.assertEqual(expectedmessage, err.__str__())
883
884     def test_node_template_with_wrong_artifacts_keyname(self):
885         """Node template keyname 'artifacts' given as 'artifactsss'."""
886         tpl_snippet = '''
887         node_templates:
888           mysql_database:
889             type: tosca.nodes.Database
890             artifactsss:
891               db_content:
892                 implementation: files/my_db_content.txt
893                 type: tosca.artifacts.File
894         '''
895         expectedmessage = _('Node template "mysql_database" contains unknown '
896                             'field "artifactsss". Refer to the definition to '
897                             'verify valid values.')
898         err = self.assertRaises(
899             exception.UnknownFieldError,
900             lambda: self._single_node_template_content_test(tpl_snippet))
901         self.assertEqual(expectedmessage, err.__str__())
902
903     def test_node_template_with_multiple_wrong_keynames(self):
904         """Node templates given with multiple wrong keynames."""
905         tpl_snippet = '''
906         node_templates:
907           mysql_dbms:
908             type: tosca.nodes.DBMS
909             propertieees:
910               root_password: aaa
911               port: 3376
912             requirements:
913               - host: server
914             interfacs:
915               Standard:
916                 configure: mysql_database_configure.sh
917         '''
918         expectedmessage = _('Node template "mysql_dbms" contains unknown '
919                             'field "propertieees". Refer to the definition to '
920                             'verify valid values.')
921         err = self.assertRaises(
922             exception.UnknownFieldError,
923             lambda: self._single_node_template_content_test(tpl_snippet))
924         self.assertEqual(expectedmessage, err.__str__())
925
926         tpl_snippet = '''
927         node_templates:
928           mysql_database:
929             type: tosca.nodes.Database
930             properties:
931               name: { get_input: db_name }
932               user: { get_input: db_user }
933               password: { get_input: db_pwd }
934             capabilitiiiies:
935               database_endpoint:
936               properties:
937                 port: { get_input: db_port }
938             requirementsss:
939               - host:
940                   node: mysql_dbms
941             interfac:
942               Standard:
943                  configure: mysql_database_configure.sh
944
945         '''
946         expectedmessage = _('Node template "mysql_database" contains unknown '
947                             'field "capabilitiiiies". Refer to the definition '
948                             'to verify valid values.')
949         err = self.assertRaises(
950             exception.UnknownFieldError,
951             lambda: self._single_node_template_content_test(tpl_snippet))
952         self.assertEqual(expectedmessage, err.__str__())
953
954     def test_node_template_type(self):
955         tpl_snippet = '''
956         node_templates:
957           mysql_database:
958             type: tosca.nodes.Databases
959             properties:
960               db_name: { get_input: db_name }
961               db_user: { get_input: db_user }
962               db_password: { get_input: db_pwd }
963             capabilities:
964               database_endpoint:
965                 properties:
966                   port: { get_input: db_port }
967             requirements:
968               - host: mysql_dbms
969             interfaces:
970               Standard:
971                  configure: mysql_database_configure.sh
972         '''
973         expectedmessage = _('Type "tosca.nodes.Databases" is not '
974                             'a valid type.')
975         err = self.assertRaises(
976             exception.InvalidTypeError,
977             lambda: self._single_node_template_content_test(tpl_snippet))
978         self.assertEqual(expectedmessage, err.__str__())
979
980     def test_node_template_requirements(self):
981         tpl_snippet = '''
982         node_templates:
983           webserver:
984             type: tosca.nodes.WebServer
985             requirements:
986               host: server
987             interfaces:
988               Standard:
989                 create: webserver_install.sh
990                 start: d.sh
991         '''
992         expectedmessage = _('"requirements" of template "webserver" must be '
993                             'of type "list".')
994         err = self.assertRaises(
995             exception.TypeMismatchError,
996             lambda: self._single_node_template_content_test(tpl_snippet))
997         self.assertEqual(expectedmessage, err.__str__())
998
999         tpl_snippet = '''
1000         node_templates:
1001           mysql_database:
1002             type: tosca.nodes.Database
1003             properties:
1004               db_name: { get_input: db_name }
1005               db_user: { get_input: db_user }
1006               db_password: { get_input: db_pwd }
1007             capabilities:
1008               database_endpoint:
1009                 properties:
1010                   port: { get_input: db_port }
1011             requirements:
1012               - host: mysql_dbms
1013               - database_endpoint: mysql_database
1014             interfaces:
1015               Standard:
1016                  configure: mysql_database_configure.sh
1017         '''
1018         expectedmessage = _('"requirements" of template "mysql_database" '
1019                             'contains unknown field "database_endpoint". '
1020                             'Refer to the definition to verify valid values.')
1021         err = self.assertRaises(
1022             exception.UnknownFieldError,
1023             lambda: self._single_node_template_content_test(tpl_snippet))
1024         self.assertEqual(expectedmessage, err.__str__())
1025
1026     def test_node_template_requirements_with_wrong_node_keyname(self):
1027         """Node template requirements keyname 'node' given as 'nodes'."""
1028         tpl_snippet = '''
1029         node_templates:
1030           mysql_database:
1031             type: tosca.nodes.Database
1032             requirements:
1033               - host:
1034                   nodes: mysql_dbms
1035
1036         '''
1037         expectedmessage = _('"requirements" of template "mysql_database" '
1038                             'contains unknown field "nodes". Refer to the '
1039                             'definition to verify valid values.')
1040         err = self.assertRaises(
1041             exception.UnknownFieldError,
1042             lambda: self._single_node_template_content_test(tpl_snippet))
1043         self.assertEqual(expectedmessage, err.__str__())
1044
1045     def test_node_template_requirements_with_wrong_capability_keyname(self):
1046         """Incorrect node template requirements keyname
1047
1048         Node template requirements keyname 'capability' given as
1049         'capabilityy'.
1050         """
1051         tpl_snippet = '''
1052         node_templates:
1053           mysql_database:
1054             type: tosca.nodes.Database
1055             requirements:
1056               - host:
1057                   node: mysql_dbms
1058               - log_endpoint:
1059                   node: logstash
1060                   capabilityy: log_endpoint
1061                   relationship:
1062                     type: tosca.relationships.ConnectsTo
1063
1064         '''
1065         expectedmessage = _('"requirements" of template "mysql_database" '
1066                             'contains unknown field "capabilityy". Refer to '
1067                             'the definition to verify valid values.')
1068         err = self.assertRaises(
1069             exception.UnknownFieldError,
1070             lambda: self._single_node_template_content_test(tpl_snippet))
1071         self.assertEqual(expectedmessage, err.__str__())
1072
1073     def test_node_template_requirements_with_wrong_relationship_keyname(self):
1074         """Incorrect node template requirements keyname
1075
1076         Node template requirements keyname 'relationship' given as
1077         'relationshipppp'.
1078         """
1079         tpl_snippet = '''
1080         node_templates:
1081           mysql_database:
1082             type: tosca.nodes.Database
1083             requirements:
1084               - host:
1085                   node: mysql_dbms
1086               - log_endpoint:
1087                   node: logstash
1088                   capability: log_endpoint
1089                   relationshipppp:
1090                     type: tosca.relationships.ConnectsTo
1091
1092         '''
1093         expectedmessage = _('"requirements" of template "mysql_database" '
1094                             'contains unknown field "relationshipppp". Refer '
1095                             'to the definition to verify valid values.')
1096         err = self.assertRaises(
1097             exception.UnknownFieldError,
1098             lambda: self._single_node_template_content_test(tpl_snippet))
1099         self.assertEqual(expectedmessage, err.__str__())
1100
1101     def test_node_template_requirements_with_wrong_occurrences_keyname(self):
1102         """Incorrect node template requirements keyname
1103
1104         Node template requirements keyname 'occurrences' given as
1105         'occurences'.
1106         """
1107         tpl_snippet = '''
1108         node_templates:
1109           mysql_database:
1110             type: tosca.nodes.Database
1111             requirements:
1112               - host:
1113                   node: mysql_dbms
1114               - log_endpoint:
1115                   node: logstash
1116                   capability: log_endpoint
1117                   relationship:
1118                     type: tosca.relationships.ConnectsTo
1119                   occurences: [0, UNBOUNDED]
1120         '''
1121         expectedmessage = _('"requirements" of template "mysql_database" '
1122                             'contains unknown field "occurences". Refer to '
1123                             'the definition to verify valid values.')
1124         err = self.assertRaises(
1125             exception.UnknownFieldError,
1126             lambda: self._single_node_template_content_test(tpl_snippet))
1127         self.assertEqual(expectedmessage, err.__str__())
1128
1129     def test_node_template_requirements_with_multiple_wrong_keynames(self):
1130         """Node templates given with multiple wrong requirements keynames."""
1131         tpl_snippet = '''
1132         node_templates:
1133           mysql_database:
1134             type: tosca.nodes.Database
1135             requirements:
1136               - host:
1137                   node: mysql_dbms
1138               - log_endpoint:
1139                   nod: logstash
1140                   capabilit: log_endpoint
1141                   relationshipppp:
1142                     type: tosca.relationships.ConnectsTo
1143
1144         '''
1145         expectedmessage = _('"requirements" of template "mysql_database" '
1146                             'contains unknown field "nod". Refer to the '
1147                             'definition to verify valid values.')
1148         err = self.assertRaises(
1149             exception.UnknownFieldError,
1150             lambda: self._single_node_template_content_test(tpl_snippet))
1151         self.assertEqual(expectedmessage, err.__str__())
1152
1153         tpl_snippet = '''
1154         node_templates:
1155           mysql_database:
1156             type: tosca.nodes.Database
1157             requirements:
1158               - host:
1159                   node: mysql_dbms
1160               - log_endpoint:
1161                   node: logstash
1162                   capabilit: log_endpoint
1163                   relationshipppp:
1164                     type: tosca.relationships.ConnectsTo
1165
1166         '''
1167         expectedmessage = _('"requirements" of template "mysql_database" '
1168                             'contains unknown field "capabilit". Refer to the '
1169                             'definition to verify valid values.')
1170         err = self.assertRaises(
1171             exception.UnknownFieldError,
1172             lambda: self._single_node_template_content_test(tpl_snippet))
1173         self.assertEqual(expectedmessage, err.__str__())
1174
1175     def test_node_template_requirements_invalid_occurrences(self):
1176         tpl_snippet = '''
1177         node_templates:
1178           server:
1179             type: tosca.nodes.Compute
1180             requirements:
1181               - log_endpoint:
1182                   capability: log_endpoint
1183                   occurrences: [0, -1]
1184         '''
1185         expectedmessage = _('Value of property "[0, -1]" is invalid.')
1186         err = self.assertRaises(
1187             exception.InvalidPropertyValueError,
1188             lambda: self._single_node_template_content_test(tpl_snippet))
1189         self.assertEqual(expectedmessage, err.__str__())
1190
1191         tpl_snippet = '''
1192         node_templates:
1193           server:
1194             type: tosca.nodes.Compute
1195             requirements:
1196               - log_endpoint:
1197                   capability: log_endpoint
1198                   occurrences: [a, w]
1199         '''
1200         expectedmessage = _('"a" is not an integer.')
1201         err = self.assertRaises(
1202             ValueError,
1203             lambda: self._single_node_template_content_test(tpl_snippet))
1204         self.assertEqual(expectedmessage, err.__str__())
1205
1206         tpl_snippet = '''
1207         node_templates:
1208           server:
1209             type: tosca.nodes.Compute
1210             requirements:
1211               - log_endpoint:
1212                   capability: log_endpoint
1213                   occurrences: -1
1214         '''
1215         expectedmessage = _('"-1" is not a list.')
1216         err = self.assertRaises(
1217             ValueError,
1218             lambda: self._single_node_template_content_test(tpl_snippet))
1219         self.assertEqual(expectedmessage, err.__str__())
1220
1221         tpl_snippet = '''
1222         node_templates:
1223           server:
1224             type: tosca.nodes.Compute
1225             requirements:
1226               - log_endpoint:
1227                   capability: log_endpoint
1228                   occurrences: [5, 1]
1229         '''
1230         expectedmessage = _('Value of property "[5, 1]" is invalid.')
1231         err = self.assertRaises(
1232             exception.InvalidPropertyValueError,
1233             lambda: self._single_node_template_content_test(tpl_snippet))
1234         self.assertEqual(expectedmessage, err.__str__())
1235
1236         tpl_snippet = '''
1237         node_templates:
1238           server:
1239             type: tosca.nodes.Compute
1240             requirements:
1241               - log_endpoint:
1242                   capability: log_endpoint
1243                   occurrences: [0, 0]
1244         '''
1245         expectedmessage = _('Value of property "[0, 0]" is invalid.')
1246         err = self.assertRaises(
1247             exception.InvalidPropertyValueError,
1248             lambda: self._single_node_template_content_test(tpl_snippet))
1249         self.assertEqual(expectedmessage, err.__str__())
1250
1251     def test_node_template_requirements_valid_occurrences(self):
1252         tpl_snippet = '''
1253         node_templates:
1254           server:
1255             type: tosca.nodes.Compute
1256             requirements:
1257               - log_endpoint:
1258                   capability: log_endpoint
1259                   occurrences: [2, 2]
1260         '''
1261         self._single_node_template_content_test(tpl_snippet)
1262
1263     def test_node_template_capabilities(self):
1264         tpl_snippet = '''
1265         node_templates:
1266           mysql_database:
1267             type: tosca.nodes.Database
1268             properties:
1269               db_name: { get_input: db_name }
1270               db_user: { get_input: db_user }
1271               db_password: { get_input: db_pwd }
1272             capabilities:
1273               http_endpoint:
1274                 properties:
1275                   port: { get_input: db_port }
1276             requirements:
1277               - host: mysql_dbms
1278             interfaces:
1279               Standard:
1280                  configure: mysql_database_configure.sh
1281         '''
1282         expectedmessage = _('"capabilities" of template "mysql_database" '
1283                             'contains unknown field "http_endpoint". Refer to '
1284                             'the definition to verify valid values.')
1285         err = self.assertRaises(
1286             exception.UnknownFieldError,
1287             lambda: self._single_node_template_content_test(tpl_snippet))
1288         self.assertEqual(expectedmessage, err.__str__())
1289
1290     def test_node_template_properties(self):
1291         tpl_snippet = '''
1292         node_templates:
1293           server:
1294             type: tosca.nodes.Compute
1295             properties:
1296               os_image: F18_x86_64
1297             capabilities:
1298               host:
1299                 properties:
1300                   disk_size: 10 GB
1301                   num_cpus: { get_input: cpus }
1302                   mem_size: 4096 MB
1303               os:
1304                 properties:
1305                   architecture: x86_64
1306                   type: Linux
1307                   distribution: Fedora
1308                   version: 18.0
1309         '''
1310         expectedmessage = _('"properties" of template "server" contains '
1311                             'unknown field "os_image". Refer to the '
1312                             'definition to verify valid values.')
1313         err = self.assertRaises(
1314             exception.UnknownFieldError,
1315             lambda: self._single_node_template_content_test(tpl_snippet))
1316         self.assertEqual(expectedmessage, err.__str__())
1317
1318     def test_node_template_interfaces(self):
1319         tpl_snippet = '''
1320         node_templates:
1321           wordpress:
1322             type: tosca.nodes.WebApplication.WordPress
1323             requirements:
1324               - host: webserver
1325               - database_endpoint: mysql_database
1326             interfaces:
1327               Standards:
1328                  create: wordpress_install.sh
1329                  configure:
1330                    implementation: wordpress_configure.sh
1331                    inputs:
1332                      wp_db_name: { get_property: [ mysql_database, db_name ] }
1333                      wp_db_user: { get_property: [ mysql_database, db_user ] }
1334                      wp_db_password: { get_property: [ mysql_database, \
1335                      db_password ] }
1336                      wp_db_port: { get_property: [ SELF, \
1337                      database_endpoint, port ] }
1338         '''
1339         expectedmessage = _('"interfaces" of template "wordpress" contains '
1340                             'unknown field "Standards". Refer to the '
1341                             'definition to verify valid values.')
1342         err = self.assertRaises(
1343             exception.UnknownFieldError,
1344             lambda: self._single_node_template_content_test(tpl_snippet))
1345         self.assertEqual(expectedmessage, err.__str__())
1346
1347         tpl_snippet = '''
1348         node_templates:
1349           wordpress:
1350             type: tosca.nodes.WebApplication.WordPress
1351             requirements:
1352               - host: webserver
1353               - database_endpoint: mysql_database
1354             interfaces:
1355               Standard:
1356                  create: wordpress_install.sh
1357                  config:
1358                    implementation: wordpress_configure.sh
1359                    inputs:
1360                      wp_db_name: { get_property: [ mysql_database, db_name ] }
1361                      wp_db_user: { get_property: [ mysql_database, db_user ] }
1362                      wp_db_password: { get_property: [ mysql_database, \
1363                      db_password ] }
1364                      wp_db_port: { get_property: [ SELF, \
1365                      database_endpoint, port ] }
1366         '''
1367         expectedmessage = _('"interfaces" of template "wordpress" contains '
1368                             'unknown field "config". Refer to the definition '
1369                             'to verify valid values.')
1370         err = self.assertRaises(
1371             exception.UnknownFieldError,
1372             lambda: self._single_node_template_content_test(tpl_snippet))
1373         self.assertEqual(expectedmessage, err.__str__())
1374
1375         tpl_snippet = '''
1376         node_templates:
1377           wordpress:
1378             type: tosca.nodes.WebApplication.WordPress
1379             requirements:
1380               - host: webserver
1381               - database_endpoint: mysql_database
1382             interfaces:
1383               Standard:
1384                  create: wordpress_install.sh
1385                  configure:
1386                    implementation: wordpress_configure.sh
1387                    input:
1388                      wp_db_name: { get_property: [ mysql_database, db_name ] }
1389                      wp_db_user: { get_property: [ mysql_database, db_user ] }
1390                      wp_db_password: { get_property: [ mysql_database, \
1391                      db_password ] }
1392                      wp_db_port: { get_ref_property: [ database_endpoint, \
1393                      database_endpoint, port ] }
1394         '''
1395         expectedmessage = _('"interfaces" of template "wordpress" contains '
1396                             'unknown field "input". Refer to the definition '
1397                             'to verify valid values.')
1398         err = self.assertRaises(
1399             exception.UnknownFieldError,
1400             lambda: self._single_node_template_content_test(tpl_snippet))
1401         self.assertEqual(expectedmessage, err.__str__())
1402
1403     def test_relationship_template_properties(self):
1404         tpl_snippet = '''
1405         relationship_templates:
1406             storage_attachto:
1407                 type: AttachesTo
1408                 properties:
1409                   device: test_device
1410         '''
1411         expectedmessage = _('"properties" of template "storage_attachto" is '
1412                             'missing required field "[\'location\']".')
1413         rel_template = (toscaparser.utils.yamlparser.
1414                         simple_parse(tpl_snippet))['relationship_templates']
1415         name = list(rel_template.keys())[0]
1416         rel_template = RelationshipTemplate(rel_template[name], name)
1417         err = self.assertRaises(exception.MissingRequiredFieldError,
1418                                 rel_template.validate)
1419         self.assertEqual(expectedmessage, six.text_type(err))
1420
1421     def test_invalid_template_version(self):
1422         tosca_tpl = os.path.join(
1423             os.path.dirname(os.path.abspath(__file__)),
1424             "data/test_invalid_template_version.yaml")
1425         self.assertRaises(exception.ValidationError, ToscaTemplate, tosca_tpl)
1426         valid_versions = ', '.join(ToscaTemplate.VALID_TEMPLATE_VERSIONS)
1427         exception.ExceptionCollector.assertExceptionMessage(
1428             exception.InvalidTemplateVersion,
1429             (_('The template version "tosca_xyz" is invalid. Valid versions '
1430                'are "%s".') % valid_versions))
1431
1432     def test_node_template_capabilities_properties(self):
1433         # validating capability property values
1434         tpl_snippet = '''
1435         node_templates:
1436           server:
1437             type: tosca.nodes.WebServer
1438             capabilities:
1439               data_endpoint:
1440                 properties:
1441                   initiator: test
1442         '''
1443         expectedmessage = _('The value "test" of property "initiator" is '
1444                             'not valid. Expected a value from "[source, '
1445                             'target, peer]".')
1446
1447         err = self.assertRaises(
1448             exception.ValidationError,
1449             lambda: self._single_node_template_content_test(tpl_snippet))
1450         self.assertEqual(expectedmessage, err.__str__())
1451
1452         tpl_snippet = '''
1453         node_templates:
1454           server:
1455             type: tosca.nodes.Compute
1456             capabilities:
1457               host:
1458                 properties:
1459                   disk_size: 10 GB
1460                   num_cpus: { get_input: cpus }
1461                   mem_size: 4096 MB
1462               os:
1463                 properties:
1464                   architecture: x86_64
1465                   type: Linux
1466                   distribution: Fedora
1467                   version: 18.0
1468               scalable:
1469                 properties:
1470                   min_instances: 1
1471                   max_instances: 3
1472                   default_instances: 5
1473         '''
1474         expectedmessage = _('"properties" of template "server": '
1475                             '"default_instances" value is not between '
1476                             '"min_instances" and "max_instances".')
1477         err = self.assertRaises(
1478             exception.ValidationError,
1479             lambda: self._single_node_template_content_test(tpl_snippet))
1480         self.assertEqual(expectedmessage, err.__str__())
1481
1482     def test_node_template_objectstorage_without_required_property(self):
1483         tpl_snippet = '''
1484         node_templates:
1485           server:
1486             type: tosca.nodes.ObjectStorage
1487             properties:
1488               maxsize: 1 GB
1489         '''
1490         expectedmessage = _('"properties" of template "server" is missing '
1491                             'required field "[\'name\']".')
1492         err = self.assertRaises(
1493             exception.MissingRequiredFieldError,
1494             lambda: self._single_node_template_content_test(tpl_snippet))
1495         self.assertEqual(expectedmessage, err.__str__())
1496
1497     def test_node_template_objectstorage_with_invalid_scalar_unit(self):
1498         tpl_snippet = '''
1499         node_templates:
1500           server:
1501             type: tosca.nodes.ObjectStorage
1502             properties:
1503               name: test
1504               maxsize: -1
1505         '''
1506         expectedmessage = _('"-1" is not a valid scalar-unit.')
1507         err = self.assertRaises(
1508             ValueError,
1509             lambda: self._single_node_template_content_test(tpl_snippet))
1510         self.assertEqual(expectedmessage, err.__str__())
1511
1512     def test_node_template_objectstorage_with_invalid_scalar_type(self):
1513         tpl_snippet = '''
1514         node_templates:
1515           server:
1516             type: tosca.nodes.ObjectStorage
1517             properties:
1518               name: test
1519               maxsize: 1 XB
1520         '''
1521         expectedmessage = _('"1 XB" is not a valid scalar-unit.')
1522         err = self.assertRaises(
1523             ValueError,
1524             lambda: self._single_node_template_content_test(tpl_snippet))
1525         self.assertEqual(expectedmessage, err.__str__())
1526
1527     def test_special_keywords(self):
1528         """Test special keywords
1529
1530            Test that special keywords, e.g. metadata, which are not part
1531            of specification do not throw any validation error.
1532         """
1533         tpl_snippet_metadata_map = '''
1534         node_templates:
1535           server:
1536             type: tosca.nodes.Compute
1537             metadata:
1538               name: server A
1539               role: master
1540         '''
1541         self._single_node_template_content_test(tpl_snippet_metadata_map)
1542
1543         tpl_snippet_metadata_inline = '''
1544         node_templates:
1545           server:
1546             type: tosca.nodes.Compute
1547             metadata: none
1548         '''
1549         self._single_node_template_content_test(tpl_snippet_metadata_inline)
1550
1551     def test_policy_valid_keynames(self):
1552         tpl_snippet = '''
1553         policies:
1554           - servers_placement:
1555               type: tosca.policies.Placement
1556               description: Apply placement policy to servers
1557               metadata: { user1: 1001, user2: 1002 }
1558               targets: [ serv1, serv2 ]
1559         '''
1560         policies = (toscaparser.utils.yamlparser.
1561                     simple_parse(tpl_snippet))['policies'][0]
1562         name = list(policies.keys())[0]
1563         Policy(name, policies[name], None, None)
1564
1565     def test_policy_invalid_keyname(self):
1566         tpl_snippet = '''
1567         policies:
1568           - servers_placement:
1569               type: tosca.policies.Placement
1570               testkey: testvalue
1571         '''
1572         policies = (toscaparser.utils.yamlparser.
1573                     simple_parse(tpl_snippet))['policies'][0]
1574         name = list(policies.keys())[0]
1575
1576         expectedmessage = _('Policy "servers_placement" contains '
1577                             'unknown field "testkey". Refer to the '
1578                             'definition to verify valid values.')
1579         err = self.assertRaises(
1580             exception.UnknownFieldError,
1581             lambda: Policy(name, policies[name], None, None))
1582         self.assertEqual(expectedmessage, err.__str__())
1583
1584     def test_policy_trigger_valid_keyname(self):
1585         tpl_snippet = '''
1586         triggers:
1587          - resize_compute:
1588              description: trigger
1589              event_type: tosca.events.resource.utilization
1590              schedule:
1591                start_time: "2015-05-07T07:00:00Z"
1592                end_time: "2015-06-07T07:00:00Z"
1593              target_filter:
1594                node: master-container
1595                requirement: host
1596                capability: Container
1597              condition:
1598                constraint: { greater_than: 50 }
1599                period: 60
1600                evaluations: 1
1601                method : average
1602              action:
1603                resize: # Operation name
1604                 inputs:
1605                  strategy: LEAST_USED
1606                  implementation: Senlin.webhook()
1607         '''
1608         triggers = (toscaparser.utils.yamlparser.
1609                     simple_parse(tpl_snippet))['triggers'][0]
1610         name = list(triggers.keys())[0]
1611         Triggers(name, triggers[name])
1612
1613     def test_policy_trigger_invalid_keyname(self):
1614         tpl_snippet = '''
1615         triggers:
1616          - resize_compute:
1617              description: trigger
1618              event_type: tosca.events.resource.utilization
1619              schedule:
1620                start_time: "2015-05-07T07:00:00Z"
1621                end_time: "2015-06-07T07:00:00Z"
1622              target_filter1:
1623                node: master-container
1624                requirement: host
1625                capability: Container
1626              condition:
1627                constraint: utilization greater_than 50%
1628                period1: 60
1629                evaluations: 1
1630                method: average
1631              action:
1632                resize: # Operation name
1633                 inputs:
1634                  strategy: LEAST_USED
1635                  implementation: Senlin.webhook()
1636         '''
1637         triggers = (toscaparser.utils.yamlparser.
1638                     simple_parse(tpl_snippet))['triggers'][0]
1639         name = list(triggers.keys())[0]
1640         expectedmessage = _(
1641             'Triggers "resize_compute" contains unknown field '
1642             '"target_filter1". Refer to the definition '
1643             'to verify valid values.')
1644         err = self.assertRaises(
1645             exception.UnknownFieldError,
1646             lambda: Triggers(name, triggers[name]))
1647         self.assertEqual(expectedmessage, err.__str__())
1648
1649     def test_policy_missing_required_keyname(self):
1650         tpl_snippet = '''
1651         policies:
1652           - servers_placement:
1653               description: test description
1654         '''
1655         policies = (toscaparser.utils.yamlparser.
1656                     simple_parse(tpl_snippet))['policies'][0]
1657         name = list(policies.keys())[0]
1658
1659         expectedmessage = _('Template "servers_placement" is missing '
1660                             'required field "type".')
1661         err = self.assertRaises(
1662             exception.MissingRequiredFieldError,
1663             lambda: Policy(name, policies[name], None, None))
1664         self.assertEqual(expectedmessage, err.__str__())
1665
1666     def test_credential_datatype(self):
1667         tosca_tpl = os.path.join(
1668             os.path.dirname(os.path.abspath(__file__)),
1669             "data/test_credential_datatype.yaml")
1670         self.assertIsNotNone(ToscaTemplate(tosca_tpl))
1671
1672     def test_invalid_default_value(self):
1673         tpl_path = os.path.join(
1674             os.path.dirname(os.path.abspath(__file__)),
1675             "data/test_invalid_input_defaults.yaml")
1676         self.assertRaises(exception.ValidationError, ToscaTemplate, tpl_path)
1677         exception.ExceptionCollector.assertExceptionMessage(
1678             ValueError, _('"two" is not an integer.'))
1679
1680     def test_invalid_capability(self):
1681         tpl_snippet = '''
1682         node_templates:
1683           server:
1684             type: tosca.nodes.Compute
1685             capabilities:
1686                 oss:
1687                     properties:
1688                         architecture: x86_64
1689         '''
1690         tpl = (toscaparser.utils.yamlparser.simple_parse(tpl_snippet))
1691         err = self.assertRaises(exception.UnknownFieldError,
1692                                 TopologyTemplate, tpl, None)
1693         expectedmessage = _('"capabilities" of template "server" contains '
1694                             'unknown field "oss". Refer to the definition '
1695                             'to verify valid values.')
1696         self.assertEqual(expectedmessage, err.__str__())
1697
1698     def test_qualified_name(self):
1699         tpl_snippet_full_name = '''
1700         node_templates:
1701           supported_type:
1702             type: tosca.nodes.Compute
1703         '''
1704         tpl = (
1705             toscaparser.utils.yamlparser.simple_parse(
1706                 tpl_snippet_full_name))
1707         TopologyTemplate(tpl, None)
1708
1709         tpl_snippet_short_name = '''
1710         node_templates:
1711           supported_type:
1712             type: Compute
1713         '''
1714         tpl = (
1715             toscaparser.utils.yamlparser.simple_parse(
1716                 tpl_snippet_short_name))
1717         TopologyTemplate(tpl, None)
1718
1719         tpl_snippet_qualified_name = '''
1720         node_templates:
1721           supported_type:
1722             type: tosca:Compute
1723         '''
1724         tpl = (
1725             toscaparser.utils.yamlparser.simple_parse(
1726                 tpl_snippet_qualified_name))
1727         TopologyTemplate(tpl, None)
1728
1729     def test_requirements_as_list(self):
1730         """Node template with requirements provided with or without list
1731
1732         Node template requirements are required to be provided as list.
1733         """
1734
1735         expectedmessage = _('"requirements" of template "my_webserver"'
1736                             ' must be of type "list".')
1737
1738         # requirements provided as dictionary
1739         tpl_snippet1 = '''
1740         node_templates:
1741           my_webserver:
1742             type: tosca.nodes.WebServer
1743             requirements:
1744               host: server
1745           server:
1746             type: tosca.nodes.Compute
1747         '''
1748         err1 = self.assertRaises(
1749             exception.TypeMismatchError,
1750             lambda: self._single_node_template_content_test(tpl_snippet1))
1751         self.assertEqual(expectedmessage, err1.__str__())
1752
1753         # requirements provided as string
1754         tpl_snippet2 = '''
1755         node_templates:
1756           my_webserver:
1757             type: tosca.nodes.WebServer
1758             requirements: server
1759           server:
1760             type: tosca.nodes.Compute
1761         '''
1762         err2 = self.assertRaises(
1763             exception.TypeMismatchError,
1764             lambda: self._single_node_template_content_test(tpl_snippet2))
1765         self.assertEqual(expectedmessage, err2.__str__())
1766
1767         # requirements provided as list
1768         tpl_snippet3 = '''
1769         node_templates:
1770           my_webserver:
1771             type: tosca.nodes.WebServer
1772             requirements:
1773               - host: server
1774           server:
1775             type: tosca.nodes.Compute
1776         '''
1777         self.assertIsNone(
1778             self._single_node_template_content_test(tpl_snippet3))
1779
1780     def test_properties_override_with_flavor_and_image(self):
1781         tpl_path = os.path.join(
1782             os.path.dirname(os.path.abspath(__file__)),
1783             "data/test_normative_type_properties_override.yaml")
1784         self.assertIsNotNone(ToscaTemplate(tpl_path))