Merge "get_attribute HOST keyword"
This commit is contained in:
commit
fc586105bb
@ -34,7 +34,7 @@ class TranslateOutputs():
|
||||
if isinstance(output.value, functions.GetAttribute):
|
||||
func = output.value
|
||||
get_parameters = [
|
||||
func.node_template_name,
|
||||
func.get_referenced_node_template().name,
|
||||
self._translate_attribute_name(func.attribute_name)]
|
||||
hot_value['get_attr'] = get_parameters
|
||||
elif isinstance(output.value, functions.GetProperty):
|
||||
|
@ -41,6 +41,7 @@ class EntityTemplate(object):
|
||||
custom_def)
|
||||
self._properties = None
|
||||
self._interfaces = None
|
||||
self._requirements = None
|
||||
self._capabilities = None
|
||||
|
||||
@property
|
||||
@ -49,8 +50,11 @@ class EntityTemplate(object):
|
||||
|
||||
@property
|
||||
def requirements(self):
|
||||
return self.type_definition.get_value(self.REQUIREMENTS,
|
||||
self.entity_tpl)
|
||||
if self._requirements is None:
|
||||
self._requirements = self.type_definition.get_value(
|
||||
self.REQUIREMENTS,
|
||||
self.entity_tpl) or []
|
||||
return self._requirements
|
||||
|
||||
@property
|
||||
def properties(self):
|
||||
|
@ -23,6 +23,9 @@ GET_ATTRIBUTE = 'get_attribute'
|
||||
GET_INPUT = 'get_input'
|
||||
|
||||
SELF = 'SELF'
|
||||
HOST = 'HOST'
|
||||
|
||||
HOSTED_ON = 'tosca.relationships.HostedOn'
|
||||
|
||||
|
||||
class Function(object):
|
||||
@ -94,12 +97,17 @@ class GetAttribute(Function):
|
||||
|
||||
Arguments:
|
||||
|
||||
* Node template name.
|
||||
* 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, ip_address ] }
|
||||
* { get_attribute: [ HOST, ip_address ] }
|
||||
"""
|
||||
|
||||
def validate(self):
|
||||
@ -107,25 +115,69 @@ class GetAttribute(Function):
|
||||
raise ValueError(_(
|
||||
'Illegal arguments for {0} function. Expected arguments: '
|
||||
'node-template-name, attribute-name').format(GET_ATTRIBUTE))
|
||||
self._find_attribute(self.args[1])
|
||||
self._find_node_template_containing_attribute()
|
||||
|
||||
def result(self):
|
||||
pass
|
||||
|
||||
def _find_attribute(self, attribute_name):
|
||||
node_tpl = self._find_node_template(self.args[0])
|
||||
found = [
|
||||
attr for attr in node_tpl.type_definition.attributes_def
|
||||
if attr.name == attribute_name]
|
||||
if len(found) == 0:
|
||||
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(
|
||||
attribute_name, node_tpl.name))
|
||||
return found[0]
|
||||
"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):
|
||||
found = [attr for attr in type_definition.attributes_def
|
||||
if attr.name == self.attribute_name]
|
||||
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.capabilities:
|
||||
if capability.type in hosted_on_rel['valid_targets']:
|
||||
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 == node_template_name:
|
||||
if node_template.name == name:
|
||||
return node_template
|
||||
raise KeyError(_(
|
||||
'No such node template: {0}.').format(node_template_name))
|
||||
|
@ -0,0 +1,32 @@
|
||||
tosca_definitions_version: tosca_simple_1.0
|
||||
|
||||
description: >
|
||||
TOSCA template for testing get_attribute with HOST keyword.
|
||||
|
||||
node_templates:
|
||||
server:
|
||||
type: tosca.nodes.Compute
|
||||
properties:
|
||||
os_type: Linux
|
||||
|
||||
dbms:
|
||||
type: tosca.nodes.DBMS
|
||||
requirements:
|
||||
- host: server
|
||||
interfaces:
|
||||
tosca.interfaces.node.Lifecycle:
|
||||
configure:
|
||||
implementation: configure.sh
|
||||
input:
|
||||
ip_address: { get_attribute: [ HOST, ip_address ] }
|
||||
|
||||
database:
|
||||
type: tosca.nodes.Database
|
||||
requirements:
|
||||
- host: dbms
|
||||
interfaces:
|
||||
tosca.interfaces.node.Lifecycle:
|
||||
configure:
|
||||
implementation: configure.sh
|
||||
input:
|
||||
ip_address: { get_attribute: [ HOST, ip_address ] }
|
@ -0,0 +1,16 @@
|
||||
tosca_definitions_version: tosca_simple_1.0
|
||||
|
||||
description: >
|
||||
TOSCA template for testing get_attribute with HOST keyword.
|
||||
|
||||
node_templates:
|
||||
server:
|
||||
type: tosca.nodes.Compute
|
||||
properties:
|
||||
os_type: Linux
|
||||
interfaces:
|
||||
tosca.interfaces.node.Lifecycle:
|
||||
configure:
|
||||
implementation: configure.sh
|
||||
input:
|
||||
ip_address: { get_attribute: [ HOST, ip_address ] }
|
@ -0,0 +1,14 @@
|
||||
tosca_definitions_version: tosca_simple_1.0
|
||||
|
||||
description: >
|
||||
TOSCA template for testing get_attribute with HOST keyword.
|
||||
|
||||
node_templates:
|
||||
server:
|
||||
type: tosca.nodes.Compute
|
||||
properties:
|
||||
os_type: Linux
|
||||
|
||||
outputs:
|
||||
ip_address:
|
||||
value: { get_attribute: [ HOST, ip_address ] }
|
@ -143,3 +143,40 @@ class GetAttributeTest(TestCase):
|
||||
'functions/test_get_attribute_unknown_attribute_name.yaml')
|
||||
self.assertIn('unknown_attribute', six.text_type(err))
|
||||
self.assertIn('server', six.text_type(err))
|
||||
|
||||
def test_get_attribute_host_keyword(self):
|
||||
tpl = self._load_template(
|
||||
'functions/test_get_attribute_host_keyword.yaml')
|
||||
|
||||
def assert_get_attribute_host_functionality(node_template_name):
|
||||
node = [x for x in tpl.nodetemplates
|
||||
if x.name == node_template_name][0]
|
||||
configure_op = [
|
||||
x for x in node.interfaces if x.name == 'configure'][0]
|
||||
ip_addr_input = configure_op.input['ip_address']
|
||||
self.assertIsInstance(ip_addr_input, functions.GetAttribute)
|
||||
self.assertEqual('server',
|
||||
ip_addr_input.get_referenced_node_template().name)
|
||||
|
||||
assert_get_attribute_host_functionality('dbms')
|
||||
assert_get_attribute_host_functionality('database')
|
||||
|
||||
def test_get_attribute_host_not_found(self):
|
||||
err = self.assertRaises(
|
||||
ValueError,
|
||||
self._load_template,
|
||||
'functions/test_get_attribute_host_not_found.yaml')
|
||||
self.assertIn(
|
||||
"get_attribute HOST keyword is used in 'server' node template but "
|
||||
"tosca.relationships.HostedOn was not found in relationship chain",
|
||||
six.text_type(err))
|
||||
|
||||
def test_get_attribute_illegal_host_in_outputs(self):
|
||||
err = self.assertRaises(
|
||||
ValueError,
|
||||
self._load_template,
|
||||
'functions/test_get_attribute_illegal_host_in_outputs.yaml')
|
||||
self.assertIn(
|
||||
"get_attribute HOST keyword is not allowed within the outputs "
|
||||
"section of the TOSCA template",
|
||||
six.text_type(err))
|
||||
|
Loading…
x
Reference in New Issue
Block a user