Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 9A175200C6A for ; Wed, 19 Apr 2017 16:04:14 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 9862B160BAA; Wed, 19 Apr 2017 14:04:14 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 99C09160B86 for ; Wed, 19 Apr 2017 16:04:12 +0200 (CEST) Received: (qmail 44918 invoked by uid 500); 19 Apr 2017 14:04:11 -0000 Mailing-List: contact dev-help@ariatosca.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@ariatosca.incubator.apache.org Delivered-To: mailing list dev@ariatosca.incubator.apache.org Received: (qmail 44907 invoked by uid 99); 19 Apr 2017 14:04:11 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd1-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 19 Apr 2017 14:04:11 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd1-us-west.apache.org (ASF Mail Server at spamd1-us-west.apache.org) with ESMTP id 3E5A4CD4CE for ; Wed, 19 Apr 2017 14:04:11 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd1-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: -4.221 X-Spam-Level: X-Spam-Status: No, score=-4.221 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, RCVD_IN_DNSWL_HI=-5, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RP_MATCHES_RCVD=-0.001, SPF_PASS=-0.001, URIBL_BLOCKED=0.001] autolearn=disabled Received: from mx1-lw-eu.apache.org ([10.40.0.8]) by localhost (spamd1-us-west.apache.org [10.40.0.7]) (amavisd-new, port 10024) with ESMTP id dqTElRjISqpY for ; Wed, 19 Apr 2017 14:04:07 +0000 (UTC) Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx1-lw-eu.apache.org (ASF Mail Server at mx1-lw-eu.apache.org) with SMTP id 46FD860CF7 for ; Wed, 19 Apr 2017 14:04:05 +0000 (UTC) Received: (qmail 44864 invoked by uid 99); 19 Apr 2017 14:04:04 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 19 Apr 2017 14:04:04 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 583CFDFBC8; Wed, 19 Apr 2017 14:04:04 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: ran@apache.org To: dev@ariatosca.incubator.apache.org Date: Wed, 19 Apr 2017 14:04:04 -0000 Message-Id: <41fb5af84f81445eab12b75c14875262@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [1/5] incubator-ariatosca git commit: ARIA-48 Revamped ARIA CLI archived-at: Wed, 19 Apr 2017 14:04:14 -0000 Repository: incubator-ariatosca Updated Branches: refs/heads/master a7e7826ed -> 8e5a1ec2f http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8e5a1ec2/tests/modeling/test_models.py ---------------------------------------------------------------------- diff --git a/tests/modeling/test_models.py b/tests/modeling/test_models.py index bd4eba4..d64cdba 100644 --- a/tests/modeling/test_models.py +++ b/tests/modeling/test_models.py @@ -100,12 +100,13 @@ def _nodes_storage(): service = storage.service.get_by_name(mock.models.SERVICE_NAME) dependency_node_template = storage.node_template.get_by_name( mock.models.DEPENDENCY_NODE_TEMPLATE_NAME) - mock.models.create_node(mock.models.DEPENDENCY_NODE_NAME, dependency_node_template, service) + mock.models.create_node(dependency_node_template, service, + name=mock.models.DEPENDENCY_NODE_NAME) dependent_node_template = mock.models.create_dependent_node_template(service.service_template, dependency_node_template) - mock.models.create_node(mock.models.DEPENDENT_NODE_NAME, dependent_node_template, service) + mock.models.create_node(dependent_node_template, service, name=mock.models.DEPENDENT_NODE_NAME) storage.service.update(service) return storage @@ -180,7 +181,7 @@ class TestServiceTemplate(object): @pytest.mark.parametrize( 'is_valid, description, created_at, updated_at, main_file_name', [ - (False, {}, now, now, '/path'), + (False, [], now, now, '/path'), (False, 'description', 'error', now, '/path'), (False, 'description', now, 'error', '/path'), (False, 'description', now, now, {}), @@ -253,7 +254,7 @@ class TestService(object): class TestExecution(object): @pytest.mark.parametrize( - 'is_valid, created_at, started_at, ended_at, error, is_system_workflow, parameters, ' + 'is_valid, created_at, started_at, ended_at, error, is_system_workflow, inputs, ' 'status, workflow_name', [ (False, m_cls, now, now, 'error', False, {}, Execution.STARTED, 'wf_name'), @@ -268,11 +269,11 @@ class TestExecution(object): (True, now, None, now, 'error', False, {}, Execution.STARTED, 'wf_name'), (True, now, now, None, 'error', False, {}, Execution.STARTED, 'wf_name'), (True, now, now, now, None, False, {}, Execution.STARTED, 'wf_name'), - (True, now, now, now, 'error', False, None, Execution.STARTED, 'wf_name'), + (True, now, now, now, 'error', False, {}, Execution.STARTED, 'wf_name'), ] ) def test_execution_model_creation(self, service_storage, is_valid, created_at, started_at, - ended_at, error, is_system_workflow, parameters, status, + ended_at, error, is_system_workflow, inputs, status, workflow_name): execution = _test_model( is_valid=is_valid, @@ -285,7 +286,7 @@ class TestExecution(object): ended_at=ended_at, error=error, is_system_workflow=is_system_workflow, - parameters=parameters, + inputs=inputs, status=status, workflow_name=workflow_name, )) @@ -299,7 +300,7 @@ class TestExecution(object): id='e_id', workflow_name='w_name', status=status, - parameters={}, + inputs={}, created_at=now, ) return execution http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8e5a1ec2/tests/orchestrator/context/test_operation.py ---------------------------------------------------------------------- diff --git a/tests/orchestrator/context/test_operation.py b/tests/orchestrator/context/test_operation.py index af8b454..c399474 100644 --- a/tests/orchestrator/context/test_operation.py +++ b/tests/orchestrator/context/test_operation.py @@ -69,16 +69,17 @@ def test_node_operation_task_execution(ctx, thread_executor): interface_name = 'Standard' operation_name = 'create' + inputs = {'putput': True} node = ctx.model.node.get_by_name(mock.models.DEPENDENCY_NODE_NAME) interface = mock.models.create_interface( node.service, interface_name, operation_name, - operation_kwargs=dict(implementation=op_path(basic_operation, module_path=__name__)) + operation_kwargs=dict(implementation=op_path(basic_operation, module_path=__name__), + inputs=inputs) ) node.interfaces[interface.name] = interface ctx.model.node.update(node) - inputs = {'putput': True} @workflow def basic_workflow(graph, **_): @@ -124,17 +125,18 @@ def test_relationship_operation_task_execution(ctx, thread_executor): interface_name = 'Configure' operation_name = 'post_configure' + inputs = {'putput': True} relationship = ctx.model.relationship.list()[0] interface = mock.models.create_interface( relationship.source_node.service, interface_name, operation_name, - operation_kwargs=dict(implementation=op_path(basic_operation, module_path=__name__)), + operation_kwargs=dict(implementation=op_path(basic_operation, module_path=__name__), + inputs=inputs), ) relationship.interfaces[interface.name] = interface ctx.model.relationship.update(relationship) - inputs = {'putput': True} @workflow def basic_workflow(graph, **_): @@ -231,21 +233,21 @@ def test_plugin_workdir(ctx, thread_executor, tmpdir): plugin = mock.models.create_plugin() ctx.model.plugin.put(plugin) node = ctx.model.node.get_by_name(mock.models.DEPENDENCY_NODE_NAME) + filename = 'test_file' + content = 'file content' + inputs = {'filename': filename, 'content': content} interface = mock.models.create_interface( node.service, interface_name, operation_name, operation_kwargs=dict( implementation='{0}.{1}'.format(__name__, _test_plugin_workdir.__name__), - plugin=plugin) + plugin=plugin, + inputs=inputs) ) node.interfaces[interface.name] = interface ctx.model.node.update(node) - filename = 'test_file' - content = 'file content' - inputs = {'filename': filename, 'content': content} - @workflow def basic_workflow(graph, **_): graph.add_tasks(api.task.OperationTask.for_node(node=node, @@ -277,21 +279,22 @@ def test_node_operation_logging(ctx, executor): interface_name, operation_name = mock.operations.NODE_OPERATIONS_INSTALL[0] node = ctx.model.node.get_by_name(mock.models.DEPENDENCY_NODE_NAME) + + inputs = { + 'op_start': 'op_start', + 'op_end': 'op_end', + } interface = mock.models.create_interface( node.service, interface_name, operation_name, operation_kwargs=dict( - implementation=op_path(logged_operation, module_path=__name__)) + implementation=op_path(logged_operation, module_path=__name__), + inputs=inputs) ) node.interfaces[interface.name] = interface ctx.model.node.update(node) - inputs = { - 'op_start': 'op_start', - 'op_end': 'op_end', - } - @workflow def basic_workflow(graph, **_): graph.add_tasks( @@ -311,20 +314,20 @@ def test_relationship_operation_logging(ctx, executor): interface_name, operation_name = mock.operations.RELATIONSHIP_OPERATIONS_INSTALL[0] relationship = ctx.model.relationship.list()[0] + inputs = { + 'op_start': 'op_start', + 'op_end': 'op_end', + } interface = mock.models.create_interface( relationship.source_node.service, interface_name, operation_name, - operation_kwargs=dict(implementation=op_path(logged_operation, module_path=__name__)) + operation_kwargs=dict(implementation=op_path(logged_operation, module_path=__name__), + inputs=inputs) ) relationship.interfaces[interface.name] = interface ctx.model.relationship.update(relationship) - inputs = { - 'op_start': 'op_start', - 'op_end': 'op_end', - } - @workflow def basic_workflow(graph, **_): graph.add_tasks( http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8e5a1ec2/tests/orchestrator/context/test_resource_render.py ---------------------------------------------------------------------- diff --git a/tests/orchestrator/context/test_resource_render.py b/tests/orchestrator/context/test_resource_render.py index 696e9b3..8249086 100644 --- a/tests/orchestrator/context/test_resource_render.py +++ b/tests/orchestrator/context/test_resource_render.py @@ -64,9 +64,9 @@ def resources(tmpdir, ctx): implicit_ctx_template_path.write(_IMPLICIT_CTX_TEMPLATE) variables_template_path = tmpdir.join(_VARIABLES_TEMPLATE_PATH) variables_template_path.write(_VARIABLES_TEMPLATE) - ctx.resource.deployment.upload(entry_id='1', - source=str(implicit_ctx_template_path), - path=_IMPLICIT_CTX_TEMPLATE_PATH) - ctx.resource.deployment.upload(entry_id='1', - source=str(variables_template_path), - path=_VARIABLES_TEMPLATE_PATH) + ctx.resource.service.upload(entry_id='1', + source=str(implicit_ctx_template_path), + path=_IMPLICIT_CTX_TEMPLATE_PATH) + ctx.resource.service.upload(entry_id='1', + source=str(variables_template_path), + path=_VARIABLES_TEMPLATE_PATH) http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8e5a1ec2/tests/orchestrator/context/test_serialize.py ---------------------------------------------------------------------- diff --git a/tests/orchestrator/context/test_serialize.py b/tests/orchestrator/context/test_serialize.py index 8b809b3..f4acc36 100644 --- a/tests/orchestrator/context/test_serialize.py +++ b/tests/orchestrator/context/test_serialize.py @@ -15,8 +15,6 @@ import pytest -import aria -from aria.storage import sql_mapi from aria.orchestrator.workflows import api from aria.orchestrator.workflows.core import engine from aria.orchestrator.workflows.executor import process @@ -34,7 +32,7 @@ def test_serialize_operation_context(context, executor, tmpdir): test_file = tmpdir.join(TEST_FILE_NAME) test_file.write(TEST_FILE_CONTENT) resource = context.resource - resource.blueprint.upload(TEST_FILE_ENTRY_ID, str(test_file)) + resource.service_template.upload(TEST_FILE_ENTRY_ID, str(test_file)) graph = _mock_workflow(ctx=context) # pylint: disable=no-value-for-parameter eng = engine.Engine(executor=executor, workflow_context=context, tasks_graph=graph) eng.execute() @@ -72,7 +70,7 @@ def _mock_operation(ctx): # a correct ctx.deployment.name tells us we kept the correct deployment_id assert ctx.service.name == mock.models.SERVICE_NAME # Here we test that the resource storage was properly re-created - test_file_content = ctx.resource.blueprint.read(TEST_FILE_ENTRY_ID, TEST_FILE_NAME) + test_file_content = ctx.resource.service_template.read(TEST_FILE_ENTRY_ID, TEST_FILE_NAME) assert test_file_content == TEST_FILE_CONTENT # a non empty plugin workdir tells us that we kept the correct base_workdir assert ctx.plugin_workdir is not None @@ -98,10 +96,3 @@ def context(tmpdir): yield result storage.release_sqlite_storage(result.model) - - -@pytest.fixture -def memory_model_storage(): - result = aria.application_model_storage(sql_mapi.SQLAlchemyModelAPI) - yield result - storage.release_sqlite_storage(result) http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8e5a1ec2/tests/orchestrator/context/test_toolbelt.py ---------------------------------------------------------------------- diff --git a/tests/orchestrator/context/test_toolbelt.py b/tests/orchestrator/context/test_toolbelt.py index cf82127..213d964 100644 --- a/tests/orchestrator/context/test_toolbelt.py +++ b/tests/orchestrator/context/test_toolbelt.py @@ -76,15 +76,16 @@ def test_host_ip(workflow_context, executor): interface_name = 'Standard' operation_name = 'create' _, dependency_node, _, _, _ = _get_elements(workflow_context) + inputs = {'putput': True} interface = mock.models.create_interface( dependency_node.service, interface_name=interface_name, operation_name=operation_name, - operation_kwargs=dict(implementation=op_path(host_ip, module_path=__name__)) + operation_kwargs=dict(implementation=op_path(host_ip, module_path=__name__), + inputs=inputs) ) dependency_node.interfaces[interface.name] = interface workflow_context.model.node.update(dependency_node) - inputs = {'putput': True} @workflow def basic_workflow(graph, **_): @@ -106,17 +107,17 @@ def test_relationship_tool_belt(workflow_context, executor): interface_name = 'Configure' operation_name = 'post_configure' _, _, _, _, relationship = _get_elements(workflow_context) + inputs = {'putput': True} interface = mock.models.create_interface( relationship.source_node.service, interface_name=interface_name, operation_name=operation_name, - operation_kwargs=dict(implementation=op_path(relationship_operation, module_path=__name__)) + operation_kwargs=dict(implementation=op_path(relationship_operation, module_path=__name__), + inputs=inputs) ) relationship.interfaces[interface.name] = interface workflow_context.model.relationship.update(relationship) - inputs = {'putput': True} - @workflow def basic_workflow(graph, **_): graph.add_tasks( http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8e5a1ec2/tests/orchestrator/context/test_workflow.py ---------------------------------------------------------------------- diff --git a/tests/orchestrator/context/test_workflow.py b/tests/orchestrator/context/test_workflow.py index fa1f387..3c35435 100644 --- a/tests/orchestrator/context/test_workflow.py +++ b/tests/orchestrator/context/test_workflow.py @@ -35,7 +35,7 @@ class TestWorkflowContext(object): assert execution.service_template == storage.service_template.get_by_name( models.SERVICE_TEMPLATE_NAME) assert execution.status == storage.execution.model_cls.PENDING - assert execution.parameters == {} + assert execution.inputs == {} assert execution.created_at <= datetime.utcnow() def test_subsequent_workflow_context_creation_do_not_fail(self, storage): @@ -49,11 +49,13 @@ class TestWorkflowContext(object): :param storage: :return WorkflowContext: """ + service = storage.service.get_by_name(models.SERVICE_NAME) return context.workflow.WorkflowContext( name='simple_context', model_storage=storage, resource_storage=None, - service_id=storage.service.get_by_name(models.SERVICE_NAME).id, + service_id=service, + execution_id=storage.execution.list(filters=dict(service=service))[0].id, workflow_name=models.WORKFLOW_NAME, task_max_attempts=models.TASK_MAX_ATTEMPTS, task_retry_interval=models.TASK_RETRY_INTERVAL @@ -66,6 +68,8 @@ def storage(): sql_mapi.SQLAlchemyModelAPI, initiator=test_storage.init_inmemory_model_storage) workflow_storage.service_template.put(models.create_service_template()) service_template = workflow_storage.service_template.get_by_name(models.SERVICE_TEMPLATE_NAME) - workflow_storage.service.put(models.create_service(service_template)) + service = models.create_service(service_template) + workflow_storage.service.put(service) + workflow_storage.execution.put(models.create_execution(service)) yield workflow_storage test_storage.release_sqlite_storage(workflow_storage) http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8e5a1ec2/tests/orchestrator/execution_plugin/test_local.py ---------------------------------------------------------------------- diff --git a/tests/orchestrator/execution_plugin/test_local.py b/tests/orchestrator/execution_plugin/test_local.py index e3612cf..58506ba 100644 --- a/tests/orchestrator/execution_plugin/test_local.py +++ b/tests/orchestrator/execution_plugin/test_local.py @@ -460,14 +460,15 @@ if __name__ == '__main__': env_var='value', inputs=None): local_script_path = script_path - script_path = os.path.basename(local_script_path) if local_script_path else None + script_path = os.path.basename(local_script_path) if local_script_path else '' + inputs = inputs or {} + process = process or {} if script_path: - workflow_context.resource.deployment.upload( + workflow_context.resource.service.upload( entry_id=str(workflow_context.service.id), source=local_script_path, path=script_path) - inputs = inputs or {} inputs.update({ 'script_path': script_path, 'process': process, @@ -481,9 +482,11 @@ if __name__ == '__main__': node.service, 'test', 'op', - operation_kwargs=dict(implementation='{0}.{1}'.format( - operations.__name__, - operations.run_script_locally.__name__)) + operation_kwargs=dict( + implementation='{0}.{1}'.format( + operations.__name__, + operations.run_script_locally.__name__), + inputs=inputs) ) node.interfaces[interface.name] = interface graph.add_tasks(api.task.OperationTask.for_node( http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8e5a1ec2/tests/orchestrator/execution_plugin/test_ssh.py ---------------------------------------------------------------------- diff --git a/tests/orchestrator/execution_plugin/test_ssh.py b/tests/orchestrator/execution_plugin/test_ssh.py index d86b6d2..a75d59a 100644 --- a/tests/orchestrator/execution_plugin/test_ssh.py +++ b/tests/orchestrator/execution_plugin/test_ssh.py @@ -217,29 +217,41 @@ class TestWithActualSSHServer(object): @workflow def mock_workflow(ctx, graph): node = ctx.model.node.get_by_name(mock.models.DEPENDENCY_NODE_NAME) + inputs = { + 'script_path': script_path, + 'fabric_env': _FABRIC_ENV, + 'process': process, + 'use_sudo': use_sudo, + 'custom_env_var': custom_input, + 'test_operation': '', + } + if hide_output: + inputs['hide_output'] = hide_output + if commands: + inputs['commands'] = commands interface = mock.models.create_interface( node.service, 'test', 'op', - operation_kwargs=dict(implementation='{0}.{1}'.format( - operations.__name__, - operation.__name__)) + operation_kwargs=dict( + implementation='{0}.{1}'.format( + operations.__name__, + operation.__name__), + inputs=inputs) ) node.interfaces[interface.name] = interface - graph.sequence(*[api.task.OperationTask.for_node( - node=node, - interface_name='test', - operation_name='op', - inputs={ - 'script_path': script_path, - 'fabric_env': _FABRIC_ENV, - 'process': process, - 'use_sudo': use_sudo, - 'hide_output': hide_output, - 'custom_env_var': custom_input, - 'test_operation': test_operation, - 'commands': commands - }) for test_operation in test_operations]) + + ops = [] + for test_operation in test_operations: + op_inputs = inputs.copy() + op_inputs['test_operation'] = test_operation + ops.append(api.task.OperationTask.for_node( + node=node, + interface_name='test', + operation_name='op', + inputs=op_inputs)) + + graph.sequence(*ops) return graph tasks_graph = mock_workflow(ctx=self._workflow_context) # pylint: disable=no-value-for-parameter eng = engine.Engine( @@ -258,7 +270,7 @@ class TestWithActualSSHServer(object): return collected[signal][0]['kwargs']['exception'] def _upload(self, source, path): - self._workflow_context.resource.deployment.upload( + self._workflow_context.resource.service.upload( entry_id=str(self._workflow_context.service.id), source=source, path=path) http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8e5a1ec2/tests/orchestrator/test_runner.py ---------------------------------------------------------------------- diff --git a/tests/orchestrator/test_runner.py b/tests/orchestrator/test_runner.py deleted file mode 100644 index 74e98ad..0000000 --- a/tests/orchestrator/test_runner.py +++ /dev/null @@ -1,74 +0,0 @@ -# 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. - -from aria import workflow -from aria.orchestrator import operation -from aria.orchestrator.workflows.api.task import OperationTask -from aria.orchestrator.runner import Runner - -from tests import mock - -import pytest - - -OPERATION_RESULTS = {} - - -@operation -def mock_create_operation(ctx, key, value, **kwargs): # pylint: disable=unused-argument - OPERATION_RESULTS[key] = value - - -@pytest.fixture(autouse=True) -def cleanup(): - OPERATION_RESULTS.clear() - - -def test_runner_no_tasks(): - @workflow - def workflow_fn(ctx, graph): # pylint: disable=unused-argument - pass - - _test_runner(workflow_fn) - - -def test_runner_tasks(): - @workflow - def workflow_fn(ctx, graph): - for node in ctx.model.node: - graph.add_tasks( - OperationTask.for_node(node=node, - interface_name='Standard', - operation_name='create')) - - _test_runner(workflow_fn) - - assert OPERATION_RESULTS.get('create') is True - - -def _initialize_model_storage_fn(model_storage): - mock.topology.create_simple_topology_single_node( - model_storage, - '{0}.{1}'.format(__name__, mock_create_operation.__name__) - ) - - -def _test_runner(workflow_fn): - runner = Runner(workflow_name='runner workflow', - workflow_fn=workflow_fn, - inputs={}, - initialize_model_storage_fn=_initialize_model_storage_fn, - service_id_fn=lambda: 1) - runner.run() http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8e5a1ec2/tests/orchestrator/test_workflow_runner.py ---------------------------------------------------------------------- diff --git a/tests/orchestrator/test_workflow_runner.py b/tests/orchestrator/test_workflow_runner.py new file mode 100644 index 0000000..54e940f --- /dev/null +++ b/tests/orchestrator/test_workflow_runner.py @@ -0,0 +1,292 @@ +# 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 json +from datetime import datetime + +import pytest +import mock + +from aria.modeling import exceptions as modeling_exceptions +from aria.modeling import models +from aria.orchestrator import exceptions +from aria.orchestrator.workflow_runner import WorkflowRunner +from aria.orchestrator.workflows.executor.process import ProcessExecutor + +from ..mock import ( + topology, + workflow as workflow_mocks +) +from ..fixtures import ( # pylint: disable=unused-import + plugins_dir, + plugin_manager, + fs_model as model, + resource_storage as resource +) + + +def test_undeclared_workflow(request): + # validating a proper error is raised when the workflow is not declared in the service + with pytest.raises(exceptions.UndeclaredWorkflowError): + _create_workflow_runner(request, 'undeclared_workflow') + + +def test_missing_workflow_implementation(service, request): + # validating a proper error is raised when the workflow code path does not exist + workflow = models.Operation( + name='test_workflow', + service=service, + implementation='nonexistent.workflow.implementation', + inputs={}) + service.workflows['test_workflow'] = workflow + + with pytest.raises(exceptions.WorkflowImplementationNotFoundError): + _create_workflow_runner(request, 'test_workflow') + + +def test_builtin_workflow_instantiation(request): + # validates the workflow runner instantiates properly when provided with a builtin workflow + # (expecting no errors to be raised on undeclared workflow or missing workflow implementation) + workflow_runner = _create_workflow_runner(request, 'install') + tasks = list(workflow_runner._tasks_graph.tasks) + assert len(tasks) == 2 # expecting two WorkflowTasks + + +def test_custom_workflow_instantiation(request): + # validates the workflow runner instantiates properly when provided with a custom workflow + # (expecting no errors to be raised on undeclared workflow or missing workflow implementation) + mock_workflow = _setup_mock_workflow_in_service(request) + workflow_runner = _create_workflow_runner(request, mock_workflow) + tasks = list(workflow_runner._tasks_graph.tasks) + assert len(tasks) == 0 # mock workflow creates no tasks + + +def test_existing_active_executions(request, service, model): + existing_active_execution = models.Execution( + service=service, + status=models.Execution.STARTED, + workflow_name='uninstall') + model.execution.put(existing_active_execution) + with pytest.raises(exceptions.ActiveExecutionsError): + _create_workflow_runner(request, 'install') + + +def test_existing_executions_but_no_active_ones(request, service, model): + existing_terminated_execution = models.Execution( + service=service, + status=models.Execution.TERMINATED, + workflow_name='uninstall') + model.execution.put(existing_terminated_execution) + # no active executions exist, so no error should be raised + _create_workflow_runner(request, 'install') + + +def test_default_executor(request): + # validates the ProcessExecutor is used by the workflow runner by default + mock_workflow = _setup_mock_workflow_in_service(request) + + with mock.patch('aria.orchestrator.workflow_runner.Engine') as mock_engine_cls: + _create_workflow_runner(request, mock_workflow) + _, engine_kwargs = mock_engine_cls.call_args + assert isinstance(engine_kwargs.get('executor'), ProcessExecutor) + + +def test_custom_executor(request): + mock_workflow = _setup_mock_workflow_in_service(request) + + custom_executor = mock.MagicMock() + with mock.patch('aria.orchestrator.workflow_runner.Engine') as mock_engine_cls: + _create_workflow_runner(request, mock_workflow, executor=custom_executor) + _, engine_kwargs = mock_engine_cls.call_args + assert engine_kwargs.get('executor') == custom_executor + + +def test_task_configuration_parameters(request): + mock_workflow = _setup_mock_workflow_in_service(request) + + task_max_attempts = 5 + task_retry_interval = 7 + with mock.patch('aria.orchestrator.workflow_runner.Engine') as mock_engine_cls: + _create_workflow_runner(request, mock_workflow, task_max_attempts=task_max_attempts, + task_retry_interval=task_retry_interval) + _, engine_kwargs = mock_engine_cls.call_args + assert engine_kwargs['workflow_context']._task_max_attempts == task_max_attempts + assert engine_kwargs['workflow_context']._task_retry_interval == task_retry_interval + + +def test_execute(request, service): + mock_workflow = _setup_mock_workflow_in_service(request) + + mock_engine = mock.MagicMock() + with mock.patch('aria.orchestrator.workflow_runner.Engine', return_value=mock_engine) \ + as mock_engine_cls: + workflow_runner = _create_workflow_runner(request, mock_workflow) + + _, engine_kwargs = mock_engine_cls.call_args + assert engine_kwargs['workflow_context'].service.id == service.id + assert engine_kwargs['workflow_context'].execution.workflow_name == 'test_workflow' + + workflow_runner.execute() + mock_engine.execute.assert_called_once_with() + + +def test_cancel_execution(request): + mock_workflow = _setup_mock_workflow_in_service(request) + + mock_engine = mock.MagicMock() + with mock.patch('aria.orchestrator.workflow_runner.Engine', return_value=mock_engine): + workflow_runner = _create_workflow_runner(request, mock_workflow) + workflow_runner.cancel() + mock_engine.cancel_execution.assert_called_once_with() + + +def test_execution_model_creation(request, service, model): + mock_workflow = _setup_mock_workflow_in_service(request) + + with mock.patch('aria.orchestrator.workflow_runner.Engine') as mock_engine_cls: + workflow_runner = _create_workflow_runner(request, mock_workflow) + + _, engine_kwargs = mock_engine_cls.call_args + assert engine_kwargs['workflow_context'].execution == workflow_runner.execution + assert model.execution.get(workflow_runner.execution.id) == workflow_runner.execution + assert workflow_runner.execution.service.id == service.id + assert workflow_runner.execution.workflow_name == mock_workflow + assert workflow_runner.execution.created_at <= datetime.utcnow() + assert workflow_runner.execution.inputs == dict() + + +def test_execution_inputs_override_workflow_inputs(request): + wf_inputs = {'input1': 'value1', 'input2': 'value2', 'input3': 5} + mock_workflow = _setup_mock_workflow_in_service( + request, + inputs=dict((name, models.Parameter.wrap(name, val)) for name, val + in wf_inputs.iteritems())) + + with mock.patch('aria.orchestrator.workflow_runner.Engine'): + workflow_runner = _create_workflow_runner( + request, mock_workflow, inputs={'input2': 'overriding-value2', 'input3': 7}) + + assert len(workflow_runner.execution.inputs) == 3 + # did not override input1 - expecting the default value from the workflow inputs + assert workflow_runner.execution.inputs['input1'].value == 'value1' + # overrode input2 + assert workflow_runner.execution.inputs['input2'].value == 'overriding-value2' + # overrode input of integer type + assert workflow_runner.execution.inputs['input3'].value == 7 + + +def test_execution_inputs_undeclared_inputs(request): + mock_workflow = _setup_mock_workflow_in_service(request) + + with pytest.raises(modeling_exceptions.UndeclaredInputsException): + _create_workflow_runner(request, mock_workflow, inputs={'undeclared_input': 'value'}) + + +def test_execution_inputs_missing_required_inputs(request): + mock_workflow = _setup_mock_workflow_in_service( + request, inputs={'required_input': models.Parameter.wrap('required_input', value=None)}) + + with pytest.raises(modeling_exceptions.MissingRequiredInputsException): + _create_workflow_runner(request, mock_workflow, inputs={}) + + +def test_execution_inputs_wrong_type_inputs(request): + mock_workflow = _setup_mock_workflow_in_service( + request, inputs={'input': models.Parameter.wrap('input', 'value')}) + + with pytest.raises(modeling_exceptions.InputsOfWrongTypeException): + _create_workflow_runner(request, mock_workflow, inputs={'input': 5}) + + +def test_execution_inputs_builtin_workflow_with_inputs(request): + # built-in workflows don't have inputs + with pytest.raises(modeling_exceptions.UndeclaredInputsException): + _create_workflow_runner(request, 'install', inputs={'undeclared_input': 'value'}) + + +def test_workflow_function_parameters(request, tmpdir): + # validating the workflow function is passed with the + # merged execution inputs, in dict form + + # the workflow function parameters will be written to this file + output_path = str(tmpdir.join('output')) + wf_inputs = {'output_path': output_path, 'input1': 'value1', 'input2': 'value2', 'input3': 5} + + mock_workflow = _setup_mock_workflow_in_service( + request, inputs=dict((name, models.Parameter.wrap(name, val)) for name, val + in wf_inputs.iteritems())) + + _create_workflow_runner(request, mock_workflow, + inputs={'input2': 'overriding-value2', 'input3': 7}) + + with open(output_path) as f: + wf_call_kwargs = json.load(f) + assert len(wf_call_kwargs) == 3 + assert wf_call_kwargs.get('input1') == 'value1' + assert wf_call_kwargs.get('input2') == 'overriding-value2' + assert wf_call_kwargs.get('input3') == 7 + + +@pytest.fixture +def service(model): + # sets up a service in the storage + service_id = topology.create_simple_topology_two_nodes(model) + service = model.service.get(service_id) + return service + + +def _setup_mock_workflow_in_service(request, inputs=None): + # sets up a mock workflow as part of the service, including uploading + # the workflow code to the service's dir on the resource storage + service = request.getfuncargvalue('service') + resource = request.getfuncargvalue('resource') + + source = workflow_mocks.__file__ + resource.service_template.upload(str(service.service_template.id), source) + mock_workflow_name = 'test_workflow' + workflow = models.Operation( + name=mock_workflow_name, + service=service, + implementation='workflow.mock_workflow', + inputs=inputs or {}) + service.workflows[mock_workflow_name] = workflow + return mock_workflow_name + + +def _create_workflow_runner(request, workflow_name, inputs=None, executor=None, + task_max_attempts=None, task_retry_interval=None): + # helper method for instantiating a workflow runner + service_id = request.getfuncargvalue('service').id + model = request.getfuncargvalue('model') + resource = request.getfuncargvalue('resource') + plugin_manager = request.getfuncargvalue('plugin_manager') + + # task configuration parameters can't be set to None, therefore only + # passing those if they've been set by the test + task_configuration_kwargs = dict() + if task_max_attempts is not None: + task_configuration_kwargs['task_max_attempts'] = task_max_attempts + if task_retry_interval is not None: + task_configuration_kwargs['task_retry_interval'] = task_retry_interval + + return WorkflowRunner( + workflow_name=workflow_name, + service_id=service_id, + inputs=inputs or {}, + executor=executor, + model_storage=model, + resource_storage=resource, + plugin_manager=plugin_manager, + **task_configuration_kwargs) http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8e5a1ec2/tests/orchestrator/workflows/api/test_task.py ---------------------------------------------------------------------- diff --git a/tests/orchestrator/workflows/api/test_task.py b/tests/orchestrator/workflows/api/test_task.py index a705199..ab62361 100644 --- a/tests/orchestrator/workflows/api/test_task.py +++ b/tests/orchestrator/workflows/api/test_task.py @@ -44,17 +44,19 @@ class TestOperationTask(object): plugin = mock.models.create_plugin('test_plugin', '0.1') ctx.model.node.update(plugin) + inputs = {'test_input': True} + interface = mock.models.create_interface( ctx.service, interface_name, operation_name, operation_kwargs=dict(plugin=plugin, - implementation='op_path')) + implementation='op_path', + inputs=inputs),) node = ctx.model.node.get_by_name(mock.models.DEPENDENT_NODE_NAME) node.interfaces[interface_name] = interface ctx.model.node.update(node) - inputs = {'test_input': True} max_attempts = 10 retry_interval = 10 ignore_failure = True @@ -90,17 +92,19 @@ class TestOperationTask(object): plugin = mock.models.create_plugin('test_plugin', '0.1') ctx.model.plugin.update(plugin) + inputs = {'test_input': True} + interface = mock.models.create_interface( ctx.service, interface_name, operation_name, operation_kwargs=dict(plugin=plugin, - implementation='op_path') + implementation='op_path', + inputs=inputs) ) relationship = ctx.model.relationship.list()[0] relationship.interfaces[interface.name] = interface - inputs = {'test_input': True} max_attempts = 10 retry_interval = 10 @@ -133,17 +137,19 @@ class TestOperationTask(object): plugin = mock.models.create_plugin('test_plugin', '0.1') ctx.model.node.update(plugin) + inputs = {'test_input': True} + interface = mock.models.create_interface( ctx.service, interface_name, operation_name, operation_kwargs=dict(plugin=plugin, - implementation='op_path') + implementation='op_path', + inputs=inputs) ) relationship = ctx.model.relationship.list()[0] relationship.interfaces[interface.name] = interface - inputs = {'test_input': True} max_attempts = 10 retry_interval = 10 http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8e5a1ec2/tests/orchestrator/workflows/core/test_engine.py ---------------------------------------------------------------------- diff --git a/tests/orchestrator/workflows/core/test_engine.py b/tests/orchestrator/workflows/core/test_engine.py index 0b48870..1a88f13 100644 --- a/tests/orchestrator/workflows/core/test_engine.py +++ b/tests/orchestrator/workflows/core/test_engine.py @@ -61,12 +61,18 @@ class BaseTest(object): retry_interval=None, ignore_failure=None): node = ctx.model.node.get_by_name(mock.models.DEPENDENCY_NODE_NAME) + + operation_kwargs = dict(implementation='{name}.{func.__name__}'.format( + name=__name__, func=func)) + if inputs: + # the operation has to declare the inputs before those may be passed + operation_kwargs['inputs'] = inputs + interface = mock.models.create_interface( node.service, 'aria.interfaces.lifecycle', 'create', - operation_kwargs=dict(implementation='{name}.{func.__name__}'.format(name=__name__, - func=func)) + operation_kwargs=operation_kwargs ) node.interfaces[interface.name] = interface return api.task.OperationTask.for_node( http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8e5a1ec2/tests/orchestrator/workflows/core/test_task_graph_into_exececution_graph.py ---------------------------------------------------------------------- diff --git a/tests/orchestrator/workflows/core/test_task_graph_into_exececution_graph.py b/tests/orchestrator/workflows/core/test_task_graph_into_exececution_graph.py deleted file mode 100644 index 514bce9..0000000 --- a/tests/orchestrator/workflows/core/test_task_graph_into_exececution_graph.py +++ /dev/null @@ -1,112 +0,0 @@ -# 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. - -from networkx import topological_sort, DiGraph - -from aria.orchestrator import context -from aria.orchestrator.workflows import api, core - -from tests import mock -from tests import storage - - -def test_task_graph_into_execution_graph(tmpdir): - interface_name = 'Standard' - operation_name = 'create' - task_context = mock.context.simple(str(tmpdir)) - node = task_context.model.node.get_by_name(mock.models.DEPENDENCY_NODE_NAME) - interface = mock.models.create_interface( - node.service, - interface_name, - operation_name, - operation_kwargs={'implementation': 'test'} - ) - node.interfaces[interface.name] = interface - task_context.model.node.update(node) - - def sub_workflow(name, **_): - return api.task_graph.TaskGraph(name) - - with context.workflow.current.push(task_context): - test_task_graph = api.task.WorkflowTask(sub_workflow, name='test_task_graph') - simple_before_task = api.task.OperationTask.for_node(node=node, - interface_name=interface_name, - operation_name=operation_name) - simple_after_task = api.task.OperationTask.for_node(node=node, - interface_name=interface_name, - operation_name=operation_name) - - inner_task_graph = api.task.WorkflowTask(sub_workflow, name='test_inner_task_graph') - inner_task = api.task.OperationTask.for_node(node=node, - interface_name=interface_name, - operation_name=operation_name) - inner_task_graph.add_tasks(inner_task) - - test_task_graph.add_tasks(simple_before_task) - test_task_graph.add_tasks(simple_after_task) - test_task_graph.add_tasks(inner_task_graph) - test_task_graph.add_dependency(inner_task_graph, simple_before_task) - test_task_graph.add_dependency(simple_after_task, inner_task_graph) - - # Direct check - execution_graph = DiGraph() - core.translation.build_execution_graph(task_graph=test_task_graph, - execution_graph=execution_graph) - execution_tasks = topological_sort(execution_graph) - - assert len(execution_tasks) == 7 - - expected_tasks_names = [ - '{0}-Start'.format(test_task_graph.id), - simple_before_task.id, - '{0}-Start'.format(inner_task_graph.id), - inner_task.id, - '{0}-End'.format(inner_task_graph.id), - simple_after_task.id, - '{0}-End'.format(test_task_graph.id) - ] - - assert expected_tasks_names == execution_tasks - - assert isinstance(_get_task_by_name(execution_tasks[0], execution_graph), - core.task.StartWorkflowTask) - - _assert_execution_is_api_task(_get_task_by_name(execution_tasks[1], execution_graph), - simple_before_task) - assert isinstance(_get_task_by_name(execution_tasks[2], execution_graph), - core.task.StartSubWorkflowTask) - - _assert_execution_is_api_task(_get_task_by_name(execution_tasks[3], execution_graph), - inner_task) - assert isinstance(_get_task_by_name(execution_tasks[4], execution_graph), - core.task.EndSubWorkflowTask) - - _assert_execution_is_api_task(_get_task_by_name(execution_tasks[5], execution_graph), - simple_after_task) - assert isinstance(_get_task_by_name(execution_tasks[6], execution_graph), - core.task.EndWorkflowTask) - storage.release_sqlite_storage(task_context.model) - - -def _assert_execution_is_api_task(execution_task, api_task): - assert execution_task.id == api_task.id - assert execution_task.name == api_task.name - assert execution_task.implementation == api_task.implementation - assert execution_task.actor == api_task.actor - assert execution_task.inputs == api_task.inputs - - -def _get_task_by_name(task_name, graph): - return graph.node[task_name]['task'] http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8e5a1ec2/tests/orchestrator/workflows/core/test_task_graph_into_execution_graph.py ---------------------------------------------------------------------- diff --git a/tests/orchestrator/workflows/core/test_task_graph_into_execution_graph.py b/tests/orchestrator/workflows/core/test_task_graph_into_execution_graph.py new file mode 100644 index 0000000..514bce9 --- /dev/null +++ b/tests/orchestrator/workflows/core/test_task_graph_into_execution_graph.py @@ -0,0 +1,112 @@ +# 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. + +from networkx import topological_sort, DiGraph + +from aria.orchestrator import context +from aria.orchestrator.workflows import api, core + +from tests import mock +from tests import storage + + +def test_task_graph_into_execution_graph(tmpdir): + interface_name = 'Standard' + operation_name = 'create' + task_context = mock.context.simple(str(tmpdir)) + node = task_context.model.node.get_by_name(mock.models.DEPENDENCY_NODE_NAME) + interface = mock.models.create_interface( + node.service, + interface_name, + operation_name, + operation_kwargs={'implementation': 'test'} + ) + node.interfaces[interface.name] = interface + task_context.model.node.update(node) + + def sub_workflow(name, **_): + return api.task_graph.TaskGraph(name) + + with context.workflow.current.push(task_context): + test_task_graph = api.task.WorkflowTask(sub_workflow, name='test_task_graph') + simple_before_task = api.task.OperationTask.for_node(node=node, + interface_name=interface_name, + operation_name=operation_name) + simple_after_task = api.task.OperationTask.for_node(node=node, + interface_name=interface_name, + operation_name=operation_name) + + inner_task_graph = api.task.WorkflowTask(sub_workflow, name='test_inner_task_graph') + inner_task = api.task.OperationTask.for_node(node=node, + interface_name=interface_name, + operation_name=operation_name) + inner_task_graph.add_tasks(inner_task) + + test_task_graph.add_tasks(simple_before_task) + test_task_graph.add_tasks(simple_after_task) + test_task_graph.add_tasks(inner_task_graph) + test_task_graph.add_dependency(inner_task_graph, simple_before_task) + test_task_graph.add_dependency(simple_after_task, inner_task_graph) + + # Direct check + execution_graph = DiGraph() + core.translation.build_execution_graph(task_graph=test_task_graph, + execution_graph=execution_graph) + execution_tasks = topological_sort(execution_graph) + + assert len(execution_tasks) == 7 + + expected_tasks_names = [ + '{0}-Start'.format(test_task_graph.id), + simple_before_task.id, + '{0}-Start'.format(inner_task_graph.id), + inner_task.id, + '{0}-End'.format(inner_task_graph.id), + simple_after_task.id, + '{0}-End'.format(test_task_graph.id) + ] + + assert expected_tasks_names == execution_tasks + + assert isinstance(_get_task_by_name(execution_tasks[0], execution_graph), + core.task.StartWorkflowTask) + + _assert_execution_is_api_task(_get_task_by_name(execution_tasks[1], execution_graph), + simple_before_task) + assert isinstance(_get_task_by_name(execution_tasks[2], execution_graph), + core.task.StartSubWorkflowTask) + + _assert_execution_is_api_task(_get_task_by_name(execution_tasks[3], execution_graph), + inner_task) + assert isinstance(_get_task_by_name(execution_tasks[4], execution_graph), + core.task.EndSubWorkflowTask) + + _assert_execution_is_api_task(_get_task_by_name(execution_tasks[5], execution_graph), + simple_after_task) + assert isinstance(_get_task_by_name(execution_tasks[6], execution_graph), + core.task.EndWorkflowTask) + storage.release_sqlite_storage(task_context.model) + + +def _assert_execution_is_api_task(execution_task, api_task): + assert execution_task.id == api_task.id + assert execution_task.name == api_task.name + assert execution_task.implementation == api_task.implementation + assert execution_task.actor == api_task.actor + assert execution_task.inputs == api_task.inputs + + +def _get_task_by_name(task_name, graph): + return graph.node[task_name]['task'] http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8e5a1ec2/tests/orchestrator/workflows/executor/test_process_executor.py ---------------------------------------------------------------------- diff --git a/tests/orchestrator/workflows/executor/test_process_executor.py b/tests/orchestrator/workflows/executor/test_process_executor.py index 502c9fd..839b9f1 100644 --- a/tests/orchestrator/workflows/executor/test_process_executor.py +++ b/tests/orchestrator/workflows/executor/test_process_executor.py @@ -21,19 +21,18 @@ from contextlib import contextmanager import pytest -from aria import application_model_storage from aria.modeling import models as aria_models -from aria.storage import sql_mapi -from aria.orchestrator import ( - events, - plugin -) +from aria.orchestrator import events from aria.utils.plugin import create as create_plugin from aria.orchestrator.workflows.executor import process - import tests.storage import tests.resources +from tests.fixtures import ( # pylint: disable=unused-import + plugins_dir, + plugin_manager, + fs_model as model +) class TestProcessExecutor(object): @@ -75,27 +74,6 @@ class TestProcessExecutor(object): @pytest.fixture -def model(tmpdir): - result = application_model_storage(sql_mapi.SQLAlchemyModelAPI, - initiator_kwargs=dict(base_dir=str(tmpdir)), - initiator=sql_mapi.init_storage) - yield result - tests.storage.release_sqlite_storage(result) - - -@pytest.fixture -def plugins_dir(tmpdir): - result = tmpdir.join('plugins') - result.mkdir() - return str(result) - - -@pytest.fixture -def plugin_manager(model, plugins_dir): - return plugin.PluginManager(model=model, plugins_dir=plugins_dir) - - -@pytest.fixture def executor(plugin_manager): result = process.ProcessExecutor(plugin_manager=plugin_manager) yield result http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8e5a1ec2/tests/orchestrator/workflows/executor/test_process_executor_concurrent_modifications.py ---------------------------------------------------------------------- diff --git a/tests/orchestrator/workflows/executor/test_process_executor_concurrent_modifications.py b/tests/orchestrator/workflows/executor/test_process_executor_concurrent_modifications.py index 6d0eb5b..88e7ae0 100644 --- a/tests/orchestrator/workflows/executor/test_process_executor_concurrent_modifications.py +++ b/tests/orchestrator/workflows/executor/test_process_executor_concurrent_modifications.py @@ -90,7 +90,8 @@ def _test(context, executor, lock_files, func, expected_failure): node.service, interface_name, operation_name, - operation_kwargs=dict(implementation='{0}.{1}'.format(__name__, func.__name__)) + operation_kwargs=dict(implementation='{0}.{1}'.format(__name__, func.__name__), + inputs=inputs) ) node.interfaces[interface.name] = interface context.model.node.update(node) http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8e5a1ec2/tests/orchestrator/workflows/executor/test_process_executor_extension.py ---------------------------------------------------------------------- diff --git a/tests/orchestrator/workflows/executor/test_process_executor_extension.py b/tests/orchestrator/workflows/executor/test_process_executor_extension.py index 0988fae..7ae337d 100644 --- a/tests/orchestrator/workflows/executor/test_process_executor_extension.py +++ b/tests/orchestrator/workflows/executor/test_process_executor_extension.py @@ -42,7 +42,8 @@ def test_decorate_extension(context, executor): interface_name, operation_name, operation_kwargs=dict(implementation='{0}.{1}'.format(__name__, - _mock_operation.__name__)) + _mock_operation.__name__), + inputs=inputs) ) node.interfaces[interface.name] = interface task = api.task.OperationTask.for_node(node=node, http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8e5a1ec2/tests/orchestrator/workflows/executor/test_process_executor_tracked_changes.py ---------------------------------------------------------------------- diff --git a/tests/orchestrator/workflows/executor/test_process_executor_tracked_changes.py b/tests/orchestrator/workflows/executor/test_process_executor_tracked_changes.py index 5512189..3a8c54b 100644 --- a/tests/orchestrator/workflows/executor/test_process_executor_tracked_changes.py +++ b/tests/orchestrator/workflows/executor/test_process_executor_tracked_changes.py @@ -90,17 +90,19 @@ def _run_workflow(context, executor, op_func, inputs=None): node = ctx.model.node.get_by_name(mock.models.DEPENDENCY_NODE_NAME) interface_name = 'test_interface' operation_name = 'operation' + wf_inputs = inputs or {} interface = mock.models.create_interface( ctx.service, interface_name, operation_name, - operation_kwargs=dict(implementation=_operation_mapping(op_func)) + operation_kwargs=dict(implementation=_operation_mapping(op_func), + inputs=wf_inputs) ) node.interfaces[interface.name] = interface task = api.task.OperationTask.for_node(node=node, interface_name=interface_name, operation_name=operation_name, - inputs=inputs or {}) + inputs=wf_inputs) graph.add_tasks(task) return graph graph = mock_workflow(ctx=context) # pylint: disable=no-value-for-parameter http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8e5a1ec2/tests/parser/service_templates.py ---------------------------------------------------------------------- diff --git a/tests/parser/service_templates.py b/tests/parser/service_templates.py index a07fba8..a8fde14 100644 --- a/tests/parser/service_templates.py +++ b/tests/parser/service_templates.py @@ -13,6 +13,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +import os + from aria.utils.caching import cachedmethod from .utils import (get_example_uri, get_test_uri, create_context, create_consumer) @@ -23,7 +25,9 @@ def consume_use_case(use_case_name, consumer_class_name='instance', cache=True): uri = get_example_uri('tosca-simple-1.0', 'use-cases', use_case_name, '{0}.yaml'.format(use_case_name)) context = create_context(uri) - #context.args.append('--inputs=' + get_example_uri('node-cellar', 'inputs.yaml')) + inputs_file = get_example_uri('tosca-simple-1.0', 'use-cases', use_case_name, 'inputs.yaml') + if os.path.isfile(inputs_file): + context.args.append('--inputs={0}'.format(inputs_file)) consumer, dumper = create_consumer(context, consumer_class_name) consumer.consume() context.validation.dump_issues() http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8e5a1ec2/tests/parser/test_tosca_simple_v1_0.py ---------------------------------------------------------------------- diff --git a/tests/parser/test_tosca_simple_v1_0.py b/tests/parser/test_tosca_simple_v1_0.py new file mode 100644 index 0000000..a583db5 --- /dev/null +++ b/tests/parser/test_tosca_simple_v1_0.py @@ -0,0 +1,112 @@ +# 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. + +from .service_templates import (consume_use_case, consume_node_cellar) + + +# Use Cases + +def test_use_case_compute_1(): + consume_use_case('compute-1', 'instance') + + +def test_use_case_software_component_1(): + consume_use_case('software-component-1', 'instance') + + +def test_use_case_block_storage_1(): + consume_use_case('block-storage-1', 'instance') + + +def test_use_case_block_storage_2(): + consume_use_case('block-storage-2', 'instance') + + +def test_use_case_block_storage_3(): + consume_use_case('block-storage-3', 'instance') + + +def test_use_case_block_storage_4(): + consume_use_case('block-storage-4', 'instance') + + +def test_use_case_block_storage_5(): + consume_use_case('block-storage-5', 'instance') + + +def test_use_case_block_storage_6(): + consume_use_case('block-storage-6', 'instance') + + +def test_use_case_object_storage_1(): + consume_use_case('object-storage-1', 'instance') + + +def test_use_case_network_1(): + consume_use_case('network-1', 'instance') + + +def test_use_case_network_2(): + consume_use_case('network-2', 'instance') + + +def test_use_case_network_3(): + consume_use_case('network-3', 'instance') + + +def test_use_case_network_4(): + consume_use_case('network-4', 'instance') + + +def test_use_case_webserver_dbms_1(): + consume_use_case('webserver-dbms-1', 'template') + + +def test_use_case_webserver_dbms_2(): + consume_use_case('webserver-dbms-2', 'instance') + + +def test_use_case_multi_tier_1(): + consume_use_case('multi-tier-1', 'instance') + + +def test_use_case_container_1(): + consume_use_case('container-1', 'template') + + +# NodeCellar + +def test_node_cellar_validation(): + consume_node_cellar('validate') + + +def test_node_cellar_validation_no_cache(): + consume_node_cellar('validate', False) + + +def test_node_cellar_presentation(): + consume_node_cellar('presentation') + + +def test_node_cellar_model(): + consume_node_cellar('template') + + +def test_node_cellar_types(): + consume_node_cellar('types') + + +def test_node_cellar_instance(): + consume_node_cellar('instance') http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8e5a1ec2/tests/utils/test_plugin.py ---------------------------------------------------------------------- diff --git a/tests/utils/test_plugin.py b/tests/utils/test_plugin.py index 09885ef..3350247 100644 --- a/tests/utils/test_plugin.py +++ b/tests/utils/test_plugin.py @@ -17,13 +17,14 @@ import os import pytest -from aria import application_model_storage from aria.orchestrator import exceptions -from aria.orchestrator import plugin from aria.utils.plugin import create as create_plugin -from aria.storage import sql_mapi -from .. import storage +from ..fixtures import ( # pylint: disable=unused-import + plugins_dir, + plugin_manager, + inmemory_model as model +) PACKAGE_NAME = 'mock-plugin' @@ -48,26 +49,6 @@ class TestPluginManager(object): @pytest.fixture -def model(): - model = application_model_storage(sql_mapi.SQLAlchemyModelAPI, - initiator=storage.init_inmemory_model_storage) - yield model - storage.release_sqlite_storage(model) - - -@pytest.fixture -def plugins_dir(tmpdir): - result = tmpdir.join('plugins') - result.mkdir() - return str(result) - - -@pytest.fixture -def plugin_manager(model, plugins_dir): - return plugin.PluginManager(model=model, plugins_dir=plugins_dir) - - -@pytest.fixture def mock_plugin(tmpdir): source_dir = tmpdir.join('mock_plugin') source_dir.mkdir() http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8e5a1ec2/tests/utils/test_threading.py ---------------------------------------------------------------------- diff --git a/tests/utils/test_threading.py b/tests/utils/test_threading.py new file mode 100644 index 0000000..d24661f --- /dev/null +++ b/tests/utils/test_threading.py @@ -0,0 +1,33 @@ +# 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 + +from aria.utils import threading + + +def test_exception_raised_from_thread(): + + def error_raising_func(): + raise ValueError('This is an error') + + thread = threading.ExceptionThread(target=error_raising_func) + thread.start() + thread.join() + + assert thread.is_error() + with pytest.raises(ValueError): + thread.raise_error_if_exists() http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8e5a1ec2/tox.ini ---------------------------------------------------------------------- diff --git a/tox.ini b/tox.ini index fa4bd5c..6ad048f 100644 --- a/tox.ini +++ b/tox.ini @@ -41,7 +41,7 @@ commands=pytest tests --cov-report term-missing --cov aria commands=pytest tests --cov-report term-missing --cov aria [testenv:pylint_code] -commands=pylint --rcfile=aria/.pylintrc --disable=fixme,missing-docstring --ignore=commands.py aria +commands=pylint --rcfile=aria/.pylintrc --disable=fixme,missing-docstring aria [testenv:pylint_tests] commands=pylint --rcfile=tests/.pylintrc --disable=fixme,missing-docstring tests