Fix more unhandled errors for full validation
Fix some errors that are not being handled for full validation. They include some invalid node template and outputs property names, and references to non-existing node templates. Also, add proper unit tests. Change-Id: Idba3382f3c8e1fcf6671a166f21ad003fdfbcc6b Closes-Bug: #1517728
This commit is contained in:
parent
a2c5ba1ab9
commit
b27cd33ad8
@ -53,14 +53,15 @@ class Schema(collections.Mapping):
|
||||
def __init__(self, name, schema_dict):
|
||||
self.name = name
|
||||
if not isinstance(schema_dict, collections.Mapping):
|
||||
msg = _('Schema "%(pname)s" must be a dict.') % dict(pname=name)
|
||||
msg = (_('Schema definition of "%(pname)s" must be a dict.')
|
||||
% dict(pname=name))
|
||||
ExceptionCollector.appendException(InvalidSchemaError(message=msg))
|
||||
|
||||
try:
|
||||
schema_dict['type']
|
||||
except KeyError:
|
||||
msg = (_('Schema "%(pname)s" must have a "type" attribute.')
|
||||
% dict(pname=name))
|
||||
msg = (_('Schema definition of "%(pname)s" must have a "type" '
|
||||
'attribute.') % dict(pname=name))
|
||||
ExceptionCollector.appendException(InvalidSchemaError(message=msg))
|
||||
|
||||
self.schema = schema_dict
|
||||
|
@ -26,7 +26,7 @@ class PropertyDef(object):
|
||||
try:
|
||||
self.schema['type']
|
||||
except KeyError:
|
||||
msg = (_('Property definition of "%(pname)s" must have a "type" '
|
||||
msg = (_('Schema definition of "%(pname)s" must have a "type" '
|
||||
'attribute.') % dict(pname=self.name))
|
||||
ExceptionCollector.appendException(
|
||||
InvalidSchemaError(message=msg))
|
||||
|
@ -42,8 +42,9 @@ class EntityTemplate(object):
|
||||
self.custom_def = custom_def
|
||||
self._validate_field(self.entity_tpl)
|
||||
if entity_name == 'node_type':
|
||||
self.type_definition = NodeType(self.entity_tpl['type'],
|
||||
custom_def)
|
||||
type = self.entity_tpl.get('type')
|
||||
self.type_definition = NodeType(type, custom_def) \
|
||||
if type is not None else None
|
||||
if entity_name == 'relationship_type':
|
||||
relationship = template.get('relationship')
|
||||
type = None
|
||||
@ -62,7 +63,8 @@ class EntityTemplate(object):
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
return self.type_definition.type
|
||||
if self.type_definition:
|
||||
return self.type_definition.type
|
||||
|
||||
@property
|
||||
def requirements(self):
|
||||
|
@ -15,6 +15,7 @@ import logging
|
||||
|
||||
from toscaparser.common.exception import ExceptionCollector
|
||||
from toscaparser.common.exception import InvalidPropertyValueError
|
||||
from toscaparser.common.exception import MissingRequiredFieldError
|
||||
from toscaparser.common.exception import TypeMismatchError
|
||||
from toscaparser.common.exception import UnknownFieldError
|
||||
from toscaparser.dataentity import DataEntity
|
||||
@ -79,6 +80,13 @@ class NodeTemplate(EntityTemplate):
|
||||
if (node in list(self.type_definition.TOSCA_DEF.keys())
|
||||
or node in self.custom_def):
|
||||
ExceptionCollector.appendException(NotImplementedError(msg))
|
||||
return
|
||||
|
||||
if node not in self.templates:
|
||||
ExceptionCollector.appendException(
|
||||
KeyError(_('Node template "%s" was not found.') % node))
|
||||
return
|
||||
|
||||
related_tpl = NodeTemplate(node, self.templates, self.custom_def)
|
||||
relationship = value.get('relationship') \
|
||||
if isinstance(value, dict) else None
|
||||
@ -106,11 +114,18 @@ class NodeTemplate(EntityTemplate):
|
||||
if not found_relationship_tpl:
|
||||
if isinstance(relationship, dict):
|
||||
relationship = relationship.get('type')
|
||||
if self.available_rel_types and \
|
||||
relationship in self.available_rel_types.keys():
|
||||
pass
|
||||
elif not relationship.startswith(rel_prfx):
|
||||
relationship = rel_prfx + relationship
|
||||
if relationship:
|
||||
if self.available_rel_types and \
|
||||
relationship in self.available_rel_types.keys():
|
||||
pass
|
||||
elif not relationship.startswith(rel_prfx):
|
||||
relationship = rel_prfx + relationship
|
||||
else:
|
||||
ExceptionCollector.appendException(
|
||||
MissingRequiredFieldError(
|
||||
what=_('"relationship" used in template '
|
||||
'"%s"') % related_tpl.name,
|
||||
required=self.TYPE))
|
||||
for rtype in self.type_definition.relationship.keys():
|
||||
if rtype.type == relationship:
|
||||
explicit_relation[rtype] = related_tpl
|
||||
|
@ -89,11 +89,11 @@ class Output(object):
|
||||
|
||||
@property
|
||||
def description(self):
|
||||
return self.attrs[self.DESCRIPTION]
|
||||
return self.attrs.get(self.DESCRIPTION)
|
||||
|
||||
@property
|
||||
def value(self):
|
||||
return self.attrs[self.VALUE]
|
||||
return self.attrs.get(self.VALUE)
|
||||
|
||||
def validate(self):
|
||||
self._validate_field()
|
||||
@ -103,9 +103,7 @@ class Output(object):
|
||||
ExceptionCollector.appendException(
|
||||
MissingRequiredFieldError(what='Output "%s"' % self.name,
|
||||
required=self.VALUE))
|
||||
try:
|
||||
self.value
|
||||
except KeyError:
|
||||
if self.value is None:
|
||||
ExceptionCollector.appendException(
|
||||
MissingRequiredFieldError(what='Output "%s"' % self.name,
|
||||
required=self.VALUE))
|
||||
|
@ -73,7 +73,7 @@ topology_template:
|
||||
db_root_password: { get_property: [ mysql_dbms, root_password ] }
|
||||
|
||||
mysql_dbms:
|
||||
type: tosca.nodes.DBMS
|
||||
type1: tosca.nodes.DBMS
|
||||
properties:
|
||||
root_password: { get_input: db_root_pwd }
|
||||
port: { get_input: db_port }
|
||||
@ -94,7 +94,11 @@ topology_template:
|
||||
webserver:
|
||||
type: tosca.nodes.WebServer
|
||||
requirements:
|
||||
- host: server
|
||||
- host: server1
|
||||
- database_endpoint:
|
||||
node: webserver
|
||||
relationship:
|
||||
type1: tosca.relationships.ConnectsTo
|
||||
interfaces:
|
||||
Standard:
|
||||
create: webserver/webserver_install.sh
|
||||
|
@ -47,7 +47,8 @@ class ConstraintTest(TestCase):
|
||||
schema = yamlparser.simple_parse(tpl_snippet)
|
||||
error = self.assertRaises(exception.InvalidSchemaError, Schema,
|
||||
'cpus', schema['cpus'])
|
||||
self.assertEqual(_('Schema "cpus" must be a dict.'), str(error))
|
||||
self.assertEqual(_('Schema definition of "cpus" must be a dict.'),
|
||||
str(error))
|
||||
|
||||
def test_schema_miss_type(self):
|
||||
tpl_snippet = '''
|
||||
@ -57,8 +58,8 @@ class ConstraintTest(TestCase):
|
||||
schema = yamlparser.simple_parse(tpl_snippet)
|
||||
error = self.assertRaises(exception.InvalidSchemaError, Schema,
|
||||
'cpus', schema['cpus'])
|
||||
self.assertEqual(_('Schema "cpus" must have a "type" attribute.'),
|
||||
str(error))
|
||||
self.assertEqual(_('Schema definition of "cpus" must have a "type" '
|
||||
'attribute.'), str(error))
|
||||
|
||||
def test_schema_none_description(self):
|
||||
tpl_snippet = '''
|
||||
|
@ -232,5 +232,5 @@ class PropertyTest(TestCase):
|
||||
schema = yamlparser.simple_parse(tpl_snippet)
|
||||
error = self.assertRaises(exception.InvalidSchemaError, PropertyDef,
|
||||
'prop', None, schema['properties']['prop'])
|
||||
self.assertEqual(_('Property definition of "prop" '
|
||||
'must have a "type" attribute.'), str(error))
|
||||
self.assertEqual(_('Schema definition of "prop" must have a "type" '
|
||||
'attribute.'), str(error))
|
||||
|
@ -490,6 +490,25 @@ class ToscaTemplateTest(TestCase):
|
||||
exception.ExceptionCollector.assertExceptionMessage(
|
||||
KeyError, err5_msg)
|
||||
|
||||
err6_msg = _('Template "mysql_dbms" is missing required field "type".')
|
||||
exception.ExceptionCollector.assertExceptionMessage(
|
||||
exception.MissingRequiredFieldError, err6_msg)
|
||||
|
||||
err7_msg = _('Node template "mysql_dbms" contains unknown field '
|
||||
'"type1". Refer to the definition to verify valid '
|
||||
'values.')
|
||||
exception.ExceptionCollector.assertExceptionMessage(
|
||||
exception.UnknownFieldError, err7_msg)
|
||||
|
||||
err8_msg = _('\'Node template "server1" was not found.\'')
|
||||
exception.ExceptionCollector.assertExceptionMessage(
|
||||
KeyError, err8_msg)
|
||||
|
||||
err9_msg = _('"relationship" used in template "webserver" is missing '
|
||||
'required field "type".')
|
||||
exception.ExceptionCollector.assertExceptionMessage(
|
||||
exception.MissingRequiredFieldError, err9_msg)
|
||||
|
||||
def test_invalid_section_names(self):
|
||||
tosca_tpl = os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
|
@ -72,9 +72,10 @@ class TopologyTemplate(object):
|
||||
tpl = NodeTemplate(name, tpls, self.custom_defs,
|
||||
self.relationship_templates,
|
||||
self.rel_types)
|
||||
if (tpl.type in tpl.type_definition.TOSCA_DEF or
|
||||
(tpl.type not in tpl.type_definition.TOSCA_DEF and
|
||||
bool(tpl.custom_def))):
|
||||
if (tpl.type_definition and
|
||||
(tpl.type in tpl.type_definition.TOSCA_DEF or
|
||||
(tpl.type not in tpl.type_definition.TOSCA_DEF and
|
||||
bool(tpl.custom_def)))):
|
||||
tpl.validate(self)
|
||||
nodetemplates.append(tpl)
|
||||
return nodetemplates
|
||||
|
Loading…
x
Reference in New Issue
Block a user