You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ariatosca.apache.org by em...@apache.org on 2017/10/31 19:34:04 UTC
[09/13] incubator-ariatosca git commit: ARIA-1 Parser test suite
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b89fdde2/extensions/aria_extension_tosca/simple_v1_0/modeling/parameters.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/parameters.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/parameters.py
index 9bafeec..60d760a 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/parameters.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/parameters.py
@@ -88,7 +88,7 @@ def get_assigned_and_defined_parameter_values(context, presentation, field_name)
definition = definitions[name]
values[name] = coerce_parameter_value(context, value, definition, value.value)
else:
- context.validation.report('assignment to undefined {0} "{1}" in "{2}"'
+ context.validation.report(u'assignment to undefined {0} "{1}" in "{2}"'
.format(field_name, name, presentation._fullname),
locator=value._locator, level=Issue.BETWEEN_TYPES)
@@ -99,7 +99,7 @@ def get_assigned_and_defined_parameter_values(context, presentation, field_name)
if (name not in values) and \
(('default' in definition._raw) or (field_name == 'attribute')):
values[name] = coerce_parameter_value(context, presentation, definition,
- definition.default)
+ definition.default, 'default')
validate_required_values(context, presentation, values, definitions)
@@ -147,11 +147,21 @@ def validate_required_values(context, presentation, values, definitions):
if not definitions:
return
+
+ def has_value(name):
+ if values is None:
+ return False
+ value = values.get(name)
+ if value is None:
+ return False
+ if isinstance(value, Value) and (value.value is None):
+ return False
+ return True
+
for name, definition in definitions.iteritems():
- if getattr(definition, 'required', False) and \
- ((values is None) or (values.get(name) is None)):
- context.validation.report('required property "%s" is not assigned a value in "%s"'
- % (name, presentation._fullname),
+ if getattr(definition, 'required', False) and not has_value(name):
+ context.validation.report(u'required property "{0}" is not assigned a value in "{1}"'
+ .format(name, presentation._fullname),
locator=presentation._get_child_locator('properties'),
level=Issue.BETWEEN_TYPES)
@@ -166,14 +176,14 @@ def merge_raw_parameter_definition(context, presentation, raw_property_definitio
our_property_definition._reset_method_cache()
type2 = our_property_definition._get_type(context)
- if type1 != type2:
- if not hasattr(type1, '_is_descendant') or not type1._is_descendant(context, type2):
- context.validation.report(
- 'property definition type "{0}" is not a descendant of overridden '
- 'property definition type "{1}"' \
- .format(type1_name, type2._name),
- locator=presentation._get_child_locator(field_name, property_name),
- level=Issue.BETWEEN_TYPES)
+ if (type1 is not type2) and \
+ (not hasattr(type1, '_is_descendant') or not type1._is_descendant(context, type2)):
+ context.validation.report(
+ u'property definition type "{0}" is not a descendant of overridden '
+ u'property definition type "{1}"' \
+ .format(our_property_definition.type, type1_name),
+ locator=presentation._get_child_locator(field_name, property_name),
+ level=Issue.BETWEEN_TYPES)
merge(raw_property_definition, our_property_definition._raw)
@@ -225,6 +235,5 @@ def coerce_parameter_value(context, presentation, definition, value, aspect=None
def convert_parameter_definitions_to_values(context, definitions):
values = OrderedDict()
for name, definition in definitions.iteritems():
- default = definition.default
- values[name] = coerce_parameter_value(context, definition, definition, default)
+ values[name] = coerce_parameter_value(context, definition, definition, definition.default)
return values
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b89fdde2/extensions/aria_extension_tosca/simple_v1_0/modeling/requirements.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/requirements.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/requirements.py
index 6bdb5b1..79958a1 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/requirements.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/requirements.py
@@ -82,7 +82,6 @@ def get_template_requirements(context, presentation):
for requirement_name, requirement_definition in requirement_definitions:
# Allowed occurrences
allowed_occurrences = requirement_definition.occurrences
- allowed_occurrences = allowed_occurrences if allowed_occurrences is not None else None
# Count actual occurrences
actual_occurrences = 0
@@ -103,28 +102,30 @@ def get_template_requirements(context, presentation):
None, presentation)
validate_requirement_assignment(context, presentation, requirement_assignment,
relationship_property_definitions,
- relationship_interface_definitions)
+ relationship_interface_definitions,
+ requirement_definition)
requirement_assignments.append((requirement_name, requirement_assignment))
elif actual_occurrences > 1:
context.validation.report(
- 'requirement "%s" is allowed only one occurrence in "%s": %d'
- % (requirement_name, presentation._fullname, actual_occurrences),
+ u'requirement "{0}" is allowed only one occurrence in "{1}": {2:d}'
+ .format(requirement_name, presentation._fullname, actual_occurrences),
locator=presentation._locator, level=Issue.BETWEEN_TYPES)
else:
if not allowed_occurrences.is_in(actual_occurrences):
if allowed_occurrences.value[1] == 'UNBOUNDED':
context.validation.report(
- 'requirement "%s" does not have at least %d occurrences in "%s": has %d'
- % (requirement_name, allowed_occurrences.value[0],
- presentation._fullname, actual_occurrences),
+ u'requirement "{0}" does not have at least {1:d} occurrences in "{3}":'
+ u' has {4:d}'
+ .format(requirement_name, allowed_occurrences.value[0],
+ presentation._fullname, actual_occurrences),
locator=presentation._locator, level=Issue.BETWEEN_TYPES)
else:
context.validation.report(
- 'requirement "%s" is allowed between %d and %d occurrences in "%s":'
- ' has %d'
- % (requirement_name, allowed_occurrences.value[0],
- allowed_occurrences.value[1], presentation._fullname,
- actual_occurrences),
+ u'requirement "{0}" is allowed between {1:d} and {2:d} occurrences in'
+ u' "{3}": has {4:d}'
+ .format(requirement_name, allowed_occurrences.value[0],
+ allowed_occurrences.value[1], presentation._fullname,
+ actual_occurrences),
locator=presentation._locator, level=Issue.BETWEEN_TYPES)
return requirement_assignments
@@ -134,7 +135,7 @@ def get_template_requirements(context, presentation):
# Utils
#
-def convert_requirement_from_definition_to_assignment(context, requirement_definition, # pylint: disable=too-many-branches
+def convert_requirement_from_definition_to_assignment(context, requirement_definition, # pylint: disable=too-many-branches
our_requirement_assignment, container):
from ..assignments import RequirementAssignment
@@ -174,9 +175,9 @@ def convert_requirement_from_definition_to_assignment(context, requirement_defin
# Make sure the type is derived
if not definition_relationship_type._is_descendant(context, relationship_type):
context.validation.report(
- 'assigned relationship type "%s" is not a descendant of declared relationship type'
- ' "%s"' \
- % (relationship_type._name, definition_relationship_type._name),
+ u'assigned relationship type "{0}" is not a descendant of declared relationship '
+ u' type "{1}"'
+ .format(relationship_type._name, definition_relationship_type._name),
locator=container._locator, level=Issue.BETWEEN_TYPES)
if relationship_type is not None:
@@ -253,12 +254,13 @@ def add_requirement_assignments(context, presentation, requirement_assignments,
or our_requirement_assignment,
requirement_assignment,
relationship_property_definitions,
- relationship_interface_definitions)
+ relationship_interface_definitions,
+ requirement_definition)
requirement_assignments.append((requirement_name, requirement_assignment))
else:
- context.validation.report('requirement "%s" not declared at node type "%s" in "%s"'
- % (requirement_name, presentation.type,
- presentation._fullname),
+ context.validation.report(u'requirement "{0}" not declared at node type "{1}" in "{2}"'
+ .format(requirement_name, presentation.type,
+ presentation._fullname),
locator=our_requirement_assignment._locator,
level=Issue.BETWEEN_TYPES)
@@ -278,7 +280,7 @@ def merge_requirement_assignment(context, relationship_property_definitions,
requirement._raw['node_filter'] = deepcopy_with_locators(our_node_filter._raw)
our_relationship = our_requirement.relationship # RelationshipAssignment
- if (our_relationship is not None) and (our_relationship.type is None):
+ if our_relationship is not None:
# Make sure we have a dict
if 'relationship' not in requirement._raw:
requirement._raw['relationship'] = OrderedDict()
@@ -291,7 +293,8 @@ def merge_requirement_assignment(context, relationship_property_definitions,
def merge_requirement_assignment_relationship(context, presentation, property_definitions,
interface_definitions, requirement, our_relationship):
- our_relationship_properties = our_relationship._raw.get('properties')
+ our_relationship_properties = our_relationship._raw.get('properties') \
+ if isinstance(our_relationship._raw, dict) else None
if our_relationship_properties:
# Make sure we have a dict
if 'properties' not in requirement._raw['relationship']:
@@ -305,10 +308,10 @@ def merge_requirement_assignment_relationship(context, presentation, property_de
coerce_parameter_value(context, presentation, definition, prop)
else:
context.validation.report(
- 'relationship property "%s" not declared at definition of requirement "%s"'
- ' in "%s"'
- % (property_name, requirement._fullname,
- presentation._container._container._fullname),
+ u'relationship property "{0}" not declared at definition of requirement "{1}"'
+ u' in "{2}"'
+ .format(property_name, requirement._fullname,
+ presentation._container._container._fullname),
locator=our_relationship._get_child_locator('properties', property_name),
level=Issue.BETWEEN_TYPES)
@@ -330,28 +333,58 @@ def merge_requirement_assignment_relationship(context, presentation, property_de
interface_definition, interface_name)
else:
context.validation.report(
- 'relationship interface "%s" not declared at definition of requirement "%s"'
- ' in "%s"'
- % (interface_name, requirement._fullname,
- presentation._container._container._fullname),
+ u'relationship interface "{0}" not declared at definition of requirement "{1}"'
+ u' in "{2}"'
+ .format(interface_name, requirement._fullname,
+ presentation._container._container._fullname),
locator=our_relationship._locator, level=Issue.BETWEEN_TYPES)
def validate_requirement_assignment(context, presentation, requirement_assignment,
relationship_property_definitions,
- relationship_interface_definitions):
+ relationship_interface_definitions, requirement_definition):
+ # Validate node
+ definition_node_type = requirement_definition._get_node_type(context)
+ assignment_node_type, node_variant = requirement_assignment._get_node(context)
+ if node_variant == 'node_template':
+ assignment_node_type = assignment_node_type._get_type(context)
+ if (assignment_node_type is not None) and (definition_node_type is not None) and \
+ (assignment_node_type is not definition_node_type) and \
+ (not definition_node_type._is_descendant(context, assignment_node_type)):
+ context.validation.report(
+ u'requirement assignment node "{0}" is not derived from node type "{1}" of requirement '
+ u'definition in {2}'
+ .format(requirement_assignment.node, requirement_definition.node,
+ presentation._container._fullname),
+ locator=presentation._locator, level=Issue.BETWEEN_TYPES)
+
+ # Validate capability
+ definition_capability_type = requirement_definition._get_capability_type(context)
+ assignment_capability_type, capability_variant = requirement_assignment._get_capability(context)
+ if capability_variant == 'capability_assignment':
+ assignment_capability_type = assignment_capability_type._get_type(context)
+ if (assignment_capability_type is not None) and (definition_capability_type is not None) and \
+ (assignment_capability_type is not definition_capability_type) and \
+ (not definition_capability_type._is_descendant(context, assignment_capability_type)):
+ context.validation.report(
+ u'requirement assignment capability "{0}" is not derived from capability type "{1}" of '
+ u'requirement definition in {2}'
+ .format(requirement_assignment.capability, requirement_definition.capability,
+ presentation._container._fullname),
+ locator=presentation._locator, level=Issue.BETWEEN_TYPES)
+
relationship = requirement_assignment.relationship
- if relationship is None:
- return
- validate_required_values(context, presentation, relationship.properties,
- relationship_property_definitions)
+ values = OrderedDict((name, prop.value)
+ for name, prop in relationship.properties.iteritems()) \
+ if (relationship and relationship.properties) else {}
+ validate_required_values(context, presentation, values, relationship_property_definitions)
if relationship_interface_definitions:
for interface_name, relationship_interface_definition \
in relationship_interface_definitions.iteritems():
interface_assignment = relationship.interfaces.get(interface_name) \
- if relationship.interfaces is not None else None
+ if (relationship and relationship.interfaces) else None
validate_required_inputs(context, presentation, interface_assignment,
relationship_interface_definition, None, interface_name)
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b89fdde2/extensions/aria_extension_tosca/simple_v1_0/modeling/substitution_mappings.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/substitution_mappings.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/substitution_mappings.py
index e2af4b8..ae2f924 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/substitution_mappings.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/substitution_mappings.py
@@ -18,8 +18,7 @@ from aria.parser.validation import Issue
def validate_substitution_mappings_requirement(context, presentation):
-
- # validate that the requirement in substitution_mapping is defined in the substitution node type
+ # Validate that the requirement in substitution_mapping is defined in the substitution node type
substitution_node_type = presentation._container._get_type(context)
if substitution_node_type is None:
return
@@ -29,7 +28,7 @@ def validate_substitution_mappings_requirement(context, presentation):
break
else:
context.validation.report(
- 'substitution mapping requirement "{0}" is not declared in node type "{1}"'.format(
+ u'substitution mapping requirement "{0}" is not declared in node type "{1}"'.format(
presentation._name, substitution_node_type._name),
locator=presentation._locator, level=Issue.BETWEEN_TYPES)
return
@@ -38,7 +37,7 @@ def validate_substitution_mappings_requirement(context, presentation):
_report_invalid_mapping_format(context, presentation, field='requirement')
return
- # validate that the mapped requirement is defined in the corresponding node template
+ # Validate that the mapped requirement is defined in the corresponding node template
node_template = _get_node_template(context, presentation)
if node_template is None:
_report_missing_node_template(context, presentation, field='requirement')
@@ -50,24 +49,24 @@ def validate_substitution_mappings_requirement(context, presentation):
break
else:
context.validation.report(
- 'substitution mapping requirement "{0}" refers to an unknown requirement of node '
- 'template "{1}": {mapped_requirement_name}'.format(
+ u'substitution mapping requirement "{0}" refers to an unknown requirement of node '
+ u'template "{1}": {mapped_requirement_name}'.format(
presentation._name, node_template._name,
mapped_requirement_name=safe_repr(mapped_requirement_name)),
locator=presentation._locator, level=Issue.BETWEEN_TYPES)
return
- # validate that the requirement's capability type in substitution_mapping is derived from the
+ # Validate that the requirement's capability type in substitution_mapping is derived from the
# requirement's capability type in the corresponding node template
substitution_type_requirement_capability_type = \
substitution_type_requirement._get_capability_type(context)
node_template_requirement_capability_type = \
node_template_requirement._get_capability(context)[0]
- if not node_template_requirement_capability_type._is_descendant(
- context, substitution_type_requirement_capability_type):
+ if not substitution_type_requirement_capability_type._is_descendant(
+ context, node_template_requirement_capability_type):
context.validation.report(
- 'substitution mapping requirement "{0}" of capability type "{1}" is not a descendant '
- 'of the mapped node template capability type "{2}"'.format(
+ u'substitution mapping requirement "{0}" of capability type "{1}" is not a descendant '
+ u'of the mapped node template capability type "{2}"'.format(
presentation._name,
substitution_type_requirement_capability_type._name,
node_template_requirement_capability_type._name),
@@ -75,8 +74,7 @@ def validate_substitution_mappings_requirement(context, presentation):
def validate_substitution_mappings_capability(context, presentation):
-
- # validate that the capability in substitution_mapping is defined in the substitution node type
+ # Validate that the capability in substitution_mapping is defined in the substitution node type
substitution_node_type = presentation._container._get_type(context)
if substitution_node_type is None:
return
@@ -84,8 +82,8 @@ def validate_substitution_mappings_capability(context, presentation):
substitution_type_capability = substitution_type_capabilities.get(presentation._name)
if substitution_type_capability is None:
context.validation.report(
- 'substitution mapping capability "{0}" '
- 'is not declared in node type "{substitution_type}"'.format(
+ u'substitution mapping capability "{0}" '
+ u'is not declared in node type "{substitution_type}"'.format(
presentation._name, substitution_type=substitution_node_type._name),
locator=presentation._locator, level=Issue.BETWEEN_TYPES)
return
@@ -94,7 +92,7 @@ def validate_substitution_mappings_capability(context, presentation):
_report_invalid_mapping_format(context, presentation, field='capability')
return
- # validate that the capability in substitution_mapping is declared in the corresponding
+ # Validate that the capability in substitution_mapping is declared in the corresponding
# node template
node_template = _get_node_template(context, presentation)
if node_template is None:
@@ -105,22 +103,21 @@ def validate_substitution_mappings_capability(context, presentation):
if node_template_capability is None:
context.validation.report(
- 'substitution mapping capability "{0}" refers to an unknown '
- 'capability of node template "{1}": {mapped_capability_name}'.format(
+ u'substitution mapping capability "{0}" refers to an unknown '
+ u'capability of node template "{1}": {mapped_capability_name}'.format(
presentation._name, node_template._name,
mapped_capability_name=safe_repr(mapped_capability_name)),
locator=presentation._locator, level=Issue.BETWEEN_TYPES)
return
- # validate that the capability type in substitution_mapping is derived from the capability type
+ # Validate that the capability type in substitution_mapping is derived from the capability type
# in the corresponding node template
substitution_type_capability_type = substitution_type_capability._get_type(context)
node_template_capability_type = node_template_capability._get_type(context)
-
if not substitution_type_capability_type._is_descendant(context, node_template_capability_type):
context.validation.report(
- 'node template capability type "{0}" is not a descendant of substitution mapping '
- 'capability "{1}" of type "{2}"'.format(
+ u'node template capability type "{0}" is not a descendant of substitution mapping '
+ u'capability "{1}" of type "{2}"'.format(
node_template_capability_type._name,
presentation._name,
substitution_type_capability_type._name),
@@ -132,7 +129,9 @@ def validate_substitution_mappings_capability(context, presentation):
#
def _validate_mapping_format(presentation):
- """Validate that the mapping is a list of 2 strings"""
+ """
+ Validate that the mapping is a list of 2 strings.
+ """
if not isinstance(presentation._raw, list) or \
len(presentation._raw) != 2 or \
not isinstance(presentation._raw[0], basestring) or \
@@ -150,8 +149,8 @@ def _get_node_template(context, presentation):
def _report_missing_node_template(context, presentation, field):
context.validation.report(
- 'substitution mappings {field} "{node_template_mapping}" '
- 'refers to an unknown node template: {node_template_name}'.format(
+ u'substitution mappings {field} "{node_template_mapping}" '
+ u'refers to an unknown node template: {node_template_name}'.format(
field=field,
node_template_mapping=presentation._name,
node_template_name=safe_repr(presentation._raw[0])),
@@ -160,7 +159,7 @@ def _report_missing_node_template(context, presentation, field):
def _report_invalid_mapping_format(context, presentation, field):
context.validation.report(
- 'substitution mapping {field} "{field_name}" is not a list of 2 strings: {value}'.format(
+ u'substitution mapping {field} "{field_name}" is not a list of 2 strings: {value}'.format(
field=field,
field_name=presentation._name,
value=safe_repr(presentation._raw)),
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b89fdde2/extensions/aria_extension_tosca/simple_v1_0/presentation/extensible.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/presentation/extensible.py b/extensions/aria_extension_tosca/simple_v1_0/presentation/extensible.py
index 0e3c94d..9fa056d 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/presentation/extensible.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/presentation/extensible.py
@@ -30,4 +30,4 @@ class ExtensiblePresentation(Presentation):
@cachedmethod
def _get_extension(self, name, default=None):
extensions = self._extensions
- return extensions.get(name, default) if extensions is not None else None # pylint: disable=no-member
+ return extensions.get(name, default) if extensions is not None else None # pylint: disable=no-member
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b89fdde2/extensions/aria_extension_tosca/simple_v1_0/presentation/field_getters.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/presentation/field_getters.py b/extensions/aria_extension_tosca/simple_v1_0/presentation/field_getters.py
index f14164a..9cd58e2 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/presentation/field_getters.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/presentation/field_getters.py
@@ -14,10 +14,12 @@
# limitations under the License.
from aria.utils.formatting import safe_repr
+from aria.utils.type import full_type_name
from aria.parser.exceptions import InvalidValueError
+from aria.parser.presentation import NULL
-def data_type_class_getter(cls):
+def data_type_class_getter(cls, allow_null=False):
"""
Wraps the field value in a specialized data type class.
@@ -26,12 +28,14 @@ def data_type_class_getter(cls):
def getter(field, presentation, context=None):
raw = field.default_get(presentation, context)
- if raw is not None:
- try:
- return cls(None, None, raw, None)
- except ValueError as e:
- raise InvalidValueError(
- '%s is not a valid "%s" in "%s": %s'
- % (field.full_name, field.full_cls_name, presentation._name, safe_repr(raw)),
- cause=e, locator=field.get_locator(raw))
+ if (raw is None) or (allow_null and (raw is NULL)):
+ return raw
+ try:
+ return cls(None, None, raw, None)
+ except ValueError as e:
+ raise InvalidValueError(
+ u'{0} is not a valid "{1}" in "{2}": {3}'
+ .format(field.full_name, full_type_name(cls), presentation._name,
+ safe_repr(raw)),
+ cause=e, locator=field.get_locator(raw))
return getter
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b89fdde2/extensions/aria_extension_tosca/simple_v1_0/presentation/field_validators.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/presentation/field_validators.py b/extensions/aria_extension_tosca/simple_v1_0/presentation/field_validators.py
index e5853d8..2ff5143 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/presentation/field_validators.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/presentation/field_validators.py
@@ -52,8 +52,8 @@ def copy_validator(template_type_name, templates_dict_name):
else:
if copy.copy is not None:
context.validation.report(
- '"copy" field refers to a %s that itself is a copy in "%s": %s'
- % (template_type_name, presentation._fullname, safe_repr(value)),
+ u'"copy" field refers to a {0} that itself is a copy in "{1}": {2}'
+ .format(template_type_name, presentation._fullname, safe_repr(value)),
locator=presentation._locator, level=Issue.BETWEEN_TYPES)
return validator_fn
@@ -84,8 +84,8 @@ def data_type_validator(type_name='data type'):
container_data_type = get_container_data_type(presentation)
if (container_data_type is not None) and (container_data_type._name == value):
context.validation.report(
- 'type of property "%s" creates a circular value hierarchy: %s'
- % (presentation._fullname, safe_repr(value)),
+ u'type of property "{0}" creates a circular value hierarchy: {1}'
+ .format(presentation._fullname, safe_repr(value)),
locator=presentation._get_child_locator('type'), level=Issue.BETWEEN_TYPES)
# Can be a complex data type
@@ -135,14 +135,14 @@ def entry_schema_validator(field, presentation, context):
if use_entry_schema:
if value is None:
context.validation.report(
- '"entry_schema" does not have a value as required by data type "%s" in "%s"'
- % (get_data_type_name(the_type), presentation._container._fullname),
+ u'"entry_schema" does not have a value as required by data type "{0}" in "{1}"'
+ .format(get_data_type_name(the_type), presentation._container._fullname),
locator=presentation._locator, level=Issue.BETWEEN_TYPES)
else:
if value is not None:
context.validation.report(
- '"entry_schema" has a value but it is not used by data type "%s" in "%s"'
- % (get_data_type_name(the_type), presentation._container._fullname),
+ u'"entry_schema" has a value but it is not used by data type "{0}" in "{1}"'
+ .format(get_data_type_name(the_type), presentation._container._fullname),
locator=presentation._locator, level=Issue.BETWEEN_TYPES)
@@ -201,8 +201,8 @@ def data_type_constraints_validator(field, presentation, context):
if value is not None:
if presentation._get_primitive_ancestor(context) is None:
context.validation.report(
- 'data type "%s" defines constraints but does not have a primitive ancestor'
- % presentation._fullname,
+ u'data type "{0}" defines constraints but does not have a primitive ancestor'
+ .format(presentation._fullname),
locator=presentation._get_child_locator(field.name), level=Issue.BETWEEN_TYPES)
@@ -220,8 +220,8 @@ def data_type_properties_validator(field, presentation, context):
if values is not None:
if presentation._get_primitive_ancestor(context) is not None:
context.validation.report(
- 'data type "%s" defines properties even though it has a primitive ancestor'
- % presentation._fullname,
+ u'data type "{0}" defines properties even though it has a primitive ancestor'
+ .format(presentation._fullname),
locator=presentation._get_child_locator(field.name), level=Issue.BETWEEN_TYPES)
@@ -272,17 +272,18 @@ def constraint_clause_in_range_validator(field, presentation, context):
# Upper bound be coercible
upper = coerce_value(context, presentation, the_type, None, None, upper, field.name)
- # Second "in_range" value must be greater than first
+ # Second "in_range" value must be greater or equal than first
if (lower is not None) and (upper is not None) and (lower >= upper):
context.validation.report(
- 'upper bound of "in_range" constraint is not greater than the lower bound'
- ' in "%s": %s <= %s'
- % (presentation._container._fullname, safe_repr(lower), safe_repr(upper)),
+ u'upper bound of "in_range" constraint is not greater than the lower bound'
+ u' in "{0}": {1} <= {2}'
+ .format(presentation._container._fullname, safe_repr(lower),
+ safe_repr(upper)),
locator=presentation._locator, level=Issue.FIELD)
else:
context.validation.report(
- 'constraint "%s" is not a list of exactly 2 elements in "%s"'
- % (field.name, presentation._fullname),
+ u'constraint "{0}" is not a list of exactly 2 elements in "{1}": {2}'
+ .format(field.name, presentation._fullname, safe_repr(values)),
locator=presentation._get_child_locator(field.name), level=Issue.FIELD)
@@ -325,8 +326,8 @@ def constraint_clause_pattern_validator(field, presentation, context):
re.compile(value)
except re.error as e:
context.validation.report(
- 'constraint "%s" is not a valid regular expression in "%s"'
- % (field.name, presentation._fullname),
+ u'constraint "{0}" is not a valid regular expression in "{1}": {2}'
+ .format(field.name, presentation._fullname, safe_repr(value)),
locator=presentation._get_child_locator(field.name), level=Issue.FIELD, exception=e)
@@ -379,21 +380,21 @@ def capability_definition_or_type_validator(field, presentation, context):
if get_type_by_name(context, value, 'capability_types') is not None:
if node is not None:
context.validation.report(
- '"%s" refers to a capability type even though "node" has a value in "%s"'
- % (presentation._name, presentation._container._fullname),
+ u'"{0}" refers to a capability type even though "node" has a value in "{1}"'
+ .format(presentation._name, presentation._container._fullname),
locator=presentation._get_child_locator(field.name), level=Issue.BETWEEN_FIELDS)
return
if node_variant == 'node_template':
context.validation.report(
- 'requirement "%s" refers to an unknown capability definition name or capability'
- ' type in "%s": %s'
- % (presentation._name, presentation._container._fullname, safe_repr(value)),
+ u'requirement "{0}" refers to an unknown capability definition name or capability'
+ u' type in "{1}": {2}'
+ .format(presentation._name, presentation._container._fullname, safe_repr(value)),
locator=presentation._get_child_locator(field.name), level=Issue.BETWEEN_TYPES)
else:
context.validation.report(
- 'requirement "%s" refers to an unknown capability type in "%s": %s'
- % (presentation._name, presentation._container._fullname, safe_repr(value)),
+ u'requirement "{0}" refers to an unknown capability type in "{1}": {2}'
+ .format(presentation._name, presentation._container._fullname, safe_repr(value)),
locator=presentation._get_child_locator(field.name), level=Issue.BETWEEN_TYPES)
@@ -412,9 +413,9 @@ def node_filter_validator(field, presentation, context):
_, node_type_variant = presentation._get_node(context)
if node_type_variant != 'node_type':
context.validation.report(
- 'requirement "%s" has a node filter even though "node" does not refer to a node'
- ' type in "%s"'
- % (presentation._fullname, presentation._container._fullname),
+ u'requirement "{0}" has a node filter even though "node" does not refer to a node'
+ u' type in "{1}"'
+ .format(presentation._fullname, presentation._container._fullname),
locator=presentation._locator, level=Issue.BETWEEN_FIELDS)
@@ -468,6 +469,54 @@ def list_node_type_or_group_type_validator(field, presentation, context):
#
+# GroupTemplate
+#
+
+def group_members_validator(field, presentation, context):
+ """
+ Makes sure that the field's elements refer to node templates and that they match the node types
+ declared in the group type.
+
+ Used with the :func:`field_validator` decorator for the ``targets`` field in
+ :class:`GroupTemplate`.
+ """
+
+ field.default_validate(presentation, context)
+
+ values = getattr(presentation, field.name)
+ if values is not None:
+ node_templates = \
+ context.presentation.get('service_template', 'topology_template', 'node_templates') \
+ or {}
+ for value in values:
+ if value not in node_templates:
+ report_issue_for_unknown_type(context, presentation, 'node template', field.name,
+ value)
+
+ group_type = presentation._get_type(context)
+ if group_type is None:
+ break
+
+ node_types = group_type._get_members(context)
+
+ is_valid = False
+
+ if value in node_templates:
+ our_node_type = node_templates[value]._get_type(context)
+ for node_type in node_types:
+ if node_type._is_descendant(context, our_node_type):
+ is_valid = True
+ break
+
+ if not is_valid:
+ context.validation.report(
+ u'group definition target does not match a node type'
+ u' declared in the group type in "{0}": {1}'
+ .format(presentation._name, safe_repr(value)),
+ locator=presentation._locator, level=Issue.BETWEEN_TYPES)
+
+
+#
# PolicyTemplate
#
@@ -484,13 +533,12 @@ def policy_targets_validator(field, presentation, context):
values = getattr(presentation, field.name)
if values is not None:
- for value in values:
- node_templates = \
- context.presentation.get('service_template', 'topology_template',
- 'node_templates') \
- or {}
- groups = context.presentation.get('service_template', 'topology_template', 'groups') \
+ node_templates = \
+ context.presentation.get('service_template', 'topology_template', 'node_templates') \
or {}
+ groups = context.presentation.get('service_template', 'topology_template', 'groups') \
+ or {}
+ for value in values:
if (value not in node_templates) and (value not in groups):
report_issue_for_unknown_type(context, presentation, 'node template or group',
field.name, value)
@@ -519,9 +567,9 @@ def policy_targets_validator(field, presentation, context):
if not is_valid:
context.validation.report(
- 'policy definition target does not match either a node type or a group type'
- ' declared in the policy type in "%s": %s'
- % (presentation._name, safe_repr(value)),
+ u'policy definition target does not match either a node type or a group type'
+ u' declared in the policy type in "{0}": {1}'
+ .format(presentation._name, safe_repr(value)),
locator=presentation._locator, level=Issue.BETWEEN_TYPES)
@@ -547,8 +595,8 @@ def node_filter_properties_validator(field, presentation, context):
for name, _ in values:
if name not in properties:
context.validation.report(
- 'node filter refers to an unknown property definition in "%s": %s'
- % (node_type._name, name),
+ u'node filter refers to an unknown property definition in "{0}": {1}'
+ .format(node_type._name, name),
locator=presentation._locator, level=Issue.BETWEEN_TYPES)
@@ -564,7 +612,7 @@ def node_filter_capabilities_validator(field, presentation, context):
field.default_validate(presentation, context)
values = getattr(presentation, field.name)
- if values is not None: # pylint: disable=too-many-nested-blocks
+ if values is not None: # pylint: disable=too-many-nested-blocks
node_type = presentation._get_node_type(context)
if node_type is not None:
capabilities = node_type._get_capabilities(context)
@@ -577,12 +625,12 @@ def node_filter_capabilities_validator(field, presentation, context):
for property_name, _ in properties:
if property_name not in capability_properties:
context.validation.report(
- 'node filter refers to an unknown capability definition'
- ' property in "%s": %s'
- % (node_type._name, property_name),
+ u'node filter refers to an unknown capability definition'
+ u' property in "{0}": {1}'
+ .format(node_type._name, property_name),
locator=presentation._locator, level=Issue.BETWEEN_TYPES)
else:
context.validation.report(
- 'node filter refers to an unknown capability definition in "%s": %s'
- % (node_type._name, name),
+ u'node filter refers to an unknown capability definition in "{0}": {1}'
+ .format(node_type._name, name),
locator=presentation._locator, level=Issue.BETWEEN_TYPES)
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b89fdde2/extensions/aria_extension_tosca/simple_v1_0/presentation/types.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/presentation/types.py b/extensions/aria_extension_tosca/simple_v1_0/presentation/types.py
index 5f9750e..f31b6c9 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/presentation/types.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/presentation/types.py
@@ -14,7 +14,7 @@
# limitations under the License.
-def convert_name_to_full_type_name(context, name, types_dict): # pylint: disable=unused-argument
+def convert_name_to_full_type_name(context, name, types_dict): # pylint: disable=unused-argument
"""
Converts a type name to its full type name, or else returns it unchanged.
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b89fdde2/extensions/aria_extension_tosca/simple_v1_0/presenter.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/presenter.py b/extensions/aria_extension_tosca/simple_v1_0/presenter.py
index 28c9f7b..3aca91d 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/presenter.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/presenter.py
@@ -23,7 +23,7 @@ from .modeling.functions import (Concat, Token, GetInput, GetProperty, GetAttrib
from .templates import ServiceTemplate
-class ToscaSimplePresenter1_0(Presenter): # pylint: disable=invalid-name,abstract-method
+class ToscaSimplePresenter1_0(Presenter): # pylint: disable=invalid-name,abstract-method
"""
ARIA presenter for the `TOSCA Simple Profile v1.0 cos01 <http://docs.oasis-open.org/tosca
/TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html>`__.
@@ -78,5 +78,5 @@ class ToscaSimplePresenter1_0(Presenter): # pylint: disable=invalid-name,abstrac
return FrozenList(import_locations) if import_locations else EMPTY_READ_ONLY_LIST
@cachedmethod
- def _get_model(self, context): # pylint: disable=no-self-use
+ def _get_model(self, context): # pylint: disable=no-self-use
return create_service_template_model(context)
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b89fdde2/extensions/aria_extension_tosca/simple_v1_0/templates.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/templates.py b/extensions/aria_extension_tosca/simple_v1_0/templates.py
index 3c36bb8..d4d012e 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/templates.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/templates.py
@@ -19,11 +19,11 @@ from aria.parser import implements_specification
from aria.parser.presentation import (has_fields, primitive_field, primitive_list_field,
object_field, object_list_field, object_dict_field,
object_sequenced_list_field, field_validator,
- type_validator, list_type_validator)
+ type_validator)
from .assignments import (PropertyAssignment, AttributeAssignment, RequirementAssignment,
CapabilityAssignment, InterfaceAssignment, ArtifactAssignment)
-from .definitions import ParameterDefinition
+from .definitions import (InputDefinition, OutputDefinition)
from .filters import NodeFilter
from .misc import (Description, MetaData, Repository, Import, SubstitutionMappings)
from .modeling.parameters import (get_assigned_and_defined_parameter_values, get_parameter_values)
@@ -34,7 +34,8 @@ from .modeling.artifacts import get_inherited_artifact_definitions
from .modeling.policies import get_policy_targets
from .modeling.copy import get_default_raw_from_copy
from .presentation.extensible import ExtensiblePresentation
-from .presentation.field_validators import copy_validator, policy_targets_validator
+from .presentation.field_validators import (copy_validator, group_members_validator,
+ policy_targets_validator)
from .presentation.types import (convert_name_to_full_type_name, get_type_by_name)
from .types import (ArtifactType, DataType, CapabilityType, InterfaceType, RelationshipType,
NodeType, GroupType, PolicyType)
@@ -182,6 +183,7 @@ class NodeTemplate(ExtensiblePresentation):
def _validate(self, context):
super(NodeTemplate, self)._validate(context)
self._get_property_values(context)
+ self._get_attribute_default_values(context)
self._get_requirements(context)
self._get_capabilities(context)
self._get_interfaces(context)
@@ -284,12 +286,17 @@ class RelationshipTemplate(ExtensiblePresentation):
return FrozenDict(get_assigned_and_defined_parameter_values(context, self, 'property'))
@cachedmethod
+ def _get_attribute_default_values(self, context):
+ return FrozenDict(get_assigned_and_defined_parameter_values(context, self, 'attribute'))
+
+ @cachedmethod
def _get_interfaces(self, context):
return FrozenDict(get_template_interfaces(context, self, 'relationship template'))
def _validate(self, context):
super(RelationshipTemplate, self)._validate(context)
self._get_property_values(context)
+ self._get_attribute_default_values(context)
self._get_interfaces(context)
def _dump(self, context):
@@ -340,7 +347,7 @@ class GroupTemplate(ExtensiblePresentation):
:type: {:obj:`basestring`: :class:`PropertyAssignment`}
"""
- @field_validator(list_type_validator('node template', 'topology_template', 'node_templates'))
+ @field_validator(group_members_validator)
@primitive_list_field(str)
def members(self):
"""
@@ -464,13 +471,13 @@ class TopologyTemplate(ExtensiblePresentation):
:type: :class:`Description`
"""
- @object_dict_field(ParameterDefinition)
+ @object_dict_field(InputDefinition)
def inputs(self):
"""
An optional list of input parameters (i.e., as parameter definitions) for the Topology
Template.
- :type: {:obj:`basestring`: :class:`ParameterDefinition`}
+ :type: {:obj:`basestring`: :class:`InputDefinition`}
"""
@object_dict_field(NodeTemplate)
@@ -506,13 +513,13 @@ class TopologyTemplate(ExtensiblePresentation):
:type: {:obj:`basestring`: :class:`PolicyTemplate`}
"""
- @object_dict_field(ParameterDefinition)
+ @object_dict_field(OutputDefinition)
def outputs(self):
"""
An optional list of output parameters (i.e., as parameter definitions) for the Topology
Template.
- :type: {:obj:`basestring`: :class:`ParameterDefinition`}
+ :type: {:obj:`basestring`: :class:`OutputDefinition`}
"""
@object_field(SubstitutionMappings)
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b89fdde2/extensions/aria_extension_tosca/simple_v1_0/types.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/types.py b/extensions/aria_extension_tosca/simple_v1_0/types.py
index 43af44b..8ab7b07 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/types.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/types.py
@@ -34,6 +34,7 @@ from .modeling.capabilities import (get_inherited_valid_source_types,
from .modeling.data_types import (get_data_type, get_inherited_constraints, coerce_data_type_value,
validate_data_type_name)
from .modeling.interfaces import (get_inherited_interface_definitions, get_inherited_operations)
+from .modeling.groups import get_inherited_members
from .modeling.policies import get_inherited_targets
from .modeling.parameters import get_inherited_parameter_definitions
from .modeling.requirements import get_inherited_requirement_definitions
@@ -70,7 +71,7 @@ class ArtifactType(ExtensiblePresentation):
"""
@field_getter(data_type_class_getter(Version))
- @primitive_field()
+ @primitive_field(str)
def version(self):
"""
An optional version for the Artifact Type definition.
@@ -153,7 +154,8 @@ class DataType(ExtensiblePresentation):
:type: :obj:`basestring`
"""
- @object_field(Version)
+ @field_getter(data_type_class_getter(Version))
+ @primitive_field(str)
def version(self):
"""
An optional version for the Data Type definition.
@@ -210,7 +212,7 @@ class DataType(ExtensiblePresentation):
if not isinstance(parent, DataType):
return parent
else:
- return parent._get_primitive_ancestor(context) # pylint: disable=no-member
+ return parent._get_primitive_ancestor(context) # pylint: disable=no-member
return None
@cachedmethod
@@ -261,7 +263,8 @@ class CapabilityType(ExtensiblePresentation):
:type: :obj:`basestring`
"""
- @object_field(Version)
+ @field_getter(data_type_class_getter(Version))
+ @primitive_field(str)
def version(self):
"""
An optional version for the Capability Type definition.
@@ -312,7 +315,9 @@ class CapabilityType(ExtensiblePresentation):
@cachedmethod
def _is_descendant(self, context, other_type):
- """returns True iff `other_type` is a descendant of the represented capability type"""
+ """
+ Checks if ``other_type`` is our descendant (or equal to us).
+ """
if other_type is None:
return False
elif other_type._name == self._name:
@@ -324,12 +329,17 @@ class CapabilityType(ExtensiblePresentation):
return FrozenDict(get_inherited_parameter_definitions(context, self, 'properties'))
@cachedmethod
+ def _get_attributes(self, context):
+ return FrozenDict(get_inherited_parameter_definitions(context, self, 'attributes'))
+
+ @cachedmethod
def _get_valid_source_types(self, context):
return get_inherited_valid_source_types(context, self)
def _validate(self, context):
super(CapabilityType, self)._validate(context)
self._get_properties(context)
+ self._get_attributes(context)
def _dump(self, context):
self._dump_content(context, (
@@ -363,7 +373,8 @@ class InterfaceType(ExtensiblePresentation):
:type: :obj:`basestring`
"""
- @object_field(Version)
+ @field_getter(data_type_class_getter(Version))
+ @primitive_field(str)
def version(self):
"""
An optional version for the Interface Type definition.
@@ -417,8 +428,7 @@ class InterfaceType(ExtensiblePresentation):
def _validate(self, context):
super(InterfaceType, self)._validate(context)
self._get_inputs(context)
- for operation in self.operations.itervalues(): # pylint: disable=no-member
- operation._validate(context)
+ self._get_operations(context)
def _dump(self, context):
self._dump_content(context, (
@@ -450,7 +460,8 @@ class RelationshipType(ExtensiblePresentation):
:type: :obj:`basestring`
"""
- @object_field(Version)
+ @field_getter(data_type_class_getter(Version))
+ @primitive_field(str)
def version(self):
"""
An optional version for the Relationship Type definition.
@@ -508,6 +519,9 @@ class RelationshipType(ExtensiblePresentation):
@cachedmethod
def _is_descendant(self, context, the_type):
+ """
+ Checks if ``other_type`` is our descendant (or equal to us).
+ """
if the_type is None:
return False
elif the_type._name == self._name:
@@ -565,7 +579,8 @@ class NodeType(ExtensiblePresentation):
:type: :obj:`basestring`
"""
- @object_field(Version)
+ @field_getter(data_type_class_getter(Version))
+ @primitive_field(str)
def version(self):
"""
An optional version for the Node Type definition.
@@ -639,6 +654,9 @@ class NodeType(ExtensiblePresentation):
@cachedmethod
def _is_descendant(self, context, the_type):
+ """
+ Checks if ``other_type`` is our descendant (or equal to us).
+ """
if the_type is None:
return False
elif the_type._name == self._name:
@@ -721,7 +739,8 @@ class GroupType(ExtensiblePresentation):
:type: :obj:`basestring`
"""
- @object_field(Version)
+ @field_getter(data_type_class_getter(Version))
+ @primitive_field(str)
def version(self):
"""
An optional version for the Group Type definition.
@@ -775,6 +794,9 @@ class GroupType(ExtensiblePresentation):
@cachedmethod
def _is_descendant(self, context, the_type):
+ """
+ Checks if ``other_type`` is our descendant (or equal to us).
+ """
if the_type is None:
return False
elif the_type._name == self._name:
@@ -786,6 +808,11 @@ class GroupType(ExtensiblePresentation):
return FrozenDict(get_inherited_parameter_definitions(context, self, 'properties'))
@cachedmethod
+ def _get_members(self, context):
+ node_types = get_inherited_members(context, self)
+ return FrozenList(node_types)
+
+ @cachedmethod
def _get_interfaces(self, context):
return FrozenDict(get_inherited_interface_definitions(context, self, 'group type'))
@@ -827,7 +854,8 @@ class PolicyType(ExtensiblePresentation):
:type: :obj:`basestring`
"""
- @object_field(Version)
+ @field_getter(data_type_class_getter(Version))
+ @primitive_field(str)
def version(self):
"""
An optional version for the Policy Type definition.
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b89fdde2/requirements.in
----------------------------------------------------------------------
diff --git a/requirements.in b/requirements.in
index c5bfc78..f71a1ee 100644
--- a/requirements.in
+++ b/requirements.in
@@ -17,7 +17,7 @@ backports.shutil_get_terminal_size>=1, <2
blinker>=1.4, <1.5
bottle>=0.12, <0.13
CacheControl[filecache]>=0.11.0, <0.13
-click>=6, < 7
+click>=6, <7
click_didyoumean>=0.0.3, <0.1
colorama>=0.3, <=0.4
Jinja2>=2.9, <3.0
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b89fdde2/requirements.txt
----------------------------------------------------------------------
diff --git a/requirements.txt b/requirements.txt
index 2af8fe3..bbbe97b 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -7,15 +7,15 @@
backports.shutil-get-terminal-size==1.0.0
blinker==1.4
bottle==0.12.13
-cachecontrol[filecache]==0.12.1
+cachecontrol[filecache]==0.12.3
click-didyoumean==0.0.3
click==6.7
colorama==0.3.9
decorator==4.1.2 # via networkx
jinja2==2.9.6
-jsonpickle==0.9.4
+jsonpickle==0.9.5
lockfile==0.12.2 # via cachecontrol
-logutils==0.3.4.1
+logutils==0.3.5
markupsafe==1.0 # via jinja2
msgpack-python==0.4.8 # via cachecontrol
networkx==2.0
@@ -23,12 +23,12 @@ prettytable==0.7.2
psutil==5.4.0
requests==2.13.0
retrying==1.3.3
-ruamel.ordereddict==0.4.9 # via ruamel.yaml
+ruamel.ordereddict==0.4.13 # via ruamel.yaml
ruamel.yaml==0.15.34
shortuuid==0.5.0
-six==1.10.0 # via retrying
-sqlalchemy==1.1.6
-wagon==0.6.0
+six==1.11.0 # via retrying
+sqlalchemy==1.1.14
+wagon==0.6.1
wheel==0.29.0 # via wagon
# The following packages are considered to be unsafe in a requirements file:
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b89fdde2/setup.py
----------------------------------------------------------------------
diff --git a/setup.py b/setup.py
index 8483c5b..c833da8 100644
--- a/setup.py
+++ b/setup.py
@@ -60,7 +60,7 @@ extras_require = {
with open(os.path.join(root_dir, 'requirements.in')) as requirements:
for requirement in requirements.readlines():
- requirement = requirement.split('#')[0].strip() # Get rid of comments or trailing comments
+ requirement = requirement.split('#', 1)[0].strip() # Remove comments
if not requirement:
continue # Skip empty and comment lines
@@ -70,7 +70,7 @@ with open(os.path.join(root_dir, 'requirements.in')) as requirements:
# https://wheel.readthedocs.io/en/latest/index.html#defining-conditional-dependencies
# https://hynek.me/articles/conditional-python-dependencies/
if ';' in requirement:
- package, condition = requirement.split(';')
+ package, condition = requirement.split(';', 1)
cond_name = ':{0}'.format(condition.strip())
extras_require.setdefault(cond_name, [])
extras_require[cond_name].append(package.strip())
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b89fdde2/tests/end2end/test_hello_world.py
----------------------------------------------------------------------
diff --git a/tests/end2end/test_hello_world.py b/tests/end2end/test_hello_world.py
index 094ffc3..eeb1781 100644
--- a/tests/end2end/test_hello_world.py
+++ b/tests/end2end/test_hello_world.py
@@ -55,7 +55,7 @@ def _verify_deployed_service_in_storage(service_name, model_storage):
service = service_templates[0].services[service_name]
assert service.name == service_name
assert len(service.executions) == 1
- assert len(service.nodes) == 2
+ assert len(service.nodes) == 1
assert service.outputs['port'].value == 9090
assert all(node.state == node.STARTED for node in service.nodes.itervalues())
assert len(service.executions[0].logs) > 0
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b89fdde2/tests/extensions/__init__.py
----------------------------------------------------------------------
diff --git a/tests/extensions/__init__.py b/tests/extensions/__init__.py
new file mode 100644
index 0000000..ae1e83e
--- /dev/null
+++ b/tests/extensions/__init__.py
@@ -0,0 +1,14 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b89fdde2/tests/extensions/aria_extension_tosca/__init__.py
----------------------------------------------------------------------
diff --git a/tests/extensions/aria_extension_tosca/__init__.py b/tests/extensions/aria_extension_tosca/__init__.py
new file mode 100644
index 0000000..ae1e83e
--- /dev/null
+++ b/tests/extensions/aria_extension_tosca/__init__.py
@@ -0,0 +1,14 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b89fdde2/tests/extensions/aria_extension_tosca/aria_v1_0/__init__.py
----------------------------------------------------------------------
diff --git a/tests/extensions/aria_extension_tosca/aria_v1_0/__init__.py b/tests/extensions/aria_extension_tosca/aria_v1_0/__init__.py
new file mode 100644
index 0000000..ae1e83e
--- /dev/null
+++ b/tests/extensions/aria_extension_tosca/aria_v1_0/__init__.py
@@ -0,0 +1,14 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b89fdde2/tests/extensions/aria_extension_tosca/aria_v1_0/test_profile.py
----------------------------------------------------------------------
diff --git a/tests/extensions/aria_extension_tosca/aria_v1_0/test_profile.py b/tests/extensions/aria_extension_tosca/aria_v1_0/test_profile.py
new file mode 100644
index 0000000..14a2e8a
--- /dev/null
+++ b/tests/extensions/aria_extension_tosca/aria_v1_0/test_profile.py
@@ -0,0 +1,22 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+
+
+def test_profile(parser):
+ parser.parse_literal("""
+tosca_definitions_version: tosca_simple_yaml_1_0
+imports:
+ - aria-1.0
+""", import_profile=True, validate_normative=True).assert_success()
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b89fdde2/tests/extensions/aria_extension_tosca/conftest.py
----------------------------------------------------------------------
diff --git a/tests/extensions/aria_extension_tosca/conftest.py b/tests/extensions/aria_extension_tosca/conftest.py
new file mode 100644
index 0000000..a2020b7
--- /dev/null
+++ b/tests/extensions/aria_extension_tosca/conftest.py
@@ -0,0 +1,45 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+
+"""
+PyTest configuration module.
+
+Add support for a "--tosca-parser" CLI option.
+"""
+
+import pytest
+
+from ...mechanisms.parsing.aria import AriaParser
+
+
+def pytest_addoption(parser):
+ parser.addoption('--tosca-parser', action='store', default='aria', help='TOSCA parser')
+
+
+def pytest_report_header(config):
+ tosca_parser = config.getoption('--tosca-parser')
+ return 'tosca-parser: {0}'.format(tosca_parser)
+
+
+@pytest.fixture(scope='session')
+def parser(request):
+ tosca_parser = request.config.getoption('--tosca-parser')
+ verbose = request.config.getoption('verbose') > 0
+ if tosca_parser == 'aria':
+ with AriaParser() as p:
+ p.verbose = verbose
+ yield p
+ else:
+ pytest.fail('configured tosca-parser not supported: {0}'.format(tosca_parser))
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b89fdde2/tests/extensions/aria_extension_tosca/simple_nfv_v1_0/__init__.py
----------------------------------------------------------------------
diff --git a/tests/extensions/aria_extension_tosca/simple_nfv_v1_0/__init__.py b/tests/extensions/aria_extension_tosca/simple_nfv_v1_0/__init__.py
new file mode 100644
index 0000000..ae1e83e
--- /dev/null
+++ b/tests/extensions/aria_extension_tosca/simple_nfv_v1_0/__init__.py
@@ -0,0 +1,14 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b89fdde2/tests/extensions/aria_extension_tosca/simple_nfv_v1_0/test_profile.py
----------------------------------------------------------------------
diff --git a/tests/extensions/aria_extension_tosca/simple_nfv_v1_0/test_profile.py b/tests/extensions/aria_extension_tosca/simple_nfv_v1_0/test_profile.py
new file mode 100644
index 0000000..fb756bc
--- /dev/null
+++ b/tests/extensions/aria_extension_tosca/simple_nfv_v1_0/test_profile.py
@@ -0,0 +1,20 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+
+
+def test_profile(parser):
+ parser.parse_literal("""
+tosca_definitions_version: tosca_simple_profile_for_nfv_1_0
+""", import_profile=True, validate_normative=True).assert_success()
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b89fdde2/tests/extensions/aria_extension_tosca/simple_v1_0/__init__.py
----------------------------------------------------------------------
diff --git a/tests/extensions/aria_extension_tosca/simple_v1_0/__init__.py b/tests/extensions/aria_extension_tosca/simple_v1_0/__init__.py
new file mode 100644
index 0000000..ae1e83e
--- /dev/null
+++ b/tests/extensions/aria_extension_tosca/simple_v1_0/__init__.py
@@ -0,0 +1,14 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b89fdde2/tests/extensions/aria_extension_tosca/simple_v1_0/data.py
----------------------------------------------------------------------
diff --git a/tests/extensions/aria_extension_tosca/simple_v1_0/data.py b/tests/extensions/aria_extension_tosca/simple_v1_0/data.py
new file mode 100644
index 0000000..104e6bb
--- /dev/null
+++ b/tests/extensions/aria_extension_tosca/simple_v1_0/data.py
@@ -0,0 +1,82 @@
+# -*- coding: utf-8 -*-
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+
+
+# Keywords
+
+TYPE_NAME_PLURAL = {
+ 'artifact': 'artifacts',
+ 'data': 'datatypes',
+ 'capability': 'capabilities',
+ 'interface': 'interfaces',
+ 'relationship': 'relationships',
+ 'node': 'nodes',
+ 'group': 'groups',
+ 'policy': 'policies'
+}
+TEMPLATE_NAME_SECTIONS = {
+ 'node': 'node_templates',
+ 'group': 'groups',
+ 'relationship': 'relationship_templates',
+ 'policy': 'policies'
+}
+PRIMITIVE_TYPE_NAMES = ('string', 'integer', 'float', 'boolean')
+PARAMETER_TYPE_NAMES = PRIMITIVE_TYPE_NAMES + ('MyType',)
+CONSTRAINTS_WITH_VALUE = ('equal', 'greater_than', 'greater_or_equal', 'less_than', 'less_or_equal')
+CONSTRAINTS_WITH_VALUE_LIST = ('valid_values',)
+CONSTRAINTS_WITH_VALUE_RANGE = ('in_range',)
+CONSTRAINTS_WITH_VALUE_NON_NEGATIVE_INT = ('length', 'min_length', 'max_length')
+
+
+# Values
+
+PRIMITIVE_VALUES = ('null', 'true', 'a string', '123', '0.123', '[]', '{}')
+NOT_A_DICT = ('null', 'true', 'a string', '123', '0.123', '[]')
+NOT_A_DICT_WITH_ONE_KEY = NOT_A_DICT + ('{}', '{k1: v1, k2: v2}',)
+NOT_A_DICT_OR_STRING = ('null', 'true', '123', '0.123', '[]')
+NOT_A_LIST = ('null', 'true', 'a string', '123', '0.123', '{}')
+NOT_A_LIST_OF_TWO = NOT_A_LIST + ('[]', '[a]', '[a, b, c]')
+NOT_A_STRING = ('null', 'true', '123', '0.123', '[]', '{}')
+NOT_A_BOOL = ('null', 'a string', '123', '0.123', '[]', '{}')
+NOT_A_RANGE = NOT_A_LIST + (
+ '[]', '[ 1 ]', '[ 1, 2, 3 ]',
+ '[ 1, 1 ]', '[ 2, 1 ]',
+ '[ 1, a string ]', '[ a string, 1 ]',
+ '[ 1.5, 2 ]', '[ 1, 2.5 ]'
+)
+OCCURRENCES = ('[ 0, 1 ]', '[ 10, UNBOUNDED ]')
+BAD_OCCURRENCES = NOT_A_RANGE + ('[ -1, 1 ]', '[ 0, unbounded ]')
+GOOD_VERSIONS = ("'6.1'", '2.0.1', '3.1.0.beta', "'1.0.0.alpha-10'")
+BAD_VERSIONS = ('a_string', '1.2.3.4.5', '1.2.beta', '1.0.0.alpha-x')
+STATUSES = ('supported', 'unsupported', 'experimental', 'deprecated')
+PARAMETER_VALUES = (
+ ('string', 'a string'),
+ ('integer', '1'),
+ ('float', '1.1'),
+ ('MyType', '{my_field: a string}')
+)
+ENTRY_SCHEMA_VALUES = (
+ ('string', 'a string', 'another string'),
+ ('integer', '1', '2'),
+ ('float', '1.1', '2.2'),
+ ('MyType', '{my_field: a string}', '{}')
+)
+ENTRY_SCHEMA_VALUES_BAD = (
+ ('string', 'a string', '1'),
+ ('integer', '1', 'a string'),
+ ('float', '1.1', 'a string'),
+ ('MyType', '{my_field: a string}', 'a string')
+)
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b89fdde2/tests/extensions/aria_extension_tosca/simple_v1_0/functions/__init__.py
----------------------------------------------------------------------
diff --git a/tests/extensions/aria_extension_tosca/simple_v1_0/functions/__init__.py b/tests/extensions/aria_extension_tosca/simple_v1_0/functions/__init__.py
new file mode 100644
index 0000000..ae1e83e
--- /dev/null
+++ b/tests/extensions/aria_extension_tosca/simple_v1_0/functions/__init__.py
@@ -0,0 +1,14 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b89fdde2/tests/extensions/aria_extension_tosca/simple_v1_0/functions/test_function_concat.py
----------------------------------------------------------------------
diff --git a/tests/extensions/aria_extension_tosca/simple_v1_0/functions/test_function_concat.py b/tests/extensions/aria_extension_tosca/simple_v1_0/functions/test_function_concat.py
new file mode 100644
index 0000000..23a274a
--- /dev/null
+++ b/tests/extensions/aria_extension_tosca/simple_v1_0/functions/test_function_concat.py
@@ -0,0 +1,102 @@
+ # -*- coding: utf-8 -*-
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+
+
+def test_functions_concat_syntax_empty(parser):
+ parser.parse_literal("""
+tosca_definitions_version: tosca_simple_yaml_1_0
+node_types:
+ MyType:
+ properties:
+ my_parameter:
+ type: string
+topology_template:
+ node_templates:
+ my_node:
+ type: MyType
+ properties:
+ my_parameter: { concat: [] }
+""").assert_success()
+
+
+def test_functions_concat_strings(parser):
+ parser.parse_literal("""
+tosca_definitions_version: tosca_simple_yaml_1_0
+node_types:
+ MyType:
+ properties:
+ my_parameter:
+ type: string
+topology_template:
+ node_templates:
+ my_node:
+ type: MyType
+ properties:
+ my_parameter: { concat: [ a, b, c ] }
+""").assert_success()
+
+
+def test_functions_concat_mixed(parser):
+ parser.parse_literal("""
+tosca_definitions_version: tosca_simple_yaml_1_0
+node_types:
+ MyType:
+ properties:
+ my_parameter:
+ type: string
+topology_template:
+ node_templates:
+ my_node:
+ type: MyType
+ properties:
+ my_parameter: { concat: [ a, 1, 1.1, null, [], {} ] }
+""").assert_success()
+
+
+def test_functions_concat_nested(parser):
+ parser.parse_literal("""
+tosca_definitions_version: tosca_simple_yaml_1_0
+node_types:
+ MyType:
+ properties:
+ my_parameter:
+ type: string
+topology_template:
+ node_templates:
+ my_node:
+ type: MyType
+ properties:
+ my_parameter: { concat: [ a, { concat: [ b, c ] } ] }
+""").assert_success()
+
+
+# Unicode
+
+def test_functions_concat_unicode(parser):
+ parser.parse_literal("""
+tosca_definitions_version: tosca_simple_yaml_1_0
+node_types:
+ 類型:
+ properties:
+ 參數:
+ type: string
+topology_template:
+ node_templates:
+ 模板:
+ type: 類型
+ properties:
+ 參數: { concat: [ 一, 二, 三 ] }
+""").assert_success()
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b89fdde2/tests/extensions/aria_extension_tosca/simple_v1_0/functions/test_function_get_artifact.py
----------------------------------------------------------------------
diff --git a/tests/extensions/aria_extension_tosca/simple_v1_0/functions/test_function_get_artifact.py b/tests/extensions/aria_extension_tosca/simple_v1_0/functions/test_function_get_artifact.py
new file mode 100644
index 0000000..6fa1a3c
--- /dev/null
+++ b/tests/extensions/aria_extension_tosca/simple_v1_0/functions/test_function_get_artifact.py
@@ -0,0 +1,156 @@
+# -*- coding: utf-8 -*-
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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 pytest
+
+
+# Syntax
+
+def test_functions_get_artifact_syntax_empty(parser):
+ parser.parse_literal("""
+tosca_definitions_version: tosca_simple_yaml_1_0
+node_types:
+ MyType:
+ properties:
+ my_parameter:
+ type: string
+topology_template:
+ node_templates:
+ my_node:
+ type: MyType
+ properties:
+ my_parameter: { get_artifact: [] } # needs at least two args
+""").assert_failure()
+
+
+# Arguments
+
+def test_functions_get_artifact_2_arguments(parser):
+ parser.parse_literal("""
+tosca_definitions_version: tosca_simple_yaml_1_0
+artifact_types:
+ MyType: {}
+node_types:
+ MyType:
+ properties:
+ my_parameter:
+ type: string
+ artifacts:
+ my_artifact:
+ type: MyType
+ file: filename
+topology_template:
+ node_templates:
+ my_node:
+ type: MyType
+ properties:
+ my_parameter: { get_artifact: [ my_node, my_artifact ] }
+""").assert_success()
+
+
+@pytest.mark.xfail(reason='not yet implemented')
+def test_functions_get_artifact_unknown(parser):
+ parser.parse_literal("""
+tosca_definitions_version: tosca_simple_yaml_1_0
+artifact_types:
+ MyType: {}
+node_types:
+ MyType:
+ properties:
+ my_parameter:
+ type: string
+ artifacts:
+ my_artifact:
+ type: MyType
+ file: filename
+topology_template:
+ node_templates:
+ my_node:
+ type: MyType
+ properties:
+ my_parameter: { get_artifact: [ unknown, my_artifact ] }
+""").assert_failure()
+
+
+def test_functions_get_artifact_3_arguments(parser):
+ parser.parse_literal("""
+tosca_definitions_version: tosca_simple_yaml_1_0
+artifact_types:
+ MyType: {}
+node_types:
+ MyType:
+ properties:
+ my_parameter:
+ type: string
+ artifacts:
+ my_artifact:
+ type: MyType
+ file: filename
+topology_template:
+ node_templates:
+ my_node:
+ type: MyType
+ properties:
+ my_parameter: { get_artifact: [ my_node, my_artifact, path ] }
+""").assert_success()
+
+
+def test_functions_get_artifact_4_arguments(parser):
+ parser.parse_literal("""
+tosca_definitions_version: tosca_simple_yaml_1_0
+artifact_types:
+ MyType: {}
+node_types:
+ MyType:
+ properties:
+ my_parameter:
+ type: string
+ artifacts:
+ my_artifact:
+ type: MyType
+ file: filename
+topology_template:
+ node_templates:
+ my_node:
+ type: MyType
+ properties:
+ my_parameter: { get_artifact: [ my_node, my_artifact, path, true ] }
+""").assert_success()
+
+
+# Unicode
+
+def test_functions_get_artifact_unicode(parser):
+ parser.parse_literal("""
+tosca_definitions_version: tosca_simple_yaml_1_0
+artifact_types:
+ 類型: {}
+node_types:
+ 類型:
+ properties:
+ 參數:
+ type: string
+ artifacts:
+ 神器:
+ type: 類型
+ file: 文件名
+topology_template:
+ node_templates:
+ 模板:
+ type: 類型
+ properties:
+ 參數: { get_artifact: [ 模板, 神器, 路徑, true ] }
+""").assert_success()