Create dictionary returning methods for certain class properties

Other than properties() and properties_def() methods in capabilities.py,
capabilitytype.py and statefulentitytype.py that switched from
returning a list to returning a dictionary (bug #1316275) there are
other methods that can benefit from a similar update:
- all_properties() in datatype.py
- attributes_def() in statefulentitytype.py
- capabilities() in entity_template.py
- capabilities() in nodetype.py
- properties() in entity_template.py

Change-Id: I5fbe8032dcf6ced0f771bdf655f669cb53688a72
Closes-Bug: #1435547
Related-Bug: #1316275
This commit is contained in:
Vahid Hashemian 2015-03-23 17:14:30 -07:00
parent 93901bea0f
commit 39e5cdeddb
22 changed files with 196 additions and 141 deletions

View File

@ -58,7 +58,7 @@ class HotResource(object):
# the property can hold a value or the intrinsic function get_input
# for value, copy it
# for get_input, convert to get_param
for prop in self.nodetemplate.properties:
for prop in self.nodetemplate.get_properties_objects():
pass
def handle_life_cycle(self):
@ -243,7 +243,7 @@ class HotResource(object):
def _get_tosca_props(self, properties):
tosca_props = {}
for prop in self.nodetemplate.properties:
for prop in self.nodetemplate.get_properties_objects():
if isinstance(prop.value, GetInput):
tosca_props[prop.name] = {'get_param': prop.value.input_name}
else:

View File

@ -25,7 +25,7 @@ class ToscaBlockStorage(HotResource):
def handle_properties(self):
tosca_props = {}
for prop in self.nodetemplate.properties:
for prop in self.nodetemplate.get_properties_objects():
if isinstance(prop.value, GetInput):
tosca_props[prop.name] = {'get_param': prop.value.input_name}
self.properties = tosca_props

View File

@ -27,7 +27,7 @@ class ToscaBlockStorageAttachment(HotResource):
def handle_properties(self):
tosca_props = {}
for prop in self.nodetemplate.properties:
for prop in self.nodetemplate.get_properties_objects():
if isinstance(prop.value, GetInput):
tosca_props[prop.name] = {'get_param': prop.value.input_name}
else:

View File

@ -69,8 +69,11 @@ class ToscaCompute(HotResource):
def handle_properties(self):
self.properties.update(self.translate_compute_flavor_and_image(
self.nodetemplate.properties,
self.nodetemplate.get_properties_objects(),
self.nodetemplate.get_capability('os')))
self.properties = self.translate_compute_flavor_and_image(
self.nodetemplate.get_properties_objects(),
self.nodetemplate.get_capability('os'))
self.properties['user_data_format'] = 'SOFTWARE_CONFIG'
# TODO(anyone): handle user key
# hardcoded here for testing

View File

@ -31,7 +31,8 @@ class ToscaNetwork(HotResource):
pass
def handle_properties(self):
tosca_props = self._get_tosca_props(self.nodetemplate.properties)
tosca_props = self._get_tosca_props(
self.nodetemplate.get_properties_objects())
net_props = {}
for key, value in tosca_props.items():
@ -69,7 +70,8 @@ class ToscaNetwork(HotResource):
if self.hide_resource:
return
tosca_props = self._get_tosca_props(self.nodetemplate.properties)
tosca_props = self._get_tosca_props(
self.nodetemplate.get_properties_objects())
subnet_props = {}

View File

@ -46,7 +46,8 @@ class ToscaNetworkPort(HotResource):
resources.insert(lo, resource)
def handle_properties(self):
tosca_props = self._get_tosca_props(self.nodetemplate.properties)
tosca_props = self._get_tosca_props(
self.nodetemplate.get_properties_objects())
port_props = {}
for key, value in tosca_props.items():

View File

@ -49,7 +49,7 @@ class TOSCATranslator(object):
# to actual value
def _resolve_input(self):
for n in self.tosca.nodetemplates:
for node_prop in n.properties:
for node_prop in n.get_properties_objects():
if isinstance(node_prop.value, dict):
try:
self.parsed_params[node_prop.value['get_input']]

View File

@ -28,7 +28,7 @@ class Capability(object):
if props:
for name, value in props.items():
props_def = self.definition.get_properties_def()
if name in props_def:
if props_def and name in props_def:
properties.append(Property(name, value,
props_def[name].schema))
return properties
@ -41,5 +41,5 @@ class Capability(object):
def get_property_value(self, name):
'''Return the value of a given property name.'''
props = self.get_properties()
if name in props:
if props and name in props:
return props[name].value

View File

@ -23,7 +23,7 @@ class DataEntity(object):
def __init__(self, datatypename, value_dict, custom_def=None):
self.custom_def = custom_def
self.datatype = DataType(datatypename, custom_def)
self.schema = self.datatype.all_properties
self.schema = self.datatype.get_all_properties()
self.value = value_dict
def validate(self):
@ -45,12 +45,13 @@ class DataEntity(object):
allowed_props = []
required_props = []
default_props = {}
for prop_def in self.schema:
allowed_props.append(prop_def.name)
if prop_def.required:
required_props.append(prop_def.name)
if prop_def.default:
default_props[prop_def.name] = prop_def.default
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()):
@ -89,9 +90,8 @@ class DataEntity(object):
return self.value
def _find_schema(self, name):
for prop_def in self.schema:
if prop_def.name == name:
return prop_def.schema
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):

View File

@ -51,7 +51,7 @@ class CapabilityTypeDef(StatefulEntityType):
def get_property_def_value(self, name):
'''Return the definition of a given property name.'''
props_def = self.get_properties_def()
if name in props_def:
if props_def and name in props_def:
return props_def[name].value
def _get_parent_capabilities(self):

View File

@ -35,12 +35,26 @@ class DataType(StatefulEntityType):
'''Return 'type' section in the datatype schema.'''
return self.entity_value(self.defs, 'type')
@property
def all_properties(self):
'''Return all properties defined in this type and its parent type.'''
def get_all_properties_objects(self):
'''Return all properties objects defined in this type
and its 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

View File

@ -111,26 +111,25 @@ class NodeType(StatefulEntityType):
def _get_relation(self, key, ndtype):
relation = None
ntype = NodeType(ndtype)
cap = ntype.capabilities
for c in cap:
if c.name == key:
for r in self.RELATIONSHIP_TYPE:
rtypedef = ntype.TOSCA_DEF[r]
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.type in properties:
if c.parent_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
@property
def capabilities(self):
def get_capabilities_objects(self):
'''Return a list of capability objects.'''
typecapabilities = []
caps = self.get_value(self.CAPABILITIES)
@ -144,6 +143,11 @@ class NodeType(StatefulEntityType):
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)
@ -192,11 +196,11 @@ class NodeType(StatefulEntityType):
return ops
def get_capability(self, name):
for key, value in self.capabilities:
if key == name:
return value
caps = self.get_capabilities()
if caps and name in caps.keys():
return caps[name].value
def get_capability_type(self, name):
for key, value in self.get_capability(name):
if key == type:
return value
captype = self.get_capability(name)
if captype and name in captype.keys():
return captype[name].value

View File

@ -58,14 +58,24 @@ class StatefulEntityType(EntityType):
def get_property_def_value(self, name):
'''Return the property definition associated with a given name.'''
props_def = self.get_properties_def()
if name in props_def:
if props_def and name in props_def.keys():
return props_def[name].value
@property
def attributes_def(self):
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

View File

@ -56,34 +56,51 @@ class EntityTemplate(object):
self.entity_tpl) or []
return self._requirements
@property
def properties(self):
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
@property
def capabilities(self):
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 _create_capabilities(self):
capability = []
caps = self.type_definition.get_value(self.CAPABILITIES,
self.entity_tpl)
if caps:
for name, props in caps.items():
for c in self.type_definition.capabilities:
if c.name == name:
cap = Capability(name, props['properties'], c)
capability.append(cap)
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):
@ -91,11 +108,9 @@ class EntityTemplate(object):
self._common_validate_properties(entitytype, properties)
def _validate_capabilities(self):
type_capabilities = self.type_definition.capabilities
allowed_caps = []
if type_capabilities:
for tcap in type_capabilities:
allowed_caps.append(tcap.name)
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:
@ -177,7 +192,7 @@ class EntityTemplate(object):
self.entity_tpl) or {}
for name, value in properties.items():
props_def = self.type_definition.get_properties_def()
if name in props_def:
if props_def and name in props_def:
prop = Property(name, value,
props_def[name].schema, self.custom_def)
props.append(prop)
@ -208,6 +223,6 @@ class EntityTemplate(object):
:param name: name of capability
:return: capability object if found, None otherwise
"""
for cap in self.capabilities:
if cap.name == name:
return cap
caps = self.get_capabilities()
if caps and name in caps.keys():
return caps[name]

View File

@ -155,8 +155,9 @@ class GetAttribute(Function):
return node_tpl
def _attribute_exists_in_type(self, type_definition):
found = [attr for attr in type_definition.attributes_def
if attr.name == self.attribute_name]
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):
@ -167,7 +168,7 @@ class GetAttribute(Function):
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.capabilities:
for capability in target_type.get_capabilities_objects():
if capability.type in hosted_on_rel['valid_targets']:
if self._attribute_exists_in_type(target_type):
return target_node
@ -258,21 +259,22 @@ class GetProperty(Function):
capability_name,
property_name):
"""Gets a node template capability property."""
for cap in node_template.capabilities:
if cap.name == capability_name:
property = None
props = cap.get_properties()
if property_name in props:
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
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,
@ -282,9 +284,8 @@ class GetProperty(Function):
def _find_property(self, property_name):
node_tpl = self._find_node_template(self.args[0])
found = [
prop for prop in node_tpl.properties
if prop.name == property_name]
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(

View File

@ -130,7 +130,7 @@ class NodeTemplate(EntityTemplate):
self._validate_requirements()
self._validate_properties(self.entity_tpl, self.type_definition)
self._validate_interfaces()
for prop in self.properties:
for prop in self.get_properties_objects():
prop.validate()
def _validate_requirements(self):

View File

@ -38,7 +38,7 @@ class IntrinsicFunctionsTest(TestCase):
if interface.name == operation][0]
def _get_property(self, node_template, property_name):
return [prop.value for prop in node_template.properties
return [prop.value for prop in node_template.get_properties_objects()
if prop.name == property_name][0]
def test_get_property(self):
@ -78,14 +78,13 @@ class IntrinsicFunctionsTest(TestCase):
def test_get_input_in_properties(self):
mysql_dbms = self._get_node('mysql_dbms')
self.assertTrue(isinstance(mysql_dbms.properties[0].value,
functions.GetInput))
self.assertTrue(mysql_dbms.properties[0].value.input_name,
'db_root_pwd')
self.assertTrue(isinstance(mysql_dbms.properties[1].value,
functions.GetInput))
self.assertTrue(mysql_dbms.properties[1].value.input_name,
'db_port')
expected_inputs = ['db_root_pwd', 'db_port']
props = mysql_dbms.get_properties()
for key in props.keys():
prop = props[key]
self.assertTrue(isinstance(prop.value, functions.GetInput))
expected_inputs.remove(prop.value.input_name)
self.assertListEqual(expected_inputs, [])
def test_get_input_in_interface(self):
mysql_dbms = self._get_node('mysql_dbms')

View File

@ -92,10 +92,11 @@ class ScalarUnitPositiveTest(TestCase):
tpl = self.tpl_snippet
nodetemplates = yamlparser.simple_parse(tpl)
nodetemplate = NodeTemplate('server', nodetemplates)
for p in nodetemplate.properties:
if p.name == 'mem_size':
self.assertIsNone(p.validate())
resolved = p.value
props = nodetemplate.get_properties()
if props and 'mem_size' in props.keys():
prop = props['mem_size']
self.assertIsNone(prop.validate())
resolved = prop.value
self.assertEqual(resolved, self.expected)
@ -167,7 +168,7 @@ class ScalarUnitNegativeTest(TestCase):
'''
nodetemplates = yamlparser.simple_parse(tpl_snippet)
nodetemplate = NodeTemplate('server', nodetemplates, self.custom_def)
for p in nodetemplate.properties:
for p in nodetemplate.get_properties_objects():
self.assertRaises(ValueError, p.validate)
# disk_size is less than 1 GB, mem_size is not in the required range.
@ -182,15 +183,16 @@ class ScalarUnitNegativeTest(TestCase):
'''
nodetemplates = yamlparser.simple_parse(tpl_snippet)
nodetemplate = NodeTemplate('server', nodetemplates, self.custom_def)
for p in nodetemplate.properties:
if p.name == 'disk_size':
error = self.assertRaises(exception.ValidationError,
p.validate)
self.assertEqual('disk_size: 500 MB must be greater or '
'equal to "1 GB".', error.__str__())
if p.name == 'mem_size':
error = self.assertRaises(exception.ValidationError,
p.validate)
self.assertEqual('mem_size: 1 MB is out of range '
'(min:1 MiB, '
'max:1 GiB).', error.__str__())
props = nodetemplate.get_properties()
if 'disk_size' in props.keys():
error = self.assertRaises(exception.ValidationError,
props['disk_size'].validate)
self.assertEqual('disk_size: 500 MB must be greater or '
'equal to "1 GB".', error.__str__())
if 'mem_size' in props.keys():
error = self.assertRaises(exception.ValidationError,
props['mem_size'].validate)
self.assertEqual('mem_size: 1 MB is out of range '
'(min:1 MiB, '
'max:1 GiB).', error.__str__())

View File

@ -42,13 +42,13 @@ class ToscaDefTest(TestCase):
'tosca.capabilities.OperatingSystem',
'tosca.capabilities.network.Bindable',
'tosca.capabilities.Scalable']),
sorted([c.type for c in compute_type.capabilities]))
sorted([c.type for c in compute_type.get_capabilities_objects()]))
self.assertEqual(
['tosca.capabilities.network.Linkable'],
[c.type for c in network_type.capabilities])
[c.type for c in network_type.get_capabilities_objects()])
endpoint_props_def_objects = \
self._get_capability_properties_def_objects(
webserver_type.capabilities,
webserver_type.get_capabilities_objects(),
'tosca.capabilities.Endpoint')
self.assertEqual(
['initiator', 'network_name', 'port',
@ -56,18 +56,21 @@ class ToscaDefTest(TestCase):
'secure', 'url_path'],
sorted([p.name for p in endpoint_props_def_objects]))
endpoint_props_def = self._get_capability_properties_def(
webserver_type.capabilities, 'tosca.capabilities.Endpoint')
webserver_type.get_capabilities_objects(),
'tosca.capabilities.Endpoint')
self.assertEqual(
['initiator', 'network_name', 'port',
'port_name', 'ports', 'protocol',
'secure', 'url_path'],
sorted(endpoint_props_def.keys()))
endpoint_prop_def = self._get_capability_property_def(
webserver_type.capabilities, 'tosca.capabilities.Endpoint',
webserver_type.get_capabilities_objects(),
'tosca.capabilities.Endpoint',
'initiator')
self.assertEqual(None, endpoint_prop_def)
os_props = self._get_capability_properties_def_objects(
compute_type.capabilities, 'tosca.capabilities.OperatingSystem')
compute_type.get_capabilities_objects(),
'tosca.capabilities.OperatingSystem')
self.assertEqual(
['architecture', 'distribution', 'type', 'version'],
sorted([p.name for p in os_props]))
@ -105,7 +108,7 @@ class ToscaDefTest(TestCase):
def test_attributes_def(self):
self.assertEqual(
['private_address', 'public_address'],
sorted([p.name for p in compute_type.attributes_def]))
sorted(compute_type.get_attributes_def().keys()))
def test_requirements(self):
self.assertEqual(

View File

@ -80,12 +80,12 @@ class ToscaTemplateTest(TestCase):
'''Test properties.'''
self.assertEqual(
expected_properties,
sorted([p.name for p in tpl.properties]))
sorted(tpl.get_properties().keys()))
'''Test capabilities.'''
self.assertEqual(
expected_capabilities,
sorted([p.name for p in tpl.capabilities]))
sorted(tpl.get_capabilities().keys()))
'''Test requirements.'''
self.assertEqual(
@ -106,21 +106,21 @@ class ToscaTemplateTest(TestCase):
if tpl.name == 'server':
'''Test property value'''
for property in tpl.properties:
if property.name == 'mem_size':
self.assertEqual(property.value, '4096 MB')
props = tpl.get_properties()
if props and 'mem_size' in props.keys():
self.assertEqual(props['mem_size'].value, '4096 MB')
'''Test capability'''
self.assertIn('os', [cap.name for cap in tpl.capabilities])
caps = tpl.get_capabilities()
self.assertIn('os', caps.keys())
os_props_objs = None
os_props = None
os_type_prop = None
for capability in tpl.capabilities:
if capability.name == 'os':
os_props_objs = \
capability.get_properties_objects()
os_props = capability.get_properties()
os_type_prop = capability.get_property_value('type')
break
if caps and 'os' in caps.keys():
capability = caps['os']
os_props_objs = capability.get_properties_objects()
os_props = capability.get_properties()
os_type_prop = capability.get_property_value('type')
break
self.assertEqual(
['Linux'],
[p.value for p in os_props_objs if p.name == 'type'])
@ -184,7 +184,8 @@ class ToscaTemplateTest(TestCase):
'tosca.capabilities.OperatingSystem',
'tosca.capabilities.network.Bindable',
'tosca.capabilities.Scalable']),
sorted([c.type for c in compute_type.capabilities]))
sorted([c.type
for c in compute_type.get_capabilities_objects()]))
def test_template_with_no_inputs(self):
tosca_tpl = self._load_template('test_no_inputs_in_template.yaml')
@ -217,7 +218,7 @@ class ToscaTemplateTest(TestCase):
if node_tpl.name == 'mongo_server':
self.assertEqual(
['disk_size', 'mem_size', 'num_cpus'],
sorted([p.name for p in node_tpl.properties]))
sorted(node_tpl.get_properties().keys()))
def test_template_requirements(self):
"""Test different formats of requirements
@ -355,7 +356,7 @@ class ToscaTemplateTest(TestCase):
tpl = NodeTemplate(name, nodetemplates, custom_def)
self.assertEqual(
expected_capabilities,
sorted([c.name for c in tpl.capabilities]))
sorted(tpl.get_capabilities().keys()))
#custom definition without capability type definition
custom_def = '''
@ -371,6 +372,6 @@ class ToscaTemplateTest(TestCase):
err = self.assertRaises(
exception.InvalidTypeError,
lambda: NodeTemplate(name, nodetemplates,
custom_def).capabilities)
custom_def).get_capabilities_objects())
self.assertEqual('Type "tosca.capabilities.TestCapability" is not '
'a valid type.', six.text_type(err))

View File

@ -129,8 +129,8 @@ class ToscaTemplateValidationTest(TestCase):
self._custom_types())
nodetemplate.validate()
nodetemplate.requirements
nodetemplate.capabilities
nodetemplate.properties
nodetemplate.get_capabilities_objects()
nodetemplate.get_properties_objects()
nodetemplate.interfaces
except Exception as err:

View File

@ -173,7 +173,7 @@ class ToscaTemplate(object):
properties, requirements, interfaces inputs and template outputs.
"""
for node_template in self.nodetemplates:
for prop in node_template.properties:
for prop in node_template.get_properties_objects():
prop.value = functions.get_function(self,
node_template,
prop.value)