Merge "custom interfaces can be used in node_templates"
This commit is contained in:
@@ -22,6 +22,9 @@ SECTIONS = (LIFECYCLE, CONFIGURE, LIFECYCLE_SHORTNAME,
|
|||||||
|
|
||||||
INTERFACEVALUE = (IMPLEMENTATION, INPUTS) = ('implementation', 'inputs')
|
INTERFACEVALUE = (IMPLEMENTATION, INPUTS) = ('implementation', 'inputs')
|
||||||
|
|
||||||
|
INTERFACE_DEF_RESERVED_WORDS = ['type', 'inputs', 'derived_from', 'version',
|
||||||
|
'description']
|
||||||
|
|
||||||
|
|
||||||
class InterfacesDef(StatefulEntityType):
|
class InterfacesDef(StatefulEntityType):
|
||||||
'''TOSCA built-in interfaces type.'''
|
'''TOSCA built-in interfaces type.'''
|
||||||
@@ -40,8 +43,16 @@ class InterfacesDef(StatefulEntityType):
|
|||||||
interfacetype = LIFECYCLE
|
interfacetype = LIFECYCLE
|
||||||
if interfacetype == CONFIGURE_SHORTNAME:
|
if interfacetype == CONFIGURE_SHORTNAME:
|
||||||
interfacetype = CONFIGURE
|
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:
|
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 value:
|
||||||
if isinstance(self.value, dict):
|
if isinstance(self.value, dict):
|
||||||
for i, j in self.value.items():
|
for i, j in self.value.items():
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ from toscaparser.common.exception import ValidationError
|
|||||||
from toscaparser.dataentity import DataEntity
|
from toscaparser.dataentity import DataEntity
|
||||||
from toscaparser.elements.interfaces import CONFIGURE
|
from toscaparser.elements.interfaces import CONFIGURE
|
||||||
from toscaparser.elements.interfaces import CONFIGURE_SHORTNAME
|
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 InterfacesDef
|
||||||
from toscaparser.elements.interfaces import LIFECYCLE
|
from toscaparser.elements.interfaces import LIFECYCLE
|
||||||
from toscaparser.elements.interfaces import LIFECYCLE_SHORTNAME
|
from toscaparser.elements.interfaces import LIFECYCLE_SHORTNAME
|
||||||
@@ -247,23 +248,42 @@ class NodeTemplate(EntityTemplate):
|
|||||||
ifaces = self.type_definition.get_value(self.INTERFACES,
|
ifaces = self.type_definition.get_value(self.INTERFACES,
|
||||||
self.entity_tpl)
|
self.entity_tpl)
|
||||||
if ifaces:
|
if ifaces:
|
||||||
for i in ifaces:
|
for name, value in ifaces.items():
|
||||||
for name, value in ifaces.items():
|
if name in (LIFECYCLE, LIFECYCLE_SHORTNAME):
|
||||||
if name in (LIFECYCLE, LIFECYCLE_SHORTNAME):
|
self._common_validate_field(
|
||||||
self._common_validate_field(
|
value, InterfacesDef.
|
||||||
value, InterfacesDef.
|
interfaces_node_lifecycle_operations,
|
||||||
interfaces_node_lifecycle_operations,
|
'interfaces')
|
||||||
'interfaces')
|
elif name in (CONFIGURE, CONFIGURE_SHORTNAME):
|
||||||
elif name in (CONFIGURE, CONFIGURE_SHORTNAME):
|
self._common_validate_field(
|
||||||
self._common_validate_field(
|
value, InterfacesDef.
|
||||||
value, InterfacesDef.
|
interfaces_relationship_configure_operations,
|
||||||
interfaces_relationship_configure_operations,
|
'interfaces')
|
||||||
'interfaces')
|
elif name in self.type_definition.interfaces.keys():
|
||||||
else:
|
self._common_validate_field(
|
||||||
ExceptionCollector.appendException(
|
value,
|
||||||
UnknownFieldError(
|
self._collect_custom_iface_operations(name),
|
||||||
what='"interfaces" of template "%s"' %
|
'interfaces')
|
||||||
self.name, field=name))
|
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):
|
def _validate_fields(self, nodetemplate):
|
||||||
for name in nodetemplate.keys():
|
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'}
|
'db_root_pwd': '12345678'}
|
||||||
self.assertIsNotNone(ToscaTemplate(tpl_path, params))
|
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):
|
def test_first_level_sections(self):
|
||||||
tpl_path = os.path.join(
|
tpl_path = os.path.join(
|
||||||
os.path.dirname(os.path.abspath(__file__)),
|
os.path.dirname(os.path.abspath(__file__)),
|
||||||
|
|||||||
@@ -35,14 +35,14 @@ SECTIONS = (DEFINITION_VERSION, DEFAULT_NAMESPACE, TEMPLATE_NAME,
|
|||||||
TOPOLOGY_TEMPLATE, TEMPLATE_AUTHOR, TEMPLATE_VERSION,
|
TOPOLOGY_TEMPLATE, TEMPLATE_AUTHOR, TEMPLATE_VERSION,
|
||||||
DESCRIPTION, IMPORTS, DSL_DEFINITIONS, NODE_TYPES,
|
DESCRIPTION, IMPORTS, DSL_DEFINITIONS, NODE_TYPES,
|
||||||
RELATIONSHIP_TYPES, RELATIONSHIP_TEMPLATES,
|
RELATIONSHIP_TYPES, RELATIONSHIP_TEMPLATES,
|
||||||
CAPABILITY_TYPES, ARTIFACT_TYPES, DATA_TYPES,
|
CAPABILITY_TYPES, ARTIFACT_TYPES, DATA_TYPES, INTERFACE_TYPES,
|
||||||
POLICY_TYPES, GROUP_TYPES, REPOSITORIES) = \
|
POLICY_TYPES, GROUP_TYPES, REPOSITORIES) = \
|
||||||
('tosca_definitions_version', 'tosca_default_namespace',
|
('tosca_definitions_version', 'tosca_default_namespace',
|
||||||
'template_name', 'topology_template', 'template_author',
|
'template_name', 'topology_template', 'template_author',
|
||||||
'template_version', 'description', 'imports', 'dsl_definitions',
|
'template_version', 'description', 'imports', 'dsl_definitions',
|
||||||
'node_types', 'relationship_types', 'relationship_templates',
|
'node_types', 'relationship_types', 'relationship_templates',
|
||||||
'capability_types', 'artifact_types', 'data_types',
|
'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
|
# Sections that are specific to individual template definitions
|
||||||
SPECIAL_SECTIONS = (METADATA) = ('metadata')
|
SPECIAL_SECTIONS = (METADATA) = ('metadata')
|
||||||
|
|
||||||
@@ -161,7 +161,7 @@ class ToscaTemplate(object):
|
|||||||
|
|
||||||
def _get_all_custom_defs(self, imports=None):
|
def _get_all_custom_defs(self, imports=None):
|
||||||
types = [IMPORTS, NODE_TYPES, CAPABILITY_TYPES, RELATIONSHIP_TYPES,
|
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_final = {}
|
||||||
custom_defs = self._get_custom_types(types, imports)
|
custom_defs = self._get_custom_types(types, imports)
|
||||||
if custom_defs:
|
if custom_defs:
|
||||||
|
|||||||
Reference in New Issue
Block a user