Added a module for intrinsic function.
Curenntly only handles get_ref_property specified in interface operation input. Renamed ntype to node_type. Change-Id: I4d95b28faba9b55a5d16b9f16dbe36bd3bcd5b4d Implements: blueprint tosca-ref-property
This commit is contained in:
parent
37851cabfc
commit
2f2e84123a
2
.gitignore
vendored
2
.gitignore
vendored
@ -49,3 +49,5 @@ ChangeLog
|
||||
# Editors
|
||||
*~
|
||||
.*.swp
|
||||
.idea
|
||||
*.iml
|
@ -14,6 +14,7 @@
|
||||
# under the License.
|
||||
|
||||
from translator.toscalib.elements.statefulentitytype import StatefulEntityType
|
||||
from translator.toscalib.functions import get_function
|
||||
|
||||
SECTIONS = (LIFECYCLE, CONFIGURE) = \
|
||||
('tosca.interfaces.node.Lifecycle',
|
||||
@ -23,17 +24,17 @@ SECTIONS = (LIFECYCLE, CONFIGURE) = \
|
||||
class InterfacesDef(StatefulEntityType):
|
||||
'''TOSCA built-in interfaces type.'''
|
||||
|
||||
def __init__(self, ntype, interfacetype,
|
||||
tpl_name=None, name=None, value=None):
|
||||
self.nodetype = ntype
|
||||
self.tpl_name = tpl_name
|
||||
def __init__(self, node_type, interfacetype,
|
||||
node_template=None, name=None, value=None):
|
||||
self.ntype = node_type
|
||||
self.node_template = node_template
|
||||
self.type = interfacetype
|
||||
self.name = name
|
||||
self.value = value
|
||||
self.implementation = None
|
||||
self.input = None
|
||||
self.defs = {}
|
||||
if ntype:
|
||||
if node_type:
|
||||
self.defs = self.TOSCA_DEF[interfacetype]
|
||||
if value:
|
||||
if isinstance(self.value, dict):
|
||||
@ -41,10 +42,19 @@ class InterfacesDef(StatefulEntityType):
|
||||
if i == 'implementation':
|
||||
self.implementation = j
|
||||
if i == 'input':
|
||||
self.input = j
|
||||
self.input = self._create_input_functions(j)
|
||||
else:
|
||||
self.implementation = value
|
||||
|
||||
def _create_input_functions(self, raw_input):
|
||||
"""Creates input functions if necessary.
|
||||
:param raw_input: Raw input as dict.
|
||||
:return: Modified input dict containing template functions.
|
||||
:rtype: dict
|
||||
"""
|
||||
return dict((k, get_function(self.node_template, v))
|
||||
for (k, v) in raw_input.items())
|
||||
|
||||
@property
|
||||
def lifecycle_ops(self):
|
||||
if self.defs:
|
||||
|
111
translator/toscalib/functions.py
Normal file
111
translator/toscalib/functions.py
Normal file
@ -0,0 +1,111 @@
|
||||
#
|
||||
# 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 abc
|
||||
|
||||
|
||||
GET_PROPERTY = 'get_property'
|
||||
GET_REF_PROPERTY = 'get_ref_property'
|
||||
|
||||
|
||||
class Function(object):
|
||||
"""An abstract type for representing a Tosca template function."""
|
||||
|
||||
__metaclass__ = abc.ABCMeta
|
||||
|
||||
def __init__(self, node_template, func_name, args):
|
||||
self.node_template = node_template
|
||||
self.name = func_name
|
||||
self.args = args
|
||||
self.validate()
|
||||
|
||||
@abc.abstractmethod
|
||||
def result(self):
|
||||
"""Invokes the function and returns its result
|
||||
|
||||
Some methods invocation may only be relevant on runtime (for example,
|
||||
getting runtime properties) and therefore its the responsibility of
|
||||
the orchestrator/translator to take care of such functions invocation.
|
||||
|
||||
:return: Function invocation result.
|
||||
"""
|
||||
return {self.name: self.args}
|
||||
|
||||
def validate(self):
|
||||
"""Validates function arguments."""
|
||||
|
||||
|
||||
class GetRefProperty(Function):
|
||||
"""Get a property via a reference expressed in the requirements section.
|
||||
|
||||
Arguments:
|
||||
- Requirement name.
|
||||
- Capability name.
|
||||
- Property to get.
|
||||
|
||||
Example:
|
||||
get_ref_property: [ database_endpoint, database_endpoint, port ]
|
||||
"""
|
||||
|
||||
def validate(self):
|
||||
if len(self.args) != 3:
|
||||
raise ValueError(
|
||||
'Expected arguments: requirement, capability, property')
|
||||
|
||||
def result(self):
|
||||
requires = self.node_template.requirements
|
||||
name = None
|
||||
if requires:
|
||||
requirement = self.args[0]
|
||||
for r in requires:
|
||||
for cap, node in r.items():
|
||||
if cap == requirement:
|
||||
name = node
|
||||
break
|
||||
if name:
|
||||
from translator.toscalib.nodetemplate import NodeTemplate
|
||||
tpl = NodeTemplate(
|
||||
name, self.node_template.node_templates)
|
||||
caps = tpl.capabilities
|
||||
required_cap = self.args[1]
|
||||
required_property = self.args[2]
|
||||
for c in caps:
|
||||
if c.name == required_cap:
|
||||
return c.properties.get(required_property)
|
||||
|
||||
|
||||
function_mappings = {
|
||||
GET_REF_PROPERTY: GetRefProperty
|
||||
}
|
||||
|
||||
|
||||
def get_function(node_template, raw_function):
|
||||
"""Gets a Function instance representing the provided template function.
|
||||
|
||||
If the format provided raw_function format is not relevant for template
|
||||
functions or if the function name doesn't exist in function mapping the
|
||||
method returns the provided raw_function.
|
||||
|
||||
:param node_template: The node template the function is specified for.
|
||||
:param raw_function: The raw function as dict.
|
||||
:return: Template function as Function instance or the raw_function if
|
||||
parsing was unsuccessful.
|
||||
"""
|
||||
if isinstance(raw_function, dict) and len(raw_function) == 1:
|
||||
func_name = list(raw_function.keys())[0]
|
||||
if func_name in function_mappings:
|
||||
func = function_mappings[func_name]
|
||||
func_args = list(raw_function.values())[0]
|
||||
return func(node_template, func_name, func_args)
|
||||
return raw_function
|
@ -78,14 +78,17 @@ class NodeTemplate(object):
|
||||
@property
|
||||
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)
|
||||
interfaces.append(iface)
|
||||
type_interfaces = self.node_type.get_value(INTERFACES,
|
||||
self.node_template)
|
||||
if type_interfaces:
|
||||
for interface_type, value in type_interfaces.items():
|
||||
for op, op_def in value.items():
|
||||
iface = InterfacesDef(self.node_type,
|
||||
interfacetype=interface_type,
|
||||
node_template=self,
|
||||
name=op,
|
||||
value=op_def)
|
||||
interfaces.append(iface)
|
||||
return interfaces
|
||||
|
||||
@property
|
||||
|
@ -14,6 +14,7 @@
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
from translator.toscalib.functions import GetRefProperty
|
||||
from translator.toscalib.tests.base import TestCase
|
||||
from translator.toscalib.tosca_template import ToscaTemplate
|
||||
|
||||
@ -104,3 +105,36 @@ class ToscaTemplateTest(TestCase):
|
||||
self.assertEqual(
|
||||
['website_url'],
|
||||
sorted([output.name for output in self.tosca.outputs]))
|
||||
|
||||
def test_interfaces(self):
|
||||
wordpress_node = [
|
||||
node for node in self.tosca.nodetemplates
|
||||
if node.name == 'wordpress'][0]
|
||||
interfaces = wordpress_node.interfaces
|
||||
self.assertEqual(2, len(interfaces))
|
||||
for interface in interfaces:
|
||||
if interface.name == 'create':
|
||||
self.assertEqual('tosca.interfaces.node.Lifecycle',
|
||||
interface.type)
|
||||
self.assertEqual('wordpress_install.sh',
|
||||
interface.implementation)
|
||||
self.assertIsNone(interface.input)
|
||||
elif interface.name == 'configure':
|
||||
self.assertEqual('tosca.interfaces.node.Lifecycle',
|
||||
interface.type)
|
||||
self.assertEqual('wordpress_configure.sh',
|
||||
interface.implementation)
|
||||
self.assertEqual(4, len(interface.input))
|
||||
wp_db_port = interface.input['wp_db_port']
|
||||
self.assertTrue(isinstance(wp_db_port, GetRefProperty))
|
||||
self.assertEqual('get_ref_property', wp_db_port.name)
|
||||
self.assertEqual(['database_endpoint',
|
||||
'database_endpoint',
|
||||
'port'],
|
||||
wp_db_port.args)
|
||||
result = wp_db_port.result()
|
||||
self.assertEqual(1, len(result))
|
||||
self.assertEqual('db_port', result['get_input'])
|
||||
else:
|
||||
raise AssertionError(
|
||||
'Unexpected interface: {0}'.format(interface.name))
|
||||
|
Loading…
Reference in New Issue
Block a user