Enable Translator with new TOSCA library (2)
Make changes to use new TOSCA pypi library. Partially Implements: blueprint use-tosca-parser-library Change-Id: I6520a2418ca5a9452babc27393aa5bee3870abfd
This commit is contained in:
parent
827e72e469
commit
717b855180
@ -16,12 +16,13 @@ import math
|
||||
import numbers
|
||||
import os
|
||||
import re
|
||||
from translator.toscalib.tosca_template import ToscaTemplate
|
||||
from translator.toscalib.utils.gettextutils import _
|
||||
import translator.toscalib.utils.yamlparser
|
||||
from toscaparser.tosca_template import ToscaTemplate
|
||||
from toscaparser.utils.gettextutils import _
|
||||
import toscaparser.utils.yamlparser
|
||||
from translator.hot.tosca_translator import TOSCATranslator as Translator
|
||||
import yaml
|
||||
|
||||
YAML_ORDER_PARSER = translator.toscalib.utils.yamlparser.simple_ordered_parse
|
||||
YAML_ORDER_PARSER = toscaparser.utils.yamlparser.simple_ordered_parse
|
||||
log = logging.getLogger('tosca')
|
||||
|
||||
|
||||
@ -221,10 +222,9 @@ class TranslationUtils(object):
|
||||
os.path.dirname(os.path.abspath(__file__)), hot_file)
|
||||
|
||||
tosca = ToscaTemplate(tosca_tpl, params)
|
||||
translate = translator.hot.tosca_translator.TOSCATranslator(tosca,
|
||||
params)
|
||||
translate = Translator(tosca, params)
|
||||
output = translate.translate()
|
||||
output_dict = translator.toscalib.utils.yamlparser.simple_parse(output)
|
||||
output_dict = toscaparser.utils.yamlparser.simple_parse(output)
|
||||
expected_output_dict = YamlUtils.get_dict(expected_hot_tpl)
|
||||
return CompareUtils.diff_dicts(output_dict, expected_output_dict)
|
||||
|
||||
|
@ -14,9 +14,9 @@
|
||||
from collections import OrderedDict
|
||||
import six
|
||||
|
||||
from translator.toscalib.functions import GetInput
|
||||
from translator.toscalib.nodetemplate import NodeTemplate
|
||||
from translator.toscalib.utils.gettextutils import _
|
||||
from toscaparser.functions import GetInput
|
||||
from toscaparser.nodetemplate import NodeTemplate
|
||||
from toscaparser.utils.gettextutils import _
|
||||
|
||||
|
||||
SECTIONS = (TYPE, PROPERTIES, MEDADATA, DEPENDS_ON, UPDATE_POLICY,
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
from toscaparser.tests.base import TestCase
|
||||
from translator.hot.syntax.hot_parameter import CONSTRAINTS
|
||||
from translator.hot.syntax.hot_parameter import DEFAULT
|
||||
from translator.hot.syntax.hot_parameter import DESCRIPTION
|
||||
@ -19,7 +20,6 @@ from translator.hot.syntax.hot_parameter import HIDDEN
|
||||
from translator.hot.syntax.hot_parameter import HotParameter
|
||||
from translator.hot.syntax.hot_parameter import LABEL
|
||||
from translator.hot.syntax.hot_parameter import TYPE
|
||||
from translator.toscalib.tests.base import TestCase
|
||||
|
||||
TEST_CONSTRAINTS = {'equal': 'allowed_values', 'greater_than': 'range'}
|
||||
|
||||
|
@ -12,12 +12,12 @@
|
||||
|
||||
|
||||
from collections import OrderedDict
|
||||
from toscaparser.parameters import Input
|
||||
from toscaparser.tests.base import TestCase
|
||||
from toscaparser.utils.gettextutils import _
|
||||
import toscaparser.utils.yamlparser
|
||||
from translator.common.utils import CompareUtils
|
||||
from translator.hot.translate_inputs import TranslateInputs
|
||||
from translator.toscalib.parameters import Input
|
||||
from translator.toscalib.tests.base import TestCase
|
||||
from translator.toscalib.utils.gettextutils import _
|
||||
import translator.toscalib.utils.yamlparser
|
||||
|
||||
|
||||
class ToscaTemplateInputValidationTest(TestCase):
|
||||
@ -25,7 +25,7 @@ class ToscaTemplateInputValidationTest(TestCase):
|
||||
def _translate_input_test(self, tpl_snippet, input_params,
|
||||
expectedmessage=None,
|
||||
expected_hot_params=None):
|
||||
inputs_dict = (translator.toscalib.utils.yamlparser.
|
||||
inputs_dict = (toscaparser.utils.yamlparser.
|
||||
simple_parse(tpl_snippet)['inputs'])
|
||||
inputs = []
|
||||
for name, attrs in inputs_dict.items():
|
||||
|
@ -11,10 +11,10 @@
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
from toscaparser.tests.base import TestCase
|
||||
from toscaparser.tosca_template import ToscaTemplate
|
||||
import toscaparser.utils.yamlparser
|
||||
from translator.hot.tosca_translator import TOSCATranslator
|
||||
from translator.toscalib.tests.base import TestCase
|
||||
from translator.toscalib.tosca_template import ToscaTemplate
|
||||
import translator.toscalib.utils.yamlparser
|
||||
|
||||
|
||||
class ToscaTemplateOutputTest(TestCase):
|
||||
@ -41,7 +41,7 @@ class ToscaTemplateOutputTest(TestCase):
|
||||
['mongo_server', 'networks', 'private', 0]}}}
|
||||
|
||||
hot_translation_dict = \
|
||||
translator.toscalib.utils.yamlparser.simple_parse(hot_translation)
|
||||
toscaparser.utils.yamlparser.simple_parse(hot_translation)
|
||||
|
||||
outputs = hot_translation_dict.get('outputs')
|
||||
for resource_name in outputs:
|
||||
|
@ -10,18 +10,18 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from toscaparser.common.exception import InvalidPropertyValueError
|
||||
from toscaparser.nodetemplate import NodeTemplate
|
||||
from toscaparser.tests.base import TestCase
|
||||
from toscaparser.utils.gettextutils import _
|
||||
import toscaparser.utils.yamlparser
|
||||
from translator.hot.tosca.tosca_block_storage import ToscaBlockStorage
|
||||
from translator.toscalib.common.exception import InvalidPropertyValueError
|
||||
from translator.toscalib.nodetemplate import NodeTemplate
|
||||
from translator.toscalib.tests.base import TestCase
|
||||
from translator.toscalib.utils.gettextutils import _
|
||||
import translator.toscalib.utils.yamlparser
|
||||
|
||||
|
||||
class ToscaBlockStoreTest(TestCase):
|
||||
|
||||
def _tosca_blockstore_test(self, tpl_snippet, expectedprops):
|
||||
nodetemplates = (translator.toscalib.utils.yamlparser.
|
||||
nodetemplates = (toscaparser.utils.yamlparser.
|
||||
simple_parse(tpl_snippet)['node_templates'])
|
||||
name = list(nodetemplates.keys())[0]
|
||||
try:
|
||||
|
@ -10,17 +10,17 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from toscaparser.nodetemplate import NodeTemplate
|
||||
from toscaparser.tests.base import TestCase
|
||||
from toscaparser.utils.gettextutils import _
|
||||
import toscaparser.utils.yamlparser
|
||||
from translator.hot.tosca.tosca_compute import ToscaCompute
|
||||
from translator.toscalib.nodetemplate import NodeTemplate
|
||||
from translator.toscalib.tests.base import TestCase
|
||||
from translator.toscalib.utils.gettextutils import _
|
||||
import translator.toscalib.utils.yamlparser
|
||||
|
||||
|
||||
class ToscaComputeTest(TestCase):
|
||||
|
||||
def _tosca_compute_test(self, tpl_snippet, expectedprops):
|
||||
nodetemplates = (translator.toscalib.utils.yamlparser.
|
||||
nodetemplates = (toscaparser.utils.yamlparser.
|
||||
simple_parse(tpl_snippet)['node_templates'])
|
||||
name = list(nodetemplates.keys())[0]
|
||||
try:
|
||||
|
@ -11,15 +11,15 @@
|
||||
# under the License.
|
||||
|
||||
import mock
|
||||
from toscaparser.tests.base import TestCase
|
||||
from translator.hot.tosca.custom_types.tosca_elasticsearch import (
|
||||
ToscaElasticsearch
|
||||
)
|
||||
from translator.toscalib.tests.base import TestCase
|
||||
|
||||
|
||||
class ToscaElasticsearchTest(TestCase):
|
||||
|
||||
@mock.patch('translator.toscalib.nodetemplate.NodeTemplate')
|
||||
@mock.patch('toscaparser.nodetemplate.NodeTemplate')
|
||||
@mock.patch('translator.hot.tosca.custom_types.tosca_elasticsearch.'
|
||||
'HotResource.__init__')
|
||||
def test_init(self, mock_hotres_init, mock_node):
|
||||
@ -29,7 +29,7 @@ class ToscaElasticsearchTest(TestCase):
|
||||
self.assertEqual(ToscaElasticsearch.toscatype,
|
||||
'tosca.nodes.SoftwareComponent.Elasticsearch')
|
||||
|
||||
@mock.patch('translator.toscalib.nodetemplate.NodeTemplate')
|
||||
@mock.patch('toscaparser.nodetemplate.NodeTemplate')
|
||||
@mock.patch('translator.hot.tosca.custom_types.tosca_elasticsearch.'
|
||||
'HotResource.__init__')
|
||||
def test_handle_properties(self, mock_hotres_init, mock_node):
|
||||
|
@ -11,13 +11,13 @@
|
||||
# under the License.
|
||||
|
||||
import mock
|
||||
from toscaparser.tests.base import TestCase
|
||||
from translator.hot.tosca.custom_types.tosca_kibana import ToscaKibana
|
||||
from translator.toscalib.tests.base import TestCase
|
||||
|
||||
|
||||
class ToscaKibanaTest(TestCase):
|
||||
|
||||
@mock.patch('translator.toscalib.nodetemplate.NodeTemplate')
|
||||
@mock.patch('toscaparser.nodetemplate.NodeTemplate')
|
||||
@mock.patch('translator.hot.tosca.custom_types.tosca_kibana.'
|
||||
'HotResource.__init__')
|
||||
def test_init(self, mock_hotres_init, mock_node):
|
||||
@ -27,7 +27,7 @@ class ToscaKibanaTest(TestCase):
|
||||
self.assertEqual(ToscaKibana.toscatype,
|
||||
'tosca.nodes.SoftwareComponent.Kibana')
|
||||
|
||||
@mock.patch('translator.toscalib.nodetemplate.NodeTemplate')
|
||||
@mock.patch('toscaparser.nodetemplate.NodeTemplate')
|
||||
@mock.patch('translator.hot.tosca.custom_types.tosca_kibana.'
|
||||
'HotResource.__init__')
|
||||
def test_handle_properties(self, mock_hotres_init, mock_node):
|
||||
|
@ -10,17 +10,17 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from toscaparser.nodetemplate import NodeTemplate
|
||||
from toscaparser.tests.base import TestCase
|
||||
from toscaparser.utils.gettextutils import _
|
||||
import toscaparser.utils.yamlparser
|
||||
from translator.hot.tosca.tosca_object_storage import ToscaObjectStorage
|
||||
from translator.toscalib.nodetemplate import NodeTemplate
|
||||
from translator.toscalib.tests.base import TestCase
|
||||
from translator.toscalib.utils.gettextutils import _
|
||||
import translator.toscalib.utils.yamlparser
|
||||
|
||||
|
||||
class ToscaObjectStoreTest(TestCase):
|
||||
|
||||
def _tosca_objectstore_test(self, tpl_snippet, expectedprops):
|
||||
nodetemplates = (translator.toscalib.utils.yamlparser.
|
||||
nodetemplates = (toscaparser.utils.yamlparser.
|
||||
simple_parse(tpl_snippet)['node_templates'])
|
||||
name = list(nodetemplates.keys())[0]
|
||||
try:
|
||||
|
@ -12,11 +12,11 @@
|
||||
# under the License.
|
||||
|
||||
import logging
|
||||
from toscaparser.common.exception import InvalidPropertyValueError
|
||||
from toscaparser.elements.scalarunit import ScalarUnit_Size
|
||||
from toscaparser.functions import GetInput
|
||||
from toscaparser.utils.gettextutils import _
|
||||
from translator.hot.syntax.hot_resource import HotResource
|
||||
from translator.toscalib.common.exception import InvalidPropertyValueError
|
||||
from translator.toscalib.elements.scalarunit import ScalarUnit_Size
|
||||
from translator.toscalib.functions import GetInput
|
||||
from translator.toscalib.utils.gettextutils import _
|
||||
|
||||
log = logging.getLogger("tosca")
|
||||
|
||||
|
@ -11,8 +11,8 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from toscaparser.functions import GetInput
|
||||
from translator.hot.syntax.hot_resource import HotResource
|
||||
from translator.toscalib.functions import GetInput
|
||||
|
||||
|
||||
class ToscaBlockStorageAttachment(HotResource):
|
||||
|
@ -12,9 +12,9 @@
|
||||
# under the License.
|
||||
|
||||
import logging
|
||||
from translator.common.utils import MemoryUnit
|
||||
from toscaparser.utils.validateutils import TOSCAVersionProperty
|
||||
import translator.common.utils
|
||||
from translator.hot.syntax.hot_resource import HotResource
|
||||
from translator.toscalib.utils.validateutils import TOSCAVersionProperty
|
||||
log = logging.getLogger('tosca')
|
||||
|
||||
# A design issue to be resolved is how to translate the generic TOSCA server
|
||||
@ -123,15 +123,15 @@ class ToscaCompute(HotResource):
|
||||
# flavors that fit the mem size
|
||||
mem = properties.get('mem_size')
|
||||
if mem:
|
||||
mem = MemoryUnit.convert_unit_size_to_num(mem,
|
||||
'MB')
|
||||
mem = translator.common.utils.MemoryUnit.convert_unit_size_to_num(
|
||||
mem, 'MB')
|
||||
match_cpu_mem = self._match_flavors(match_cpu, FLAVORS,
|
||||
'mem_size', mem)
|
||||
# flavors that fit the disk size
|
||||
disk = properties.get('disk_size')
|
||||
if disk:
|
||||
disk = MemoryUnit.convert_unit_size_to_num(disk,
|
||||
'GB')
|
||||
disk = translator.common.utils.MemoryUnit.\
|
||||
convert_unit_size_to_num(disk, 'GB')
|
||||
match_cpu_mem_disk = self._match_flavors(match_cpu_mem, FLAVORS,
|
||||
'disk_size', disk)
|
||||
# if multiple match, pick the flavor with the least memory
|
||||
|
@ -11,8 +11,8 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from toscaparser.common.exception import InvalidPropertyValueError
|
||||
from translator.hot.syntax.hot_resource import HotResource
|
||||
from translator.toscalib.common.exception import InvalidPropertyValueError
|
||||
|
||||
|
||||
class ToscaNetwork(HotResource):
|
||||
|
@ -11,8 +11,8 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from toscaparser.elements.scalarunit import ScalarUnit_Size
|
||||
from translator.hot.syntax.hot_resource import HotResource
|
||||
from translator.toscalib.elements.scalarunit import ScalarUnit_Size
|
||||
|
||||
|
||||
class ToscaObjectStorage(HotResource):
|
||||
|
@ -12,11 +12,11 @@
|
||||
# under the License.
|
||||
|
||||
import logging
|
||||
from toscaparser.dataentity import DataEntity
|
||||
from toscaparser.elements.scalarunit import ScalarUnit_Size
|
||||
from toscaparser.utils.gettextutils import _
|
||||
from toscaparser.utils.validateutils import TOSCAVersionProperty
|
||||
from translator.hot.syntax.hot_parameter import HotParameter
|
||||
from translator.toscalib.dataentity import DataEntity
|
||||
from translator.toscalib.elements.scalarunit import ScalarUnit_Size
|
||||
from translator.toscalib.utils.gettextutils import _
|
||||
from translator.toscalib.utils.validateutils import TOSCAVersionProperty
|
||||
|
||||
|
||||
INPUT_CONSTRAINTS = (CONSTRAINTS, DESCRIPTION, LENGTH, RANGE,
|
||||
|
@ -13,6 +13,10 @@
|
||||
|
||||
import six
|
||||
|
||||
from toscaparser.functions import GetAttribute
|
||||
from toscaparser.functions import GetInput
|
||||
from toscaparser.functions import GetProperty
|
||||
from toscaparser.relationship_template import RelationshipTemplate
|
||||
from translator.hot.syntax.hot_resource import HotResource
|
||||
from translator.hot.tosca.custom_types.tosca_collectd import ToscaCollectd
|
||||
from translator.hot.tosca.custom_types.tosca_elasticsearch import (
|
||||
@ -41,10 +45,6 @@ from translator.hot.tosca.tosca_software_component import (
|
||||
)
|
||||
from translator.hot.tosca.tosca_web_application import ToscaWebApplication
|
||||
from translator.hot.tosca.tosca_webserver import ToscaWebserver
|
||||
from translator.toscalib.functions import GetAttribute
|
||||
from translator.toscalib.functions import GetInput
|
||||
from translator.toscalib.functions import GetProperty
|
||||
from translator.toscalib.relationship_template import RelationshipTemplate
|
||||
|
||||
|
||||
SECTIONS = (TYPE, PROPERTIES, REQUIREMENTS, INTERFACES, LIFECYCLE, INPUT) = \
|
||||
|
@ -18,9 +18,9 @@ import sys
|
||||
|
||||
from cliff import command
|
||||
|
||||
from toscaparser.tosca_template import ToscaTemplate
|
||||
from translator.hot.tosca_translator import TOSCATranslator
|
||||
from translator.osc import utils
|
||||
from translator.toscalib.tosca_template import ToscaTemplate
|
||||
|
||||
|
||||
class TranslateTemplate(command.Command):
|
||||
|
@ -11,8 +11,8 @@
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
from toscaparser.tosca_template import ToscaTemplate
|
||||
from translator.tests.base import TestCase
|
||||
from translator.toscalib.tosca_template import ToscaTemplate
|
||||
|
||||
|
||||
class ToscaMongoNodejsTest(TestCase):
|
||||
|
@ -11,8 +11,8 @@
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
from toscaparser.tests.base import TestCase
|
||||
import translator.common.utils
|
||||
from translator.toscalib.tests.base import TestCase
|
||||
|
||||
|
||||
class CommonUtilsTest(TestCase):
|
||||
|
@ -1,45 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from translator.toscalib.properties import Property
|
||||
|
||||
|
||||
class Capability(object):
|
||||
'''TOSCA built-in capabilities type.'''
|
||||
|
||||
def __init__(self, name, properties, definition):
|
||||
self.name = name
|
||||
self._properties = properties
|
||||
self.definition = definition
|
||||
|
||||
def get_properties_objects(self):
|
||||
'''Return a list of property objects.'''
|
||||
properties = []
|
||||
props = self._properties
|
||||
if props:
|
||||
for name, value in props.items():
|
||||
props_def = self.definition.get_properties_def()
|
||||
if props_def and name in props_def:
|
||||
properties.append(Property(name, value,
|
||||
props_def[name].schema))
|
||||
return properties
|
||||
|
||||
def get_properties(self):
|
||||
'''Return a dictionary of property name-object pairs.'''
|
||||
return {prop.name: prop
|
||||
for prop in self.get_properties_objects()}
|
||||
|
||||
def get_property_value(self, name):
|
||||
'''Return the value of a given property name.'''
|
||||
props = self.get_properties()
|
||||
if props and name in props:
|
||||
return props[name].value
|
@ -1,100 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
'''
|
||||
TOSCA exception classes
|
||||
'''
|
||||
import logging
|
||||
import sys
|
||||
|
||||
from translator.toscalib.utils.gettextutils import _
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TOSCAException(Exception):
|
||||
'''Base exception class for TOSCA
|
||||
|
||||
To correctly use this class, inherit from it and define
|
||||
a 'msg_fmt' property.
|
||||
|
||||
'''
|
||||
|
||||
_FATAL_EXCEPTION_FORMAT_ERRORS = False
|
||||
|
||||
message = _('An unknown exception occurred.')
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
try:
|
||||
self.message = self.msg_fmt % kwargs
|
||||
except KeyError:
|
||||
exc_info = sys.exc_info()
|
||||
log.exception(_('Exception in string format operation: %s')
|
||||
% exc_info[1])
|
||||
|
||||
if TOSCAException._FATAL_EXCEPTION_FORMAT_ERRORS:
|
||||
raise exc_info[0]
|
||||
|
||||
def __str__(self):
|
||||
return self.message
|
||||
|
||||
@staticmethod
|
||||
def set_fatal_format_exception(flag):
|
||||
if isinstance(flag, bool):
|
||||
TOSCAException._FATAL_EXCEPTION_FORMAT_ERRORS = flag
|
||||
|
||||
|
||||
class MissingRequiredFieldError(TOSCAException):
|
||||
msg_fmt = _('%(what)s is missing required field: "%(required)s".')
|
||||
|
||||
|
||||
class UnknownFieldError(TOSCAException):
|
||||
msg_fmt = _('%(what)s contain(s) unknown field: "%(field)s", '
|
||||
'refer to the definition to verify valid values.')
|
||||
|
||||
|
||||
class TypeMismatchError(TOSCAException):
|
||||
msg_fmt = _('%(what)s must be of type: "%(type)s".')
|
||||
|
||||
|
||||
class InvalidNodeTypeError(TOSCAException):
|
||||
msg_fmt = _('Node type "%(what)s" is not a valid type.')
|
||||
|
||||
|
||||
class InvalidTypeError(TOSCAException):
|
||||
msg_fmt = _('Type "%(what)s" is not a valid type.')
|
||||
|
||||
|
||||
class InvalidSchemaError(TOSCAException):
|
||||
msg_fmt = _("%(message)s")
|
||||
|
||||
|
||||
class ValidationError(TOSCAException):
|
||||
msg_fmt = _("%(message)s")
|
||||
|
||||
|
||||
class UnknownInputError(TOSCAException):
|
||||
msg_fmt = _('Unknown input: %(input_name)s')
|
||||
|
||||
|
||||
class InvalidPropertyValueError(TOSCAException):
|
||||
msg_fmt = _('Value of property "%(what)s" is invalid.')
|
||||
|
||||
|
||||
class InvalidTemplateVersion(TOSCAException):
|
||||
msg_fmt = _('The template version "%(what)s" is invalid. '
|
||||
'The valid versions are: "%(valid_versions)s"')
|
||||
|
||||
|
||||
class InvalidTOSCAVersionPropertyException(TOSCAException):
|
||||
msg_fmt = _('Value of TOSCA version property "%(what)s" is invalid.')
|
@ -1,159 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from translator.toscalib.common.exception import MissingRequiredFieldError
|
||||
from translator.toscalib.common.exception import TypeMismatchError
|
||||
from translator.toscalib.common.exception import UnknownFieldError
|
||||
from translator.toscalib.elements.constraints import Schema
|
||||
from translator.toscalib.elements.datatype import DataType
|
||||
from translator.toscalib.elements.scalarunit import ScalarUnit_Frequency
|
||||
from translator.toscalib.elements.scalarunit import ScalarUnit_Size
|
||||
from translator.toscalib.elements.scalarunit import ScalarUnit_Time
|
||||
|
||||
from translator.toscalib.utils.gettextutils import _
|
||||
from translator.toscalib.utils import validateutils
|
||||
|
||||
|
||||
class DataEntity(object):
|
||||
'''A complex data value entity.'''
|
||||
|
||||
def __init__(self, datatypename, value_dict, custom_def=None):
|
||||
self.custom_def = custom_def
|
||||
self.datatype = DataType(datatypename, custom_def)
|
||||
self.schema = self.datatype.get_all_properties()
|
||||
self.value = value_dict
|
||||
|
||||
def validate(self):
|
||||
'''Validate the value by the definition of the datatype.'''
|
||||
|
||||
# A datatype can not have both 'type' and 'properties' definitions.
|
||||
# If the datatype has 'type' definition
|
||||
if self.datatype.value_type:
|
||||
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)
|
||||
# If the datatype has 'properties' definition
|
||||
else:
|
||||
if not isinstance(self.value, dict):
|
||||
raise TypeMismatchError(what=self.value,
|
||||
type=self.datatype.type)
|
||||
allowed_props = []
|
||||
required_props = []
|
||||
default_props = {}
|
||||
if self.schema:
|
||||
allowed_props = self.schema.keys()
|
||||
for name, prop_def in self.schema.items():
|
||||
if prop_def.required:
|
||||
required_props.append(name)
|
||||
if prop_def.default:
|
||||
default_props[name] = prop_def.default
|
||||
|
||||
# check allowed field
|
||||
for value_key in list(self.value.keys()):
|
||||
if value_key not in allowed_props:
|
||||
raise UnknownFieldError(what=_('Data value of type %s')
|
||||
% self.datatype.type,
|
||||
field=value_key)
|
||||
|
||||
# check default field
|
||||
for def_key, def_value in list(default_props.items()):
|
||||
if def_key not in list(self.value.keys()):
|
||||
self.value[def_key] = def_value
|
||||
|
||||
# check missing field
|
||||
missingprop = []
|
||||
for req_key in required_props:
|
||||
if req_key not in list(self.value.keys()):
|
||||
missingprop.append(req_key)
|
||||
if missingprop:
|
||||
raise MissingRequiredFieldError(what=_('Data value of type %s')
|
||||
% self.datatype.type,
|
||||
required=missingprop)
|
||||
|
||||
# check every field
|
||||
for name, value in list(self.value.items()):
|
||||
prop_schema = Schema(name, self._find_schema(name))
|
||||
# check if field value meets type defined
|
||||
DataEntity.validate_datatype(prop_schema.type, value,
|
||||
prop_schema.entry_schema,
|
||||
self.custom_def)
|
||||
# check if field value meets constraints defined
|
||||
if prop_schema.constraints:
|
||||
for constraint in prop_schema.constraints:
|
||||
constraint.validate(value)
|
||||
|
||||
return self.value
|
||||
|
||||
def _find_schema(self, name):
|
||||
if self.schema and name in self.schema.keys():
|
||||
return self.schema[name].schema
|
||||
|
||||
@staticmethod
|
||||
def validate_datatype(type, value, entry_schema=None, custom_def=None):
|
||||
'''Validate value with given type.
|
||||
|
||||
If type is list or map, validate its entry by entry_schema(if defined)
|
||||
If type is a user-defined complex datatype, custom_def is required.
|
||||
'''
|
||||
if type == Schema.STRING:
|
||||
return validateutils.validate_string(value)
|
||||
elif type == Schema.INTEGER:
|
||||
return validateutils.validate_integer(value)
|
||||
elif type == Schema.FLOAT:
|
||||
return validateutils.validate_float(value)
|
||||
elif type == Schema.NUMBER:
|
||||
return validateutils.validate_number(value)
|
||||
elif type == Schema.BOOLEAN:
|
||||
return validateutils.validate_boolean(value)
|
||||
elif type == Schema.TIMESTAMP:
|
||||
validateutils.validate_timestamp(value)
|
||||
return value
|
||||
elif type == Schema.LIST:
|
||||
validateutils.validate_list(value)
|
||||
if entry_schema:
|
||||
DataEntity.validate_entry(value, entry_schema, custom_def)
|
||||
return value
|
||||
elif type == Schema.SCALAR_UNIT_SIZE:
|
||||
return ScalarUnit_Size(value).validate_scalar_unit()
|
||||
elif type == Schema.SCALAR_UNIT_FREQUENCY:
|
||||
return ScalarUnit_Frequency(value).validate_scalar_unit()
|
||||
elif type == Schema.SCALAR_UNIT_TIME:
|
||||
return ScalarUnit_Time(value).validate_scalar_unit()
|
||||
elif type == Schema.VERSION:
|
||||
return validateutils.TOSCAVersionProperty(value).get_version()
|
||||
elif type == Schema.MAP:
|
||||
validateutils.validate_map(value)
|
||||
if entry_schema:
|
||||
DataEntity.validate_entry(value, entry_schema, custom_def)
|
||||
return value
|
||||
else:
|
||||
data = DataEntity(type, value, custom_def)
|
||||
return data.validate()
|
||||
|
||||
@staticmethod
|
||||
def validate_entry(value, entry_schema, custom_def=None):
|
||||
'''Validate entries for map and list.'''
|
||||
schema = Schema(None, entry_schema)
|
||||
valuelist = value
|
||||
if isinstance(value, dict):
|
||||
valuelist = list(value.values())
|
||||
for v in valuelist:
|
||||
DataEntity.validate_datatype(schema.type, v, schema.entry_schema,
|
||||
custom_def)
|
||||
if schema.constraints:
|
||||
for constraint in schema.constraints:
|
||||
constraint.validate(v)
|
||||
return value
|
@ -1,720 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
##########################################################################
|
||||
# The content of this file reflects TOSCA Simple Profile in YAML version
|
||||
# 1.0.0. It describes the definition for TOSCA types including Node Type,
|
||||
# Relationship Type, Capability Type and Interfaces.
|
||||
##########################################################################
|
||||
tosca_definitions_version: tosca_simple_yaml_1_0
|
||||
|
||||
##########################################################################
|
||||
# Node Type.
|
||||
# A Node Type is a reusable entity that defines the type of one or more
|
||||
# Node Templates.
|
||||
##########################################################################
|
||||
tosca.nodes.Root:
|
||||
description: >
|
||||
The TOSCA root node all other TOSCA base node types derive from.
|
||||
attributes:
|
||||
tosca_id:
|
||||
type: string
|
||||
tosca_name:
|
||||
type: string
|
||||
state:
|
||||
type: string
|
||||
capabilities:
|
||||
feature:
|
||||
type: tosca.capabilities.Node
|
||||
requirements:
|
||||
- dependency:
|
||||
capability: tosca.capabilities.Node
|
||||
node: tosca.nodes.Root
|
||||
relationship: tosca.relationships.DependsOn
|
||||
occurrences: [ 0, UNBOUNDED ]
|
||||
interfaces:
|
||||
Standard:
|
||||
type: tosca.interfaces.node.lifecycle.Standard
|
||||
|
||||
tosca.nodes.Compute:
|
||||
derived_from: tosca.nodes.Root
|
||||
attributes:
|
||||
private_address:
|
||||
type: string
|
||||
public_address:
|
||||
type: string
|
||||
capabilities:
|
||||
host:
|
||||
type: tosca.capabilities.Container
|
||||
binding:
|
||||
type: tosca.capabilities.network.Bindable
|
||||
os:
|
||||
type: tosca.capabilities.OperatingSystem
|
||||
scalable:
|
||||
type: tosca.capabilities.Scalable
|
||||
requirements:
|
||||
- local_storage:
|
||||
capability: tosca.capabilities.Attachment
|
||||
node: tosca.nodes.BlockStorage
|
||||
relationship: tosca.relationships.AttachesTo
|
||||
occurrences: [0, UNBOUNDED]
|
||||
|
||||
tosca.nodes.SoftwareComponent:
|
||||
derived_from: tosca.nodes.Root
|
||||
properties:
|
||||
# domain-specific software component version
|
||||
component_version:
|
||||
type: version
|
||||
required: false
|
||||
description: >
|
||||
Software component version.
|
||||
admin_credential:
|
||||
type: tosca.datatypes.Credential
|
||||
required: false
|
||||
requirements:
|
||||
- host:
|
||||
capability: tosca.capabilities.Container
|
||||
node: tosca.nodes.Compute
|
||||
relationship: tosca.relationships.HostedOn
|
||||
|
||||
tosca.nodes.DBMS:
|
||||
derived_from: tosca.nodes.SoftwareComponent
|
||||
properties:
|
||||
port:
|
||||
required: no
|
||||
type: integer
|
||||
description: >
|
||||
The port the DBMS service will listen to for data and requests.
|
||||
root_password:
|
||||
required: no
|
||||
type: string
|
||||
description: >
|
||||
The root password for the DBMS service.
|
||||
capabilities:
|
||||
host:
|
||||
type: tosca.capabilities.Container
|
||||
valid_source_types: [tosca.nodes.Database]
|
||||
|
||||
tosca.nodes.Database:
|
||||
derived_from: tosca.nodes.Root
|
||||
properties:
|
||||
user:
|
||||
required: no
|
||||
type: string
|
||||
description: >
|
||||
User account name for DB administration
|
||||
name:
|
||||
required: no
|
||||
type: string
|
||||
description: >
|
||||
The name of the database.
|
||||
password:
|
||||
required: no
|
||||
type: string
|
||||
description: >
|
||||
The password for the DB user account
|
||||
requirements:
|
||||
- host:
|
||||
capability: tosca.capabilities.Container
|
||||
node: tosca.nodes.DBMS
|
||||
relationship: tosca.relationships.HostedOn
|
||||
capabilities:
|
||||
database_endpoint:
|
||||
type: tosca.capabilities.Endpoint.Database
|
||||
|
||||
tosca.nodes.WebServer:
|
||||
derived_from: tosca.nodes.SoftwareComponent
|
||||
capabilities:
|
||||
data_endpoint:
|
||||
type: tosca.capabilities.Endpoint
|
||||
admin_endpoint:
|
||||
type: tosca.capabilities.Endpoint.Admin
|
||||
host:
|
||||
type: tosca.capabilities.Container
|
||||
valid_source_types: [tosca.nodes.WebApplication]
|
||||
|
||||
tosca.nodes.WebApplication:
|
||||
derived_from: tosca.nodes.Root
|
||||
properties:
|
||||
context_root:
|
||||
type: string
|
||||
required: false
|
||||
requirements:
|
||||
- host:
|
||||
capability: tosca.capabilities.Container
|
||||
node: tosca.nodes.WebServer
|
||||
relationship: tosca.relationships.HostedOn
|
||||
capabilities:
|
||||
app_endpoint:
|
||||
type: tosca.capabilities.Endpoint
|
||||
|
||||
tosca.nodes.BlockStorage:
|
||||
derived_from: tosca.nodes.Root
|
||||
properties:
|
||||
size:
|
||||
type: scalar-unit.size
|
||||
constraints:
|
||||
- greater_or_equal: 1 MB
|
||||
volume_id:
|
||||
type: string
|
||||
required: false
|
||||
snapshot_id:
|
||||
type: string
|
||||
required: false
|
||||
attributes:
|
||||
volume_id:
|
||||
type: string
|
||||
capabilities:
|
||||
attachment:
|
||||
type: tosca.capabilities.Attachment
|
||||
|
||||
tosca.nodes.network.Network:
|
||||
derived_from: tosca.nodes.Root
|
||||
description: >
|
||||
The TOSCA Network node represents a simple, logical network service.
|
||||
properties:
|
||||
ip_version:
|
||||
type: integer
|
||||
required: no
|
||||
default: 4
|
||||
constraints:
|
||||
- valid_values: [ 4, 6 ]
|
||||
description: >
|
||||
The IP version of the requested network. Valid values are 4 for ipv4
|
||||
or 6 for ipv6.
|
||||
cidr:
|
||||
type: string
|
||||
required: no
|
||||
description: >
|
||||
The cidr block of the requested network.
|
||||
start_ip:
|
||||
type: string
|
||||
required: no
|
||||
description: >
|
||||
The IP address to be used as the start of a pool of addresses within
|
||||
the full IP range derived from the cidr block.
|
||||
end_ip:
|
||||
type: string
|
||||
required: no
|
||||
description: >
|
||||
The IP address to be used as the end of a pool of addresses within
|
||||
the full IP range derived from the cidr block.
|
||||
gateway_ip:
|
||||
type: string
|
||||
required: no
|
||||
description: >
|
||||
The gateway IP address.
|
||||
network_name:
|
||||
type: string
|
||||
required: no
|
||||
description: >
|
||||
An identifier that represents an existing Network instance in the
|
||||
underlying cloud infrastructure or can be used as the name of the
|
||||
newly created network. If network_name is provided and no other
|
||||
properties are provided (with exception of network_id), then an
|
||||
existing network instance will be used. If network_name is provided
|
||||
alongside with more properties then a new network with this name will
|
||||
be created.
|
||||
network_id:
|
||||
type: string
|
||||
required: no
|
||||
description: >
|
||||
An identifier that represents an existing Network instance in the
|
||||
underlying cloud infrastructure. This property is mutually exclusive
|
||||
with all other properties except network_name. This can be used alone
|
||||
or together with network_name to identify an existing network.
|
||||
segmentation_id:
|
||||
type: string
|
||||
required: no
|
||||
description: >
|
||||
A segmentation identifier in the underlying cloud infrastructure.
|
||||
E.g. VLAN ID, GRE tunnel ID, etc..
|
||||
dhcp_enabled:
|
||||
type: boolean
|
||||
required: no
|
||||
default: true
|
||||
description: >
|
||||
Indicates should DHCP service be enabled on the network or not.
|
||||
capabilities:
|
||||
link:
|
||||
type: tosca.capabilities.network.Linkable
|
||||
|
||||
tosca.nodes.network.Port:
|
||||
derived_from: tosca.nodes.Root
|
||||
description: >
|
||||
The TOSCA Port node represents a logical entity that associates between
|
||||
Compute and Network normative types. The Port node type effectively
|
||||
represents a single virtual NIC on the Compute node instance.
|
||||
properties:
|
||||
ip_address:
|
||||
type: string
|
||||
required: no
|
||||
description: >
|
||||
Allow the user to set a static IP.
|
||||
order:
|
||||
type: integer
|
||||
required: no
|
||||
default: 0
|
||||
constraints:
|
||||
- greater_or_equal: 0
|
||||
description: >
|
||||
The order of the NIC on the compute instance (e.g. eth2).
|
||||
is_default:
|
||||
type: boolean
|
||||
required: no
|
||||
default: false
|
||||
description: >
|
||||
If is_default=true this port will be used for the default gateway
|
||||
route. Only one port that is associated to single compute node can
|
||||
set as is_default=true.
|
||||
ip_range_start:
|
||||
type: string
|
||||
required: no
|
||||
description: >
|
||||
Defines the starting IP of a range to be allocated for the compute
|
||||
instances that are associated with this Port.
|
||||
ip_range_end:
|
||||
type: string
|
||||
required: no
|
||||
description: >
|
||||
Defines the ending IP of a range to be allocated for the compute
|
||||
instances that are associated with this Port.
|
||||
attributes:
|
||||
ip_address:
|
||||
type: string
|
||||
requirements:
|
||||
- binding:
|
||||
description: >
|
||||
Binding requirement expresses the relationship between Port and
|
||||
Compute nodes. Effectevely it indicates that the Port will be
|
||||
attached to specific Compute node instance
|
||||
capability: tosca.capabilities.network.Bindable
|
||||
relationship: tosca.relationships.network.BindsTo
|
||||
- link:
|
||||
description: >
|
||||
Link requirement expresses the relationship between Port and Network
|
||||
nodes. It indicates which network this port will connect to.
|
||||
capability: tosca.capabilities.network.Linkable
|
||||
relationship: tosca.relationships.network.LinksTo
|
||||
|
||||
tosca.nodes.ObjectStorage:
|
||||
derived_from: tosca.nodes.Root
|
||||
description: >
|
||||
The TOSCA ObjectStorage node represents storage that provides the ability
|
||||
to store data as objects (or BLOBs of data) without consideration for the
|
||||
underlying filesystem or devices
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
required: yes
|
||||
description: >
|
||||
The logical name of the object store (or container).
|
||||
size:
|
||||
type: scalar-unit.size
|
||||
required: no
|
||||
constraints:
|
||||
- greater_or_equal: 0 GB
|
||||
description: >
|
||||
The requested initial storage size.
|
||||
maxsize:
|
||||
type: scalar-unit.size
|
||||
required: no
|
||||
constraints:
|
||||
- greater_or_equal: 0 GB
|
||||
description: >
|
||||
The requested maximum storage size.
|
||||
capabilities:
|
||||
storage_endpoint:
|
||||
type: tosca.capabilities.Endpoint
|
||||
|
||||
##########################################################################
|
||||
# Relationship Type.
|
||||
# A Relationship Type is a reusable entity that defines the type of one
|
||||
# or more relationships between Node Types or Node Templates.
|
||||
##########################################################################
|
||||
tosca.relationships.Root:
|
||||
description: >
|
||||
The TOSCA root Relationship Type all other TOSCA base Relationship Types
|
||||
derive from.
|
||||
attributes:
|
||||
tosca_id:
|
||||
type: string
|
||||
tosca_name:
|
||||
type: string
|
||||
interfaces:
|
||||
Configure:
|
||||
type: tosca.interfaces.relationship.Configure
|
||||
|
||||
tosca.relationships.DependsOn:
|
||||
derived_from: tosca.relationships.Root
|
||||
|
||||
tosca.relationships.HostedOn:
|
||||
derived_from: tosca.relationships.Root
|
||||
valid_target_types: [ tosca.capabilities.Container ]
|
||||
|
||||
tosca.relationships.ConnectsTo:
|
||||
derived_from: tosca.relationships.Root
|
||||
valid_target_types: [ tosca.capabilities.Endpoint ]
|
||||
credential:
|
||||
type: tosca.datatypes.Credential
|
||||
required: false
|
||||
|
||||
tosca.relationships.AttachesTo:
|
||||
derived_from: tosca.relationships.Root
|
||||
valid_target_types: [ tosca.capabilities.Attachment ]
|
||||
properties:
|
||||
location:
|
||||
required: true
|
||||
type: string
|
||||
constraints:
|
||||
- min_length: 1
|
||||
device:
|
||||
required: false
|
||||
type: string
|
||||
|
||||
tosca.relationships.network.LinksTo:
|
||||
derived_from: tosca.relationships.DependsOn
|
||||
valid_target_types: [ tosca.capabilities.network.Linkable ]
|
||||
|
||||
tosca.relationships.network.BindsTo:
|
||||
derived_from: tosca.relationships.DependsOn
|
||||
valid_target_types: [ tosca.capabilities.network.Bindable ]
|
||||
|
||||
##########################################################################
|
||||
# Capability Type.
|
||||
# A Capability Type is a reusable entity that describes a kind of
|
||||
# capability that a Node Type can declare to expose.
|
||||
##########################################################################
|
||||
tosca.capabilities.Root:
|
||||
description: >
|
||||
The TOSCA root Capability Type all other TOSCA base Capability Types
|
||||
derive from.
|
||||
|
||||
tosca.capabilities.Node:
|
||||
derived_from: tosca.capabilities.Root
|
||||
|
||||
tosca.capabilities.Container:
|
||||
derived_from: tosca.capabilities.Root
|
||||
properties:
|
||||
num_cpus:
|
||||
required: no
|
||||
type: integer
|
||||
constraints:
|
||||
- greater_or_equal: 1
|
||||
cpu_frequency:
|
||||
required: no
|
||||
type: scalar-unit.frequency
|
||||
constraints:
|
||||
- greater_or_equal: 0.1 GHz
|
||||
disk_size:
|
||||
required: no
|
||||
type: scalar-unit.size
|
||||
constraints:
|
||||
- greater_or_equal: 0 MB
|
||||
mem_size:
|
||||
required: no
|
||||
type: scalar-unit.size
|
||||
constraints:
|
||||
- greater_or_equal: 0 MB
|
||||
|
||||
tosca.capabilities.Endpoint:
|
||||
derived_from: tosca.capabilities.Root
|
||||
properties:
|
||||
protocol:
|
||||
type: string
|
||||
default: tcp
|
||||
port:
|
||||
type: tosca.datatypes.network.PortDef
|
||||
required: false
|
||||
secure:
|
||||
type: boolean
|
||||
default: false
|
||||
url_path:
|
||||
type: string
|
||||
required: false
|
||||
port_name:
|
||||
type: string
|
||||
required: false
|
||||
network_name:
|
||||
type: string
|
||||
required: false
|
||||
initiator:
|
||||
type: string
|
||||
default: source
|
||||
constraints:
|
||||
- valid_values: [source, target, peer]
|
||||
ports:
|
||||
type: map
|
||||
required: false
|
||||
constraints:
|
||||
- min_length: 1
|
||||
entry_schema:
|
||||
type: tosca.datatypes.network.PortDef
|
||||
attributes:
|
||||
public_address:
|
||||
type: string
|
||||
private_address:
|
||||
type: string
|
||||
|
||||
tosca.capabilities.Endpoint.Admin:
|
||||
derived_from: tosca.capabilities.Endpoint
|
||||
properties:
|
||||
secure: true
|
||||
|
||||
tosca.capabilities.Scalable:
|
||||
derived_from: tosca.capabilities.Root
|
||||
properties:
|
||||
min_instances:
|
||||
type: integer
|
||||
required: yes
|
||||
default: 1
|
||||
description: >
|
||||
This property is used to indicate the minimum number of instances
|
||||
that should be created for the associated TOSCA Node Template by
|
||||
a TOSCA orchestrator.
|
||||
max_instances:
|
||||
type: integer
|
||||
required: yes
|
||||
default: 1
|
||||
description: >
|
||||
This property is used to indicate the maximum number of instances
|
||||
that should be created for the associated TOSCA Node Template by
|
||||
a TOSCA orchestrator.
|
||||
default_instances:
|
||||
type: integer
|
||||
required: no
|
||||
description: >
|
||||
An optional property that indicates the requested default number
|
||||
of instances that should be the starting number of instances a
|
||||
TOSCA orchestrator should attempt to allocate.
|
||||
The value for this property MUST be in the range between the values
|
||||
set for min_instances and max_instances properties.
|
||||
|
||||
tosca.capabilities.Endpoint.Database:
|
||||
derived_from: tosca.capabilities.Endpoint
|
||||
|
||||
tosca.capabilities.Attachment:
|
||||
derived_from: tosca.capabilities.Root
|
||||
|
||||
tosca.capabilities.network.Linkable:
|
||||
derived_from: tosca.capabilities.Root
|
||||
description: >
|
||||
A node type that includes the Linkable capability indicates that it can
|
||||
be pointed by tosca.relationships.network.LinksTo relationship type, which
|
||||
represents an association relationship between Port and Network node types.
|
||||
|
||||
tosca.capabilities.network.Bindable:
|
||||
derived_from: tosca.capabilities.Root
|
||||
description: >
|
||||
A node type that includes the Bindable capability indicates that it can
|
||||
be pointed by tosca.relationships.network.BindsTo relationship type, which
|
||||
represents a network association relationship between Port and Compute node
|
||||
types.
|
||||
|
||||
tosca.capabilities.OperatingSystem:
|
||||
derived_from: tosca.capabilities.Root
|
||||
properties:
|
||||
architecture:
|
||||
required: false
|
||||
type: string
|
||||
description: >
|
||||
The host Operating System (OS) architecture.
|
||||
type:
|
||||
required: false
|
||||
type: string
|
||||
description: >
|
||||
The host Operating System (OS) type.
|
||||
distribution:
|
||||
required: false
|
||||
type: string
|
||||
description: >
|
||||
The host Operating System (OS) distribution. Examples of valid values
|
||||
for an “type” of “Linux” would include:
|
||||
debian, fedora, rhel and ubuntu.
|
||||
version:
|
||||
required: false
|
||||
type: version
|
||||
description: >
|
||||
The host Operating System version.
|
||||
|
||||
##########################################################################
|
||||
# Interfaces Type.
|
||||
# The Interfaces element describes a list of one or more interface
|
||||
# definitions for a modelable entity (e.g., a Node or Relationship Type)
|
||||
# as defined within the TOSCA Simple Profile specification.
|
||||
##########################################################################
|
||||
tosca.interfaces.node.lifecycle.Standard:
|
||||
create:
|
||||
description: Standard lifecycle create operation.
|
||||
configure:
|
||||
description: Standard lifecycle configure operation.
|
||||
start:
|
||||
description: Standard lifecycle start operation.
|
||||
stop:
|
||||
description: Standard lifecycle stop operation.
|
||||
delete:
|
||||
description: Standard lifecycle delete operation.
|
||||
|
||||
tosca.interfaces.relationship.Configure:
|
||||
pre_configure_source:
|
||||
description: Operation to pre-configure the source endpoint.
|
||||
pre_configure_target:
|
||||
description: Operation to pre-configure the target endpoint.
|
||||
post_configure_source:
|
||||
description: Operation to post-configure the source endpoint.
|
||||
post_configure_target:
|
||||
description: Operation to post-configure the target endpoint.
|
||||
add_target:
|
||||
description: Operation to add a target node.
|
||||
remove_target:
|
||||
description: Operation to remove a target node.
|
||||
add_source: >
|
||||
description: Operation to notify the target node of a source node which
|
||||
is now available via a relationship.
|
||||
description:
|
||||
target_changed: >
|
||||
description: Operation to notify source some property or attribute of the
|
||||
target changed
|
||||
|
||||
##########################################################################
|
||||
# Data Type.
|
||||
# A Datatype is a complex data type declaration which contains other
|
||||
# complex or simple data types.
|
||||
##########################################################################
|
||||
tosca.datatypes.network.NetworkInfo:
|
||||
properties:
|
||||
network_name:
|
||||
type: string
|
||||
network_id:
|
||||
type: string
|
||||
addresses:
|
||||
type: list
|
||||
entry_schema:
|
||||
type: string
|
||||
|
||||
tosca.datatypes.network.PortInfo:
|
||||
properties:
|
||||
port_name:
|
||||
type: string
|
||||
port_id:
|
||||
type: string
|
||||
network_id:
|
||||
type: string
|
||||
mac_address:
|
||||
type: string
|
||||
addresses:
|
||||
type: list
|
||||
entry_schema:
|
||||
type: string
|
||||
|
||||
tosca.datatypes.network.PortDef:
|
||||
type: integer
|
||||
constraints:
|
||||
- in_range: [ 1, 65535 ]
|
||||
|
||||
tosca.datatypes.network.PortSpec:
|
||||
properties:
|
||||
protocol:
|
||||
type: string
|
||||
required: true
|
||||
default: tcp
|
||||
constraints:
|
||||
- valid_values: [ udp, tcp, igmp ]
|
||||
target:
|
||||
type: list
|
||||
entry_schema:
|
||||
type: PortDef
|
||||
target_range:
|
||||
type: range
|
||||
constraints:
|
||||
- in_range: [ 1, 65535 ]
|
||||
source:
|
||||
type: list
|
||||
entry_schema:
|
||||
type: PortDef
|
||||
source_range:
|
||||
type: range
|
||||
constraints:
|
||||
- in_range: [ 1, 65535 ]
|
||||
|
||||
tosca.datatypes.Credential:
|
||||
properties:
|
||||
protocol:
|
||||
type: string
|
||||
token_type:
|
||||
type: string
|
||||
token:
|
||||
type: string
|
||||
keys:
|
||||
type: map
|
||||
entry_schema:
|
||||
type: string
|
||||
user:
|
||||
type: string
|
||||
required: false
|
||||
|
||||
##########################################################################
|
||||
# Artifact Type.
|
||||
# An Artifact Type is a reusable entity that defines the type of one or more
|
||||
# files which Node Types or Node Templates can have dependent relationships
|
||||
# and used during operations such as during installation or deployment.
|
||||
##########################################################################
|
||||
tosca.artifacts.Root:
|
||||
description: >
|
||||
The TOSCA Artifact Type all other TOSCA Artifact Types derive from
|
||||
properties:
|
||||
version: version
|
||||
|
||||
tosca.artifacts.File:
|
||||
derived_from: tosca.artifacts.Root
|
||||
|
||||
tosca.artifacts.Deployment:
|
||||
derived_from: tosca.artifacts.Root
|
||||
description: TOSCA base type for deployment artifacts
|
||||
|
||||
tosca.artifacts.Deployment.Image:
|
||||
derived_from: tosca.artifacts.Deployment
|
||||
|
||||
tosca.artifacts.Deployment.Image.VM:
|
||||
derived_from: tosca.artifacts.Deployment.Image
|
||||
|
||||
tosca.artifacts.Implementation:
|
||||
derived_from: tosca.artifacts.Root
|
||||
description: TOSCA base type for implementation artifacts
|
||||
|
||||
tosca.artifacts.Implementation.Bash:
|
||||
derived_from: tosca.artifacts.Implementation
|
||||
description: Script artifact for the Unix Bash shell
|
||||
mime_type: application/x-sh
|
||||
file_ext: [ sh ]
|
||||
|
||||
tosca.artifacts.Implementation.Python:
|
||||
derived_from: tosca.artifacts.Implementation
|
||||
description: Artifact for the interpreted Python language
|
||||
mime_type: application/x-python
|
||||
file_ext: [ py ]
|
||||
|
||||
tosca.artifacts.Deployment.Image.Container.Docker:
|
||||
derived_from: tosca.artifacts.Deployment.Image
|
||||
description: Docker container image
|
||||
|
||||
tosca.artifacts.Deployment.Image.VM.ISO:
|
||||
derived_from: tosca.artifacts.Deployment.Image
|
||||
description: Virtual Machine (VM) image in ISO disk format
|
||||
mime_type: application/octet-stream
|
||||
file_ext: [ iso ]
|
||||
|
||||
tosca.artifacts.Deployment.Image.VM.QCOW2:
|
||||
derived_from: tosca.artifacts.Deployment.Image
|
||||
description: Virtual Machine (VM) image in QCOW v2 standard disk format
|
||||
mime_type: application/octet-stream
|
||||
file_ext: [ qcow2 ]
|
@ -1,45 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from translator.toscalib.elements.statefulentitytype import StatefulEntityType
|
||||
|
||||
|
||||
class ArtifactTypeDef(StatefulEntityType):
|
||||
'''TOSCA built-in artifacts type.'''
|
||||
|
||||
def __init__(self, atype, custom_def=None):
|
||||
super(ArtifactTypeDef, self).__init__(atype, self.ARTIFACT_PREFIX,
|
||||
custom_def)
|
||||
self.type = atype
|
||||
self.properties = None
|
||||
if self.PROPERTIES in self.defs:
|
||||
self.properties = self.defs[self.PROPERTIES]
|
||||
self.parent_artifacts = self._get_parent_artifacts()
|
||||
|
||||
def _get_parent_artifacts(self):
|
||||
artifacts = {}
|
||||
parent_artif = self.parent_type
|
||||
if parent_artif:
|
||||
while parent_artif != 'tosca.artifacts.Root':
|
||||
artifacts[parent_artif] = self.TOSCA_DEF[parent_artif]
|
||||
parent_artif = artifacts[parent_artif]['derived_from']
|
||||
return artifacts
|
||||
|
||||
@property
|
||||
def parent_type(self):
|
||||
'''Return an artifact this artifact is derived from.'''
|
||||
return self.derived_from(self.defs)
|
||||
|
||||
def get_artifact(self, name):
|
||||
'''Return the definition of an artifact field by name.'''
|
||||
if name in self.defs:
|
||||
return self.defs[name]
|
@ -1,20 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
class AttributeDef(object):
|
||||
'''TOSCA built-in Attribute type.'''
|
||||
|
||||
def __init__(self, name, value=None, schema=None):
|
||||
self.name = name
|
||||
self.value = value
|
||||
self.schema = schema
|
@ -1,69 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from translator.toscalib.elements.property_definition import PropertyDef
|
||||
from translator.toscalib.elements.statefulentitytype import StatefulEntityType
|
||||
|
||||
|
||||
class CapabilityTypeDef(StatefulEntityType):
|
||||
'''TOSCA built-in capabilities type.'''
|
||||
|
||||
def __init__(self, name, ctype, ntype, custom_def=None):
|
||||
self.name = name
|
||||
super(CapabilityTypeDef, self).__init__(ctype, self.CAPABILITY_PREFIX,
|
||||
custom_def)
|
||||
self.nodetype = ntype
|
||||
self.properties = None
|
||||
if self.PROPERTIES in self.defs:
|
||||
self.properties = self.defs[self.PROPERTIES]
|
||||
self.parent_capabilities = self._get_parent_capabilities()
|
||||
|
||||
def get_properties_def_objects(self):
|
||||
'''Return a list of property definition objects.'''
|
||||
properties = []
|
||||
parent_properties = {}
|
||||
if self.parent_capabilities:
|
||||
for type, value in self.parent_capabilities.items():
|
||||
parent_properties[type] = value.get('properties')
|
||||
if self.properties:
|
||||
for prop, schema in self.properties.items():
|
||||
properties.append(PropertyDef(prop, None, schema))
|
||||
if parent_properties:
|
||||
for parent, props in parent_properties.items():
|
||||
for prop, schema in props.items():
|
||||
properties.append(PropertyDef(prop, None, schema))
|
||||
return properties
|
||||
|
||||
def get_properties_def(self):
|
||||
'''Return a dictionary of property definition name-object pairs.'''
|
||||
return {prop.name: prop
|
||||
for prop in self.get_properties_def_objects()}
|
||||
|
||||
def get_property_def_value(self, name):
|
||||
'''Return the definition of a given property name.'''
|
||||
props_def = self.get_properties_def()
|
||||
if props_def and name in props_def:
|
||||
return props_def[name].value
|
||||
|
||||
def _get_parent_capabilities(self):
|
||||
capabilities = {}
|
||||
parent_cap = self.parent_type
|
||||
if parent_cap:
|
||||
while parent_cap != 'tosca.capabilities.Root':
|
||||
capabilities[parent_cap] = self.TOSCA_DEF[parent_cap]
|
||||
parent_cap = capabilities[parent_cap]['derived_from']
|
||||
return capabilities
|
||||
|
||||
@property
|
||||
def parent_type(self):
|
||||
'''Return a capability this capability is derived from.'''
|
||||
return self.derived_from(self.defs)
|
@ -1,569 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import collections
|
||||
import datetime
|
||||
import re
|
||||
|
||||
from translator.toscalib.common.exception import InvalidSchemaError
|
||||
from translator.toscalib.common.exception import ValidationError
|
||||
from translator.toscalib.elements import scalarunit
|
||||
from translator.toscalib.functions import is_function
|
||||
from translator.toscalib.utils.gettextutils import _
|
||||
|
||||
|
||||
class Schema(collections.Mapping):
|
||||
|
||||
KEYS = (
|
||||
TYPE, REQUIRED, DESCRIPTION,
|
||||
DEFAULT, CONSTRAINTS, ENTRYSCHEMA
|
||||
) = (
|
||||
'type', 'required', 'description',
|
||||
'default', 'constraints', 'entry_schema'
|
||||
)
|
||||
|
||||
PROPERTY_TYPES = (
|
||||
INTEGER, STRING, BOOLEAN, FLOAT,
|
||||
NUMBER, TIMESTAMP, LIST, MAP,
|
||||
SCALAR_UNIT_SIZE, SCALAR_UNIT_FREQUENCY, SCALAR_UNIT_TIME,
|
||||
PORTDEF, VERSION
|
||||
) = (
|
||||
'integer', 'string', 'boolean', 'float',
|
||||
'number', 'timestamp', 'list', 'map',
|
||||
'scalar-unit.size', 'scalar-unit.frequency', 'scalar-unit.time',
|
||||
'PortDef', 'version'
|
||||
)
|
||||
|
||||
SCALAR_UNIT_SIZE_DEFAULT = 'B'
|
||||
SCALAR_UNIT_SIZE_DICT = {'B': 1, 'KB': 1000, 'KIB': 1024, 'MB': 1000000,
|
||||
'MIB': 1048576, 'GB': 1000000000,
|
||||
'GIB': 1073741824, 'TB': 1000000000000,
|
||||
'TIB': 1099511627776}
|
||||
|
||||
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)
|
||||
raise InvalidSchemaError(message=msg)
|
||||
|
||||
try:
|
||||
schema_dict['type']
|
||||
except KeyError:
|
||||
msg = _("Schema %(pname)s must have type.") % dict(pname=name)
|
||||
raise InvalidSchemaError(message=msg)
|
||||
|
||||
self.schema = schema_dict
|
||||
self._len = None
|
||||
self.constraints_list = []
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
return self.schema[self.TYPE]
|
||||
|
||||
@property
|
||||
def required(self):
|
||||
return self.schema.get(self.REQUIRED, True)
|
||||
|
||||
@property
|
||||
def description(self):
|
||||
return self.schema.get(self.DESCRIPTION, '')
|
||||
|
||||
@property
|
||||
def default(self):
|
||||
return self.schema.get(self.DEFAULT)
|
||||
|
||||
@property
|
||||
def constraints(self):
|
||||
if not self.constraints_list:
|
||||
constraint_schemata = self.schema.get(self.CONSTRAINTS)
|
||||
if constraint_schemata:
|
||||
self.constraints_list = [Constraint(self.name,
|
||||
self.type,
|
||||
cschema)
|
||||
for cschema in constraint_schemata]
|
||||
return self.constraints_list
|
||||
|
||||
@property
|
||||
def entry_schema(self):
|
||||
return self.schema.get(self.ENTRYSCHEMA)
|
||||
|
||||
def __getitem__(self, key):
|
||||
return self.schema[key]
|
||||
|
||||
def __iter__(self):
|
||||
for k in self.KEYS:
|
||||
try:
|
||||
self.schema[k]
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
yield k
|
||||
|
||||
def __len__(self):
|
||||
if self._len is None:
|
||||
self._len = len(list(iter(self)))
|
||||
return self._len
|
||||
|
||||
|
||||
class Constraint(object):
|
||||
'''Parent class for constraints for a Property or Input.'''
|
||||
|
||||
CONSTRAINTS = (EQUAL, GREATER_THAN,
|
||||
GREATER_OR_EQUAL, LESS_THAN, LESS_OR_EQUAL, IN_RANGE,
|
||||
VALID_VALUES, LENGTH, MIN_LENGTH, MAX_LENGTH, PATTERN) = \
|
||||
('equal', 'greater_than', 'greater_or_equal', 'less_than',
|
||||
'less_or_equal', 'in_range', 'valid_values', 'length',
|
||||
'min_length', 'max_length', 'pattern')
|
||||
|
||||
def __new__(cls, property_name, property_type, constraint):
|
||||
if cls is not Constraint:
|
||||
return super(Constraint, cls).__new__(cls)
|
||||
|
||||
if(not isinstance(constraint, collections.Mapping) or
|
||||
len(constraint) != 1):
|
||||
raise InvalidSchemaError(message=_('Invalid constraint schema.'))
|
||||
|
||||
for type in constraint.keys():
|
||||
ConstraintClass = get_constraint_class(type)
|
||||
if not ConstraintClass:
|
||||
msg = _('Invalid constraint type "%s".') % type
|
||||
raise InvalidSchemaError(message=msg)
|
||||
|
||||
return ConstraintClass(property_name, property_type, constraint)
|
||||
|
||||
def __init__(self, property_name, property_type, constraint):
|
||||
self.property_name = property_name
|
||||
self.property_type = property_type
|
||||
self.constraint_value = constraint[self.constraint_key]
|
||||
self.constraint_value_msg = self.constraint_value
|
||||
if self.property_type in scalarunit.ScalarUnit.SCALAR_UNIT_TYPES:
|
||||
self.constraint_value = self._get_scalarunit_constraint_value()
|
||||
# check if constraint is valid for property type
|
||||
if property_type not in self.valid_prop_types:
|
||||
msg = _('Constraint type "%(ctype)s" is not valid '
|
||||
'for data type "%(dtype)s".') % dict(
|
||||
ctype=self.constraint_key,
|
||||
dtype=property_type)
|
||||
raise InvalidSchemaError(message=msg)
|
||||
|
||||
def _get_scalarunit_constraint_value(self):
|
||||
if self.property_type in scalarunit.ScalarUnit.SCALAR_UNIT_TYPES:
|
||||
ScalarUnit_Class = (scalarunit.
|
||||
get_scalarunit_class(self.property_type))
|
||||
if isinstance(self.constraint_value, list):
|
||||
return [ScalarUnit_Class(v).get_num_from_scalar_unit()
|
||||
for v in self.constraint_value]
|
||||
else:
|
||||
return (ScalarUnit_Class(self.constraint_value).
|
||||
get_num_from_scalar_unit())
|
||||
|
||||
def _err_msg(self, value):
|
||||
return _('Property %s could not be validated.') % self.property_name
|
||||
|
||||
def validate(self, value):
|
||||
self.value_msg = value
|
||||
if self.property_type in scalarunit.ScalarUnit.SCALAR_UNIT_TYPES:
|
||||
value = scalarunit.get_scalarunit_value(self.property_type, value)
|
||||
if not self._is_valid(value):
|
||||
err_msg = self._err_msg(value)
|
||||
raise ValidationError(message=err_msg)
|
||||
|
||||
|
||||
class Equal(Constraint):
|
||||
"""Constraint class for "equal"
|
||||
|
||||
Constrains a property or parameter to a value equal to ('=')
|
||||
the value declared.
|
||||
"""
|
||||
|
||||
constraint_key = Constraint.EQUAL
|
||||
|
||||
valid_prop_types = Schema.PROPERTY_TYPES
|
||||
|
||||
def _is_valid(self, value):
|
||||
if value == self.constraint_value:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def _err_msg(self, value):
|
||||
return (_('%(pname)s: %(pvalue)s is not equal to "%(cvalue)s".') %
|
||||
dict(pname=self.property_name,
|
||||
pvalue=self.value_msg,
|
||||
cvalue=self.constraint_value_msg))
|
||||
|
||||
|
||||
class GreaterThan(Constraint):
|
||||
"""Constraint class for "greater_than"
|
||||
|
||||
Constrains a property or parameter to a value greater than ('>')
|
||||
the value declared.
|
||||
"""
|
||||
|
||||
constraint_key = Constraint.GREATER_THAN
|
||||
|
||||
valid_types = (int, float, datetime.date,
|
||||
datetime.time, datetime.datetime)
|
||||
|
||||
valid_prop_types = (Schema.INTEGER, Schema.FLOAT, Schema.TIMESTAMP,
|
||||
Schema.SCALAR_UNIT_SIZE, Schema.SCALAR_UNIT_FREQUENCY,
|
||||
Schema.SCALAR_UNIT_TIME)
|
||||
|
||||
def __init__(self, property_name, property_type, constraint):
|
||||
super(GreaterThan, self).__init__(property_name, property_type,
|
||||
constraint)
|
||||
if not isinstance(constraint[self.GREATER_THAN], self.valid_types):
|
||||
raise InvalidSchemaError(message=_('greater_than must '
|
||||
'be comparable.'))
|
||||
|
||||
def _is_valid(self, value):
|
||||
if value > self.constraint_value:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def _err_msg(self, value):
|
||||
return (_('%(pname)s: %(pvalue)s must be greater than "%(cvalue)s".') %
|
||||
dict(pname=self.property_name,
|
||||
pvalue=self.value_msg,
|
||||
cvalue=self.constraint_value_msg))
|
||||
|
||||
|
||||
class GreaterOrEqual(Constraint):
|
||||
"""Constraint class for "greater_or_equal"
|
||||
|
||||
Constrains a property or parameter to a value greater than or equal
|
||||
to ('>=') the value declared.
|
||||
"""
|
||||
|
||||
constraint_key = Constraint.GREATER_OR_EQUAL
|
||||
|
||||
valid_types = (int, float, datetime.date,
|
||||
datetime.time, datetime.datetime)
|
||||
|
||||
valid_prop_types = (Schema.INTEGER, Schema.FLOAT, Schema.TIMESTAMP,
|
||||
Schema.SCALAR_UNIT_SIZE, Schema.SCALAR_UNIT_FREQUENCY,
|
||||
Schema.SCALAR_UNIT_TIME)
|
||||
|
||||
def __init__(self, property_name, property_type, constraint):
|
||||
super(GreaterOrEqual, self).__init__(property_name, property_type,
|
||||
constraint)
|
||||
if not isinstance(self.constraint_value, self.valid_types):
|
||||
raise InvalidSchemaError(message=_('greater_or_equal must '
|
||||
'be comparable.'))
|
||||
|
||||
def _is_valid(self, value):
|
||||
if is_function(value) or value >= self.constraint_value:
|
||||
return True
|
||||
return False
|
||||
|
||||
def _err_msg(self, value):
|
||||
return (_('%(pname)s: %(pvalue)s must be greater or equal '
|
||||
'to "%(cvalue)s".') %
|
||||
dict(pname=self.property_name,
|
||||
pvalue=self.value_msg,
|
||||
cvalue=self.constraint_value_msg))
|
||||
|
||||
|
||||
class LessThan(Constraint):
|
||||
"""Constraint class for "less_than"
|
||||
|
||||
Constrains a property or parameter to a value less than ('<')
|
||||
the value declared.
|
||||
"""
|
||||
|
||||
constraint_key = Constraint.LESS_THAN
|
||||
|
||||
valid_types = (int, float, datetime.date,
|
||||
datetime.time, datetime.datetime)
|
||||
|
||||
valid_prop_types = (Schema.INTEGER, Schema.FLOAT, Schema.TIMESTAMP,
|
||||
Schema.SCALAR_UNIT_SIZE, Schema.SCALAR_UNIT_FREQUENCY,
|
||||
Schema.SCALAR_UNIT_TIME)
|
||||
|
||||
def __init__(self, property_name, property_type, constraint):
|
||||
super(LessThan, self).__init__(property_name, property_type,
|
||||
constraint)
|
||||
if not isinstance(self.constraint_value, self.valid_types):
|
||||
raise InvalidSchemaError(message=_('less_than must '
|
||||
'be comparable.'))
|
||||
|
||||
def _is_valid(self, value):
|
||||
if value < self.constraint_value:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def _err_msg(self, value):
|
||||
return (_('%(pname)s: %(pvalue)s must be less than "%(cvalue)s".') %
|
||||
dict(pname=self.property_name,
|
||||
pvalue=self.value_msg,
|
||||
cvalue=self.constraint_value_msg))
|
||||
|
||||
|
||||
class LessOrEqual(Constraint):
|
||||
"""Constraint class for "less_or_equal"
|
||||
|
||||
Constrains a property or parameter to a value less than or equal
|
||||
to ('<=') the value declared.
|
||||
"""
|
||||
|
||||
constraint_key = Constraint.LESS_OR_EQUAL
|
||||
|
||||
valid_types = (int, float, datetime.date,
|
||||
datetime.time, datetime.datetime)
|
||||
|
||||
valid_prop_types = (Schema.INTEGER, Schema.FLOAT, Schema.TIMESTAMP,
|
||||
Schema.SCALAR_UNIT_SIZE, Schema.SCALAR_UNIT_FREQUENCY,
|
||||
Schema.SCALAR_UNIT_TIME)
|
||||
|
||||
def __init__(self, property_name, property_type, constraint):
|
||||
super(LessOrEqual, self).__init__(property_name, property_type,
|
||||
constraint)
|
||||
if not isinstance(self.constraint_value, self.valid_types):
|
||||
raise InvalidSchemaError(message=_('less_or_equal must '
|
||||
'be comparable.'))
|
||||
|
||||
def _is_valid(self, value):
|
||||
if value <= self.constraint_value:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def _err_msg(self, value):
|
||||
return (_('%(pname)s: %(pvalue)s must be less or '
|
||||
'equal to "%(cvalue)s".') %
|
||||
dict(pname=self.property_name,
|
||||
pvalue=self.value_msg,
|
||||
cvalue=self.constraint_value_msg))
|
||||
|
||||
|
||||
class InRange(Constraint):
|
||||
"""Constraint class for "in_range"
|
||||
|
||||
Constrains a property or parameter to a value in range of (inclusive)
|
||||
the two values declared.
|
||||
"""
|
||||
|
||||
constraint_key = Constraint.IN_RANGE
|
||||
|
||||
valid_types = (int, float, datetime.date,
|
||||
datetime.time, datetime.datetime)
|
||||
|
||||
valid_prop_types = (Schema.INTEGER, Schema.FLOAT, Schema.TIMESTAMP,
|
||||
Schema.SCALAR_UNIT_SIZE, Schema.SCALAR_UNIT_FREQUENCY,
|
||||
Schema.SCALAR_UNIT_TIME)
|
||||
|
||||
def __init__(self, property_name, property_type, constraint):
|
||||
super(InRange, self).__init__(property_name, property_type, constraint)
|
||||
if(not isinstance(self.constraint_value, collections.Sequence) or
|
||||
(len(constraint[self.IN_RANGE]) != 2)):
|
||||
raise InvalidSchemaError(message=_('in_range must be a list.'))
|
||||
|
||||
for value in self.constraint_value:
|
||||
if not isinstance(value, self.valid_types):
|
||||
raise InvalidSchemaError(_('in_range value must '
|
||||
'be comparable.'))
|
||||
|
||||
self.min = self.constraint_value[0]
|
||||
self.max = self.constraint_value[1]
|
||||
|
||||
def _is_valid(self, value):
|
||||
if value < self.min:
|
||||
return False
|
||||
if value > self.max:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def _err_msg(self, value):
|
||||
return (_('%(pname)s: %(pvalue)s is out of range '
|
||||
'(min:%(vmin)s, max:%(vmax)s).') %
|
||||
dict(pname=self.property_name,
|
||||
pvalue=self.value_msg,
|
||||
vmin=self.constraint_value_msg[0],
|
||||
vmax=self.constraint_value_msg[1]))
|
||||
|
||||
|
||||
class ValidValues(Constraint):
|
||||
"""Constraint class for "valid_values"
|
||||
|
||||
Constrains a property or parameter to a value that is in the list of
|
||||
declared values.
|
||||
"""
|
||||
constraint_key = Constraint.VALID_VALUES
|
||||
|
||||
valid_prop_types = Schema.PROPERTY_TYPES
|
||||
|
||||
def __init__(self, property_name, property_type, constraint):
|
||||
super(ValidValues, self).__init__(property_name, property_type,
|
||||
constraint)
|
||||
if not isinstance(self.constraint_value, collections.Sequence):
|
||||
raise InvalidSchemaError(message=_('valid_values must be a list.'))
|
||||
|
||||
def _is_valid(self, value):
|
||||
if isinstance(value, list):
|
||||
return all(v in self.constraint_value for v in value)
|
||||
return value in self.constraint_value
|
||||
|
||||
def _err_msg(self, value):
|
||||
allowed = '[%s]' % ', '.join(str(a) for a in self.constraint_value)
|
||||
return (_('%(pname)s: %(pvalue)s is not an valid '
|
||||
'value "%(cvalue)s".') %
|
||||
dict(pname=self.property_name,
|
||||
pvalue=value,
|
||||
cvalue=allowed))
|
||||
|
||||
|
||||
class Length(Constraint):
|
||||
"""Constraint class for "length"
|
||||
|
||||
Constrains the property or parameter to a value of a given length.
|
||||
"""
|
||||
|
||||
constraint_key = Constraint.LENGTH
|
||||
|
||||
valid_types = (int, )
|
||||
|
||||
valid_prop_types = (Schema.STRING, )
|
||||
|
||||
def __init__(self, property_name, property_type, constraint):
|
||||
super(Length, self).__init__(property_name, property_type, constraint)
|
||||
if not isinstance(self.constraint_value, self.valid_types):
|
||||
raise InvalidSchemaError(message=_('length must be integer.'))
|
||||
|
||||
def _is_valid(self, value):
|
||||
if isinstance(value, str) and len(value) == self.constraint_value:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def _err_msg(self, value):
|
||||
return (_('length of %(pname)s: %(pvalue)s must be equal '
|
||||
'to "%(cvalue)s".') %
|
||||
dict(pname=self.property_name,
|
||||
pvalue=value,
|
||||
cvalue=self.constraint_value))
|
||||
|
||||
|
||||
class MinLength(Constraint):
|
||||
"""Constraint class for "min_length"
|
||||
|
||||
Constrains the property or parameter to a value to a minimum length.
|
||||
"""
|
||||
|
||||
constraint_key = Constraint.MIN_LENGTH
|
||||
|
||||
valid_types = (int, )
|
||||
|
||||
valid_prop_types = (Schema.STRING, )
|
||||
|
||||
def __init__(self, property_name, property_type, constraint):
|
||||
super(MinLength, self).__init__(property_name, property_type,
|
||||
constraint)
|
||||
if not isinstance(self.constraint_value, self.valid_types):
|
||||
raise InvalidSchemaError(message=_('min_length must be integer.'))
|
||||
|
||||
def _is_valid(self, value):
|
||||
if isinstance(value, str) and len(value) >= self.constraint_value:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def _err_msg(self, value):
|
||||
return (_('length of %(pname)s: %(pvalue)s must be '
|
||||
'at least "%(cvalue)s".') %
|
||||
dict(pname=self.property_name,
|
||||
pvalue=value,
|
||||
cvalue=self.constraint_value))
|
||||
|
||||
|
||||
class MaxLength(Constraint):
|
||||
"""Constraint class for "max_length"
|
||||
|
||||
Constrains the property or parameter to a value to a maximum length.
|
||||
"""
|
||||
|
||||
constraint_key = Constraint.MAX_LENGTH
|
||||
|
||||
valid_types = (int, )
|
||||
|
||||
valid_prop_types = (Schema.STRING, )
|
||||
|
||||
def __init__(self, property_name, property_type, constraint):
|
||||
super(MaxLength, self).__init__(property_name, property_type,
|
||||
constraint)
|
||||
if not isinstance(self.constraint_value, self.valid_types):
|
||||
raise InvalidSchemaError(message=_('max_length must be integer.'))
|
||||
|
||||
def _is_valid(self, value):
|
||||
if isinstance(value, str) and len(value) <= self.constraint_value:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def _err_msg(self, value):
|
||||
return (_('length of %(pname)s: %(pvalue)s must be no greater '
|
||||
'than "%(cvalue)s".') %
|
||||
dict(pname=self.property_name,
|
||||
pvalue=value,
|
||||
cvalue=self.constraint_value))
|
||||
|
||||
|
||||
class Pattern(Constraint):
|
||||
"""Constraint class for "pattern"
|
||||
|
||||
Constrains the property or parameter to a value that is allowed by
|
||||
the provided regular expression.
|
||||
"""
|
||||
|
||||
constraint_key = Constraint.PATTERN
|
||||
|
||||
valid_types = (str, )
|
||||
|
||||
valid_prop_types = (Schema.STRING, )
|
||||
|
||||
def __init__(self, property_name, property_type, constraint):
|
||||
super(Pattern, self).__init__(property_name, property_type, constraint)
|
||||
if not isinstance(self.constraint_value, self.valid_types):
|
||||
raise InvalidSchemaError(message=_('pattern must be string.'))
|
||||
self.match = re.compile(self.constraint_value).match
|
||||
|
||||
def _is_valid(self, value):
|
||||
match = self.match(value)
|
||||
return match is not None and match.end() == len(value)
|
||||
|
||||
def _err_msg(self, value):
|
||||
return (_('%(pname)s: "%(pvalue)s" does not match '
|
||||
'pattern "%(cvalue)s".') %
|
||||
dict(pname=self.property_name,
|
||||
pvalue=value,
|
||||
cvalue=self.constraint_value))
|
||||
|
||||
|
||||
constraint_mapping = {
|
||||
Constraint.EQUAL: Equal,
|
||||
Constraint.GREATER_THAN: GreaterThan,
|
||||
Constraint.GREATER_OR_EQUAL: GreaterOrEqual,
|
||||
Constraint.LESS_THAN: LessThan,
|
||||
Constraint.LESS_OR_EQUAL: LessOrEqual,
|
||||
Constraint.IN_RANGE: InRange,
|
||||
Constraint.VALID_VALUES: ValidValues,
|
||||
Constraint.LENGTH: Length,
|
||||
Constraint.MIN_LENGTH: MinLength,
|
||||
Constraint.MAX_LENGTH: MaxLength,
|
||||
Constraint.PATTERN: Pattern
|
||||
}
|
||||
|
||||
|
||||
def get_constraint_class(type):
|
||||
return constraint_mapping.get(type)
|
@ -1,56 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
from translator.toscalib.elements.statefulentitytype import StatefulEntityType
|
||||
|
||||
|
||||
class DataType(StatefulEntityType):
|
||||
'''TOSCA built-in and user defined complex data type.'''
|
||||
|
||||
def __init__(self, datatypename, custom_def=None):
|
||||
super(DataType, self).__init__(datatypename, self.DATATYPE_PREFIX,
|
||||
custom_def)
|
||||
self.custom_def = custom_def
|
||||
|
||||
@property
|
||||
def parent_type(self):
|
||||
'''Return a datatype this datatype is derived from.'''
|
||||
ptype = self.derived_from(self.defs)
|
||||
if ptype:
|
||||
return DataType(ptype, self.custom_def)
|
||||
return None
|
||||
|
||||
@property
|
||||
def value_type(self):
|
||||
'''Return 'type' section in the datatype schema.'''
|
||||
return self.entity_value(self.defs, 'type')
|
||||
|
||||
def get_all_properties_objects(self):
|
||||
'''Return all properties objects defined in type and parent type.'''
|
||||
props_def = self.get_properties_def_objects()
|
||||
ptype = self.parent_type
|
||||
while ptype:
|
||||
props_def.extend(ptype.get_properties_def_objects())
|
||||
ptype = ptype.parent_type
|
||||
return props_def
|
||||
|
||||
def get_all_properties(self):
|
||||
'''Return a dictionary of all property definition name-object pairs.'''
|
||||
return {prop.name: prop
|
||||
for prop in self.get_all_properties_objects()}
|
||||
|
||||
def get_all_property_value(self, name):
|
||||
'''Return the value of a given property name.'''
|
||||
props_def = self.get_all_properties()
|
||||
if props_def and name in props_def.key():
|
||||
return props_def[name].value
|
@ -1,95 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import logging
|
||||
import os
|
||||
import translator.toscalib.utils.yamlparser
|
||||
|
||||
log = logging.getLogger('tosca')
|
||||
|
||||
|
||||
class EntityType(object):
|
||||
'''Base class for TOSCA elements.'''
|
||||
|
||||
SECTIONS = (DERIVED_FROM, PROPERTIES, ATTRIBUTES, REQUIREMENTS,
|
||||
INTERFACES, CAPABILITIES, TYPE, ARTIFACTS) = \
|
||||
('derived_from', 'properties', 'attributes', 'requirements',
|
||||
'interfaces', 'capabilities', 'type', 'artifacts')
|
||||
|
||||
'''TOSCA definition file.'''
|
||||
TOSCA_DEF_FILE = os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"TOSCA_definition_1_0.yaml")
|
||||
|
||||
loader = translator.toscalib.utils.yamlparser.load_yaml
|
||||
|
||||
TOSCA_DEF = loader(TOSCA_DEF_FILE)
|
||||
|
||||
RELATIONSHIP_TYPE = (DEPENDSON, HOSTEDON, CONNECTSTO, ATTACHESTO,
|
||||
LINKSTO, BINDSTO) = \
|
||||
('tosca.relationships.DependsOn',
|
||||
'tosca.relationships.HostedOn',
|
||||
'tosca.relationships.ConnectsTo',
|
||||
'tosca.relationships.AttachesTo',
|
||||
'tosca.relationships.network.LinksTo',
|
||||
'tosca.relationships.network.BindsTo')
|
||||
|
||||
NODE_PREFIX = 'tosca.nodes.'
|
||||
RELATIONSHIP_PREFIX = 'tosca.relationships.'
|
||||
CAPABILITY_PREFIX = 'tosca.capabilities.'
|
||||
INTERFACE_PREFIX = 'tosca.interfaces.'
|
||||
ARTIFACT_PREFIX = 'tosca.artifacts.'
|
||||
# currently the data types are defined only for network
|
||||
# but may have changes in the future.
|
||||
DATATYPE_PREFIX = 'tosca.datatypes.network.'
|
||||
TOSCA = 'tosca'
|
||||
|
||||
def derived_from(self, defs):
|
||||
'''Return a type this type is derived from.'''
|
||||
return self.entity_value(defs, 'derived_from')
|
||||
|
||||
def is_derived_from(self, type_str):
|
||||
'''Check if object inherits from the given type.
|
||||
|
||||
Returns true if this object is derived from 'type_str'.
|
||||
False otherwise.
|
||||
'''
|
||||
if not self.type:
|
||||
return False
|
||||
elif self.type == type_str:
|
||||
return True
|
||||
elif self.parent_type:
|
||||
return self.parent_type.is_derived_from(type_str)
|
||||
else:
|
||||
return False
|
||||
|
||||
def entity_value(self, defs, key):
|
||||
if key in defs:
|
||||
return defs[key]
|
||||
|
||||
def get_value(self, ndtype, defs=None, parent=None):
|
||||
value = None
|
||||
if defs is None:
|
||||
defs = self.defs
|
||||
if ndtype in defs:
|
||||
value = defs[ndtype]
|
||||
if parent and not value:
|
||||
p = self.parent_type
|
||||
while value is None:
|
||||
# check parent node
|
||||
if not p:
|
||||
break
|
||||
if p and p.type == 'tosca.nodes.Root':
|
||||
break
|
||||
value = p.get_value(ndtype)
|
||||
p = p.parent_type
|
||||
return value
|
@ -1,74 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from translator.toscalib.common.exception import UnknownFieldError
|
||||
from translator.toscalib.elements.statefulentitytype import StatefulEntityType
|
||||
|
||||
SECTIONS = (LIFECYCLE, CONFIGURE, LIFECYCLE_SHORTNAME,
|
||||
CONFIGURE_SHORTNAME) = \
|
||||
('tosca.interfaces.node.lifecycle.Standard',
|
||||
'tosca.interfaces.relationship.Configure',
|
||||
'Standard', 'Configure')
|
||||
|
||||
INTERFACEVALUE = (IMPLEMENTATION, INPUTS) = ('implementation', 'inputs')
|
||||
|
||||
|
||||
class InterfacesDef(StatefulEntityType):
|
||||
'''TOSCA built-in interfaces type.'''
|
||||
|
||||
def __init__(self, node_type, interfacetype,
|
||||
node_template=None, name=None, value=None):
|
||||
self.ntype = node_type
|
||||
self.node_template = node_template
|
||||
self.type = interfacetype
|
||||
self.name = name
|
||||
self.value = value
|
||||
self.implementation = None
|
||||
self.inputs = None
|
||||
self.defs = {}
|
||||
if interfacetype == LIFECYCLE_SHORTNAME:
|
||||
interfacetype = LIFECYCLE
|
||||
if interfacetype == CONFIGURE_SHORTNAME:
|
||||
interfacetype = CONFIGURE
|
||||
if node_type:
|
||||
self.defs = self.TOSCA_DEF[interfacetype]
|
||||
if value:
|
||||
if isinstance(self.value, dict):
|
||||
for i, j in self.value.items():
|
||||
if i == IMPLEMENTATION:
|
||||
self.implementation = j
|
||||
elif i == INPUTS:
|
||||
self.inputs = j
|
||||
else:
|
||||
what = ('Interfaces of template %s' %
|
||||
self.node_template.name)
|
||||
raise UnknownFieldError(what=what, field=i)
|
||||
else:
|
||||
self.implementation = value
|
||||
|
||||
@property
|
||||
def lifecycle_ops(self):
|
||||
if self.defs:
|
||||
if self.type == LIFECYCLE:
|
||||
return self._ops()
|
||||
|
||||
@property
|
||||
def configure_ops(self):
|
||||
if self.defs:
|
||||
if self.type == CONFIGURE:
|
||||
return self._ops()
|
||||
|
||||
def _ops(self):
|
||||
ops = []
|
||||
for name in list(self.defs.keys()):
|
||||
ops.append(name)
|
||||
return ops
|
@ -1,200 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from translator.toscalib.elements.capabilitytype import CapabilityTypeDef
|
||||
import translator.toscalib.elements.interfaces as ifaces
|
||||
from translator.toscalib.elements.interfaces import InterfacesDef
|
||||
from translator.toscalib.elements.relationshiptype import RelationshipType
|
||||
from translator.toscalib.elements.statefulentitytype import StatefulEntityType
|
||||
|
||||
|
||||
class NodeType(StatefulEntityType):
|
||||
'''TOSCA built-in node type.'''
|
||||
|
||||
def __init__(self, ntype, custom_def=None):
|
||||
super(NodeType, self).__init__(ntype, self.NODE_PREFIX, custom_def)
|
||||
self.custom_def = custom_def
|
||||
|
||||
@property
|
||||
def parent_type(self):
|
||||
'''Return a node this node is derived from.'''
|
||||
pnode = self.derived_from(self.defs)
|
||||
if pnode:
|
||||
return NodeType(pnode)
|
||||
|
||||
@property
|
||||
def relationship(self):
|
||||
'''Return a dictionary of relationships to other node types.
|
||||
|
||||
This method returns a dictionary of named relationships that nodes
|
||||
of the current node type (self) can have to other nodes (of specific
|
||||
types) in a TOSCA template.
|
||||
|
||||
'''
|
||||
relationship = {}
|
||||
requires = self.get_all_requirements()
|
||||
if requires:
|
||||
# NOTE(sdmonov): Check if requires is a dict.
|
||||
# If it is a dict convert it to a list of dicts.
|
||||
# This is needed because currently the code below supports only
|
||||
# lists as requirements definition. The following check will
|
||||
# make sure if a map (dict) was provided it will be converted to
|
||||
# a list before proceeding to the parsing.
|
||||
if isinstance(requires, dict):
|
||||
requires = [{key: value} for key, value in requires.items()]
|
||||
|
||||
keyword = None
|
||||
node_type = None
|
||||
for require in requires:
|
||||
for key, req in require.items():
|
||||
if 'relationship' in req:
|
||||
relation = req.get('relationship')
|
||||
if 'type' in relation:
|
||||
relation = relation.get('type')
|
||||
node_type = req.get('node')
|
||||
value = req
|
||||
if node_type:
|
||||
keyword = 'node'
|
||||
else:
|
||||
# If value is a dict and has a type key
|
||||
# we need to lookup the node type using
|
||||
# the capability type
|
||||
value = req
|
||||
if isinstance(value, dict):
|
||||
captype = value['capability']
|
||||
value = (self.
|
||||
_get_node_type_by_cap(key, captype))
|
||||
relation = self._get_relation(key, value)
|
||||
keyword = key
|
||||
node_type = value
|
||||
rtype = RelationshipType(relation, keyword, req)
|
||||
relatednode = NodeType(node_type, self.custom_def)
|
||||
relationship[rtype] = relatednode
|
||||
return relationship
|
||||
|
||||
def _get_node_type_by_cap(self, key, cap):
|
||||
'''Find the node type that has the provided capability
|
||||
|
||||
This method will lookup all node types if they have the
|
||||
provided capability.
|
||||
'''
|
||||
|
||||
# Filter the node types
|
||||
node_types = [node_type for node_type in self.TOSCA_DEF.keys()
|
||||
if node_type.startswith(self.NODE_PREFIX) and
|
||||
node_type != 'tosca.nodes.Root']
|
||||
|
||||
for node_type in node_types:
|
||||
node_def = self.TOSCA_DEF[node_type]
|
||||
if isinstance(node_def, dict) and 'capabilities' in node_def:
|
||||
node_caps = node_def['capabilities']
|
||||
for value in node_caps.values():
|
||||
if isinstance(value, dict) and \
|
||||
'type' in value and value['type'] == cap:
|
||||
return node_type
|
||||
|
||||
def _get_relation(self, key, ndtype):
|
||||
relation = None
|
||||
ntype = NodeType(ndtype)
|
||||
caps = ntype.get_capabilities()
|
||||
if caps and key in caps.keys():
|
||||
c = caps[key]
|
||||
for r in self.RELATIONSHIP_TYPE:
|
||||
rtypedef = ntype.TOSCA_DEF[r]
|
||||
for properties in rtypedef.values():
|
||||
if c.type in properties:
|
||||
relation = r
|
||||
break
|
||||
if relation:
|
||||
break
|
||||
else:
|
||||
for properties in rtypedef.values():
|
||||
if c.parent_type in properties:
|
||||
relation = r
|
||||
break
|
||||
return relation
|
||||
|
||||
def get_capabilities_objects(self):
|
||||
'''Return a list of capability objects.'''
|
||||
typecapabilities = []
|
||||
caps = self.get_value(self.CAPABILITIES)
|
||||
if caps is None:
|
||||
caps = self.get_value(self.CAPABILITIES, None, True)
|
||||
if caps:
|
||||
for name, value in caps.items():
|
||||
ctype = value.get('type')
|
||||
cap = CapabilityTypeDef(name, ctype, self.type,
|
||||
self.custom_def)
|
||||
typecapabilities.append(cap)
|
||||
return typecapabilities
|
||||
|
||||
def get_capabilities(self):
|
||||
'''Return a dictionary of capability name-objects pairs.'''
|
||||
return {cap.name: cap
|
||||
for cap in self.get_capabilities_objects()}
|
||||
|
||||
@property
|
||||
def requirements(self):
|
||||
return self.get_value(self.REQUIREMENTS)
|
||||
|
||||
def get_all_requirements(self):
|
||||
requires = self.requirements
|
||||
parent_node = self.parent_type
|
||||
if requires is None:
|
||||
requires = self.get_value(self.REQUIREMENTS, None, True)
|
||||
parent_node = parent_node.parent_type
|
||||
if parent_node:
|
||||
while parent_node.type != 'tosca.nodes.Root':
|
||||
req = parent_node.get_value(self.REQUIREMENTS, None, True)
|
||||
for r in req:
|
||||
if r not in requires:
|
||||
requires.append(r)
|
||||
parent_node = parent_node.parent_type
|
||||
return requires
|
||||
|
||||
@property
|
||||
def interfaces(self):
|
||||
return self.get_value(self.INTERFACES)
|
||||
|
||||
@property
|
||||
def lifecycle_inputs(self):
|
||||
'''Return inputs to life cycle operations if found.'''
|
||||
inputs = []
|
||||
interfaces = self.interfaces
|
||||
if interfaces:
|
||||
for name, value in interfaces.items():
|
||||
if name == ifaces.LIFECYCLE:
|
||||
for x, y in value.items():
|
||||
if x == 'inputs':
|
||||
for i in y.iterkeys():
|
||||
inputs.append(i)
|
||||
return inputs
|
||||
|
||||
@property
|
||||
def lifecycle_operations(self):
|
||||
'''Return available life cycle operations if found.'''
|
||||
ops = None
|
||||
interfaces = self.interfaces
|
||||
if interfaces:
|
||||
i = InterfacesDef(self.type, ifaces.LIFECYCLE)
|
||||
ops = i.lifecycle_ops
|
||||
return ops
|
||||
|
||||
def get_capability(self, name):
|
||||
caps = self.get_capabilities()
|
||||
if caps and name in caps.keys():
|
||||
return caps[name].value
|
||||
|
||||
def get_capability_type(self, name):
|
||||
captype = self.get_capability(name)
|
||||
if captype and name in captype.keys():
|
||||
return captype[name].value
|
@ -1,45 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from translator.toscalib.common.exception import InvalidSchemaError
|
||||
|
||||
|
||||
class PropertyDef(object):
|
||||
'''TOSCA built-in Property type.'''
|
||||
|
||||
def __init__(self, name, value=None, schema=None):
|
||||
self.name = name
|
||||
self.value = value
|
||||
self.schema = schema
|
||||
|
||||
try:
|
||||
self.schema['type']
|
||||
except KeyError:
|
||||
msg = (_("Property definition of %(pname)s must have type.") %
|
||||
dict(pname=self.name))
|
||||
raise InvalidSchemaError(message=msg)
|
||||
|
||||
@property
|
||||
def required(self):
|
||||
if self.schema:
|
||||
for prop_key, prop_value in self.schema.items():
|
||||
if prop_key == 'required' and prop_value:
|
||||
return True
|
||||
return False
|
||||
|
||||
@property
|
||||
def default(self):
|
||||
if self.schema:
|
||||
for prop_key, prop_value in self.schema.items():
|
||||
if prop_key == 'default':
|
||||
return prop_value
|
||||
return None
|
@ -1,33 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from translator.toscalib.elements.statefulentitytype import StatefulEntityType
|
||||
|
||||
|
||||
class RelationshipType(StatefulEntityType):
|
||||
'''TOSCA built-in relationship type.'''
|
||||
def __init__(self, type, capability_name=None, custom_def=None):
|
||||
super(RelationshipType, self).__init__(type, self.RELATIONSHIP_PREFIX,
|
||||
custom_def)
|
||||
self.capability_name = capability_name
|
||||
self.custom_def = custom_def
|
||||
|
||||
@property
|
||||
def parent_type(self):
|
||||
'''Return a relationship this reletionship is derived from.'''
|
||||
prel = self.derived_from(self.defs)
|
||||
if prel:
|
||||
return RelationshipType(prel)
|
||||
|
||||
@property
|
||||
def valid_target_types(self):
|
||||
return self.entity_value(self.defs, 'valid_target_types')
|
@ -1,124 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import logging
|
||||
import re
|
||||
|
||||
from translator.toscalib.utils.gettextutils import _
|
||||
from translator.toscalib.utils import validateutils
|
||||
|
||||
log = logging.getLogger('tosca')
|
||||
|
||||
|
||||
class ScalarUnit(object):
|
||||
'''Parent class for scalar-unit type.'''
|
||||
|
||||
SCALAR_UNIT_TYPES = (
|
||||
SCALAR_UNIT_SIZE, SCALAR_UNIT_FREQUENCY, SCALAR_UNIT_TIME
|
||||
) = (
|
||||
'scalar-unit.size', 'scalar-unit.frequency', 'scalar-unit.time'
|
||||
)
|
||||
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
|
||||
def _check_unit_in_scalar_standard_units(self, input_unit):
|
||||
"""Check whether the input unit is following specified standard
|
||||
|
||||
If unit is not following specified standard, convert it to standard
|
||||
unit after displaying a warning message.
|
||||
"""
|
||||
if input_unit in self.SCALAR_UNIT_DICT.keys():
|
||||
return input_unit
|
||||
else:
|
||||
for key in self.SCALAR_UNIT_DICT.keys():
|
||||
if key.upper() == input_unit.upper():
|
||||
log.warning(_('Given unit %(unit)s does not follow scalar '
|
||||
'unit standards; using %(key)s instead.') % {
|
||||
'unit': input_unit, 'key': key})
|
||||
return key
|
||||
msg = (_('Provided unit "%(unit)s" is not valid. The valid units'
|
||||
' are %(valid_units)s') % {'unit': input_unit,
|
||||
'valid_units': sorted(self.SCALAR_UNIT_DICT.keys())})
|
||||
raise ValueError(msg)
|
||||
|
||||
def validate_scalar_unit(self):
|
||||
regex = re.compile('([0-9.]+)\s*(\w+)')
|
||||
try:
|
||||
result = regex.match(str(self.value)).groups()
|
||||
validateutils.str_to_num(result[0])
|
||||
scalar_unit = self._check_unit_in_scalar_standard_units(result[1])
|
||||
self.value = ' '.join([result[0], scalar_unit])
|
||||
return self.value
|
||||
|
||||
except Exception:
|
||||
raise ValueError(_('"%s" is not a valid scalar-unit')
|
||||
% self.value)
|
||||
|
||||
def get_num_from_scalar_unit(self, unit=None):
|
||||
if unit:
|
||||
unit = self._check_unit_in_scalar_standard_units(unit)
|
||||
else:
|
||||
unit = self.SCALAR_UNIT_DEFAULT
|
||||
self.validate_scalar_unit()
|
||||
|
||||
regex = re.compile('([0-9.]+)\s*(\w+)')
|
||||
result = regex.match(str(self.value)).groups()
|
||||
converted = (float(validateutils.str_to_num(result[0]))
|
||||
* self.SCALAR_UNIT_DICT[result[1]]
|
||||
/ self.SCALAR_UNIT_DICT[unit])
|
||||
if converted - int(converted) < 0.0000000000001:
|
||||
converted = int(converted)
|
||||
return converted
|
||||
|
||||
|
||||
class ScalarUnit_Size(ScalarUnit):
|
||||
|
||||
SCALAR_UNIT_DEFAULT = 'B'
|
||||
SCALAR_UNIT_DICT = {'B': 1, 'kB': 1000, 'KiB': 1024, 'MB': 1000000,
|
||||
'MiB': 1048576, 'GB': 1000000000,
|
||||
'GiB': 1073741824, 'TB': 1000000000000,
|
||||
'TiB': 1099511627776}
|
||||
|
||||
|
||||
class ScalarUnit_Time(ScalarUnit):
|
||||
|
||||
SCALAR_UNIT_DEFAULT = 'ms'
|
||||
SCALAR_UNIT_DICT = {'d': 86400, 'h': 3600, 'm': 60, 's': 1,
|
||||
'ms': 0.001, 'us': 0.000001, 'ns': 0.000000001}
|
||||
|
||||
|
||||
class ScalarUnit_Frequency(ScalarUnit):
|
||||
|
||||
SCALAR_UNIT_DEFAULT = 'GHz'
|
||||
SCALAR_UNIT_DICT = {'Hz': 1, 'kHz': 1000,
|
||||
'MHz': 1000000, 'GHz': 1000000000}
|
||||
|
||||
|
||||
scalarunit_mapping = {
|
||||
ScalarUnit.SCALAR_UNIT_FREQUENCY: ScalarUnit_Frequency,
|
||||
ScalarUnit.SCALAR_UNIT_SIZE: ScalarUnit_Size,
|
||||
ScalarUnit.SCALAR_UNIT_TIME: ScalarUnit_Time,
|
||||
}
|
||||
|
||||
|
||||
def get_scalarunit_class(type):
|
||||
return scalarunit_mapping.get(type)
|
||||
|
||||
|
||||
def get_scalarunit_value(type, value, unit=None):
|
||||
if type in ScalarUnit.SCALAR_UNIT_TYPES:
|
||||
ScalarUnit_Class = get_scalarunit_class(type)
|
||||
return (ScalarUnit_Class(value).
|
||||
get_num_from_scalar_unit(unit))
|
||||
else:
|
||||
raise TypeError(_('"%s" is not a valid scalar-unit type') % type)
|
@ -1,81 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from translator.toscalib.common.exception import InvalidTypeError
|
||||
from translator.toscalib.elements.attribute_definition import AttributeDef
|
||||
from translator.toscalib.elements.entitytype import EntityType
|
||||
from translator.toscalib.elements.property_definition import PropertyDef
|
||||
|
||||
|
||||
class StatefulEntityType(EntityType):
|
||||
'''Class representing TOSCA states.'''
|
||||
|
||||
interfaces_node_lifecycle_operations = ['create',
|
||||
'configure', 'start',
|
||||
'stop', 'delete']
|
||||
|
||||
interfaces_relationship_confiure_operations = ['post_configure_source',
|
||||
'post_configure_target',
|
||||
'add_target',
|
||||
'remove_target']
|
||||
|
||||
def __init__(self, entitytype, prefix, custom_def=None):
|
||||
entire_entitytype = entitytype
|
||||
if not entitytype.startswith(self.TOSCA):
|
||||
entire_entitytype = prefix + entitytype
|
||||
if entire_entitytype in list(self.TOSCA_DEF.keys()):
|
||||
self.defs = self.TOSCA_DEF[entire_entitytype]
|
||||
entitytype = entire_entitytype
|
||||
elif custom_def and entitytype in list(custom_def.keys()):
|
||||
self.defs = custom_def[entitytype]
|
||||
else:
|
||||
raise InvalidTypeError(what=entitytype)
|
||||
self.type = entitytype
|
||||
|
||||
def get_properties_def_objects(self):
|
||||
'''Return a list of property definition objects.'''
|
||||
properties = []
|
||||
props = self.get_value(self.PROPERTIES)
|
||||
if props:
|
||||
for prop, schema in props.items():
|
||||
properties.append(PropertyDef(prop, None, schema))
|
||||
return properties
|
||||
|
||||
def get_properties_def(self):
|
||||
'''Return a dictionary of property definition name-object pairs.'''
|
||||
return {prop.name: prop
|
||||
for prop in self.get_properties_def_objects()}
|
||||
|
||||
def get_property_def_value(self, name):
|
||||
'''Return the property definition associated with a given name.'''
|
||||
props_def = self.get_properties_def()
|
||||
if props_def and name in props_def.keys():
|
||||
return props_def[name].value
|
||||
|
||||
def get_attributes_def_objects(self):
|
||||
'''Return a list of attribute definition objects.'''
|
||||
attrs = self.get_value(self.ATTRIBUTES)
|
||||
if attrs:
|
||||
return [AttributeDef(attr, None, schema)
|
||||
for attr, schema in attrs.items()]
|
||||
return []
|
||||
|
||||
def get_attributes_def(self):
|
||||
'''Return a dictionary of attribute definition name-object pairs.'''
|
||||
return {attr.name: attr
|
||||
for attr in self.get_attributes_def_objects()}
|
||||
|
||||
def get_attribute_def_value(self, name):
|
||||
'''Return the attribute definition associated with a given name.'''
|
||||
attrs_def = self.get_attributes_def()
|
||||
if attrs_def and name in attrs_def.keys():
|
||||
return attrs_def[name].value
|
@ -1,276 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from translator.toscalib.capabilities import Capability
|
||||
from translator.toscalib.common.exception import MissingRequiredFieldError
|
||||
from translator.toscalib.common.exception import UnknownFieldError
|
||||
from translator.toscalib.common.exception import ValidationError
|
||||
from translator.toscalib.elements.interfaces import InterfacesDef
|
||||
from translator.toscalib.elements.nodetype import NodeType
|
||||
from translator.toscalib.elements.relationshiptype import RelationshipType
|
||||
from translator.toscalib.properties import Property
|
||||
|
||||
|
||||
class EntityTemplate(object):
|
||||
'''Base class for TOSCA templates.'''
|
||||
|
||||
SECTIONS = (DERIVED_FROM, PROPERTIES, REQUIREMENTS,
|
||||
INTERFACES, CAPABILITIES, TYPE, DESCRIPTION, DIRECTIVES,
|
||||
ATTRIBUTES, ARTIFACTS, NODE_FILTER, COPY) = \
|
||||
('derived_from', 'properties', 'requirements', 'interfaces',
|
||||
'capabilities', 'type', 'description', 'directives',
|
||||
'attributes', 'artifacts', 'node_filter', 'copy')
|
||||
REQUIREMENTS_SECTION = (NODE, CAPABILITY, RELATIONSHIP, OCCURRENCES) = \
|
||||
('node', 'capability', 'relationship',
|
||||
'occurrences')
|
||||
|
||||
def __init__(self, name, template, entity_name, custom_def=None):
|
||||
self.name = name
|
||||
self.entity_tpl = template
|
||||
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)
|
||||
if entity_name == 'relationship_type':
|
||||
relationship = template.get('relationship')
|
||||
type = None
|
||||
if relationship and isinstance(relationship, dict):
|
||||
type = relationship.get('type')
|
||||
elif isinstance(relationship, str):
|
||||
type = self.entity_tpl['relationship']
|
||||
else:
|
||||
type = self.entity_tpl['type']
|
||||
self.type_definition = RelationshipType(type,
|
||||
None, custom_def)
|
||||
self._properties = None
|
||||
self._interfaces = None
|
||||
self._requirements = None
|
||||
self._capabilities = None
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
return self.type_definition.type
|
||||
|
||||
@property
|
||||
def requirements(self):
|
||||
if self._requirements is None:
|
||||
self._requirements = self.type_definition.get_value(
|
||||
self.REQUIREMENTS,
|
||||
self.entity_tpl) or []
|
||||
return self._requirements
|
||||
|
||||
def get_properties_objects(self):
|
||||
'''Return properties objects for this template.'''
|
||||
if self._properties is None:
|
||||
self._properties = self._create_properties()
|
||||
return self._properties
|
||||
|
||||
def get_properties(self):
|
||||
'''Return a dictionary of property name-object pairs.'''
|
||||
return {prop.name: prop
|
||||
for prop in self.get_properties_objects()}
|
||||
|
||||
def get_property_value(self, name):
|
||||
'''Return the value of a given property name.'''
|
||||
props = self.get_properties()
|
||||
if props and name in props.keys():
|
||||
return props[name].value
|
||||
|
||||
@property
|
||||
def interfaces(self):
|
||||
if self._interfaces is None:
|
||||
self._interfaces = self._create_interfaces()
|
||||
return self._interfaces
|
||||
|
||||
def get_capabilities_objects(self):
|
||||
'''Return capabilities objects for this template.'''
|
||||
if not self._capabilities:
|
||||
self._capabilities = self._create_capabilities()
|
||||
return self._capabilities
|
||||
|
||||
def get_capabilities(self):
|
||||
'''Return a dictionary of capability name-object pairs.'''
|
||||
return {cap.name: cap
|
||||
for cap in self.get_capabilities_objects()}
|
||||
|
||||
def is_derived_from(self, type_str):
|
||||
'''Check if object inherits from the given type.
|
||||
|
||||
Returns true if this object is derived from 'type_str'.
|
||||
False otherwise.
|
||||
'''
|
||||
if not self.type:
|
||||
return False
|
||||
elif self.type == type_str:
|
||||
return True
|
||||
elif self.parent_type:
|
||||
return self.parent_type.is_derived_from(type_str)
|
||||
else:
|
||||
return False
|
||||
|
||||
def _create_capabilities(self):
|
||||
capability = []
|
||||
caps = self.type_definition.get_value(self.CAPABILITIES,
|
||||
self.entity_tpl)
|
||||
if caps:
|
||||
for name, props in caps.items():
|
||||
capabilities = self.type_definition.get_capabilities()
|
||||
if name in capabilities.keys():
|
||||
c = capabilities[name]
|
||||
cap = Capability(name, props['properties'], c)
|
||||
capability.append(cap)
|
||||
return capability
|
||||
|
||||
def _validate_properties(self, template, entitytype):
|
||||
properties = entitytype.get_value(self.PROPERTIES, template)
|
||||
self._common_validate_properties(entitytype, properties)
|
||||
|
||||
def _validate_capabilities(self):
|
||||
type_capabilities = self.type_definition.get_capabilities()
|
||||
allowed_caps = \
|
||||
type_capabilities.keys() if type_capabilities else []
|
||||
capabilities = self.type_definition.get_value(self.CAPABILITIES,
|
||||
self.entity_tpl)
|
||||
if capabilities:
|
||||
self._common_validate_field(capabilities, allowed_caps,
|
||||
'Capabilities')
|
||||
self._validate_capabilities_properties(capabilities)
|
||||
|
||||
def _validate_capabilities_properties(self, capabilities):
|
||||
for cap, props in capabilities.items():
|
||||
capabilitydef = self.get_capability(cap).definition
|
||||
self._common_validate_properties(capabilitydef,
|
||||
props[self.PROPERTIES])
|
||||
|
||||
# validating capability properties values
|
||||
for prop in self.get_capability(cap).get_properties_objects():
|
||||
prop.validate()
|
||||
|
||||
# TODO(srinivas_tadepalli): temporary work around to validate
|
||||
# default_instances until standardized in specification
|
||||
if cap == "scalable" and prop.name == "default_instances":
|
||||
prop_dict = props[self.PROPERTIES]
|
||||
min_instances = prop_dict.get("min_instances")
|
||||
max_instances = prop_dict.get("max_instances")
|
||||
default_instances = prop_dict.get("default_instances")
|
||||
if not (min_instances <= default_instances
|
||||
<= max_instances):
|
||||
err_msg = ("Properties of template %s : "
|
||||
"default_instances value is not"
|
||||
" between min_instances and "
|
||||
"max_instances" % self.name)
|
||||
raise ValidationError(message=err_msg)
|
||||
|
||||
def _common_validate_properties(self, entitytype, properties):
|
||||
allowed_props = []
|
||||
required_props = []
|
||||
for p in entitytype.get_properties_def_objects():
|
||||
allowed_props.append(p.name)
|
||||
if p.required:
|
||||
required_props.append(p.name)
|
||||
if properties:
|
||||
self._common_validate_field(properties, allowed_props,
|
||||
'Properties')
|
||||
# make sure it's not missing any property required by a tosca type
|
||||
missingprop = []
|
||||
for r in required_props:
|
||||
if r not in properties.keys():
|
||||
missingprop.append(r)
|
||||
if missingprop:
|
||||
raise MissingRequiredFieldError(
|
||||
what='Properties of template %s' % self.name,
|
||||
required=missingprop)
|
||||
else:
|
||||
if required_props:
|
||||
raise MissingRequiredFieldError(
|
||||
what='Properties of template %s' % self.name,
|
||||
required=missingprop)
|
||||
|
||||
def _validate_field(self, template):
|
||||
if not isinstance(template, dict):
|
||||
raise MissingRequiredFieldError(
|
||||
what='Template %s' % self.name, required=self.TYPE)
|
||||
try:
|
||||
relationship = template.get('relationship')
|
||||
if relationship and not isinstance(relationship, str):
|
||||
relationship[self.TYPE]
|
||||
elif isinstance(relationship, str):
|
||||
template['relationship']
|
||||
else:
|
||||
template[self.TYPE]
|
||||
except KeyError:
|
||||
raise MissingRequiredFieldError(
|
||||
what='Template %s' % self.name, required=self.TYPE)
|
||||
|
||||
def _common_validate_field(self, schema, allowedlist, section):
|
||||
for name in schema:
|
||||
if name not in allowedlist:
|
||||
raise UnknownFieldError(
|
||||
what='%(section)s of template %(nodename)s'
|
||||
% {'section': section, 'nodename': self.name},
|
||||
field=name)
|
||||
|
||||
def _create_properties(self):
|
||||
props = []
|
||||
properties = self.type_definition.get_value(self.PROPERTIES,
|
||||
self.entity_tpl) or {}
|
||||
for name, value in properties.items():
|
||||
props_def = self.type_definition.get_properties_def()
|
||||
if props_def and name in props_def:
|
||||
prop = Property(name, value,
|
||||
props_def[name].schema, self.custom_def)
|
||||
props.append(prop)
|
||||
for p in self.type_definition.get_properties_def_objects():
|
||||
if p.default is not None and p.name not in properties.keys():
|
||||
prop = Property(p.name, p.default, p.schema, self.custom_def)
|
||||
props.append(prop)
|
||||
return props
|
||||
|
||||
def _create_interfaces(self):
|
||||
interfaces = []
|
||||
type_interfaces = None
|
||||
if isinstance(self.type_definition, RelationshipType):
|
||||
if isinstance(self.entity_tpl, dict):
|
||||
for rel_def, value in self.entity_tpl.items():
|
||||
if rel_def != 'type':
|
||||
rel_def = self.entity_tpl.get(rel_def)
|
||||
rel = None
|
||||
if isinstance(rel_def, dict):
|
||||
rel = rel_def.get('relationship')
|
||||
if rel:
|
||||
if self.INTERFACES in rel:
|
||||
type_interfaces = rel[self.INTERFACES]
|
||||
break
|
||||
else:
|
||||
type_interfaces = self.type_definition.get_value(self.INTERFACES,
|
||||
self.entity_tpl)
|
||||
if type_interfaces:
|
||||
for interface_type, value in type_interfaces.items():
|
||||
for op, op_def in value.items():
|
||||
iface = InterfacesDef(self.type_definition,
|
||||
interfacetype=interface_type,
|
||||
node_template=self,
|
||||
name=op,
|
||||
value=op_def)
|
||||
interfaces.append(iface)
|
||||
return interfaces
|
||||
|
||||
def get_capability(self, name):
|
||||
"""Provide named capability
|
||||
|
||||
:param name: name of capability
|
||||
:return: capability object if found, None otherwise
|
||||
"""
|
||||
caps = self.get_capabilities()
|
||||
if caps and name in caps.keys():
|
||||
return caps[name]
|
@ -1,378 +0,0 @@
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
import abc
|
||||
import six
|
||||
|
||||
from translator.toscalib.common.exception import UnknownInputError
|
||||
from translator.toscalib.utils.gettextutils import _
|
||||
|
||||
|
||||
GET_PROPERTY = 'get_property'
|
||||
GET_ATTRIBUTE = 'get_attribute'
|
||||
GET_INPUT = 'get_input'
|
||||
|
||||
SELF = 'SELF'
|
||||
HOST = 'HOST'
|
||||
|
||||
HOSTED_ON = 'tosca.relationships.HostedOn'
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class Function(object):
|
||||
"""An abstract type for representing a Tosca template function."""
|
||||
|
||||
def __init__(self, tosca_tpl, context, name, args):
|
||||
self.tosca_tpl = tosca_tpl
|
||||
self.context = context
|
||||
self.name = name
|
||||
self.args = args
|
||||
self.validate()
|
||||
|
||||
@abc.abstractmethod
|
||||
def result(self):
|
||||
"""Invokes the function and returns its result
|
||||
|
||||
Some methods invocation may only be relevant on runtime (for example,
|
||||
getting runtime properties) and therefore its the responsibility of
|
||||
the orchestrator/translator to take care of such functions invocation.
|
||||
|
||||
:return: Function invocation result.
|
||||
"""
|
||||
return {self.name: self.args}
|
||||
|
||||
@abc.abstractmethod
|
||||
def validate(self):
|
||||
"""Validates function arguments."""
|
||||
pass
|
||||
|
||||
|
||||
class GetInput(Function):
|
||||
"""Get a property value declared within the input of the service template.
|
||||
|
||||
Arguments:
|
||||
|
||||
* Input name.
|
||||
|
||||
Example:
|
||||
|
||||
* get_input: port
|
||||
"""
|
||||
|
||||
def validate(self):
|
||||
if len(self.args) != 1:
|
||||
raise ValueError(_(
|
||||
'Expected one argument for get_input function but received: '
|
||||
'{0}.').format(self.args))
|
||||
inputs = [input.name for input in self.tosca_tpl.inputs]
|
||||
if self.args[0] not in inputs:
|
||||
raise UnknownInputError(input_name=self.args[0])
|
||||
|
||||
def result(self):
|
||||
found_input = [input_def for input_def in self.tosca_tpl.inputs
|
||||
if self.input_name == input_def.name][0]
|
||||
return found_input.default
|
||||
|
||||
@property
|
||||
def input_name(self):
|
||||
return self.args[0]
|
||||
|
||||
|
||||
class GetAttribute(Function):
|
||||
"""Get an attribute value of an entity defined in the service template
|
||||
|
||||
Node template attributes values are set in runtime and therefore its the
|
||||
responsibility of the Tosca engine to implement the evaluation of
|
||||
get_attribute functions.
|
||||
|
||||
Arguments:
|
||||
|
||||
* Node template name | HOST.
|
||||
* Attribute name.
|
||||
|
||||
If the HOST keyword is passed as the node template name argument the
|
||||
function will search each node template along the HostedOn relationship
|
||||
chain until a node which contains the attribute is found.
|
||||
|
||||
Examples:
|
||||
|
||||
* { get_attribute: [ server, private_address ] }
|
||||
* { get_attribute: [ HOST, private_address ] }
|
||||
"""
|
||||
|
||||
def validate(self):
|
||||
if len(self.args) != 2:
|
||||
raise ValueError(_(
|
||||
'Illegal arguments for {0} function. Expected arguments: '
|
||||
'node-template-name, attribute-name').format(GET_ATTRIBUTE))
|
||||
self._find_node_template_containing_attribute()
|
||||
|
||||
def result(self):
|
||||
return self.args
|
||||
|
||||
def get_referenced_node_template(self):
|
||||
"""Gets the NodeTemplate instance the get_attribute function refers to.
|
||||
|
||||
If HOST keyword was used as the node template argument, the node
|
||||
template which contains the attribute along the HostedOn relationship
|
||||
chain will be returned.
|
||||
"""
|
||||
return self._find_node_template_containing_attribute()
|
||||
|
||||
def _find_node_template_containing_attribute(self):
|
||||
if self.node_template_name == HOST:
|
||||
# Currently this is the only way to tell whether the function
|
||||
# is used within the outputs section of the TOSCA template.
|
||||
if isinstance(self.context, list):
|
||||
raise ValueError(_(
|
||||
"get_attribute HOST keyword is not allowed within the "
|
||||
"outputs section of the TOSCA template"))
|
||||
node_tpl = self._find_host_containing_attribute()
|
||||
if not node_tpl:
|
||||
raise ValueError(_(
|
||||
"get_attribute HOST keyword is used in '{0}' node "
|
||||
"template but {1} was not found "
|
||||
"in relationship chain").format(self.context.name,
|
||||
HOSTED_ON))
|
||||
else:
|
||||
node_tpl = self._find_node_template(self.args[0])
|
||||
if not self._attribute_exists_in_type(node_tpl.type_definition):
|
||||
raise KeyError(_(
|
||||
"Attribute '{0}' not found in node template: {1}.").format(
|
||||
self.attribute_name, node_tpl.name))
|
||||
return node_tpl
|
||||
|
||||
def _attribute_exists_in_type(self, type_definition):
|
||||
attrs_def = type_definition.get_attributes_def()
|
||||
found = [attrs_def[self.attribute_name]] \
|
||||
if self.attribute_name in attrs_def else []
|
||||
return len(found) == 1
|
||||
|
||||
def _find_host_containing_attribute(self, node_template_name=SELF):
|
||||
node_template = self._find_node_template(node_template_name)
|
||||
from translator.toscalib.elements.entitytype import EntityType
|
||||
hosted_on_rel = EntityType.TOSCA_DEF[HOSTED_ON]
|
||||
for r in node_template.requirements:
|
||||
for requirement, target_name in r.items():
|
||||
target_node = self._find_node_template(target_name)
|
||||
target_type = target_node.type_definition
|
||||
for capability in target_type.get_capabilities_objects():
|
||||
if capability.type in hosted_on_rel['valid_target_types']:
|
||||
if self._attribute_exists_in_type(target_type):
|
||||
return target_node
|
||||
return self._find_host_containing_attribute(
|
||||
target_name)
|
||||
return None
|
||||
|
||||
def _find_node_template(self, node_template_name):
|
||||
name = self.context.name if node_template_name == SELF else \
|
||||
node_template_name
|
||||
for node_template in self.tosca_tpl.nodetemplates:
|
||||
if node_template.name == name:
|
||||
return node_template
|
||||
raise KeyError(_(
|
||||
'No such node template: {0}.').format(node_template_name))
|
||||
|
||||
@property
|
||||
def node_template_name(self):
|
||||
return self.args[0]
|
||||
|
||||
@property
|
||||
def attribute_name(self):
|
||||
return self.args[1]
|
||||
|
||||
|
||||
class GetProperty(Function):
|
||||
"""Get a property value of an entity defined in the same service template.
|
||||
|
||||
Arguments:
|
||||
|
||||
* Node template name.
|
||||
* Requirement or capability name (optional).
|
||||
* Property name.
|
||||
|
||||
If requirement or capability name is specified, the behavior is as follows:
|
||||
The req or cap name is first looked up in the specified node template's
|
||||
requirements.
|
||||
If found, it would search for a matching capability
|
||||
of an other node template and get its property as specified in function
|
||||
arguments.
|
||||
Otherwise, the req or cap name would be looked up in the specified
|
||||
node template's capabilities and if found, it would return the property of
|
||||
the capability as specified in function arguments.
|
||||
|
||||
Examples:
|
||||
|
||||
* { get_property: [ mysql_server, port ] }
|
||||
* { get_property: [ SELF, db_port ] }
|
||||
* { get_property: [ SELF, database_endpoint, port ] }
|
||||
"""
|
||||
|
||||
def validate(self):
|
||||
if len(self.args) < 2 or len(self.args) > 3:
|
||||
raise ValueError(_(
|
||||
'Expected arguments: [node-template-name, req-or-cap '
|
||||
'(optional), property name.'))
|
||||
if len(self.args) == 2:
|
||||
prop = self._find_property(self.args[1]).value
|
||||
if not isinstance(prop, Function):
|
||||
get_function(self.tosca_tpl, self.context, prop)
|
||||
elif len(self.args) == 3:
|
||||
get_function(self.tosca_tpl,
|
||||
self.context,
|
||||
self._find_req_or_cap_property(self.args[1],
|
||||
self.args[2]))
|
||||
else:
|
||||
raise NotImplementedError(_(
|
||||
'Nested properties are not supported.'))
|
||||
|
||||
def _find_req_or_cap_property(self, req_or_cap, property_name):
|
||||
node_tpl = self._find_node_template(self.args[0])
|
||||
# Find property in node template's requirements
|
||||
for r in node_tpl.requirements:
|
||||
for req, node_name in r.items():
|
||||
if req == req_or_cap:
|
||||
node_template = self._find_node_template(node_name)
|
||||
return self._get_capability_property(
|
||||
node_template,
|
||||
req,
|
||||
property_name)
|
||||
# If requirement was not found, look in node template's capabilities
|
||||
return self._get_capability_property(node_tpl,
|
||||
req_or_cap,
|
||||
property_name)
|
||||
|
||||
def _get_capability_property(self,
|
||||
node_template,
|
||||
capability_name,
|
||||
property_name):
|
||||
"""Gets a node template capability property."""
|
||||
caps = node_template.get_capabilities()
|
||||
if caps and capability_name in caps.keys():
|
||||
cap = caps[capability_name]
|
||||
property = None
|
||||
props = cap.get_properties()
|
||||
if props and property_name in props.keys():
|
||||
property = props[property_name].value
|
||||
if not property:
|
||||
raise KeyError(_(
|
||||
"Property '{0}' not found in capability '{1}' of node"
|
||||
" template '{2}' referenced from node template"
|
||||
" '{3}'.").format(property_name,
|
||||
capability_name,
|
||||
node_template.name,
|
||||
self.context.name))
|
||||
return property
|
||||
msg = _("Requirement/Capability '{0}' referenced from '{1}' node "
|
||||
"template not found in '{2}' node template.").format(
|
||||
capability_name,
|
||||
self.context.name,
|
||||
node_template.name)
|
||||
raise KeyError(msg)
|
||||
|
||||
def _find_property(self, property_name):
|
||||
node_tpl = self._find_node_template(self.args[0])
|
||||
props = node_tpl.get_properties()
|
||||
found = [props[property_name]] if property_name in props else []
|
||||
if len(found) == 0:
|
||||
raise KeyError(_(
|
||||
"Property: '{0}' not found in node template: {1}.").format(
|
||||
property_name, node_tpl.name))
|
||||
return found[0]
|
||||
|
||||
def _find_node_template(self, node_template_name):
|
||||
if node_template_name == SELF:
|
||||
return self.context
|
||||
for node_template in self.tosca_tpl.nodetemplates:
|
||||
if node_template.name == node_template_name:
|
||||
return node_template
|
||||
raise KeyError(_(
|
||||
'No such node template: {0}.').format(node_template_name))
|
||||
|
||||
def result(self):
|
||||
if len(self.args) == 3:
|
||||
property_value = self._find_req_or_cap_property(self.args[1],
|
||||
self.args[2])
|
||||
else:
|
||||
property_value = self._find_property(self.args[1]).value
|
||||
if isinstance(property_value, Function):
|
||||
return property_value
|
||||
return get_function(self.tosca_tpl,
|
||||
self.context,
|
||||
property_value)
|
||||
|
||||
@property
|
||||
def node_template_name(self):
|
||||
return self.args[0]
|
||||
|
||||
@property
|
||||
def property_name(self):
|
||||
if len(self.args) > 2:
|
||||
return self.args[2]
|
||||
return self.args[1]
|
||||
|
||||
@property
|
||||
def req_or_cap(self):
|
||||
if len(self.args) > 2:
|
||||
return self.args[1]
|
||||
return None
|
||||
|
||||
|
||||
function_mappings = {
|
||||
GET_PROPERTY: GetProperty,
|
||||
GET_INPUT: GetInput,
|
||||
GET_ATTRIBUTE: GetAttribute
|
||||
}
|
||||
|
||||
|
||||
def is_function(function):
|
||||
"""Returns True if the provided function is a Tosca intrinsic function.
|
||||
|
||||
Examples:
|
||||
|
||||
* "{ get_property: { SELF, port } }"
|
||||
* "{ get_input: db_name }"
|
||||
* Function instance
|
||||
|
||||
:param function: Function as string or a Function instance.
|
||||
:return: True if function is a Tosca intrinsic function, otherwise False.
|
||||
"""
|
||||
if isinstance(function, dict) and len(function) == 1:
|
||||
func_name = list(function.keys())[0]
|
||||
return func_name in function_mappings
|
||||
return isinstance(function, Function)
|
||||
|
||||
|
||||
def get_function(tosca_tpl, node_template, raw_function):
|
||||
"""Gets a Function instance representing the provided template function.
|
||||
|
||||
If the format provided raw_function format is not relevant for template
|
||||
functions or if the function name doesn't exist in function mapping the
|
||||
method returns the provided raw_function.
|
||||
|
||||
:param tosca_tpl: The tosca template.
|
||||
:param node_template: The node template the function is specified for.
|
||||
:param raw_function: The raw function as dict.
|
||||
:return: Template function as Function instance or the raw_function if
|
||||
parsing was unsuccessful.
|
||||
"""
|
||||
if is_function(raw_function):
|
||||
func_name = list(raw_function.keys())[0]
|
||||
if func_name in function_mappings:
|
||||
func = function_mappings[func_name]
|
||||
func_args = list(raw_function.values())[0]
|
||||
if not isinstance(func_args, list):
|
||||
func_args = [func_args]
|
||||
return func(tosca_tpl, node_template, func_name, func_args)
|
||||
return raw_function
|
@ -1,27 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
class NodeGroup(object):
|
||||
|
||||
def __init__(self, name, group_templates, member_nodes):
|
||||
self.name = name
|
||||
self.tpl = group_templates
|
||||
self.members = member_nodes
|
||||
|
||||
@property
|
||||
def member_names(self):
|
||||
return self.tpl.get('members')
|
||||
|
||||
@property
|
||||
def policies(self):
|
||||
return self.tpl.get('policies')
|
@ -1,218 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
import logging
|
||||
|
||||
from translator.toscalib.common.exception import TypeMismatchError
|
||||
from translator.toscalib.common.exception import UnknownFieldError
|
||||
from translator.toscalib.elements.interfaces import CONFIGURE
|
||||
from translator.toscalib.elements.interfaces import CONFIGURE_SHORTNAME
|
||||
from translator.toscalib.elements.interfaces import InterfacesDef
|
||||
from translator.toscalib.elements.interfaces import LIFECYCLE
|
||||
from translator.toscalib.elements.interfaces import LIFECYCLE_SHORTNAME
|
||||
from translator.toscalib.elements.relationshiptype import RelationshipType
|
||||
from translator.toscalib.entity_template import EntityTemplate
|
||||
from translator.toscalib.relationship_template import RelationshipTemplate
|
||||
from translator.toscalib.utils.gettextutils import _
|
||||
|
||||
log = logging.getLogger('tosca')
|
||||
|
||||
|
||||
class NodeTemplate(EntityTemplate):
|
||||
'''Node template from a Tosca profile.'''
|
||||
def __init__(self, name, node_templates, custom_def=None,
|
||||
available_rel_tpls=None, available_rel_types=None):
|
||||
super(NodeTemplate, self).__init__(name, node_templates[name],
|
||||
'node_type',
|
||||
custom_def)
|
||||
self.templates = node_templates
|
||||
self._validate_fields(node_templates[name])
|
||||
self.custom_def = custom_def
|
||||
self.related = {}
|
||||
self.relationship_tpl = []
|
||||
self.available_rel_tpls = available_rel_tpls
|
||||
self.available_rel_types = available_rel_types
|
||||
self._relationships = {}
|
||||
|
||||
@property
|
||||
def relationships(self):
|
||||
if not self._relationships:
|
||||
requires = self.requirements
|
||||
if requires:
|
||||
for r in requires:
|
||||
for r1, value in r.items():
|
||||
explicit = self._get_explicit_relationship(r, value)
|
||||
if explicit:
|
||||
for key, value in explicit.items():
|
||||
self._relationships[key] = value
|
||||
return self._relationships
|
||||
|
||||
def _get_explicit_relationship(self, req, value):
|
||||
"""Handle explicit relationship
|
||||
|
||||
For example,
|
||||
- req:
|
||||
node: DBMS
|
||||
relationship: tosca.relationships.HostedOn
|
||||
"""
|
||||
explicit_relation = {}
|
||||
node = value.get('node') if isinstance(value, dict) else value
|
||||
|
||||
if node:
|
||||
# TODO(spzala) implement look up once Glance meta data is available
|
||||
# to find a matching TOSCA node using the TOSCA types
|
||||
msg = _('Lookup by TOSCA types are not supported. '
|
||||
'Requirement for %s can not be full-filled.') % self.name
|
||||
if (node in list(self.type_definition.TOSCA_DEF.keys())
|
||||
or node in self.custom_def):
|
||||
raise NotImplementedError(msg)
|
||||
related_tpl = NodeTemplate(node, self.templates, self.custom_def)
|
||||
relationship = value.get('relationship') \
|
||||
if isinstance(value, dict) else None
|
||||
# check if it's type has relationship defined
|
||||
if not relationship:
|
||||
parent_reqs = self.type_definition.get_all_requirements()
|
||||
for key in req.keys():
|
||||
for req_dict in parent_reqs:
|
||||
if key in req_dict.keys():
|
||||
relationship = (req_dict.get(key).
|
||||
get('relationship'))
|
||||
break
|
||||
if relationship:
|
||||
found_relationship_tpl = False
|
||||
# apply available relationship templates if found
|
||||
for tpl in self.available_rel_tpls:
|
||||
if tpl.name == relationship:
|
||||
rtype = RelationshipType(tpl.type, None,
|
||||
self.custom_def)
|
||||
explicit_relation[rtype] = related_tpl
|
||||
self.relationship_tpl.append(tpl)
|
||||
found_relationship_tpl = True
|
||||
# create relationship template object.
|
||||
rel_prfx = self.type_definition.RELATIONSHIP_PREFIX
|
||||
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
|
||||
for rtype in self.type_definition.relationship.keys():
|
||||
if rtype.type == relationship:
|
||||
explicit_relation[rtype] = related_tpl
|
||||
related_tpl._add_relationship_template(req,
|
||||
rtype.type)
|
||||
elif self.available_rel_types:
|
||||
if relationship in self.available_rel_types.keys():
|
||||
rel_type_def = self.available_rel_types.\
|
||||
get(relationship)
|
||||
if 'derived_from' in rel_type_def:
|
||||
super_type = \
|
||||
rel_type_def.get('derived_from')
|
||||
if not super_type.startswith(rel_prfx):
|
||||
super_type = rel_prfx + super_type
|
||||
if rtype.type == super_type:
|
||||
explicit_relation[rtype] = related_tpl
|
||||
related_tpl.\
|
||||
_add_relationship_template(
|
||||
req, rtype.type)
|
||||
return explicit_relation
|
||||
|
||||
def _add_relationship_template(self, requirement, rtype):
|
||||
req = requirement.copy()
|
||||
req['type'] = rtype
|
||||
tpl = RelationshipTemplate(req, rtype, None)
|
||||
self.relationship_tpl.append(tpl)
|
||||
|
||||
def get_relationship_template(self):
|
||||
return self.relationship_tpl
|
||||
|
||||
def _add_next(self, nodetpl, relationship):
|
||||
self.related[nodetpl] = relationship
|
||||
|
||||
@property
|
||||
def related_nodes(self):
|
||||
if not self.related:
|
||||
for relation, node in self.type_definition.relationship.items():
|
||||
for tpl in self.templates:
|
||||
if tpl == node.type:
|
||||
self.related[NodeTemplate(tpl)] = relation
|
||||
return self.related.keys()
|
||||
|
||||
def validate(self, tosca_tpl=None):
|
||||
self._validate_capabilities()
|
||||
self._validate_requirements()
|
||||
self._validate_properties(self.entity_tpl, self.type_definition)
|
||||
self._validate_interfaces()
|
||||
for prop in self.get_properties_objects():
|
||||
prop.validate()
|
||||
|
||||
def _validate_requirements(self):
|
||||
type_requires = self.type_definition.get_all_requirements()
|
||||
allowed_reqs = ["template"]
|
||||
if type_requires:
|
||||
for treq in type_requires:
|
||||
for key, value in treq.items():
|
||||
allowed_reqs.append(key)
|
||||
if isinstance(value, dict):
|
||||
for key in value:
|
||||
allowed_reqs.append(key)
|
||||
|
||||
requires = self.type_definition.get_value(self.REQUIREMENTS,
|
||||
self.entity_tpl)
|
||||
if requires:
|
||||
if not isinstance(requires, list):
|
||||
raise TypeMismatchError(
|
||||
what='Requirements of template %s' % self.name,
|
||||
type='list')
|
||||
for req in requires:
|
||||
for r1, value in req.items():
|
||||
if isinstance(value, dict):
|
||||
self._validate_requirements_keys(value)
|
||||
allowed_reqs.append(r1)
|
||||
self._common_validate_field(req, allowed_reqs, 'Requirements')
|
||||
|
||||
def _validate_requirements_keys(self, requirement):
|
||||
for key in requirement.keys():
|
||||
if key not in self.REQUIREMENTS_SECTION:
|
||||
raise UnknownFieldError(
|
||||
what='Requirements of template %s' % self.name,
|
||||
field=key)
|
||||
|
||||
def _validate_interfaces(self):
|
||||
ifaces = self.type_definition.get_value(self.INTERFACES,
|
||||
self.entity_tpl)
|
||||
if ifaces:
|
||||
for i in ifaces:
|
||||
for name, value in ifaces.items():
|
||||
if name in (LIFECYCLE, LIFECYCLE_SHORTNAME):
|
||||
self._common_validate_field(
|
||||
value, InterfacesDef.
|
||||
interfaces_node_lifecycle_operations,
|
||||
'Interfaces')
|
||||
elif name in (CONFIGURE, CONFIGURE_SHORTNAME):
|
||||
self._common_validate_field(
|
||||
value, InterfacesDef.
|
||||
interfaces_relationship_confiure_operations,
|
||||
'Interfaces')
|
||||
else:
|
||||
raise UnknownFieldError(
|
||||
what='Interfaces of template %s' % self.name,
|
||||
field=name)
|
||||
|
||||
def _validate_fields(self, nodetemplate):
|
||||
for name in nodetemplate.keys():
|
||||
if name not in self.SECTIONS:
|
||||
raise UnknownFieldError(what='Node template %s'
|
||||
% self.name, field=name)
|
@ -1,110 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
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')
|
||||
|
||||
|
||||
class Input(object):
|
||||
|
||||
INPUTFIELD = (TYPE, DESCRIPTION, DEFAULT, CONSTRAINTS) = \
|
||||
('type', 'description', 'default', 'constraints')
|
||||
|
||||
def __init__(self, name, schema_dict):
|
||||
self.name = name
|
||||
self.schema = Schema(name, schema_dict)
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
return self.schema.type
|
||||
|
||||
@property
|
||||
def description(self):
|
||||
return self.schema.description
|
||||
|
||||
@property
|
||||
def default(self):
|
||||
return self.schema.default
|
||||
|
||||
@property
|
||||
def constraints(self):
|
||||
return self.schema.constraints
|
||||
|
||||
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:
|
||||
if name not in self.INPUTFIELD:
|
||||
raise UnknownFieldError(what='Input %s' % self.name,
|
||||
field=name)
|
||||
|
||||
def validate_type(self, input_type):
|
||||
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):
|
||||
|
||||
OUTPUTFIELD = (DESCRIPTION, VALUE) = ('description', 'value')
|
||||
|
||||
def __init__(self, name, attrs):
|
||||
self.name = name
|
||||
self.attrs = attrs
|
||||
|
||||
@property
|
||||
def description(self):
|
||||
return self.attrs[self.DESCRIPTION]
|
||||
|
||||
@property
|
||||
def value(self):
|
||||
return self.attrs[self.VALUE]
|
||||
|
||||
def validate(self):
|
||||
self._validate_field()
|
||||
|
||||
def _validate_field(self):
|
||||
if not isinstance(self.attrs, dict):
|
||||
raise MissingRequiredFieldError(what='Output %s' % self.name,
|
||||
required=self.VALUE)
|
||||
try:
|
||||
self.value
|
||||
except KeyError:
|
||||
raise MissingRequiredFieldError(what='Output %s' % self.name,
|
||||
required=self.VALUE)
|
||||
for name in self.attrs:
|
||||
if name not in self.OUTPUTFIELD:
|
||||
raise UnknownFieldError(what='Output %s' % self.name,
|
||||
field=name)
|
@ -1,76 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from translator.toscalib.dataentity import DataEntity
|
||||
from translator.toscalib.elements.constraints import Schema
|
||||
from translator.toscalib.functions import is_function
|
||||
|
||||
|
||||
class Property(object):
|
||||
'''TOSCA built-in Property type.'''
|
||||
|
||||
PROPERTY_KEYS = (
|
||||
TYPE, REQUIRED, DESCRIPTION, DEFAULT, CONSTRAINTS
|
||||
) = (
|
||||
'type', 'required', 'description', 'default', 'constraints'
|
||||
)
|
||||
|
||||
ENTRY_SCHEMA_KEYS = (
|
||||
ENTRYTYPE, ENTRYPROPERTIES
|
||||
) = (
|
||||
'type', 'properties'
|
||||
)
|
||||
|
||||
def __init__(self, property_name, value, schema_dict, custom_def=None):
|
||||
self.name = property_name
|
||||
self.value = value
|
||||
self.custom_def = custom_def
|
||||
self.schema = Schema(property_name, schema_dict)
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
return self.schema.type
|
||||
|
||||
@property
|
||||
def required(self):
|
||||
return self.schema.required
|
||||
|
||||
@property
|
||||
def description(self):
|
||||
return self.schema.description
|
||||
|
||||
@property
|
||||
def default(self):
|
||||
return self.schema.default
|
||||
|
||||
@property
|
||||
def constraints(self):
|
||||
return self.schema.constraints
|
||||
|
||||
@property
|
||||
def entry_schema(self):
|
||||
return self.schema.entry_schema
|
||||
|
||||
def validate(self):
|
||||
'''Validate if not a reference property.'''
|
||||
if not is_function(self.value):
|
||||
if self.type == Schema.STRING:
|
||||
self.value = str(self.value)
|
||||
self.value = DataEntity.validate_datatype(self.type, self.value,
|
||||
self.entry_schema,
|
||||
self.custom_def)
|
||||
self._validate_constraints()
|
||||
|
||||
def _validate_constraints(self):
|
||||
if self.constraints:
|
||||
for constraint in self.constraints:
|
||||
constraint.validate(self.value)
|
@ -1,68 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
import logging
|
||||
|
||||
from translator.toscalib.entity_template import EntityTemplate
|
||||
from translator.toscalib.properties import Property
|
||||
|
||||
SECTIONS = (DERIVED_FROM, PROPERTIES, REQUIREMENTS,
|
||||
INTERFACES, CAPABILITIES, TYPE) = \
|
||||
('derived_from', 'properties', 'requirements', 'interfaces',
|
||||
'capabilities', 'type')
|
||||
|
||||
log = logging.getLogger('tosca')
|
||||
|
||||
|
||||
class RelationshipTemplate(EntityTemplate):
|
||||
'''Relationship template.'''
|
||||
def __init__(self, relationship_template, name, custom_def=None):
|
||||
super(RelationshipTemplate, self).__init__(name,
|
||||
relationship_template,
|
||||
'relationship_type',
|
||||
custom_def)
|
||||
self.name = name.lower()
|
||||
|
||||
def get_properties_objects(self):
|
||||
'''Return properties objects for this template.'''
|
||||
if self._properties is None:
|
||||
self._properties = self._create_relationship_properties()
|
||||
return self._properties
|
||||
|
||||
def _create_relationship_properties(self):
|
||||
props = []
|
||||
properties = {}
|
||||
relationship = self.entity_tpl.get('relationship')
|
||||
if relationship:
|
||||
properties = self.type_definition.get_value(self.PROPERTIES,
|
||||
relationship) or {}
|
||||
if not properties:
|
||||
properties = self.entity_tpl.get(self.PROPERTIES) or {}
|
||||
|
||||
if properties:
|
||||
for name, value in properties.items():
|
||||
props_def = self.type_definition.get_properties_def()
|
||||
if props_def and name in props_def:
|
||||
if name in properties.keys():
|
||||
value = properties.get(name)
|
||||
prop = Property(name, value,
|
||||
props_def[name].schema, self.custom_def)
|
||||
props.append(prop)
|
||||
for p in self.type_definition.get_properties_def_objects():
|
||||
if p.default is not None and p.name not in properties.keys():
|
||||
prop = Property(p.name, p.default, p.schema, self.custom_def)
|
||||
props.append(prop)
|
||||
return props
|
||||
|
||||
def validate(self):
|
||||
self._validate_properties(self.entity_tpl, self.type_definition)
|
@ -21,7 +21,7 @@ import fixtures
|
||||
import testscenarios
|
||||
import testtools
|
||||
|
||||
from translator.toscalib.tosca_template import ToscaTemplate
|
||||
from toscaparser.tosca_template import ToscaTemplate
|
||||
|
||||
_TRUE_VALUES = ('True', 'true', '1', 'yes')
|
||||
|
||||
|
@ -13,11 +13,11 @@
|
||||
import datetime
|
||||
import yaml
|
||||
|
||||
from translator.toscalib.common import exception
|
||||
from translator.toscalib.elements.constraints import Constraint
|
||||
from translator.toscalib.elements.constraints import Schema
|
||||
from translator.toscalib.tests.base import TestCase
|
||||
from translator.toscalib.utils import yamlparser
|
||||
from toscaparser.common import exception
|
||||
from toscaparser.elements.constraints import Constraint
|
||||
from toscaparser.elements.constraints import Schema
|
||||
from toscaparser.tests.base import TestCase
|
||||
from toscaparser.utils import yamlparser
|
||||
|
||||
|
||||
class ConstraintTest(TestCase):
|
||||
|
@ -13,13 +13,13 @@
|
||||
import os
|
||||
|
||||
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
|
||||
from toscaparser.common import exception
|
||||
from toscaparser.dataentity import DataEntity
|
||||
from toscaparser.elements.datatype import DataType
|
||||
from toscaparser.parameters import Input
|
||||
from toscaparser.tests.base import TestCase
|
||||
from toscaparser.tosca_template import ToscaTemplate
|
||||
from toscaparser.utils import yamlparser
|
||||
|
||||
|
||||
class DataTypeTest(TestCase):
|
||||
|
@ -10,8 +10,8 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from translator.toscalib.common import exception
|
||||
from translator.toscalib.tests.base import TestCase
|
||||
from toscaparser.common import exception
|
||||
from toscaparser.tests.base import TestCase
|
||||
|
||||
|
||||
class ExceptionTest(TestCase):
|
||||
|
@ -12,10 +12,10 @@
|
||||
|
||||
import os
|
||||
import six
|
||||
from translator.toscalib.common import exception
|
||||
from translator.toscalib import functions
|
||||
from translator.toscalib.tests.base import TestCase
|
||||
from translator.toscalib.tosca_template import ToscaTemplate
|
||||
from toscaparser.common import exception
|
||||
from toscaparser import functions
|
||||
from toscaparser.tests.base import TestCase
|
||||
from toscaparser.tosca_template import ToscaTemplate
|
||||
|
||||
|
||||
class IntrinsicFunctionsTest(TestCase):
|
||||
|
@ -10,10 +10,10 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from translator.toscalib.common import exception
|
||||
from translator.toscalib.properties import Property
|
||||
from translator.toscalib.tests.base import TestCase
|
||||
from translator.toscalib.utils import yamlparser
|
||||
from toscaparser.common import exception
|
||||
from toscaparser.properties import Property
|
||||
from toscaparser.tests.base import TestCase
|
||||
from toscaparser.utils import yamlparser
|
||||
|
||||
|
||||
class PropertyTest(TestCase):
|
||||
|
@ -10,13 +10,13 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from translator.toscalib.common import exception
|
||||
from translator.toscalib.elements.scalarunit import ScalarUnit_Frequency
|
||||
from translator.toscalib.elements.scalarunit import ScalarUnit_Size
|
||||
from translator.toscalib.elements.scalarunit import ScalarUnit_Time
|
||||
from translator.toscalib.nodetemplate import NodeTemplate
|
||||
from translator.toscalib.tests.base import TestCase
|
||||
from translator.toscalib.utils import yamlparser
|
||||
from toscaparser.common import exception
|
||||
from toscaparser.elements.scalarunit import ScalarUnit_Frequency
|
||||
from toscaparser.elements.scalarunit import ScalarUnit_Size
|
||||
from toscaparser.elements.scalarunit import ScalarUnit_Time
|
||||
from toscaparser.nodetemplate import NodeTemplate
|
||||
from toscaparser.tests.base import TestCase
|
||||
from toscaparser.utils import yamlparser
|
||||
|
||||
|
||||
class ScalarUnitPositiveTest(TestCase):
|
||||
|
@ -12,11 +12,11 @@
|
||||
|
||||
import os
|
||||
|
||||
from translator.toscalib.tests.base import TestCase
|
||||
from translator.toscalib.topology_template import TopologyTemplate
|
||||
import translator.toscalib.utils.yamlparser
|
||||
from toscaparser.tests.base import TestCase
|
||||
from toscaparser.topology_template import TopologyTemplate
|
||||
import toscaparser.utils.yamlparser
|
||||
|
||||
YAML_LOADER = translator.toscalib.utils.yamlparser.load_yaml
|
||||
YAML_LOADER = toscaparser.utils.yamlparser.load_yaml
|
||||
|
||||
|
||||
class TopologyTemplateTest(TestCase):
|
||||
|
@ -10,11 +10,11 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from translator.toscalib.common import exception
|
||||
from translator.toscalib.elements.artifacttype import ArtifactTypeDef
|
||||
import translator.toscalib.elements.interfaces as ifaces
|
||||
from translator.toscalib.elements.nodetype import NodeType
|
||||
from translator.toscalib.tests.base import TestCase
|
||||
from toscaparser.common import exception
|
||||
from toscaparser.elements.artifacttype import ArtifactTypeDef
|
||||
import toscaparser.elements.interfaces as ifaces
|
||||
from toscaparser.elements.nodetype import NodeType
|
||||
from toscaparser.tests.base import TestCase
|
||||
|
||||
compute_type = NodeType('tosca.nodes.Compute')
|
||||
component_type = NodeType('tosca.nodes.SoftwareComponent')
|
||||
|
@ -13,15 +13,15 @@
|
||||
import os
|
||||
import six
|
||||
|
||||
from translator.toscalib.common import exception
|
||||
import translator.toscalib.elements.interfaces as ifaces
|
||||
from translator.toscalib.elements.nodetype import NodeType
|
||||
from translator.toscalib.functions import GetInput
|
||||
from translator.toscalib.functions import GetProperty
|
||||
from translator.toscalib.nodetemplate import NodeTemplate
|
||||
from translator.toscalib.tests.base import TestCase
|
||||
from translator.toscalib.tosca_template import ToscaTemplate
|
||||
import translator.toscalib.utils.yamlparser
|
||||
from toscaparser.common import exception
|
||||
import toscaparser.elements.interfaces as ifaces
|
||||
from toscaparser.elements.nodetype import NodeType
|
||||
from toscaparser.functions import GetInput
|
||||
from toscaparser.functions import GetProperty
|
||||
from toscaparser.nodetemplate import NodeTemplate
|
||||
from toscaparser.tests.base import TestCase
|
||||
from toscaparser.tosca_template import ToscaTemplate
|
||||
import toscaparser.utils.yamlparser
|
||||
|
||||
|
||||
class ToscaTemplateTest(TestCase):
|
||||
@ -324,7 +324,7 @@ class ToscaTemplateTest(TestCase):
|
||||
self._requirements_not_implemented(tpl_snippet_3, 'my_webserver2')
|
||||
|
||||
def _requirements_not_implemented(self, tpl_snippet, tpl_name):
|
||||
nodetemplates = (translator.toscalib.utils.yamlparser.
|
||||
nodetemplates = (toscaparser.utils.yamlparser.
|
||||
simple_parse(tpl_snippet))['node_templates']
|
||||
self.assertRaises(
|
||||
NotImplementedError,
|
||||
@ -355,9 +355,9 @@ class ToscaTemplateTest(TestCase):
|
||||
required: no
|
||||
'''
|
||||
expected_capabilities = ['test_cap']
|
||||
nodetemplates = (translator.toscalib.utils.yamlparser.
|
||||
nodetemplates = (toscaparser.utils.yamlparser.
|
||||
simple_parse(tpl_snippet))['node_templates']
|
||||
custom_def = (translator.toscalib.utils.yamlparser.
|
||||
custom_def = (toscaparser.utils.yamlparser.
|
||||
simple_parse(custom_def))
|
||||
name = list(nodetemplates.keys())[0]
|
||||
tpl = NodeTemplate(name, nodetemplates, custom_def)
|
||||
@ -373,7 +373,7 @@ class ToscaTemplateTest(TestCase):
|
||||
test_cap:
|
||||
type: tosca.capabilities.TestCapability
|
||||
'''
|
||||
custom_def = (translator.toscalib.utils.yamlparser.
|
||||
custom_def = (toscaparser.utils.yamlparser.
|
||||
simple_parse(custom_def))
|
||||
tpl = NodeTemplate(name, nodetemplates, custom_def)
|
||||
err = self.assertRaises(
|
||||
|
@ -13,14 +13,14 @@
|
||||
import os
|
||||
import six
|
||||
|
||||
from translator.toscalib.common import exception
|
||||
from translator.toscalib.nodetemplate import NodeTemplate
|
||||
from translator.toscalib.parameters import Input
|
||||
from translator.toscalib.parameters import Output
|
||||
from translator.toscalib.relationship_template import RelationshipTemplate
|
||||
from translator.toscalib.tests.base import TestCase
|
||||
from translator.toscalib.tosca_template import ToscaTemplate
|
||||
import translator.toscalib.utils.yamlparser
|
||||
from toscaparser.common import exception
|
||||
from toscaparser.nodetemplate import NodeTemplate
|
||||
from toscaparser.parameters import Input
|
||||
from toscaparser.parameters import Output
|
||||
from toscaparser.relationship_template import RelationshipTemplate
|
||||
from toscaparser.tests.base import TestCase
|
||||
from toscaparser.tosca_template import ToscaTemplate
|
||||
import toscaparser.utils.yamlparser
|
||||
|
||||
|
||||
class ToscaTemplateValidationTest(TestCase):
|
||||
@ -58,7 +58,7 @@ class ToscaTemplateValidationTest(TestCase):
|
||||
constraint:
|
||||
- valid_values: [ 1, 2, 4, 8 ]
|
||||
'''
|
||||
inputs = (translator.toscalib.utils.yamlparser.
|
||||
inputs = (toscaparser.utils.yamlparser.
|
||||
simple_parse(tpl_snippet)['inputs'])
|
||||
name, attrs = list(inputs.items())[0]
|
||||
input = Input(name, attrs)
|
||||
@ -77,7 +77,7 @@ class ToscaTemplateValidationTest(TestCase):
|
||||
description: IP address of server instance.
|
||||
values: { get_property: [server, private_address] }
|
||||
'''
|
||||
outputs = (translator.toscalib.utils.yamlparser.
|
||||
outputs = (toscaparser.utils.yamlparser.
|
||||
simple_parse(tpl_snippet)['outputs'])
|
||||
name, attrs = list(outputs.items())[0]
|
||||
output = Output(name, attrs)
|
||||
@ -95,7 +95,7 @@ class ToscaTemplateValidationTest(TestCase):
|
||||
descriptions: IP address of server instance.
|
||||
value: { get_property: [server, private_address] }
|
||||
'''
|
||||
outputs = (translator.toscalib.utils.yamlparser.
|
||||
outputs = (toscaparser.utils.yamlparser.
|
||||
simple_parse(tpl_snippet)['outputs'])
|
||||
name, attrs = list(outputs.items())[0]
|
||||
output = Output(name, attrs)
|
||||
@ -113,7 +113,7 @@ class ToscaTemplateValidationTest(TestCase):
|
||||
def_file = os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"data/custom_types/wordpress.yaml")
|
||||
custom_type = translator.toscalib.utils.yamlparser.load_yaml(def_file)
|
||||
custom_type = toscaparser.utils.yamlparser.load_yaml(def_file)
|
||||
node_types = custom_type['node_types']
|
||||
for name in node_types:
|
||||
defintion = node_types[name]
|
||||
@ -122,7 +122,7 @@ class ToscaTemplateValidationTest(TestCase):
|
||||
|
||||
def _single_node_template_content_test(self, tpl_snippet, expectederror,
|
||||
expectedmessage):
|
||||
nodetemplates = (translator.toscalib.utils.yamlparser.
|
||||
nodetemplates = (toscaparser.utils.yamlparser.
|
||||
simple_ordered_parse(tpl_snippet))['node_templates']
|
||||
name = list(nodetemplates.keys())[0]
|
||||
try:
|
||||
@ -648,7 +648,7 @@ class ToscaTemplateValidationTest(TestCase):
|
||||
|
||||
def _single_rel_template_content_test(self, tpl_snippet, expectederror,
|
||||
expectedmessage):
|
||||
rel_template = (translator.toscalib.utils.yamlparser.
|
||||
rel_template = (toscaparser.utils.yamlparser.
|
||||
simple_parse(tpl_snippet))['relationship_templates']
|
||||
name = list(rel_template.keys())[0]
|
||||
rel_template = RelationshipTemplate(rel_template[name], name)
|
||||
|
@ -10,10 +10,10 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from translator.toscalib.common.exception import (
|
||||
from toscaparser.common.exception import (
|
||||
InvalidTOSCAVersionPropertyException)
|
||||
from translator.toscalib.tests.base import TestCase
|
||||
from translator.toscalib.utils.validateutils import TOSCAVersionProperty
|
||||
from toscaparser.tests.base import TestCase
|
||||
from toscaparser.utils.validateutils import TOSCAVersionProperty
|
||||
|
||||
|
||||
class TOSCAVersionPropertyTest(TestCase):
|
||||
|
@ -1,213 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
import logging
|
||||
|
||||
from translator.toscalib.common import exception
|
||||
from translator.toscalib import functions
|
||||
from translator.toscalib.groups import NodeGroup
|
||||
from translator.toscalib.nodetemplate import NodeTemplate
|
||||
from translator.toscalib.parameters import Input
|
||||
from translator.toscalib.parameters import Output
|
||||
from translator.toscalib.relationship_template import RelationshipTemplate
|
||||
from translator.toscalib.tpl_relationship_graph import ToscaGraph
|
||||
|
||||
|
||||
# Topology template key names
|
||||
SECTIONS = (DESCRIPTION, INPUTS, NODE_TEMPLATES,
|
||||
RELATIONSHIP_TEMPLATES, OUTPUTS, GROUPS,
|
||||
SUBSTITUION_MAPPINGS) = \
|
||||
('description', 'inputs', 'node_templates',
|
||||
'relationship_templates', 'outputs', 'groups',
|
||||
'substitution_mappings')
|
||||
|
||||
log = logging.getLogger("tosca.model")
|
||||
|
||||
|
||||
class TopologyTemplate(object):
|
||||
|
||||
'''Load the template data.'''
|
||||
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()
|
||||
self.relationship_templates = self._relationship_templates()
|
||||
self.nodetemplates = self._nodetemplates()
|
||||
self.outputs = self._outputs()
|
||||
self.graph = ToscaGraph(self.nodetemplates)
|
||||
self.groups = self._groups()
|
||||
self._process_intrinsic_functions()
|
||||
|
||||
def _inputs(self):
|
||||
inputs = []
|
||||
for name, attrs in self._tpl_inputs().items():
|
||||
input = Input(name, attrs)
|
||||
if self.parsed_params and name in self.parsed_params:
|
||||
input.validate(self.parsed_params[name])
|
||||
inputs.append(input)
|
||||
return inputs
|
||||
|
||||
def _nodetemplates(self):
|
||||
nodetemplates = []
|
||||
tpls = self._tpl_nodetemplates()
|
||||
for name in tpls:
|
||||
tpl = NodeTemplate(name, tpls, self.custom_defs,
|
||||
self.relationship_templates,
|
||||
self.rel_types)
|
||||
tpl.validate(self)
|
||||
nodetemplates.append(tpl)
|
||||
return nodetemplates
|
||||
|
||||
def _relationship_templates(self):
|
||||
rel_templates = []
|
||||
tpls = self._tpl_relationship_templates()
|
||||
for name in tpls:
|
||||
tpl = RelationshipTemplate(tpls[name], name, self.custom_defs)
|
||||
rel_templates.append(tpl)
|
||||
return rel_templates
|
||||
|
||||
def _outputs(self):
|
||||
outputs = []
|
||||
for name, attrs in self._tpl_outputs().items():
|
||||
output = Output(name, attrs)
|
||||
output.validate()
|
||||
outputs.append(output)
|
||||
return outputs
|
||||
|
||||
def _substitution_mappings(self):
|
||||
pass
|
||||
|
||||
def _groups(self):
|
||||
groups = []
|
||||
for group_name, group_tpl in self._tpl_groups().items():
|
||||
member_names = group_tpl.get('members')
|
||||
if member_names and len(member_names) > 1:
|
||||
group = NodeGroup(group_name, group_tpl,
|
||||
self._get_group_memerbs(member_names))
|
||||
groups.append(group)
|
||||
else:
|
||||
raise ValueError
|
||||
return groups
|
||||
|
||||
def _get_group_memerbs(self, member_names):
|
||||
member_nodes = []
|
||||
for member in member_names:
|
||||
for node in self.nodetemplates:
|
||||
if node.name == member:
|
||||
member_nodes.append(node)
|
||||
return member_nodes
|
||||
|
||||
# topology template can act like node template
|
||||
# it is exposed by substitution_mappings.
|
||||
def nodetype(self):
|
||||
pass
|
||||
|
||||
def capabilities(self):
|
||||
pass
|
||||
|
||||
def requirements(self):
|
||||
pass
|
||||
|
||||
def _tpl_description(self):
|
||||
description = self.tpl.get(DESCRIPTION)
|
||||
if description:
|
||||
description = description.rstrip()
|
||||
return description
|
||||
|
||||
def _tpl_inputs(self):
|
||||
return self.tpl.get(INPUTS) or {}
|
||||
|
||||
def _tpl_nodetemplates(self):
|
||||
return self.tpl[NODE_TEMPLATES]
|
||||
|
||||
def _tpl_relationship_templates(self):
|
||||
return self.tpl.get(RELATIONSHIP_TEMPLATES) or {}
|
||||
|
||||
def _tpl_outputs(self):
|
||||
return self.tpl.get(OUTPUTS) or {}
|
||||
|
||||
def _tpl_substitution_mappings(self):
|
||||
return self.tpl.get(SUBSTITUION_MAPPINGS) or {}
|
||||
|
||||
def _tpl_groups(self):
|
||||
return self.tpl.get(GROUPS) or {}
|
||||
|
||||
def _validate_field(self):
|
||||
for name in self.tpl:
|
||||
if name not in SECTIONS:
|
||||
raise exception.UnknownFieldError(what='Template', field=name)
|
||||
|
||||
def _process_intrinsic_functions(self):
|
||||
"""Process intrinsic functions
|
||||
|
||||
Current implementation processes functions within node template
|
||||
properties, requirements, interfaces inputs and template outputs.
|
||||
"""
|
||||
for node_template in self.nodetemplates:
|
||||
for prop in node_template.get_properties_objects():
|
||||
prop.value = functions.get_function(self,
|
||||
node_template,
|
||||
prop.value)
|
||||
for interface in node_template.interfaces:
|
||||
if interface.inputs:
|
||||
for name, value in interface.inputs.items():
|
||||
interface.inputs[name] = functions.get_function(
|
||||
self,
|
||||
node_template,
|
||||
value)
|
||||
if node_template.requirements:
|
||||
for req in node_template.requirements:
|
||||
rel = req
|
||||
for req_name, req_item in req.items():
|
||||
if isinstance(req_item, dict):
|
||||
rel = req_item.get('relationship')
|
||||
break
|
||||
if rel and 'properties' in rel:
|
||||
for key, value in rel['properties'].items():
|
||||
rel['properties'][key] = functions.get_function(
|
||||
self,
|
||||
req,
|
||||
value)
|
||||
if node_template.get_capabilities_objects():
|
||||
for cap in node_template.get_capabilities_objects():
|
||||
if cap.get_properties_objects():
|
||||
for prop in cap.get_properties_objects():
|
||||
propvalue = functions.get_function(
|
||||
self,
|
||||
node_template,
|
||||
prop.value)
|
||||
if isinstance(propvalue, functions.GetInput):
|
||||
propvalue = propvalue.result()
|
||||
for p, v in cap._properties.items():
|
||||
if p == prop.name:
|
||||
cap._properties[p] = propvalue
|
||||
for rel, node in node_template.relationships.items():
|
||||
rel_tpls = node.relationship_tpl
|
||||
if rel_tpls:
|
||||
for rel_tpl in rel_tpls:
|
||||
for interface in rel_tpl.interfaces:
|
||||
if interface.inputs:
|
||||
for name, value in interface.inputs.items():
|
||||
interface.inputs[name] = \
|
||||
functions.get_function(self,
|
||||
rel_tpl,
|
||||
value)
|
||||
for output in self.outputs:
|
||||
func = functions.get_function(self, self.outputs, output.value)
|
||||
if isinstance(func, functions.GetAttribute):
|
||||
output.attrs[output.VALUE] = func
|
@ -1,150 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
from translator.toscalib.common.exception import InvalidTemplateVersion
|
||||
from translator.toscalib.common.exception import MissingRequiredFieldError
|
||||
from translator.toscalib.common.exception import UnknownFieldError
|
||||
from translator.toscalib.topology_template import TopologyTemplate
|
||||
from translator.toscalib.tpl_relationship_graph import ToscaGraph
|
||||
import translator.toscalib.utils.yamlparser
|
||||
|
||||
|
||||
# TOSCA template key names
|
||||
SECTIONS = (DEFINITION_VERSION, DEFAULT_NAMESPACE, TEMPLATE_NAME,
|
||||
TOPOLOGY_TEMPLATE, TEMPLATE_AUTHOR, TEMPLATE_VERSION,
|
||||
DESCRIPTION, IMPORTS, DSL_DEFINITIONS, NODE_TYPES,
|
||||
RELATIONSHIP_TYPES, RELATIONSHIP_TEMPLATES,
|
||||
CAPABILITY_TYPES, ARTIFACT_TYPES, DATATYPE_DEFINITIONS) = \
|
||||
('tosca_definitions_version', 'tosca_default_namespace',
|
||||
'template_name', 'topology_template', 'template_author',
|
||||
'template_version', 'description', 'imports', 'dsl_definitions',
|
||||
'node_types', 'relationship_types', 'relationship_templates',
|
||||
'capability_types', 'artifact_types', 'datatype_definitions')
|
||||
|
||||
log = logging.getLogger("tosca.model")
|
||||
|
||||
YAML_LOADER = translator.toscalib.utils.yamlparser.load_yaml
|
||||
|
||||
|
||||
class ToscaTemplate(object):
|
||||
|
||||
VALID_TEMPLATE_VERSIONS = ['tosca_simple_yaml_1_0']
|
||||
|
||||
'''Load the template data.'''
|
||||
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()
|
||||
self.description = self._tpl_description()
|
||||
self.topology_template = self._topology_template()
|
||||
self.inputs = self._inputs()
|
||||
self.relationship_templates = self._relationship_templates()
|
||||
self.nodetemplates = self._nodetemplates()
|
||||
self.outputs = self._outputs()
|
||||
self.graph = ToscaGraph(self.nodetemplates)
|
||||
|
||||
def _topology_template(self):
|
||||
return TopologyTemplate(self._tpl_topology_template(),
|
||||
self._get_all_custom_defs(),
|
||||
self.relationship_types,
|
||||
self.parsed_params)
|
||||
|
||||
def _inputs(self):
|
||||
return self.topology_template.inputs
|
||||
|
||||
def _nodetemplates(self):
|
||||
return self.topology_template.nodetemplates
|
||||
|
||||
def _relationship_templates(self):
|
||||
return self.topology_template.relationship_templates
|
||||
|
||||
def _outputs(self):
|
||||
return self.topology_template.outputs
|
||||
|
||||
def _tpl_version(self):
|
||||
return self.tpl[DEFINITION_VERSION]
|
||||
|
||||
def _tpl_description(self):
|
||||
return self.tpl[DESCRIPTION].rstrip()
|
||||
|
||||
def _tpl_imports(self):
|
||||
if IMPORTS in self.tpl:
|
||||
return self.tpl[IMPORTS]
|
||||
|
||||
def _tpl_relationship_types(self):
|
||||
return self._get_custom_types(RELATIONSHIP_TYPES)
|
||||
|
||||
def _tpl_relationship_templates(self):
|
||||
topology_template = self._tpl_topology_template()
|
||||
if RELATIONSHIP_TEMPLATES in topology_template.keys():
|
||||
return topology_template[RELATIONSHIP_TEMPLATES]
|
||||
else:
|
||||
return None
|
||||
|
||||
def _tpl_topology_template(self):
|
||||
return self.tpl.get(TOPOLOGY_TEMPLATE)
|
||||
|
||||
def _get_all_custom_defs(self):
|
||||
types = [NODE_TYPES, CAPABILITY_TYPES, RELATIONSHIP_TYPES,
|
||||
DATATYPE_DEFINITIONS]
|
||||
custom_defs = {}
|
||||
for type in types:
|
||||
custom_def = self._get_custom_types(type)
|
||||
if custom_def:
|
||||
custom_defs.update(custom_def)
|
||||
return custom_defs
|
||||
|
||||
def _get_custom_types(self, type_definition):
|
||||
# Handle custom types defined in outer template file
|
||||
custom_defs = {}
|
||||
imports = self._tpl_imports()
|
||||
if imports:
|
||||
for definition in imports:
|
||||
if os.path.isabs(definition):
|
||||
def_file = definition
|
||||
else:
|
||||
tpl_dir = os.path.dirname(os.path.abspath(self.path))
|
||||
def_file = os.path.join(tpl_dir, definition)
|
||||
custom_type = YAML_LOADER(def_file)
|
||||
outer_custom_types = custom_type.get(type_definition)
|
||||
if outer_custom_types:
|
||||
custom_defs.update(outer_custom_types)
|
||||
|
||||
# Handle custom types defined in current template file
|
||||
inner_custom_types = self.tpl.get(type_definition) or {}
|
||||
if inner_custom_types:
|
||||
custom_defs.update(inner_custom_types)
|
||||
return custom_defs
|
||||
|
||||
def _validate_field(self):
|
||||
try:
|
||||
version = self._tpl_version()
|
||||
self._validate_version(version)
|
||||
except KeyError:
|
||||
raise MissingRequiredFieldError(what='Template',
|
||||
required=DEFINITION_VERSION)
|
||||
for name in self.tpl:
|
||||
if name not in SECTIONS:
|
||||
raise UnknownFieldError(what='Template', field=name)
|
||||
|
||||
def _validate_version(self, version):
|
||||
if version not in self.VALID_TEMPLATE_VERSIONS:
|
||||
raise InvalidTemplateVersion(
|
||||
what=version,
|
||||
valid_versions=', '. join(self.VALID_TEMPLATE_VERSIONS))
|
@ -1,46 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
class ToscaGraph(object):
|
||||
'''Graph of Tosca Node Templates.'''
|
||||
def __init__(self, nodetemplates):
|
||||
self.nodetemplates = nodetemplates
|
||||
self.vertices = {}
|
||||
self._create()
|
||||
|
||||
def _create_vertex(self, node):
|
||||
if node not in self.vertices:
|
||||
self.vertices[node.name] = node
|
||||
|
||||
def _create_edge(self, node1, node2, relationship):
|
||||
if node1 not in self.vertices:
|
||||
self._create_vertex(node1)
|
||||
self.vertices[node1.name]._add_next(node2,
|
||||
relationship)
|
||||
|
||||
def vertex(self, node):
|
||||
if node in self.vertices:
|
||||
return self.vertices[node]
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self.vertices.values())
|
||||
|
||||
def _create(self):
|
||||
for node in self.nodetemplates:
|
||||
relation = node.relationships
|
||||
if relation:
|
||||
for rel, nodetpls in relation.items():
|
||||
for tpl in self.nodetemplates:
|
||||
if tpl.name == nodetpls.name:
|
||||
self._create_edge(node, tpl, rel)
|
||||
self._create_vertex(node)
|
@ -1,22 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import gettext
|
||||
import os
|
||||
|
||||
_localedir = os.environ.get('heat-translator'.upper() + '_LOCALEDIR')
|
||||
_t = gettext.translation('heat-translator', localedir=_localedir,
|
||||
fallback=True)
|
||||
|
||||
|
||||
def _(msg):
|
||||
return _t.gettext(msg)
|
@ -1,154 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import collections
|
||||
import dateutil.parser
|
||||
import logging
|
||||
import numbers
|
||||
import re
|
||||
import six
|
||||
|
||||
from translator.toscalib.common.exception import (
|
||||
InvalidTOSCAVersionPropertyException)
|
||||
from translator.toscalib.utils.gettextutils import _
|
||||
log = logging.getLogger('tosca')
|
||||
|
||||
|
||||
def str_to_num(value):
|
||||
'''Convert a string representation of a number into a numeric type.'''
|
||||
if isinstance(value, numbers.Number):
|
||||
return value
|
||||
try:
|
||||
return int(value)
|
||||
except ValueError:
|
||||
return float(value)
|
||||
|
||||
|
||||
def validate_number(value):
|
||||
return str_to_num(value)
|
||||
|
||||
|
||||
def validate_integer(value):
|
||||
if not isinstance(value, int):
|
||||
try:
|
||||
value = int(value)
|
||||
except Exception:
|
||||
raise ValueError(_('"%s" is not an integer') % value)
|
||||
return value
|
||||
|
||||
|
||||
def validate_float(value):
|
||||
if not isinstance(value, float):
|
||||
raise ValueError(_('"%s" is not a float') % value)
|
||||
return validate_number(value)
|
||||
|
||||
|
||||
def validate_string(value):
|
||||
if not isinstance(value, six.string_types):
|
||||
raise ValueError(_('"%s" is not a string') % value)
|
||||
return value
|
||||
|
||||
|
||||
def validate_list(value):
|
||||
if not isinstance(value, list):
|
||||
raise ValueError(_('"%s" is not a list') % value)
|
||||
return value
|
||||
|
||||
|
||||
def validate_map(value):
|
||||
if not isinstance(value, collections.Mapping):
|
||||
raise ValueError(_('"%s" is not a map') % value)
|
||||
return value
|
||||
|
||||
|
||||
def validate_boolean(value):
|
||||
if isinstance(value, bool):
|
||||
return value
|
||||
|
||||
if isinstance(value, str):
|
||||
normalised = value.lower()
|
||||
if normalised in ['true', 'false']:
|
||||
return normalised == 'true'
|
||||
raise ValueError(_('"%s" is not a boolean') % value)
|
||||
|
||||
|
||||
def validate_timestamp(value):
|
||||
return dateutil.parser.parse(value)
|
||||
|
||||
|
||||
class TOSCAVersionProperty(object):
|
||||
|
||||
VERSION_RE = re.compile('^(?P<major_version>([0-9][0-9]*))'
|
||||
'(\.(?P<minor_version>([0-9][0-9]*)))?'
|
||||
'(\.(?P<fix_version>([0-9][0-9]*)))?'
|
||||
'(\.(?P<qualifier>([0-9A-Za-z]+)))?'
|
||||
'(\-(?P<build_version>[0-9])*)?$')
|
||||
|
||||
def __init__(self, version):
|
||||
self.version = str(version)
|
||||
match = self.VERSION_RE.match(self.version)
|
||||
if not match:
|
||||
raise InvalidTOSCAVersionPropertyException(what=(self.version))
|
||||
ver = match.groupdict()
|
||||
if self.version in ['0', '0.0', '0.0.0']:
|
||||
log.warning(_('Version assumed as not provided'))
|
||||
self.version = None
|
||||
self.minor_version = ver['minor_version']
|
||||
self.major_version = ver['major_version']
|
||||
self.fix_version = ver['fix_version']
|
||||
self.qualifier = self._validate_qualifier(ver['qualifier'])
|
||||
self.build_version = self._validate_build(ver['build_version'])
|
||||
self._validate_major_version(self.major_version)
|
||||
|
||||
def _validate_major_version(self, value):
|
||||
"""Validate major version
|
||||
|
||||
Checks if only major version is provided and assumes
|
||||
minor version as 0.
|
||||
Eg: If version = 18, then it returns version = '18.0'
|
||||
"""
|
||||
|
||||
if self.minor_version is None and self.build_version is None and \
|
||||
value != '0':
|
||||
log.warning(_('Minor version assumed "0"'))
|
||||
self.version = '.'.join([value, '0'])
|
||||
return value
|
||||
|
||||
def _validate_qualifier(self, value):
|
||||
"""Validate qualifier
|
||||
|
||||
TOSCA version is invalid if a qualifier is present without the
|
||||
fix version or with all of major, minor and fix version 0s.
|
||||
|
||||
For example, the following versions are invalid
|
||||
18.0.abc
|
||||
0.0.0.abc
|
||||
"""
|
||||
if (self.fix_version is None and value) or \
|
||||
(self.minor_version == self.major_version ==
|
||||
self.fix_version == '0' and value):
|
||||
raise InvalidTOSCAVersionPropertyException(what=(self.version))
|
||||
return value
|
||||
|
||||
def _validate_build(self, value):
|
||||
"""Validate build version
|
||||
|
||||
TOSCA version is invalid if build version is present without the
|
||||
qualifier.
|
||||
Eg: version = 18.0.0-1 is invalid.
|
||||
"""
|
||||
if not self.qualifier and value:
|
||||
raise InvalidTOSCAVersionPropertyException(what=(self.version))
|
||||
return value
|
||||
|
||||
def get_version(self):
|
||||
return self.version
|
@ -1,61 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import codecs
|
||||
from collections import OrderedDict
|
||||
import yaml
|
||||
|
||||
if hasattr(yaml, 'CSafeLoader'):
|
||||
yaml_loader = yaml.CSafeLoader
|
||||
else:
|
||||
yaml_loader = yaml.SafeLoader
|
||||
|
||||
|
||||
def load_yaml(path):
|
||||
with codecs.open(path, encoding='utf-8', errors='strict') as f:
|
||||
return yaml.load(f.read(), Loader=yaml_loader)
|
||||
|
||||
|
||||
def simple_parse(tmpl_str):
|
||||
try:
|
||||
tpl = yaml.load(tmpl_str, Loader=yaml_loader)
|
||||
except yaml.YAMLError as yea:
|
||||
raise ValueError(yea)
|
||||
else:
|
||||
if tpl is None:
|
||||
tpl = {}
|
||||
return tpl
|
||||
|
||||
|
||||
def ordered_load(stream, Loader=yaml.Loader, object_pairs_hook=OrderedDict):
|
||||
class OrderedLoader(Loader):
|
||||
pass
|
||||
|
||||
def construct_mapping(loader, node):
|
||||
loader.flatten_mapping(node)
|
||||
return object_pairs_hook(loader.construct_pairs(node))
|
||||
|
||||
OrderedLoader.add_constructor(
|
||||
yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG,
|
||||
construct_mapping)
|
||||
return yaml.load(stream, OrderedLoader)
|
||||
|
||||
|
||||
def simple_ordered_parse(tmpl_str):
|
||||
try:
|
||||
tpl = ordered_load(tmpl_str)
|
||||
except yaml.YAMLError as yea:
|
||||
raise ValueError(yea)
|
||||
else:
|
||||
if tpl is None:
|
||||
tpl = {}
|
||||
return tpl
|
Loading…
Reference in New Issue
Block a user