Add support for SOURCE and TARGET in get_property and get_attribute functions

Change-Id: I17181c8adb23f7e55c49c780d6bfaba9c26fc985
Related-Bug: 1554507
This commit is contained in:
Miguel Caballer 2016-03-09 12:53:23 +01:00
parent 76986c545c
commit b480a11678
6 changed files with 151 additions and 6 deletions

View File

@ -19,6 +19,7 @@ from toscaparser.common.exception import ExceptionCollector
from toscaparser.common.exception import UnknownInputError
from toscaparser.dataentity import DataEntity
from toscaparser.elements.entity_type import EntityType
from toscaparser.elements.relationshiptype import RelationshipType
from toscaparser.utils.gettextutils import _
@ -28,6 +29,8 @@ GET_INPUT = 'get_input'
SELF = 'SELF'
HOST = 'HOST'
TARGET = 'TARGET'
SOURCE = 'SOURCE'
HOSTED_ON = 'tosca.relationships.HostedOn'
@ -210,6 +213,20 @@ class GetAttribute(Function):
target_name)
def _find_node_template(self, node_template_name):
if node_template_name == TARGET:
if not isinstance(self.context.type_definition, RelationshipType):
ExceptionCollector.appendException(
KeyError(_('"TARGET" keyword can only be used in context'
' to "Relationships" target node')))
return
return self.context.target
if node_template_name == SOURCE:
if not isinstance(self.context.type_definition, RelationshipType):
ExceptionCollector.appendException(
KeyError(_('"SOURCE" keyword can only be used in context'
' to "Relationships" source node')))
return
return self.context.source
name = self.context.name \
if node_template_name == SELF and \
not isinstance(self.context, list) \
@ -236,7 +253,7 @@ class GetProperty(Function):
Arguments:
* Node template name.
* Node template name | SELF | HOST | SOURCE | TARGET.
* Requirement or capability name (optional).
* Property name.
@ -364,6 +381,20 @@ class GetProperty(Function):
# enable the HOST value in the function
if node_template_name == HOST:
return self._find_host_containing_property()
if node_template_name == TARGET:
if not isinstance(self.context.type_definition, RelationshipType):
ExceptionCollector.appendException(
KeyError(_('"TARGET" keyword can only be used in context'
' to "Relationships" target node')))
return
return self.context.target
if node_template_name == SOURCE:
if not isinstance(self.context.type_definition, RelationshipType):
ExceptionCollector.appendException(
KeyError(_('"SOURCE" keyword can only be used in context'
' to "Relationships" source node')))
return
return self.context.source
if not hasattr(self.tosca_tpl, 'nodetemplates'):
return
for node_template in self.tosca_tpl.nodetemplates:

View File

@ -114,6 +114,8 @@ class NodeTemplate(EntityTemplate):
rtype = RelationshipType(tpl.type, None,
self.custom_def)
explicit_relation[rtype] = related_tpl
tpl.target = related_tpl
tpl.source = self
self.relationship_tpl.append(tpl)
found_relationship_tpl = True
# create relationship template object.
@ -137,7 +139,8 @@ class NodeTemplate(EntityTemplate):
if rtype.type == relationship:
explicit_relation[rtype] = related_tpl
related_tpl._add_relationship_template(req,
rtype.type)
rtype.type,
self)
elif self.available_rel_types:
if relationship in self.available_rel_types.keys():
rel_type_def = self.available_rel_types.\
@ -151,13 +154,13 @@ class NodeTemplate(EntityTemplate):
explicit_relation[rtype] = related_tpl
related_tpl.\
_add_relationship_template(
req, rtype.type)
req, rtype.type, self)
return explicit_relation
def _add_relationship_template(self, requirement, rtype):
def _add_relationship_template(self, requirement, rtype, source):
req = requirement.copy()
req['type'] = rtype
tpl = RelationshipTemplate(req, rtype, self.custom_def)
tpl = RelationshipTemplate(req, rtype, self.custom_def, self, source)
self.relationship_tpl.append(tpl)
def get_relationship_template(self):

View File

@ -26,12 +26,15 @@ log = logging.getLogger('tosca')
class RelationshipTemplate(EntityTemplate):
'''Relationship template.'''
def __init__(self, relationship_template, name, custom_def=None):
def __init__(self, relationship_template, name, custom_def=None,
target=None, source=None):
super(RelationshipTemplate, self).__init__(name,
relationship_template,
'relationship_type',
custom_def)
self.name = name.lower()
self.target = target
self.source = source
def get_properties_objects(self):
'''Return properties objects for this template.'''

View File

@ -0,0 +1,30 @@
tosca_definitions_version: tosca_simple_yaml_1_0
description: >
TOSCA template for testing get_attribute with TARGET ans SOURCE keywords.
topology_template:
node_templates:
mysql:
type: tosca.nodes.DBMS
properties:
root_password: rootpw
port: 3306
requirements:
- host:
node: db_server
relationship:
type: tosca.relationships.HostedOn
interfaces:
Configure:
pre_configure_source:
implementation: some_script.sh
inputs:
target_test: { get_attribute: [ TARGET, public_address ] }
source_port: { get_attribute: [ SOURCE, tosca_name ] }
db_server:
type: tosca.nodes.Compute

View File

@ -0,0 +1,35 @@
tosca_definitions_version: tosca_simple_yaml_1_0
description: >
TOSCA template for testing get_property with TARGET ans SOURCE keywords.
imports:
- ../custom_types/compute_with_prop.yaml
topology_template:
node_templates:
mysql:
type: tosca.nodes.DBMS
properties:
root_password: rootpw
port: 3306
requirements:
- host:
node: db_server
relationship:
type: tosca.relationships.HostedOn
interfaces:
Configure:
pre_configure_source:
implementation: some_script.sh
inputs:
target_test: { get_property: [ TARGET, test ] }
source_port: { get_property: [ SOURCE, port ] }
db_server:
type: tosca.nodes.ComputeWithProp
properties:
test: 1

View File

@ -157,6 +157,26 @@ class IntrinsicFunctionsTest(TestCase):
self.assertTrue(isinstance(some_input, functions.GetProperty))
self.assertEqual('someval', some_input.result())
def test_get_property_source_target_keywords(self):
tosca_tpl = os.path.join(
os.path.dirname(os.path.abspath(__file__)),
"data/functions/test_get_property_source_target_keywords.yaml")
tosca = ToscaTemplate(tosca_tpl)
for node in tosca.nodetemplates:
for relationship, trgt in node.relationships.items():
rel_template = trgt.get_relationship_template()[0]
break
operation = self._get_operation(rel_template.interfaces,
'pre_configure_source')
target_test = operation.inputs['target_test']
self.assertTrue(isinstance(target_test, functions.GetProperty))
self.assertEqual(1, target_test.result())
source_port = operation.inputs['source_port']
self.assertTrue(isinstance(source_port, functions.GetProperty))
self.assertEqual(3306, source_port.result())
class GetAttributeTest(TestCase):
@ -166,6 +186,11 @@ class GetAttributeTest(TestCase):
'data',
filename))
def _get_operation(self, interfaces, operation):
return [
interface for interface in interfaces
if interface.name == operation][0]
def test_get_attribute_in_outputs(self):
tpl = self._load_template('tosca_single_instance_wordpress.yaml')
website_url_output = [
@ -256,3 +281,21 @@ class GetAttributeTest(TestCase):
ValueError,
_('Illegal arguments for function "get_attribute". '
'Expected arguments: "node-template-name", "attribute-name"'))
def test_get_attribute_source_target_keywords(self):
tosca_tpl = os.path.join(
os.path.dirname(os.path.abspath(__file__)),
"data/functions/test_get_attribute_source_target_keywords.yaml")
tosca = ToscaTemplate(tosca_tpl)
for node in tosca.nodetemplates:
for relationship, trgt in node.relationships.items():
rel_template = trgt.get_relationship_template()[0]
break
operation = self._get_operation(rel_template.interfaces,
'pre_configure_source')
target_test = operation.inputs['target_test']
self.assertTrue(isinstance(target_test, functions.GetAttribute))
source_port = operation.inputs['source_port']
self.assertTrue(isinstance(source_port, functions.GetAttribute))