diff --git a/toscaparser/functions.py b/toscaparser/functions.py index 62b2fc9..011efde 100644 --- a/toscaparser/functions.py +++ b/toscaparser/functions.py @@ -26,6 +26,7 @@ from toscaparser.utils.gettextutils import _ GET_PROPERTY = 'get_property' GET_ATTRIBUTE = 'get_attribute' GET_INPUT = 'get_input' +CONCAT = 'concat' SELF = 'SELF' HOST = 'HOST' @@ -522,10 +523,39 @@ class GetProperty(Function): return None +class Concat(Function): + """Validate the function and provide an instance of the function + + Concatenation of values are supposed to be produced at runtime and + therefore its the responsibility of the TOSCA engine to implement the + evaluation of Concat functions. + + Arguments: + + * List of strings that needs to be concatenated + + Example: + + [ 'http://', + get_attribute: [ server, public_address ], + ':' , + get_attribute: [ server, port ] ] + """ + + def validate(self): + if len(self.args) < 1: + ExceptionCollector.appendException( + ValueError(_('Invalid arguments for function "{0}". Expected ' + 'at least one arguments.').format(CONCAT))) + + def result(self): + return self + function_mappings = { GET_PROPERTY: GetProperty, GET_INPUT: GetInput, - GET_ATTRIBUTE: GetAttribute + GET_ATTRIBUTE: GetAttribute, + CONCAT: Concat } diff --git a/toscaparser/tests/data/functions/test_concat.yaml b/toscaparser/tests/data/functions/test_concat.yaml new file mode 100644 index 0000000..22fcfb4 --- /dev/null +++ b/toscaparser/tests/data/functions/test_concat.yaml @@ -0,0 +1,30 @@ +tosca_definitions_version: tosca_simple_yaml_1_0 + +description: Template for deploying a single server with concat function. + +topology_template: + node_templates: + server: + type: tosca.nodes.Compute + capabilities: + # Host container properties + host: + properties: + num_cpus: 2 + disk_size: 10 GB + mem_size: 512 MB + # Guest Operating System properties + os: + properties: + # host Operating System image properties + architecture: x86_64 + type: Linux + distribution: RHEL + version: 6.5 + outputs: + url: + description: Concatenate the URL for a server from template values. + value: { concat: [ 'http://', + get_attribute: [ server, public_address ], + ':' , + get_attribute: [ server, port ] ] } \ No newline at end of file diff --git a/toscaparser/tests/data/functions/test_concat_invalid.yaml b/toscaparser/tests/data/functions/test_concat_invalid.yaml new file mode 100644 index 0000000..7c7b0aa --- /dev/null +++ b/toscaparser/tests/data/functions/test_concat_invalid.yaml @@ -0,0 +1,9 @@ +tosca_definitions_version: tosca_simple_yaml_1_0 + +description: Template for deploying a single server with invalid concat function. + +topology_template: + outputs: + invalid_concat_syntax: + description: test concat with invalid syntax. + value: { concat: []} \ No newline at end of file diff --git a/toscaparser/tests/test_functions.py b/toscaparser/tests/test_functions.py index 7062df4..2a6225d 100644 --- a/toscaparser/tests/test_functions.py +++ b/toscaparser/tests/test_functions.py @@ -299,3 +299,26 @@ class GetAttributeTest(TestCase): self.assertTrue(isinstance(target_test, functions.GetAttribute)) source_port = operation.inputs['source_port'] self.assertTrue(isinstance(source_port, functions.GetAttribute)) + + +class ConcatTest(TestCase): + + def _load_template(self, filename): + return ToscaTemplate(os.path.join( + os.path.dirname(os.path.abspath(__file__)), + filename)) + + def test_validate_concat(self): + tosca = self._load_template("data/functions/test_concat.yaml") + server_url_output = [ + output for output in tosca.outputs if output.name == 'url'][0] + func = functions.get_function(self, tosca.outputs, + server_url_output.value) + self.assertIsInstance(func, functions.Concat) + + self.assertRaises(exception.ValidationError, self._load_template, + 'data/functions/test_concat_invalid.yaml') + exception.ExceptionCollector.assertExceptionMessage( + ValueError, + _('Invalid arguments for function "concat". Expected at least ' + 'one arguments.'))