diff options
Diffstat (limited to 'tosca2heat/tosca-parser/toscaparser/elements')
11 files changed, 153 insertions, 21 deletions
diff --git a/tosca2heat/tosca-parser/toscaparser/elements/TOSCA_definition_1_0.yaml b/tosca2heat/tosca-parser/toscaparser/elements/TOSCA_definition_1_0.yaml index c1c1cd4..ede5fa5 100644 --- a/tosca2heat/tosca-parser/toscaparser/elements/TOSCA_definition_1_0.yaml +++ b/tosca2heat/tosca-parser/toscaparser/elements/TOSCA_definition_1_0.yaml @@ -390,7 +390,7 @@ tosca.nodes.Container.Application: requirements: - host: capability: tosca.capabilities.Container - node: tosca.nodes.Container + node: tosca.nodes.Container.Runtime relationship: tosca.relationships.HostedOn tosca.nodes.Container.Runtime: @@ -544,7 +544,7 @@ tosca.capabilities.Endpoint: tosca.capabilities.Endpoint.Admin: derived_from: tosca.capabilities.Endpoint properties: - secure: + secure: type: boolean default: true constraints: @@ -815,14 +815,19 @@ tosca.datatypes.Credential: properties: protocol: type: string + required: false token_type: type: string + default: password + required: true token: type: string + required: true keys: type: map entry_schema: type: string + required: false user: type: string required: false diff --git a/tosca2heat/tosca-parser/toscaparser/elements/artifacttype.py b/tosca2heat/tosca-parser/toscaparser/elements/artifacttype.py index 3bfd7d0..887e99a 100644 --- a/tosca2heat/tosca-parser/toscaparser/elements/artifacttype.py +++ b/tosca2heat/tosca-parser/toscaparser/elements/artifacttype.py @@ -20,6 +20,7 @@ class ArtifactTypeDef(StatefulEntityType): super(ArtifactTypeDef, self).__init__(atype, self.ARTIFACT_PREFIX, custom_def) self.type = atype + self.custom_def = custom_def self.properties = None if self.PROPERTIES in self.defs: self.properties = self.defs[self.PROPERTIES] @@ -27,17 +28,24 @@ class ArtifactTypeDef(StatefulEntityType): def _get_parent_artifacts(self): artifacts = {} - parent_artif = self.parent_type + parent_artif = self.parent_type.type if self.parent_type else None if parent_artif: while parent_artif != 'tosca.artifacts.Root': + # only support normative artifact, shall be modified future 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) + '''Return a artifact entity from which this entity is derived.''' + if not hasattr(self, 'defs'): + return None + partifact_entity = self.derived_from(self.defs) + if partifact_entity: + return ArtifactTypeDef(partifact_entity, self.custom_def) + else: + return None def get_artifact(self, name): '''Return the definition of an artifact field by name.''' diff --git a/tosca2heat/tosca-parser/toscaparser/elements/capabilitytype.py b/tosca2heat/tosca-parser/toscaparser/elements/capabilitytype.py index 0413443..865690e 100644 --- a/tosca2heat/tosca-parser/toscaparser/elements/capabilitytype.py +++ b/tosca2heat/tosca-parser/toscaparser/elements/capabilitytype.py @@ -16,6 +16,7 @@ from toscaparser.elements.statefulentitytype import StatefulEntityType class CapabilityTypeDef(StatefulEntityType): '''TOSCA built-in capabilities type.''' + TOSCA_TYPEURI_CAPABILITY_ROOT = 'tosca.capabilities.Root' def __init__(self, name, ctype, ntype, custom_def=None): self.name = name @@ -23,6 +24,7 @@ class CapabilityTypeDef(StatefulEntityType): custom_def) self.nodetype = ntype self.properties = None + self.custom_def = custom_def if self.PROPERTIES in self.defs: self.properties = self.defs[self.PROPERTIES] self.parent_capabilities = self._get_parent_capabilities(custom_def) @@ -61,7 +63,8 @@ class CapabilityTypeDef(StatefulEntityType): capabilities = {} parent_cap = self.parent_type if parent_cap: - while parent_cap != 'tosca.capabilities.Root': + parent_cap = parent_cap.type + while parent_cap != self.TOSCA_TYPEURI_CAPABILITY_ROOT: if parent_cap in self.TOSCA_DEF.keys(): capabilities[parent_cap] = self.TOSCA_DEF[parent_cap] elif custom_def and parent_cap in custom_def.keys(): @@ -72,4 +75,9 @@ class CapabilityTypeDef(StatefulEntityType): @property def parent_type(self): '''Return a capability this capability is derived from.''' - return self.derived_from(self.defs) + if not hasattr(self, 'defs'): + return None + pnode = self.derived_from(self.defs) + if pnode: + return CapabilityTypeDef(self.name, pnode, + self.nodetype, self.custom_def) diff --git a/tosca2heat/tosca-parser/toscaparser/elements/constraints.py b/tosca2heat/tosca-parser/toscaparser/elements/constraints.py index 9883da3..8594b85 100644 --- a/tosca2heat/tosca-parser/toscaparser/elements/constraints.py +++ b/tosca2heat/tosca-parser/toscaparser/elements/constraints.py @@ -18,6 +18,7 @@ import toscaparser from toscaparser.common.exception import ExceptionCollector from toscaparser.common.exception import InvalidSchemaError from toscaparser.common.exception import ValidationError +from toscaparser.elements.portspectype import PortSpec from toscaparser.elements import scalarunit from toscaparser.utils.gettextutils import _ @@ -36,12 +37,12 @@ class Schema(collections.Mapping): INTEGER, STRING, BOOLEAN, FLOAT, RANGE, NUMBER, TIMESTAMP, LIST, MAP, SCALAR_UNIT_SIZE, SCALAR_UNIT_FREQUENCY, SCALAR_UNIT_TIME, - PORTDEF, VERSION + VERSION, PORTDEF, PORTSPEC ) = ( 'integer', 'string', 'boolean', 'float', 'range', 'number', 'timestamp', 'list', 'map', 'scalar-unit.size', 'scalar-unit.frequency', 'scalar-unit.time', - 'PortDef', 'version' + 'version', 'PortDef', PortSpec.SHORTNAME ) SCALAR_UNIT_SIZE_DEFAULT = 'B' @@ -127,8 +128,6 @@ class Constraint(object): 'less_or_equal', 'in_range', 'valid_values', 'length', 'min_length', 'max_length', 'pattern') - UNBOUNDED = 'UNBOUNDED' - def __new__(cls, property_name, property_type, constraint): if cls is not Constraint: return super(Constraint, cls).__new__(cls) @@ -370,6 +369,7 @@ class InRange(Constraint): Constrains a property or parameter to a value in range of (inclusive) the two values declared. """ + UNBOUNDED = 'UNBOUNDED' constraint_key = Constraint.IN_RANGE diff --git a/tosca2heat/tosca-parser/toscaparser/elements/datatype.py b/tosca2heat/tosca-parser/toscaparser/elements/datatype.py index 7e05a69..93d1b3a 100644 --- a/tosca2heat/tosca-parser/toscaparser/elements/datatype.py +++ b/tosca2heat/tosca-parser/toscaparser/elements/datatype.py @@ -18,7 +18,8 @@ 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, + super(DataType, self).__init__(datatypename, + self.DATATYPE_NETWORK_PREFIX, custom_def) self.custom_def = custom_def diff --git a/tosca2heat/tosca-parser/toscaparser/elements/entity_type.py b/tosca2heat/tosca-parser/toscaparser/elements/entity_type.py index 5d620a5..9b9787b 100644 --- a/tosca2heat/tosca-parser/toscaparser/elements/entity_type.py +++ b/tosca2heat/tosca-parser/toscaparser/elements/entity_type.py @@ -56,7 +56,8 @@ class EntityType(object): GROUP_PREFIX = 'tosca.groups.' # currently the data types are defined only for network # but may have changes in the future. - DATATYPE_PREFIX = 'tosca.datatypes.network.' + DATATYPE_PREFIX = 'tosca.datatypes.' + DATATYPE_NETWORK_PREFIX = DATATYPE_PREFIX + 'network.' TOSCA = 'tosca' def derived_from(self, defs): @@ -106,8 +107,14 @@ class EntityType(object): value[k] = v if isinstance(value, list): for p_value in parent_value: - if p_value not in value: - value.append(p_value) + if isinstance(p_value, dict): + if list(p_value.keys())[0] not in [ + list(item.keys())[0] for item in + value]: + value.append(p_value) + else: + if p_value not in value: + value.append(p_value) else: value = copy.copy(parent_value) p = p.parent_type diff --git a/tosca2heat/tosca-parser/toscaparser/elements/grouptype.py b/tosca2heat/tosca-parser/toscaparser/elements/grouptype.py index ec5571c..5587f05 100644 --- a/tosca2heat/tosca-parser/toscaparser/elements/grouptype.py +++ b/tosca2heat/tosca-parser/toscaparser/elements/grouptype.py @@ -52,6 +52,17 @@ class GroupType(StatefulEntityType): self._validate_metadata(self.meta_data) @property + def parent_type(self): + '''Return a group statefulentity of this entity is derived from.''' + if not hasattr(self, 'defs'): + return None + pgroup_entity = self.derived_from(self.defs) + if pgroup_entity: + return GroupType(pgroup_entity, self.custom_def) + else: + return None + + @property def description(self): return self.group_description diff --git a/tosca2heat/tosca-parser/toscaparser/elements/policytype.py b/tosca2heat/tosca-parser/toscaparser/elements/policytype.py index 04cbab5..8fbb0f0 100644 --- a/tosca2heat/tosca-parser/toscaparser/elements/policytype.py +++ b/tosca2heat/tosca-parser/toscaparser/elements/policytype.py @@ -28,6 +28,7 @@ class PolicyType(StatefulEntityType): super(PolicyType, self).__init__(ptype, self.POLICY_PREFIX, custom_def) self.type = ptype + self.custom_def = custom_def self._validate_keys() self.meta_data = None @@ -55,7 +56,7 @@ class PolicyType(StatefulEntityType): def _get_parent_policies(self): policies = {} - parent_policy = self.parent_type + parent_policy = self.parent_type.type if self.parent_type else None if parent_policy: while parent_policy != 'tosca.policies.Root': policies[parent_policy] = self.TOSCA_DEF[parent_policy] @@ -64,8 +65,12 @@ class PolicyType(StatefulEntityType): @property def parent_type(self): - '''Return a policy this policy is derived from.''' - return self.derived_from(self.defs) + '''Return a policy statefulentity of this node is derived from.''' + if not hasattr(self, 'defs'): + return None + ppolicy_entity = self.derived_from(self.defs) + if ppolicy_entity: + return PolicyType(ppolicy_entity, self.custom_def) def get_policy(self, name): '''Return the definition of a policy field by name.''' diff --git a/tosca2heat/tosca-parser/toscaparser/elements/portspectype.py b/tosca2heat/tosca-parser/toscaparser/elements/portspectype.py new file mode 100644 index 0000000..d32e97e --- /dev/null +++ b/tosca2heat/tosca-parser/toscaparser/elements/portspectype.py @@ -0,0 +1,86 @@ +# 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 toscaparser.common.exception import ExceptionCollector +from toscaparser.common.exception import InvalidTypeAdditionalRequirementsError +from toscaparser.utils.gettextutils import _ +import toscaparser.utils.validateutils as validateutils + +log = logging.getLogger('tosca') + + +class PortSpec(object): + '''Parent class for tosca.datatypes.network.PortSpec type.''' + + SHORTNAME = 'PortSpec' + TYPE_URI = 'tosca.datatypes.network.' + SHORTNAME + + PROPERTY_NAMES = ( + PROTOCOL, SOURCE, SOURCE_RANGE, + TARGET, TARGET_RANGE + ) = ( + 'protocol', 'source', 'source_range', + 'target', 'target_range' + ) + + # TODO(TBD) May want to make this a subclass of DataType + # and change init method to set PortSpec's properties + def __init__(self): + pass + + # The following additional requirements MUST be tested: + # 1) A valid PortSpec MUST have at least one of the following properties: + # target, target_range, source or source_range. + # 2) A valid PortSpec MUST have a value for the source property that + # is within the numeric range specified by the property source_range + # when source_range is specified. + # 3) A valid PortSpec MUST have a value for the target property that is + # within the numeric range specified by the property target_range + # when target_range is specified. + @staticmethod + def validate_additional_req(properties, prop_name, custom_def=None, ): + try: + source = properties.get(PortSpec.SOURCE) + source_range = properties.get(PortSpec.SOURCE_RANGE) + target = properties.get(PortSpec.TARGET) + target_range = properties.get(PortSpec.TARGET_RANGE) + + # verify one of the specified values is set + if source is None and source_range is None and \ + target is None and target_range is None: + ExceptionCollector.appendException( + InvalidTypeAdditionalRequirementsError( + type=PortSpec.TYPE_URI)) + # Validate source value is in specified range + if source and source_range: + validateutils.validate_value_in_range(source, source_range, + PortSpec.SOURCE) + else: + from toscaparser.dataentity import DataEntity + portdef = DataEntity('PortDef', source, None, PortSpec.SOURCE) + portdef.validate() + # Validate target value is in specified range + if target and target_range: + validateutils.validate_value_in_range(target, target_range, + PortSpec.TARGET) + else: + from toscaparser.dataentity import DataEntity + portdef = DataEntity('PortDef', source, None, PortSpec.TARGET) + portdef.validate() + except Exception: + msg = _('"%(value)s" do not meet requirements ' + 'for type "%(type)s".') \ + % {'value': properties, 'type': PortSpec.SHORTNAME} + ExceptionCollector.appendException( + ValueError(msg)) diff --git a/tosca2heat/tosca-parser/toscaparser/elements/relationshiptype.py b/tosca2heat/tosca-parser/toscaparser/elements/relationshiptype.py index 9462d38..25440ca 100644 --- a/tosca2heat/tosca-parser/toscaparser/elements/relationshiptype.py +++ b/tosca2heat/tosca-parser/toscaparser/elements/relationshiptype.py @@ -26,7 +26,7 @@ class RelationshipType(StatefulEntityType): '''Return a relationship this reletionship is derived from.''' prel = self.derived_from(self.defs) if prel: - return RelationshipType(prel) + return RelationshipType(prel, self.custom_def) @property def valid_target_types(self): diff --git a/tosca2heat/tosca-parser/toscaparser/elements/tosca_type_validation.py b/tosca2heat/tosca-parser/toscaparser/elements/tosca_type_validation.py index 16764bc..82b0b46 100644 --- a/tosca2heat/tosca-parser/toscaparser/elements/tosca_type_validation.py +++ b/tosca2heat/tosca-parser/toscaparser/elements/tosca_type_validation.py @@ -22,12 +22,13 @@ class TypeValidation(object): DSL_DEFINITIONS, NODE_TYPES, REPOSITORIES, DATA_TYPES, ARTIFACT_TYPES, GROUP_TYPES, RELATIONSHIP_TYPES, CAPABILITY_TYPES, - INTERFACE_TYPES, POLICY_TYPES) = \ + INTERFACE_TYPES, POLICY_TYPES, + TOPOLOGY_TEMPLATE) = \ ('tosca_definitions_version', 'description', 'imports', 'dsl_definitions', 'node_types', 'repositories', 'data_types', 'artifact_types', 'group_types', 'relationship_types', 'capability_types', - 'interface_types', 'policy_types') + 'interface_types', 'policy_types', 'topology_template') VALID_TEMPLATE_VERSIONS = ['tosca_simple_yaml_1_0'] exttools = ExtTools() VALID_TEMPLATE_VERSIONS.extend(exttools.get_versions()) |