Add full support for PortDef data type
Add translation support for tosca.datatypes.network.PortDef data type and create unit tests for it. Change-Id: Iec56590d2d00cfb1a36f03339bd041b9ab35dd12 Closes-Bug: #1477735
This commit is contained in:
parent
a951b93c16
commit
1d096b3852
|
@ -85,7 +85,7 @@ def parse_parameters(parameter_list):
|
|||
def translate(sourcetype, path, parsed_params):
|
||||
output = None
|
||||
if sourcetype == "tosca":
|
||||
tosca = ToscaTemplate(path)
|
||||
tosca = ToscaTemplate(path, parsed_params)
|
||||
translator = TOSCATranslator(tosca, parsed_params)
|
||||
output = translator.translate()
|
||||
return output
|
||||
|
|
|
@ -211,7 +211,7 @@ class TranslationUtils(object):
|
|||
expected_hot_tpl = os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)), hot_file)
|
||||
|
||||
tosca = ToscaTemplate(tosca_tpl)
|
||||
tosca = ToscaTemplate(tosca_tpl, params)
|
||||
translate = translator.hot.tosca_translator.TOSCATranslator(tosca,
|
||||
params)
|
||||
output = translate.translate()
|
||||
|
|
|
@ -46,7 +46,8 @@ TOSCA_TO_HOT_INPUT_TYPES = {'string': 'string',
|
|||
'float': 'number',
|
||||
'boolean': 'boolean',
|
||||
'timestamp': 'string',
|
||||
'null': 'string'}
|
||||
'null': 'string',
|
||||
'PortDef': 'number'}
|
||||
|
||||
|
||||
class TranslateInputs(object):
|
||||
|
|
|
@ -24,7 +24,7 @@ class ToscaMongoNodejsTest(TestCase):
|
|||
tosca_tpl = os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"../toscalib/tests/data/tosca_nodejs_mongodb_two_instances.yaml")
|
||||
tosca = ToscaTemplate(tosca_tpl)
|
||||
tosca = ToscaTemplate(tosca_tpl, parsed_params)
|
||||
|
||||
def test_relationship_def(self):
|
||||
expected_relationship = ['tosca.relationships.HostedOn']
|
||||
|
|
|
@ -38,8 +38,10 @@ class DataEntity(object):
|
|||
# A datatype can not have both 'type' and 'properties' definitions.
|
||||
# If the datatype has 'type' definition
|
||||
if self.datatype.value_type:
|
||||
DataEntity.validate_datatype(self.datatype.value_type, self.value,
|
||||
None, self.custom_def)
|
||||
self.value = DataEntity.validate_datatype(self.datatype.value_type,
|
||||
self.value,
|
||||
None,
|
||||
self.custom_def)
|
||||
schema = Schema(None, self.datatype.defs)
|
||||
for constraint in schema.constraints:
|
||||
constraint.validate(self.value)
|
||||
|
|
|
@ -34,11 +34,13 @@ class Schema(collections.Mapping):
|
|||
PROPERTY_TYPES = (
|
||||
INTEGER, STRING, BOOLEAN, FLOAT,
|
||||
NUMBER, TIMESTAMP, LIST, MAP,
|
||||
SCALAR_UNIT_SIZE, SCALAR_UNIT_FREQUENCY, SCALAR_UNIT_TIME
|
||||
SCALAR_UNIT_SIZE, SCALAR_UNIT_FREQUENCY, SCALAR_UNIT_TIME,
|
||||
PORTDEF
|
||||
) = (
|
||||
'integer', 'string', 'boolean', 'float',
|
||||
'number', 'timestamp', 'list', 'map',
|
||||
'scalar-unit.size', 'scalar-unit.frequency', 'scalar-unit.time'
|
||||
'scalar-unit.size', 'scalar-unit.frequency', 'scalar-unit.time',
|
||||
'PortDef'
|
||||
)
|
||||
|
||||
SCALAR_UNIT_SIZE_DEFAULT = 'B'
|
||||
|
|
|
@ -15,7 +15,10 @@ import logging
|
|||
|
||||
from translator.toscalib.common.exception import MissingRequiredFieldError
|
||||
from translator.toscalib.common.exception import UnknownFieldError
|
||||
from translator.toscalib.dataentity import DataEntity
|
||||
from translator.toscalib.elements.constraints import Schema
|
||||
from translator.toscalib.elements.entitytype import EntityType
|
||||
from translator.toscalib.utils.gettextutils import _
|
||||
|
||||
|
||||
log = logging.getLogger('tosca')
|
||||
|
@ -46,9 +49,11 @@ class Input(object):
|
|||
def constraints(self):
|
||||
return self.schema.constraints
|
||||
|
||||
def validate(self):
|
||||
def validate(self, value=None):
|
||||
self._validate_field()
|
||||
self.validate_type(self.type)
|
||||
if value:
|
||||
self._validate_value(value)
|
||||
|
||||
def _validate_field(self):
|
||||
for name in self.schema:
|
||||
|
@ -60,6 +65,16 @@ class Input(object):
|
|||
if input_type not in Schema.PROPERTY_TYPES:
|
||||
raise ValueError(_('Invalid type %s') % type)
|
||||
|
||||
def _validate_value(self, value):
|
||||
tosca = EntityType.TOSCA_DEF
|
||||
datatype = None
|
||||
if self.type in tosca:
|
||||
datatype = tosca[self.type]
|
||||
elif EntityType.DATATYPE_PREFIX + self.type in tosca:
|
||||
datatype = tosca[EntityType.DATATYPE_PREFIX + self.type]
|
||||
|
||||
DataEntity.validate_datatype(self.type, value, None, datatype)
|
||||
|
||||
|
||||
class Output(object):
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ topology_template:
|
|||
type: string
|
||||
description: Root password for MySQL.
|
||||
db_port:
|
||||
type: integer
|
||||
type: PortDef
|
||||
description: Port for the MySQL database.
|
||||
|
||||
node_templates:
|
||||
|
|
|
@ -30,7 +30,7 @@ topology_template:
|
|||
type: string
|
||||
description: Root password for MySQL.
|
||||
db_port:
|
||||
type: integer
|
||||
type: PortDef
|
||||
description: Port for the MySQL database.
|
||||
default: 3306
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ from testtools.testcase import skip
|
|||
from translator.toscalib.common import exception
|
||||
from translator.toscalib.dataentity import DataEntity
|
||||
from translator.toscalib.elements.datatype import DataType
|
||||
from translator.toscalib.parameters import Input
|
||||
from translator.toscalib.tests.base import TestCase
|
||||
from translator.toscalib.tosca_template import ToscaTemplate
|
||||
from translator.toscalib.utils import yamlparser
|
||||
|
@ -114,6 +115,24 @@ class DataTypeTest(TestCase):
|
|||
data = DataEntity('PortSpec', value.get('user_port'))
|
||||
self.assertIsNotNone(data.validate())
|
||||
|
||||
def test_built_in_nested_datatype_portdef(self):
|
||||
tpl_snippet = '''
|
||||
inputs:
|
||||
db_port:
|
||||
type: PortDef
|
||||
description: Port for the MySQL database
|
||||
'''
|
||||
inputs = yamlparser.simple_parse(tpl_snippet)['inputs']
|
||||
name, attrs = list(inputs.items())[0]
|
||||
input = Input(name, attrs)
|
||||
self.assertIsNone(input.validate(3360))
|
||||
try:
|
||||
input.validate(336000)
|
||||
except Exception as err:
|
||||
self.assertTrue(isinstance(err, exception.ValidationError))
|
||||
self.assertEqual('None: 336000 is out of range (min:1, '
|
||||
'max:65535).', err.__str__())
|
||||
|
||||
def test_custom_datatype(self):
|
||||
value_snippet = '''
|
||||
name: Mike
|
||||
|
|
|
@ -37,10 +37,12 @@ log = logging.getLogger("tosca.model")
|
|||
class TopologyTemplate(object):
|
||||
|
||||
'''Load the template data.'''
|
||||
def __init__(self, template, custom_defs, rel_types=None):
|
||||
def __init__(self, template, custom_defs,
|
||||
rel_types=None, parsed_params=None):
|
||||
self.tpl = template
|
||||
self.custom_defs = custom_defs
|
||||
self.rel_types = rel_types
|
||||
self.parsed_params = parsed_params
|
||||
self._validate_field()
|
||||
self.description = self._tpl_description()
|
||||
self.inputs = self._inputs()
|
||||
|
@ -55,7 +57,8 @@ class TopologyTemplate(object):
|
|||
inputs = []
|
||||
for name, attrs in self._tpl_inputs().items():
|
||||
input = Input(name, attrs)
|
||||
input.validate()
|
||||
if self.parsed_params and name in self.parsed_params:
|
||||
input.validate(self.parsed_params[name])
|
||||
inputs.append(input)
|
||||
return inputs
|
||||
|
||||
|
|
|
@ -44,9 +44,10 @@ class ToscaTemplate(object):
|
|||
VALID_TEMPLATE_VERSIONS = ['tosca_simple_yaml_1_0']
|
||||
|
||||
'''Load the template data.'''
|
||||
def __init__(self, path):
|
||||
def __init__(self, path, parsed_params=None):
|
||||
self.tpl = YAML_LOADER(path)
|
||||
self.path = path
|
||||
self.parsed_params = parsed_params
|
||||
self._validate_field()
|
||||
self.version = self._tpl_version()
|
||||
self.relationship_types = self._tpl_relationship_types()
|
||||
|
@ -61,7 +62,8 @@ class ToscaTemplate(object):
|
|||
def _topology_template(self):
|
||||
return TopologyTemplate(self._tpl_topology_template(),
|
||||
self._get_all_custom_defs(),
|
||||
self.relationship_types)
|
||||
self.relationship_types,
|
||||
self.parsed_params)
|
||||
|
||||
def _inputs(self):
|
||||
return self.topology_template.inputs
|
||||
|
|
|
@ -34,8 +34,11 @@ def validate_number(value):
|
|||
|
||||
def validate_integer(value):
|
||||
if not isinstance(value, int):
|
||||
raise ValueError(_('"%s" is not an integer') % value)
|
||||
return validate_number(value)
|
||||
try:
|
||||
value = int(value)
|
||||
except Exception:
|
||||
raise ValueError(_('"%s" is not an integer') % value)
|
||||
return value
|
||||
|
||||
|
||||
def validate_float(value):
|
||||
|
|
Loading…
Reference in New Issue