Remove tosca node template inheritance from node type.
Tosca node templates and node type should be separate. This will also make tosca properties and properties definition cleaner. Change-Id: I67cb60af1849fb02d0c982f82c8e4858aa21f2fc Implements: blueprint tosca-nodetemplate-inheritance
This commit is contained in:
parent
6369ed3166
commit
78ded47386
@ -14,7 +14,7 @@
|
||||
# under the License.
|
||||
|
||||
from translator.toscalib.elements.entitytype import EntityType
|
||||
from translator.toscalib.elements.properties import PropertyDef
|
||||
from translator.toscalib.elements.property_definition import PropertyDef
|
||||
|
||||
|
||||
class CapabilityTypeDef(EntityType):
|
||||
@ -41,11 +41,11 @@ class CapabilityTypeDef(EntityType):
|
||||
for k, v in schema.items():
|
||||
if k == 'default':
|
||||
prop_val = v
|
||||
properties.append(PropertyDef(prop, self.type,
|
||||
schema, prop_val))
|
||||
properties.append(PropertyDef(prop,
|
||||
prop_val, schema))
|
||||
if self.properties:
|
||||
for prop, value in self.properties.items():
|
||||
properties.append(PropertyDef(prop, self.type, None, value))
|
||||
properties.append(PropertyDef(prop, value, None))
|
||||
return properties
|
||||
|
||||
@property
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
from translator.toscalib.elements.capabilitytype import CapabilityTypeDef
|
||||
from translator.toscalib.elements.interfaces import InterfacesDef
|
||||
from translator.toscalib.elements.properties import PropertyDef
|
||||
from translator.toscalib.elements.property_definition import PropertyDef
|
||||
from translator.toscalib.elements.relationshiptype import RelationshipType
|
||||
from translator.toscalib.elements.statefulentitytype import StatefulEntityType
|
||||
from translator.toscalib.utils.gettextutils import _
|
||||
@ -50,10 +50,10 @@ class NodeType(StatefulEntityType):
|
||||
def properties_def(self):
|
||||
'''Return a list of property definition objects.'''
|
||||
properties = []
|
||||
props = self._get_value(PROPERTIES)
|
||||
props = self.get_value(PROPERTIES)
|
||||
if props:
|
||||
for prop, schema in props.items():
|
||||
properties.append(PropertyDef(prop, self.type, schema))
|
||||
properties.append(PropertyDef(prop, None, schema))
|
||||
return properties
|
||||
|
||||
@property
|
||||
@ -69,11 +69,11 @@ class NodeType(StatefulEntityType):
|
||||
requires = self.requirements
|
||||
parent_node = self.parent_type
|
||||
if requires is None:
|
||||
requires = self._get_value(REQUIREMENTS, None, True)
|
||||
requires = self.get_value(REQUIREMENTS, None, True)
|
||||
parent_node = parent_node.parent_type
|
||||
if parent_node:
|
||||
while parent_node.type != 'tosca.nodes.Root':
|
||||
req = parent_node._get_value(REQUIREMENTS, None, True)
|
||||
req = parent_node.get_value(REQUIREMENTS, None, True)
|
||||
requires.extend(req)
|
||||
parent_node = parent_node.parent_type
|
||||
if requires:
|
||||
@ -107,9 +107,9 @@ class NodeType(StatefulEntityType):
|
||||
typecapabilities = []
|
||||
self.cap_prop = None
|
||||
self.cap_type = None
|
||||
caps = self._get_value(CAPABILITIES)
|
||||
caps = self.get_value(CAPABILITIES)
|
||||
if caps is None:
|
||||
caps = self._get_value(CAPABILITIES, None, True)
|
||||
caps = self.get_value(CAPABILITIES, None, True)
|
||||
if caps:
|
||||
cproperties = None
|
||||
for name, value in caps.items():
|
||||
@ -123,11 +123,11 @@ class NodeType(StatefulEntityType):
|
||||
|
||||
@property
|
||||
def requirements(self):
|
||||
return self._get_value(REQUIREMENTS)
|
||||
return self.get_value(REQUIREMENTS)
|
||||
|
||||
@property
|
||||
def interfaces(self):
|
||||
return self._get_value(INTERFACES)
|
||||
return self.get_value(INTERFACES)
|
||||
|
||||
@property
|
||||
def lifecycle_inputs(self):
|
||||
@ -163,7 +163,7 @@ class NodeType(StatefulEntityType):
|
||||
if key == type:
|
||||
return value
|
||||
|
||||
def _get_value(self, ndtype, defs=None, parent=None):
|
||||
def get_value(self, ndtype, defs=None, parent=None):
|
||||
value = None
|
||||
if defs is None:
|
||||
defs = self.defs
|
||||
@ -177,6 +177,6 @@ class NodeType(StatefulEntityType):
|
||||
break
|
||||
if p and p.type == 'tosca.nodes.Root':
|
||||
break
|
||||
value = p._get_value(ndtype)
|
||||
value = p.get_value(ndtype)
|
||||
p = p.parent_type
|
||||
return value
|
||||
|
31
translator/toscalib/elements/property_definition.py
Normal file
31
translator/toscalib/elements/property_definition.py
Normal file
@ -0,0 +1,31 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
#
|
||||
# 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 PropertyDef(object):
|
||||
'''TOSCA built-in Property type.'''
|
||||
|
||||
def __init__(self, name, value=None, schema=None):
|
||||
self.name = name
|
||||
self.value = value
|
||||
self.schema = schema
|
||||
|
||||
@property
|
||||
def required(self):
|
||||
if self.schema:
|
||||
for prop_key, prop_vale in self.schema.items():
|
||||
if prop_key == 'required' and prop_vale:
|
||||
return True
|
||||
return False
|
@ -19,7 +19,7 @@ import logging
|
||||
from translator.toscalib.elements.capabilitytype import CapabilityTypeDef
|
||||
from translator.toscalib.elements.interfaces import InterfacesDef
|
||||
from translator.toscalib.elements.nodetype import NodeType
|
||||
from translator.toscalib.elements.properties import PropertyDef
|
||||
from translator.toscalib.properties import Property
|
||||
from translator.toscalib.utils.gettextutils import _
|
||||
|
||||
SECTIONS = (DERIVED_FROM, PROPERTIES, REQUIREMENTS,
|
||||
@ -30,74 +30,70 @@ SECTIONS = (DERIVED_FROM, PROPERTIES, REQUIREMENTS,
|
||||
log = logging.getLogger('tosca')
|
||||
|
||||
|
||||
class NodeTemplate(NodeType):
|
||||
class NodeTemplate(object):
|
||||
'''Node template from a Tosca profile.'''
|
||||
def __init__(self, name, nodetemplates):
|
||||
super(NodeTemplate, self).__init__(nodetemplates[name]['type'])
|
||||
def __init__(self, name, node_templates):
|
||||
self.name = name
|
||||
self.nodetemplates = nodetemplates
|
||||
self.nodetemplate = nodetemplates[self.name]
|
||||
self.type = self.nodetemplate['type']
|
||||
self.type_properties = self.properties_def
|
||||
self.type_capabilities = self.capabilities
|
||||
self.type_lifecycle_ops = self.lifecycle_operations
|
||||
self.type_relationship = self.relationship
|
||||
self.node_type = NodeType(node_templates[name]['type'])
|
||||
self.node_templates = node_templates
|
||||
self.node_template = node_templates[self.name]
|
||||
self.type = self.node_template['type']
|
||||
self.related = {}
|
||||
|
||||
@property
|
||||
def tpl_requirements(self):
|
||||
return self._get_value(REQUIREMENTS, self.nodetemplate)
|
||||
def requirements(self):
|
||||
return self.node_type.get_value(REQUIREMENTS, self.node_template)
|
||||
|
||||
@property
|
||||
def tpl_relationship(self):
|
||||
tpl_relation = {}
|
||||
requires = self.tpl_requirements
|
||||
def relationship(self):
|
||||
relation = {}
|
||||
requires = self.requirements
|
||||
if requires:
|
||||
for r in requires:
|
||||
for cap, node in r.items():
|
||||
for relationship_type in self.type_relationship.keys():
|
||||
if cap == relationship_type.capability_name:
|
||||
rtpl = NodeTemplate(node, self.nodetemplates)
|
||||
tpl_relation[relationship_type] = rtpl
|
||||
return tpl_relation
|
||||
for rtype in self.node_type.relationship.keys():
|
||||
if cap == rtype.capability_name:
|
||||
rtpl = NodeTemplate(node, self.node_templates)
|
||||
relation[rtype] = rtpl
|
||||
return relation
|
||||
|
||||
@property
|
||||
def tpl_capabilities(self):
|
||||
tpl_cap = []
|
||||
def capabilities(self):
|
||||
capability = []
|
||||
properties = {}
|
||||
cap_type = None
|
||||
caps = self._get_value(CAPABILITIES, self.nodetemplate)
|
||||
caps = self.node_type.get_value(CAPABILITIES, self.node_template)
|
||||
if caps:
|
||||
for name, value in caps.items():
|
||||
for prop, val in value.items():
|
||||
properties = val
|
||||
for c in self.type_capabilities:
|
||||
for c in self.node_type.capabilities:
|
||||
if c.name == name:
|
||||
cap_type = c.type
|
||||
cap = CapabilityTypeDef(name, cap_type,
|
||||
self.name, properties)
|
||||
tpl_cap.append(cap)
|
||||
return tpl_cap
|
||||
capability.append(cap)
|
||||
return capability
|
||||
|
||||
@property
|
||||
def tpl_interfaces(self):
|
||||
tpl_ifaces = []
|
||||
ifaces = self._get_value(INTERFACES, self.nodetemplate)
|
||||
def interfaces(self):
|
||||
interfaces = []
|
||||
ifaces = self.node_type.get_value(INTERFACES, self.node_template)
|
||||
if ifaces:
|
||||
for i in ifaces:
|
||||
for name, value in ifaces.items():
|
||||
for ops, val in value.items():
|
||||
iface = InterfacesDef(None, name, self.name,
|
||||
ops, val)
|
||||
tpl_ifaces.append(iface)
|
||||
return tpl_ifaces
|
||||
interfaces.append(iface)
|
||||
return interfaces
|
||||
|
||||
@property
|
||||
def properties(self):
|
||||
tpl_props = []
|
||||
properties = self._get_value(PROPERTIES, self.nodetemplate)
|
||||
props = []
|
||||
properties = self.node_type.get_value(PROPERTIES, self.node_template)
|
||||
requiredprop = []
|
||||
for p in self.type_properties:
|
||||
for p in self.node_type.properties_def:
|
||||
if p.required:
|
||||
requiredprop.append(p.name)
|
||||
if properties:
|
||||
@ -111,14 +107,16 @@ class NodeTemplate(NodeType):
|
||||
"one or more required properties %(prop)s")
|
||||
% {'tpl': self.name, 'prop': missingprop})
|
||||
for name, value in properties.items():
|
||||
prop = PropertyDef(name, self.type, None, value, self.name)
|
||||
tpl_props.append(prop)
|
||||
for p in self.node_type.properties_def:
|
||||
if p.name == name:
|
||||
prop = Property(name, value, p.schema)
|
||||
props.append(prop)
|
||||
else:
|
||||
if requiredprop:
|
||||
raise ValueError(_("Node template %(tpl)s is missing"
|
||||
"one or more required properties %(prop)s")
|
||||
% {'tpl': self.name, 'prop': requiredprop})
|
||||
return tpl_props
|
||||
return props
|
||||
|
||||
def _add_next(self, nodetpl, relationship):
|
||||
self.related[nodetpl] = relationship
|
||||
@ -126,24 +124,24 @@ class NodeTemplate(NodeType):
|
||||
@property
|
||||
def related_nodes(self):
|
||||
if not self.related:
|
||||
for relation, node in self.tpl_relationship.items():
|
||||
for tpl in self.nodetemplates:
|
||||
for relation, node in self.node_type.relationship.items():
|
||||
for tpl in self.node_templates:
|
||||
if tpl == node.type:
|
||||
self.related[NodeTemplate(tpl)] = relation
|
||||
return self.related.keys()
|
||||
|
||||
def ref_property(self, cap, cap_name, property):
|
||||
requires = self.tpl_requirements
|
||||
tpl_name = None
|
||||
requires = self.node_type.requirements
|
||||
name = None
|
||||
if requires:
|
||||
for r in requires:
|
||||
for cap, node in r.items():
|
||||
if cap == cap:
|
||||
tpl_name = node
|
||||
name = node
|
||||
break
|
||||
if tpl_name:
|
||||
tpl = NodeTemplate(tpl_name, self.nodetemplates)
|
||||
caps = tpl.tpl_capabilities
|
||||
if name:
|
||||
tpl = NodeTemplate(name, self.node_templates)
|
||||
caps = tpl.capabilities
|
||||
for c in caps:
|
||||
if c.name == cap_name:
|
||||
if c.property == property:
|
||||
|
@ -17,7 +17,7 @@
|
||||
import logging
|
||||
|
||||
from translator.toscalib.elements.constraints import Constraint
|
||||
from translator.toscalib.elements.properties import PropertyDef
|
||||
from translator.toscalib.properties import Property
|
||||
|
||||
log = logging.getLogger('tosca')
|
||||
|
||||
@ -33,17 +33,17 @@ class Input(object):
|
||||
|
||||
@property
|
||||
def description(self):
|
||||
if PropertyDef.DESCRIPTION in self.schema:
|
||||
if Property.DESCRIPTION in self.schema:
|
||||
return self.schema['description']
|
||||
|
||||
@property
|
||||
def default(self):
|
||||
if self.PropertyDef.DEFAULT in self.schema:
|
||||
if self.Property.DEFAULT in self.schema:
|
||||
return self.schema['default']
|
||||
|
||||
@property
|
||||
def constraints(self):
|
||||
if PropertyDef.CONSTRAINTS in self.schema:
|
||||
if Property.CONSTRAINTS in self.schema:
|
||||
return self.schema['constraints']
|
||||
|
||||
def validate(self):
|
||||
@ -52,7 +52,7 @@ class Input(object):
|
||||
self.validate_constraints(self.constraints)
|
||||
|
||||
def validate_type(self, input_type):
|
||||
if input_type not in PropertyDef.PROPERTIY_TYPES:
|
||||
if input_type not in Property.PROPERTIY_TYPES:
|
||||
raise ValueError(_('Invalid type %s') % type)
|
||||
|
||||
def validate_constraints(self, constraints):
|
||||
|
@ -16,7 +16,7 @@
|
||||
from translator.toscalib.elements.constraints import Constraint
|
||||
|
||||
|
||||
class PropertyDef(object):
|
||||
class Property(object):
|
||||
'''TOSCA built-in Property type.'''
|
||||
|
||||
PROPERTY_KEYS = (
|
||||
@ -25,29 +25,17 @@ class PropertyDef(object):
|
||||
'type', 'required', 'description', 'default', 'constraints'
|
||||
)
|
||||
PROPERTIY_TYPES = (
|
||||
INTEGER,
|
||||
STRING, NUMBER, BOOLEAN,
|
||||
LIST
|
||||
INTEGER, STRING, BOOLEAN,
|
||||
FLOAT, TIMESTAMP
|
||||
) = (
|
||||
'integer',
|
||||
'string', 'number', 'boolean',
|
||||
'list'
|
||||
'integer', 'string', 'boolean',
|
||||
'float', 'timestamp'
|
||||
)
|
||||
|
||||
def __init__(self, name, nodetype, schema=None, value=None, tpl_name=None):
|
||||
self.name = name
|
||||
self.nodetype = nodetype
|
||||
self.schema = schema
|
||||
def __init__(self, property_name, value, schema=None):
|
||||
self.name = property_name
|
||||
self.value = value
|
||||
self.tpl_name = tpl_name
|
||||
|
||||
@property
|
||||
def required(self):
|
||||
if self.schema:
|
||||
for prop_key, prop_vale in self.schema.items():
|
||||
if prop_key == self.REQUIRED and prop_vale:
|
||||
return True
|
||||
return False
|
||||
self.schema = schema
|
||||
|
||||
@property
|
||||
def constraints(self):
|
@ -75,24 +75,24 @@ class ToscaTemplateTest(TestCase):
|
||||
'''Test capabilities.'''
|
||||
self.assertEqual(
|
||||
expected_capabilities,
|
||||
sorted([p.name for p in tpl.tpl_capabilities]))
|
||||
sorted([p.name for p in tpl.capabilities]))
|
||||
|
||||
'''Test requirements.'''
|
||||
self.assertEqual(
|
||||
expected_requirements, tpl.tpl_requirements)
|
||||
expected_requirements, tpl.requirements)
|
||||
|
||||
'''Test relationship.'''
|
||||
self.assertEqual(
|
||||
expected_relationshp,
|
||||
[x.type for x in tpl.tpl_relationship.keys()])
|
||||
[x.type for x in tpl.relationship.keys()])
|
||||
self.assertEqual(
|
||||
expected_host,
|
||||
[y.name for y in tpl.tpl_relationship.values()])
|
||||
[y.name for y in tpl.relationship.values()])
|
||||
|
||||
'''Test interfaces.'''
|
||||
self.assertEqual(
|
||||
expected_interface,
|
||||
[x.type for x in tpl.tpl_interfaces])
|
||||
[x.type for x in tpl.interfaces])
|
||||
|
||||
'''Test property value'''
|
||||
if tpl.name == 'server':
|
||||
|
@ -39,8 +39,8 @@ class ToscaGraph(object):
|
||||
|
||||
def _create(self):
|
||||
for node in self.nodetemplates:
|
||||
if node.tpl_relationship:
|
||||
relation = node.tpl_relationship
|
||||
if node.relationship:
|
||||
relation = node.relationship
|
||||
for relation, nodetpls in relation.items():
|
||||
for tpl in self.nodetemplates:
|
||||
if tpl.name == nodetpls.name:
|
||||
|
Loading…
x
Reference in New Issue
Block a user