Merge "custom interfaces can be used in node_templates"

This commit is contained in:
Jenkins 2016-11-23 14:34:43 +00:00 committed by Gerrit Code Review
commit debd7053a2
7 changed files with 132 additions and 21 deletions

View File

@ -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():

View File

@ -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():

View 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:

View File

@ -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

View File

@ -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

View File

@ -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__)),

View 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: