Merge "custom interfaces can be used in node_templates"
This commit is contained in:
commit
debd7053a2
@ -22,6 +22,9 @@ SECTIONS = (LIFECYCLE, CONFIGURE, LIFECYCLE_SHORTNAME,
|
||||
|
||||
INTERFACEVALUE = (IMPLEMENTATION, INPUTS) = ('implementation', 'inputs')
|
||||
|
||||
INTERFACE_DEF_RESERVED_WORDS = ['type', 'inputs', 'derived_from', 'version',
|
||||
'description']
|
||||
|
||||
|
||||
class InterfacesDef(StatefulEntityType):
|
||||
'''TOSCA built-in interfaces type.'''
|
||||
@ -40,8 +43,16 @@ class InterfacesDef(StatefulEntityType):
|
||||
interfacetype = LIFECYCLE
|
||||
if interfacetype == CONFIGURE_SHORTNAME:
|
||||
interfacetype = CONFIGURE
|
||||
if hasattr(self.ntype, 'interfaces') \
|
||||
and self.ntype.interfaces \
|
||||
and interfacetype in self.ntype.interfaces:
|
||||
interfacetype = self.ntype.interfaces[interfacetype]['type']
|
||||
if node_type:
|
||||
self.defs = self.TOSCA_DEF[interfacetype]
|
||||
if self.node_template.custom_def \
|
||||
and interfacetype in self.node_template.custom_def:
|
||||
self.defs = self.node_template.custom_def[interfacetype]
|
||||
else:
|
||||
self.defs = self.TOSCA_DEF[interfacetype]
|
||||
if value:
|
||||
if isinstance(self.value, dict):
|
||||
for i, j in self.value.items():
|
||||
|
@ -22,6 +22,7 @@ from toscaparser.common.exception import ValidationError
|
||||
from toscaparser.dataentity import DataEntity
|
||||
from toscaparser.elements.interfaces import CONFIGURE
|
||||
from toscaparser.elements.interfaces import CONFIGURE_SHORTNAME
|
||||
from toscaparser.elements.interfaces import INTERFACE_DEF_RESERVED_WORDS
|
||||
from toscaparser.elements.interfaces import InterfacesDef
|
||||
from toscaparser.elements.interfaces import LIFECYCLE
|
||||
from toscaparser.elements.interfaces import LIFECYCLE_SHORTNAME
|
||||
@ -247,23 +248,42 @@ class NodeTemplate(EntityTemplate):
|
||||
ifaces = self.type_definition.get_value(self.INTERFACES,
|
||||
self.entity_tpl)
|
||||
if ifaces:
|
||||
for i in ifaces:
|
||||
for name, value in ifaces.items():
|
||||
if name in (LIFECYCLE, LIFECYCLE_SHORTNAME):
|
||||
self._common_validate_field(
|
||||
value, InterfacesDef.
|
||||
interfaces_node_lifecycle_operations,
|
||||
'interfaces')
|
||||
elif name in (CONFIGURE, CONFIGURE_SHORTNAME):
|
||||
self._common_validate_field(
|
||||
value, InterfacesDef.
|
||||
interfaces_relationship_configure_operations,
|
||||
'interfaces')
|
||||
else:
|
||||
ExceptionCollector.appendException(
|
||||
UnknownFieldError(
|
||||
what='"interfaces" of template "%s"' %
|
||||
self.name, field=name))
|
||||
for name, value in ifaces.items():
|
||||
if name in (LIFECYCLE, LIFECYCLE_SHORTNAME):
|
||||
self._common_validate_field(
|
||||
value, InterfacesDef.
|
||||
interfaces_node_lifecycle_operations,
|
||||
'interfaces')
|
||||
elif name in (CONFIGURE, CONFIGURE_SHORTNAME):
|
||||
self._common_validate_field(
|
||||
value, InterfacesDef.
|
||||
interfaces_relationship_configure_operations,
|
||||
'interfaces')
|
||||
elif name in self.type_definition.interfaces.keys():
|
||||
self._common_validate_field(
|
||||
value,
|
||||
self._collect_custom_iface_operations(name),
|
||||
'interfaces')
|
||||
else:
|
||||
ExceptionCollector.appendException(
|
||||
UnknownFieldError(
|
||||
what='"interfaces" of template "%s"' %
|
||||
self.name, field=name))
|
||||
|
||||
def _collect_custom_iface_operations(self, name):
|
||||
allowed_operations = []
|
||||
nodetype_iface_def = self.type_definition.interfaces[name]
|
||||
allowed_operations.extend(nodetype_iface_def.keys())
|
||||
if 'type' in nodetype_iface_def:
|
||||
iface_type = nodetype_iface_def['type']
|
||||
if iface_type in self.type_definition.custom_def:
|
||||
iface_type_def = self.type_definition.custom_def[iface_type]
|
||||
else:
|
||||
iface_type_def = self.type_definition.TOSCA_DEF[iface_type]
|
||||
allowed_operations.extend(iface_type_def.keys())
|
||||
allowed_operations = [op for op in allowed_operations if
|
||||
op not in INTERFACE_DEF_RESERVED_WORDS]
|
||||
return allowed_operations
|
||||
|
||||
def _validate_fields(self, nodetemplate):
|
||||
for name in nodetemplate.keys():
|
||||
|
20
toscaparser/tests/data/custom_types/custom_interface.yaml
Normal file
20
toscaparser/tests/data/custom_types/custom_interface.yaml
Normal file
@ -0,0 +1,20 @@
|
||||
tosca_definitions_version: tosca_simple_yaml_1_0
|
||||
|
||||
description: >
|
||||
This template contains custom defined interface type
|
||||
and a node type which uses this custom interface
|
||||
|
||||
interface_types:
|
||||
tosca.interfaces.CustomInterface:
|
||||
derived_from: tosca.interfaces.Root
|
||||
CustomOp:
|
||||
CustomOp2:
|
||||
|
||||
node_types:
|
||||
tosca.nodes.CustomInterfaceTest:
|
||||
derived_from: tosca.nodes.WebApplication
|
||||
interfaces:
|
||||
CustomInterface:
|
||||
type: tosca.interfaces.CustomInterface
|
||||
CustomOp3:
|
||||
|
@ -0,0 +1,23 @@
|
||||
tosca_definitions_version: tosca_simple_yaml_1_0
|
||||
|
||||
description: >
|
||||
TOSCA simple profile with valid custom interface and operations.
|
||||
|
||||
imports:
|
||||
- custom_types/custom_interface.yaml
|
||||
|
||||
topology_template:
|
||||
|
||||
node_templates:
|
||||
customInterfaceTest:
|
||||
type: tosca.nodes.CustomInterfaceTest
|
||||
interfaces:
|
||||
CustomInterface:
|
||||
CustomOp: # operation from interface_type with additional inputs
|
||||
inputs:
|
||||
param:
|
||||
type: string
|
||||
CustomOp3: # operation from node_type with additional inputs
|
||||
inputs:
|
||||
param3:
|
||||
type: string
|
@ -0,0 +1,19 @@
|
||||
tosca_definitions_version: tosca_simple_yaml_1_0
|
||||
|
||||
description: >
|
||||
TOSCA simple profile with invalid custom operation.
|
||||
|
||||
imports:
|
||||
- custom_types/custom_interface.yaml
|
||||
|
||||
topology_template:
|
||||
|
||||
node_templates:
|
||||
customInterfaceTest:
|
||||
type: tosca.nodes.CustomInterfaceTest
|
||||
interfaces:
|
||||
CustomInterface:
|
||||
CustomOp4: # invalid operation
|
||||
inputs:
|
||||
param3:
|
||||
type: string
|
@ -39,6 +39,24 @@ class ToscaTemplateValidationTest(TestCase):
|
||||
'db_root_pwd': '12345678'}
|
||||
self.assertIsNotNone(ToscaTemplate(tpl_path, params))
|
||||
|
||||
def test_custom_interface_allowed(self):
|
||||
tpl_path = os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"data/test_custom_interface_in_template.yaml")
|
||||
self.assertIsNotNone(ToscaTemplate(tpl_path))
|
||||
|
||||
def test_custom_interface_invalid_operation(self):
|
||||
tpl_path = os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"data/test_custom_interface_invalid_operation.yaml")
|
||||
self.assertRaises(exception.ValidationError,
|
||||
ToscaTemplate, tpl_path)
|
||||
exception.ExceptionCollector.assertExceptionMessage(
|
||||
exception.UnknownFieldError,
|
||||
_('"interfaces" of template "customInterfaceTest" '
|
||||
'contains unknown field "CustomOp4". '
|
||||
'Refer to the definition to verify valid values.'))
|
||||
|
||||
def test_first_level_sections(self):
|
||||
tpl_path = os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
|
@ -35,14 +35,14 @@ SECTIONS = (DEFINITION_VERSION, DEFAULT_NAMESPACE, TEMPLATE_NAME,
|
||||
TOPOLOGY_TEMPLATE, TEMPLATE_AUTHOR, TEMPLATE_VERSION,
|
||||
DESCRIPTION, IMPORTS, DSL_DEFINITIONS, NODE_TYPES,
|
||||
RELATIONSHIP_TYPES, RELATIONSHIP_TEMPLATES,
|
||||
CAPABILITY_TYPES, ARTIFACT_TYPES, DATA_TYPES,
|
||||
CAPABILITY_TYPES, ARTIFACT_TYPES, DATA_TYPES, INTERFACE_TYPES,
|
||||
POLICY_TYPES, GROUP_TYPES, REPOSITORIES) = \
|
||||
('tosca_definitions_version', 'tosca_default_namespace',
|
||||
'template_name', 'topology_template', 'template_author',
|
||||
'template_version', 'description', 'imports', 'dsl_definitions',
|
||||
'node_types', 'relationship_types', 'relationship_templates',
|
||||
'capability_types', 'artifact_types', 'data_types',
|
||||
'policy_types', 'group_types', 'repositories')
|
||||
'interface_types', 'policy_types', 'group_types', 'repositories')
|
||||
# Sections that are specific to individual template definitions
|
||||
SPECIAL_SECTIONS = (METADATA) = ('metadata')
|
||||
|
||||
@ -161,7 +161,7 @@ class ToscaTemplate(object):
|
||||
|
||||
def _get_all_custom_defs(self, imports=None):
|
||||
types = [IMPORTS, NODE_TYPES, CAPABILITY_TYPES, RELATIONSHIP_TYPES,
|
||||
DATA_TYPES, POLICY_TYPES, GROUP_TYPES]
|
||||
DATA_TYPES, INTERFACE_TYPES, POLICY_TYPES, GROUP_TYPES]
|
||||
custom_defs_final = {}
|
||||
custom_defs = self._get_custom_types(types, imports)
|
||||
if custom_defs:
|
||||
|
Loading…
Reference in New Issue
Block a user