http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/dd5bfa93/tests/modeling/test_models.py ---------------------------------------------------------------------- diff --git a/tests/modeling/test_models.py b/tests/modeling/test_models.py new file mode 100644 index 0000000..c8d36e0 --- /dev/null +++ b/tests/modeling/test_models.py @@ -0,0 +1,835 @@ +# 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 datetime import datetime +from contextlib import contextmanager + +import pytest + +from aria import application_model_storage +from aria.storage import ( + exceptions, + sql_mapi, +) +from aria.modeling.models import ( + ServiceTemplate, + Service, + ServiceUpdate, + ServiceUpdateStep, + ServiceModification, + Execution, + Task, + Plugin, + Relationship, + NodeTemplate, + Node, + Parameter, + Type +) + +from tests import mock +from ..storage import release_sqlite_storage, init_inmemory_model_storage + + +@contextmanager +def sql_storage(storage_func): + storage = None + try: + storage = storage_func() + yield storage + finally: + if storage: + release_sqlite_storage(storage) + + +def _empty_storage(): + return application_model_storage(sql_mapi.SQLAlchemyModelAPI, + initiator=init_inmemory_model_storage) + + +def _service_template_storage(): + storage = _empty_storage() + service_template = mock.models.create_service_template() + storage.service_template.put(service_template) + storage.type.put(Type(variant='node')) + return storage + + +def _service_storage(): + storage = _service_template_storage() + service = mock.models.create_service( + storage.service_template.get_by_name(mock.models.SERVICE_TEMPLATE_NAME)) + storage.service.put(service) + return storage + + +def _service_update_storage(): + storage = _service_storage() + service_update = ServiceUpdate( + service=storage.service.list()[0], + created_at=now, + service_plan={}, + ) + storage.service_update.put(service_update) + return storage + + +def _node_template_storage(): + storage = _service_storage() + service_template = storage.service_template.list()[0] + node_template = mock.models.create_dependency_node_template(service_template) + storage.node_template.put(node_template) + return storage + + +def _nodes_storage(): + storage = _nodes_storage() # ??? + service = storage.service.get_by_name(mock.models.SERVICE_NAME) + dependent_node_template = storage.node_template.get_by_name(mock.models.DEPENDENT_NODE_NAME) + dependency_node_template = storage.node_template.get_by_name(mock.models.DEPENDENCY_NODE_NAME) + dependency_node = mock.models.create_dependency_node(dependency_node_template, service) + dependent_node = mock.models.create_dependent_node(dependent_node_template, service) + storage.node.put(dependency_node) + storage.node.put(dependent_node) + return storage + + +def _execution_storage(): + storage = _service_storage() + execution = mock.models.create_execution(storage.service.list()[0]) + plugin = mock.models.create_plugin() + storage.execution.put(execution) + storage.plugin.put(plugin) + return storage + + [email protected] +def empty_storage(): + with sql_storage(_empty_storage) as storage: + yield storage + + [email protected] +def service_template_storage(): + with sql_storage(_service_template_storage) as storage: + yield storage + + [email protected] +def service_storage(): + with sql_storage(_service_storage) as storage: + yield storage + + [email protected] +def service_update_storage(): + with sql_storage(_service_update_storage) as storage: + yield storage + + [email protected] +def node_template_storage(): + with sql_storage(_node_template_storage) as storage: + yield storage + + [email protected] +def nodes_storage(): + with sql_storage(_nodes_storage) as storage: + yield storage + + [email protected] +def execution_storage(): + with sql_storage(_execution_storage) as storage: + yield storage + + +m_cls = type('MockClass') +now = datetime.utcnow() + + +def _test_model(is_valid, storage, model_cls, model_kwargs): + if is_valid: + model = model_cls(**model_kwargs) + getattr(storage, model_cls.__modelname__).put(model) + return model + else: + with pytest.raises((exceptions.StorageError, TypeError),): + getattr(storage, model_cls.__modelname__).put(model_cls(**model_kwargs)) + + +class TestServiceTemplate(object): + + @pytest.mark.parametrize( + 'is_valid, description, created_at, updated_at, main_file_name', + [ + (True, 'description', now, now, '/path'), + (False, {}, now, now, '/path'), + (False, 'description', 'error', now, '/path'), + (False, 'description', now, 'error', '/path'), + (False, 'description', now, now, {}), + (True, 'description', now, now, '/path'), + ] + ) + + def test_service_template_model_creation(self, empty_storage, is_valid, description, created_at, + updated_at, main_file_name): + _test_model(is_valid=is_valid, + storage=empty_storage, + model_cls=ServiceTemplate, + model_kwargs=dict( + description=description, + created_at=created_at, + updated_at=updated_at, + main_file_name=main_file_name) + ) + + +class TestService(object): + + @pytest.mark.parametrize( + 'is_valid, name, created_at, description, inputs, permalink, ' + 'outputs, scaling_groups, updated_at', + [ + (False, m_cls, now, 'desc', {}, 'perlnk', {}, {}, now), + (False, 'name', m_cls, 'desc', {}, 'perlnk', {}, {}, now), + (False, 'name', now, m_cls, {}, 'perlnk', {}, {}, now), + (False, 'name', now, 'desc', {}, m_cls, {}, {}, now), + (False, 'name', now, 'desc', {}, 'perlnk', m_cls, {}, now), + (False, 'name', now, 'desc', {}, 'perlnk', {}, m_cls, now), + (False, 'name', now, 'desc', {}, 'perlnk', {}, {}, m_cls), + + (True, 'name', now, 'desc', {}, 'perlnk', {}, {}, now), + (True, None, now, 'desc', {}, 'perlnk', {}, {}, now), + (True, 'name', now, 'desc', {}, 'perlnk', {}, {}, now), + (True, 'name', now, None, {}, 'perlnk', {}, {}, now), + (True, 'name', now, 'desc', {}, 'perlnk', {}, {}, now), + (True, 'name', now, 'desc', {}, None, {}, {}, now), + (True, 'name', now, 'desc', {}, 'perlnk', {}, {}, now), + (True, 'name', now, 'desc', {}, 'perlnk', {}, None, now), + (True, 'name', now, 'desc', {}, 'perlnk', {}, {}, None), + (True, 'name', now, 'desc', {}, 'perlnk', {}, {}, now), + ] + ) + def test_service_model_creation(self, service_storage, is_valid, name, created_at, description, + inputs, permalink, outputs, scaling_groups, updated_at): + service = _test_model( + is_valid=is_valid, + storage=service_storage, + model_cls=Service, + model_kwargs=dict( + name=name, + service_template=service_storage.service_template.list()[0], + created_at=created_at, + description=description, + inputs=inputs, + permalink=permalink, + outputs=outputs, + scaling_groups=scaling_groups, + updated_at=updated_at + )) + if is_valid: + assert service.service_template == \ + service_storage.service_template.list()[0] + + +class TestExecution(object): + + @pytest.mark.parametrize( + 'is_valid, created_at, started_at, ended_at, error, is_system_workflow, parameters, ' + 'status, workflow_name', + [ + (False, m_cls, now, now, 'error', False, {}, Execution.STARTED, 'wf_name'), + (False, now, m_cls, now, 'error', False, {}, Execution.STARTED, 'wf_name'), + (False, now, now, m_cls, 'error', False, {}, Execution.STARTED, 'wf_name'), + (False, now, now, now, m_cls, False, {}, Execution.STARTED, 'wf_name'), + (False, now, now, now, 'error', False, m_cls, Execution.STARTED, 'wf_name'), + (False, now, now, now, 'error', False, {}, m_cls, 'wf_name'), + (False, now, now, now, 'error', False, {}, Execution.STARTED, m_cls), + + (True, now, now, now, 'error', False, {}, Execution.STARTED, 'wf_name'), + (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'), + ] + ) + def test_execution_model_creation(self, service_storage, is_valid, created_at, started_at, + ended_at, error, is_system_workflow, parameters, status, + workflow_name): + execution = _test_model( + is_valid=is_valid, + storage=service_storage, + model_cls=Execution, + model_kwargs=dict( + service=service_storage.service.list()[0], + created_at=created_at, + started_at=started_at, + ended_at=ended_at, + error=error, + is_system_workflow=is_system_workflow, + parameters=parameters, + status=status, + workflow_name=workflow_name, + )) + if is_valid: + assert execution.service == service_storage.service.list()[0] + assert execution.service_template == service_storage.service_template.list()[0] + + def test_execution_status_transition(self): + def create_execution(status): + execution = Execution( + id='e_id', + workflow_name='w_name', + status=status, + parameters={}, + created_at=now, + ) + return execution + + valid_transitions = { + Execution.PENDING: [Execution.STARTED, + Execution.CANCELLED, + Execution.PENDING], + Execution.STARTED: [Execution.FAILED, + Execution.TERMINATED, + Execution.CANCELLED, + Execution.CANCELLING, + Execution.STARTED], + Execution.CANCELLING: [Execution.FAILED, + Execution.TERMINATED, + Execution.CANCELLED, + Execution.CANCELLING], + Execution.FAILED: [Execution.FAILED], + Execution.TERMINATED: [Execution.TERMINATED], + Execution.CANCELLED: [Execution.CANCELLED] + } + + invalid_transitions = { + Execution.PENDING: [Execution.FAILED, + Execution.TERMINATED, + Execution.CANCELLING], + Execution.STARTED: [Execution.PENDING], + Execution.CANCELLING: [Execution.PENDING, + Execution.STARTED], + Execution.FAILED: [Execution.PENDING, + Execution.STARTED, + Execution.TERMINATED, + Execution.CANCELLED, + Execution.CANCELLING], + Execution.TERMINATED: [Execution.PENDING, + Execution.STARTED, + Execution.FAILED, + Execution.CANCELLED, + Execution.CANCELLING], + Execution.CANCELLED: [Execution.PENDING, + Execution.STARTED, + Execution.FAILED, + Execution.TERMINATED, + Execution.CANCELLING], + } + + for current_status, valid_transitioned_statues in valid_transitions.items(): + for transitioned_status in valid_transitioned_statues: + execution = create_execution(current_status) + execution.status = transitioned_status + + for current_status, invalid_transitioned_statues in invalid_transitions.items(): + for transitioned_status in invalid_transitioned_statues: + execution = create_execution(current_status) + with pytest.raises(ValueError): + execution.status = transitioned_status + + +class TestServiceUpdate(object): + @pytest.mark.parametrize( + 'is_valid, created_at, service_plan, service_update_nodes, ' + 'service_update_service, service_update_node_templates, ' + 'modified_entity_ids, state', + [ + (False, m_cls, {}, {}, {}, [], {}, 'state'), + (False, now, m_cls, {}, {}, [], {}, 'state'), + (False, now, {}, m_cls, {}, [], {}, 'state'), + (False, now, {}, {}, m_cls, [], {}, 'state'), + (False, now, {}, {}, {}, m_cls, {}, 'state'), + (False, now, {}, {}, {}, [], m_cls, 'state'), + (False, now, {}, {}, {}, [], {}, m_cls), + + (True, now, {}, {}, {}, [], {}, 'state'), + (True, now, {}, None, {}, [], {}, 'state'), + (True, now, {}, {}, None, [], {}, 'state'), + (True, now, {}, {}, {}, None, {}, 'state'), + (True, now, {}, {}, {}, [], None, 'state'), + (True, now, {}, {}, {}, [], {}, None), + ] + ) + def test_service_update_model_creation(self, service_storage, is_valid, created_at, + service_plan, service_update_nodes, + service_update_service, service_update_node_templates, + modified_entity_ids, state): + service_update = _test_model( + is_valid=is_valid, + storage=service_storage, + model_cls=ServiceUpdate, + model_kwargs=dict( + service=service_storage.service.list()[0], + created_at=created_at, + service_plan=service_plan, + service_update_nodes=service_update_nodes, + service_update_service=service_update_service, + service_update_node_templates=service_update_node_templates, + modified_entity_ids=modified_entity_ids, + state=state + )) + if is_valid: + assert service_update.service == \ + service_storage.service.list()[0] + + +class TestServiceUpdateStep(object): + + @pytest.mark.parametrize( + 'is_valid, action, entity_id, entity_type', + [ + (False, m_cls, 'id', ServiceUpdateStep.ENTITY_TYPES.NODE), + (False, ServiceUpdateStep.ACTION_TYPES.ADD, m_cls, + ServiceUpdateStep.ENTITY_TYPES.NODE), + (False, ServiceUpdateStep.ACTION_TYPES.ADD, 'id', m_cls), + + (True, ServiceUpdateStep.ACTION_TYPES.ADD, 'id', + ServiceUpdateStep.ENTITY_TYPES.NODE) + ] + ) + def test_service_update_step_model_creation(self, service_update_storage, is_valid, action, + entity_id, entity_type): + service_update_step = _test_model( + is_valid=is_valid, + storage=service_update_storage, + model_cls=ServiceUpdateStep, + model_kwargs=dict( + service_update= + service_update_storage.service_update.list()[0], + action=action, + entity_id=entity_id, + entity_type=entity_type + )) + if is_valid: + assert service_update_step.service_update == \ + service_update_storage.service_update.list()[0] + + def test_service_update_step_order(self): + add_node = ServiceUpdateStep( + id='add_step', + action='add', + entity_type='node', + entity_id='node_id') + + modify_node = ServiceUpdateStep( + id='modify_step', + action='modify', + entity_type='node', + entity_id='node_id') + + remove_node = ServiceUpdateStep( + id='remove_step', + action='remove', + entity_type='node', + entity_id='node_id') + + for step in (add_node, modify_node, remove_node): + assert hash((step.id, step.entity_id)) == hash(step) + + assert remove_node < modify_node < add_node + assert not remove_node > modify_node > add_node + + add_rel = ServiceUpdateStep( + id='add_step', + action='add', + entity_type='relationship', + entity_id='relationship_id') + + remove_rel = ServiceUpdateStep( + id='remove_step', + action='remove', + entity_type='relationship', + entity_id='relationship_id') + + assert remove_rel < remove_node < add_node < add_rel + assert not add_node < None + + +class TestServiceModification(object): + @pytest.mark.parametrize( + 'is_valid, context, created_at, ended_at, modified_node_templates, nodes, status', + [ + (False, m_cls, now, now, {}, {}, ServiceModification.STARTED), + (False, {}, m_cls, now, {}, {}, ServiceModification.STARTED), + (False, {}, now, m_cls, {}, {}, ServiceModification.STARTED), + (False, {}, now, now, m_cls, {}, ServiceModification.STARTED), + (False, {}, now, now, {}, m_cls, ServiceModification.STARTED), + (False, {}, now, now, {}, {}, m_cls), + + (True, {}, now, now, {}, {}, ServiceModification.STARTED), + (True, {}, now, None, {}, {}, ServiceModification.STARTED), + (True, {}, now, now, None, {}, ServiceModification.STARTED), + (True, {}, now, now, {}, None, ServiceModification.STARTED), + ] + ) + def test_service_modification_model_creation(self, service_storage, is_valid, context, + created_at, ended_at, modified_node_templates, + nodes, status): + service_modification = _test_model( + is_valid=is_valid, + storage=service_storage, + model_cls=ServiceModification, + model_kwargs=dict( + service=service_storage.service.list()[0], + context=context, + created_at=created_at, + ended_at=ended_at, + modified_node_templates=modified_node_templates, + nodes=nodes, + status=status, + )) + if is_valid: + assert service_modification.service == \ + service_storage.service.list()[0] + + +class TestNodeTemplate(object): + @pytest.mark.parametrize( + 'is_valid, name, default_instances, max_instances, min_instances, plugin_specifications, ' + 'properties', + [ + (False, m_cls, 1, 1, 1, [], {}), + (False, 'name', m_cls, 1, 1, [], {}), + (False, 'name', 1, m_cls, 1, [], {}), + (False, 'name', 1, 1, m_cls, [], {}), + (False, 'name', 1, 1, 1, m_cls, {}), + (False, 'name', 1, 1, 1, None, {}), + + (True, 'name', 1, 1, 1, [], {}), + ] + ) + def test_node_template_model_creation(self, service_storage, is_valid, name, default_instances, + max_instances, min_instances, plugin_specifications, + properties): + node_template = _test_model( + is_valid=is_valid, + storage=service_storage, + model_cls=NodeTemplate, + model_kwargs=dict( + name=name, + type=service_storage.type.list()[0], + default_instances=default_instances, + max_instances=max_instances, + min_instances=min_instances, + plugin_specifications=plugin_specifications, + properties=properties, + service_template=service_storage.service_template.list()[0] + )) + if is_valid: + assert node_template.service_template == \ + service_storage.service_template.list()[0] + + +class TestNode(object): + @pytest.mark.parametrize( + 'is_valid, name, runtime_properties, scaling_groups, state, version', + [ + (False, m_cls, {}, [], 'state', 1), + (False, 'name', m_cls, [], 'state', 1), + (False, 'name', {}, m_cls, 'state', 1), + (False, 'name', {}, [], m_cls, 1), + (False, m_cls, {}, [], 'state', m_cls), + + (True, 'name', {}, [], 'state', 1), + (True, None, {}, [], 'state', 1), + (True, 'name', None, [], 'state', 1), + (True, 'name', {}, None, 'state', 1), + (True, 'name', {}, [], 'state', None), + ] + ) + def test_node_model_creation(self, node_template_storage, is_valid, name, runtime_properties, + scaling_groups, state, version): + node = _test_model( + is_valid=is_valid, + storage=node_template_storage, + model_cls=Node, + model_kwargs=dict( + node_template=node_template_storage.node_template.list()[0], + type=node_template_storage.type.list()[0], + name=name, + runtime_properties=runtime_properties, + scaling_groups=scaling_groups, + state=state, + version=version, + service=node_template_storage.service.list()[0] + )) + if is_valid: + assert node.node_template == node_template_storage.node_template.list()[0] + assert node.service == \ + node_template_storage.service.list()[0] + + +class TestNodeInstanceIP(object): + + ip = '1.1.1.1' + + def test_ip_on_none_hosted_node(self, service_storage): + node_template = self._node_template(service_storage, ip='not considered') + node = self._node(service_storage, + node_template, + is_host=False, + ip='not considered') + assert node.ip is None + + def test_property_ip_on_host_node(self, service_storage): + node_template = self._node_template(service_storage, ip=self.ip) + node = self._node(service_storage, node_template, is_host=True, ip=None) + assert node.ip == self.ip + + def test_runtime_property_ip_on_host_node(self, service_storage): + node_template = self._node_template(service_storage, ip='not considered') + node = self._node(service_storage, node_template, is_host=True, ip=self.ip) + assert node.ip == self.ip + + def test_no_ip_configured_on_host_node(self, service_storage): + node_template = self._node_template(service_storage, ip=None) + node = self._node(service_storage, node_template, is_host=True, ip=None) + assert node.ip is None + + def test_runtime_property_on_hosted_node(self, service_storage): + host_node_template = self._node_template(service_storage, ip=None) + host_node = self._node(service_storage, + host_node_template, + is_host=True, + ip=self.ip) + node_template = self._node_template(service_storage, ip=None) + node = self._node(service_storage, + node_template, + is_host=False, + ip=None, + host_fk=host_node.id) + assert node.ip == self.ip + + def _node_template(self, storage, ip): + kwargs = dict( + name='node_template', + type=storage.type.list()[0], + default_instances=1, + max_instances=1, + min_instances=1, + service_template=storage.service_template.list()[0] + ) + if ip: + kwargs['properties'] = {'ip': Parameter(name='ip', type_name='string', value=ip)} + node = NodeTemplate(**kwargs) + storage.node_template.put(node) + return node + + def _node(self, storage, node, is_host, ip, host_fk=None): + kwargs = dict( + name='node', + node_template=node, + type=storage.type.list()[0], + runtime_properties={}, + state='', + service=storage.service.list()[0] + ) + if ip: + kwargs['runtime_properties']['ip'] = ip + if is_host: + kwargs['host_fk'] = 1 + elif host_fk: + kwargs['host_fk'] = host_fk + node = Node(**kwargs) + storage.node.put(node) + return node + + [email protected]('Should be reworked into relationship') +class TestRelationship(object): + def test_relationship_model_creation(self, nodes_storage): + nodes = nodes_storage.node + source_node = nodes.get_by_name(mock.models.DEPENDENT_NODE_NAME) + target_node = nodes.get_by_name(mock.models.DEPENDENCY_NODE_NAME) + + relationship = mock.models.create_relationship( + source=source_node, + target=nodes_storage.node.get_by_name(mock.models.DEPENDENCY_NODE_NAME) + ) + nodes_storage.relationship.put(relationship) + + relationship_instance = _test_model( + is_valid=True, + storage=nodes_storage, + model_cls=Relationship, + model_kwargs=dict( + relationship=relationship, + source_node=source_node, + target_node=target_node + )) + assert relationship_instance.relationship == relationship + assert relationship_instance.source_node == source_node + assert relationship_instance.target_node == target_node + + +class TestPlugin(object): + @pytest.mark.parametrize( + 'is_valid, archive_name, distribution, distribution_release, ' + 'distribution_version, package_name, package_source, ' + 'package_version, supported_platform, supported_py_versions, uploaded_at, wheels', + [ + (False, m_cls, 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', 'pak_src', 'pak_ver', + 'sup_plat', [], now, []), + (False, 'arc_name', m_cls, 'dis_rel', 'dis_ver', 'pak_name', 'pak_src', 'pak_ver', + 'sup_plat', [], now, []), + (False, 'arc_name', 'dis_name', m_cls, 'dis_ver', 'pak_name', 'pak_src', 'pak_ver', + 'sup_plat', [], now, []), + (False, 'arc_name', 'dis_name', 'dis_rel', m_cls, 'pak_name', 'pak_src', 'pak_ver', + 'sup_plat', [], now, []), + (False, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', m_cls, 'pak_src', 'pak_ver', + 'sup_plat', [], now, []), + (False, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', m_cls, 'pak_ver', + 'sup_plat', [], now, []), + (False, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', 'pak_src', m_cls, + 'sup_plat', [], now, []), + (False, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', 'pak_src', + 'pak_ver', m_cls, [], now, []), + (False, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', 'pak_src', + 'pak_ver', 'sup_plat', m_cls, now, []), + (False, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', 'pak_src', + 'pak_ver', 'sup_plat', [], m_cls, []), + (False, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', 'pak_src', + 'pak_ver', 'sup_plat', [], now, m_cls), + + (True, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', 'pak_src', 'pak_ver', + 'sup_plat', [], now, []), + (True, 'arc_name', None, 'dis_rel', 'dis_ver', 'pak_name', 'pak_src', 'pak_ver', + 'sup_plat', [], now, []), + (True, 'arc_name', 'dis_name', None, 'dis_ver', 'pak_name', 'pak_src', 'pak_ver', + 'sup_plat', [], now, []), + (True, 'arc_name', 'dis_name', 'dis_rel', None, 'pak_name', 'pak_src', 'pak_ver', + 'sup_plat', [], now, []), + (True, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', 'pak_src', + 'pak_ver', 'sup_plat', [], now, []), + (True, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', None, 'pak_ver', + 'sup_plat', [], now, []), + (True, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', 'pak_src', None, + 'sup_plat', [], now, []), + (True, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', 'pak_src', + 'pak_ver', None, [], now, []), + (True, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', 'pak_src', + 'pak_ver', 'sup_plat', None, now, []), + (True, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', 'pak_src', + 'pak_ver', 'sup_plat', [], now, []), + ] + ) + def test_plugin_model_creation(self, empty_storage, is_valid, archive_name, distribution, + distribution_release, distribution_version, package_name, + package_source, package_version, supported_platform, + supported_py_versions, uploaded_at, wheels): + _test_model(is_valid=is_valid, + storage=empty_storage, + model_cls=Plugin, + model_kwargs=dict( + archive_name=archive_name, + distribution=distribution, + distribution_release=distribution_release, + distribution_version=distribution_version, + package_name=package_name, + package_source=package_source, + package_version=package_version, + supported_platform=supported_platform, + supported_py_versions=supported_py_versions, + uploaded_at=uploaded_at, + wheels=wheels, + )) + + +class TestTask(object): + + @pytest.mark.parametrize( + 'is_valid, status, due_at, started_at, ended_at, max_attempts, retry_count, ' + 'retry_interval, ignore_failure, name, operation_mapping, inputs, plugin_id', + [ + (False, m_cls, now, now, now, 1, 1, 1, True, 'name', 'map', {}, '1'), + (False, Task.STARTED, m_cls, now, now, 1, 1, 1, True, 'name', 'map', {}, '1'), + (False, Task.STARTED, now, m_cls, now, 1, 1, 1, True, 'name', 'map', {}, '1'), + (False, Task.STARTED, now, now, m_cls, 1, 1, 1, True, 'name', 'map', {}, '1'), + (False, Task.STARTED, now, now, now, m_cls, 1, 1, True, 'name', 'map', {}, '1'), + (False, Task.STARTED, now, now, now, 1, m_cls, 1, True, 'name', 'map', {}, '1'), + (False, Task.STARTED, now, now, now, 1, 1, m_cls, True, 'name', 'map', {}, '1'), + (False, Task.STARTED, now, now, now, 1, 1, 1, True, m_cls, 'map', {}, '1'), + (False, Task.STARTED, now, now, now, 1, 1, 1, True, 'name', m_cls, {}, '1'), + (False, Task.STARTED, now, now, now, 1, 1, 1, True, 'name', 'map', m_cls, '1'), + (False, Task.STARTED, now, now, now, 1, 1, 1, True, 'name', 'map', {}, m_cls), + (False, Task.STARTED, now, now, now, 1, 1, 1, True, 'name', 'map', None, '1'), + + (True, Task.STARTED, now, now, now, 1, 1, 1, True, 'name', 'map', {}, '1'), + (True, Task.STARTED, None, now, now, 1, 1, 1, True, 'name', 'map', {}, '1'), + (True, Task.STARTED, now, None, now, 1, 1, 1, True, 'name', 'map', {}, '1'), + (True, Task.STARTED, now, now, None, 1, 1, 1, True, 'name', 'map', {}, '1'), + (True, Task.STARTED, now, now, now, 1, None, 1, True, 'name', 'map', {}, '1'), + (True, Task.STARTED, now, now, now, 1, 1, None, True, 'name', 'map', {}, '1'), + (True, Task.STARTED, now, now, now, 1, 1, 1, None, 'name', 'map', {}, '1'), + (True, Task.STARTED, now, now, now, 1, 1, 1, True, None, 'map', {}, '1'), + (True, Task.STARTED, now, now, now, 1, 1, 1, True, 'name', None, {}, '1'), + (True, Task.STARTED, now, now, now, 1, 1, 1, True, 'name', 'map', {}, None), + ] + ) + def test_task_model_creation(self, execution_storage, is_valid, status, due_at, started_at, + ended_at, max_attempts, retry_count, retry_interval, + ignore_failure, name, operation_mapping, inputs, plugin_id): + task = _test_model( + is_valid=is_valid, + storage=execution_storage, + model_cls=Task, + model_kwargs=dict( + status=status, + execution=execution_storage.execution.list()[0], + due_at=due_at, + started_at=started_at, + ended_at=ended_at, + max_attempts=max_attempts, + retry_count=retry_count, + retry_interval=retry_interval, + ignore_failure=ignore_failure, + name=name, + implementation=operation_mapping, + inputs=inputs, + plugin_fk=plugin_id, + )) + if is_valid: + assert task.execution == execution_storage.execution.list()[0] + if task.plugin: + assert task.plugin == execution_storage.plugin.list()[0] + + def test_task_max_attempts_validation(self): + def create_task(max_attempts): + Task(execution_fk='eid', + name='name', + implementation='', + inputs={}, + max_attempts=max_attempts) + create_task(max_attempts=1) + create_task(max_attempts=2) + create_task(max_attempts=Task.INFINITE_RETRIES) + with pytest.raises(ValueError): + create_task(max_attempts=0) + with pytest.raises(ValueError): + create_task(max_attempts=-2)
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/dd5bfa93/tests/orchestrator/context/test_operation.py ---------------------------------------------------------------------- diff --git a/tests/orchestrator/context/test_operation.py b/tests/orchestrator/context/test_operation.py index 8ac8d49..7817a90 100644 --- a/tests/orchestrator/context/test_operation.py +++ b/tests/orchestrator/context/test_operation.py @@ -84,7 +84,7 @@ def test_node_operation_task_execution(ctx, executor): operation_context = global_test_holder[api.task.OperationTask.NAME_FORMAT.format( type='node', - id=node.id, + id=node.name, interface=interface_name, operation=operation_name )] @@ -95,7 +95,7 @@ def test_node_operation_task_execution(ctx, executor): assert operation_context.task.actor == node assert operation_context.task.name == api.task.OperationTask.NAME_FORMAT.format( type='node', - id=node.id, + id=node.name, interface=interface_name, operation=operation_name ) @@ -140,7 +140,7 @@ def test_relationship_operation_task_execution(ctx, executor): operation_context = global_test_holder[api.task.OperationTask.NAME_FORMAT.format( type='relationship', - id=relationship.id, + id=relationship.name, interface=interface_name, operation=operation_name )] @@ -205,7 +205,7 @@ def test_invalid_task_operation_id(ctx, executor): op_node_id = global_test_holder[api.task.OperationTask.NAME_FORMAT.format( type='node', - id=node.id, + id=node.name, interface=interface_name, operation=operation_name )] @@ -218,7 +218,8 @@ def test_plugin_workdir(ctx, executor, tmpdir): operation_name = 'create' plugin = mock.models.create_plugin() - plugin.name = 'mock_plugin' + ctx.model.plugin.put(plugin) + plugin_specification = mock.models.create_plugin_specification() node = ctx.model.node.get_by_name(mock.models.DEPENDENCY_NODE_NAME) interface = mock.models.create_interface( node.service, @@ -226,10 +227,10 @@ def test_plugin_workdir(ctx, executor, tmpdir): operation_name, operation_kwargs=dict( implementation='{0}.{1}'.format(__name__, _test_plugin_workdir.__name__), - plugin=plugin) + plugin_specification=plugin_specification) ) node.interfaces[interface.name] = interface - node.plugins = [plugin] + node.plugin_specifications = [plugin_specification] ctx.model.node.update(node) filename = 'test_file' http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/dd5bfa93/tests/orchestrator/context/test_serialize.py ---------------------------------------------------------------------- diff --git a/tests/orchestrator/context/test_serialize.py b/tests/orchestrator/context/test_serialize.py index 9e5a0b4..2ec999c 100644 --- a/tests/orchestrator/context/test_serialize.py +++ b/tests/orchestrator/context/test_serialize.py @@ -44,14 +44,17 @@ def test_serialize_operation_context(context, executor, tmpdir): def _mock_workflow(ctx, graph): node = ctx.model.node.get_by_name(mock.models.DEPENDENCY_NODE_NAME) plugin = mock.models.create_plugin() + ctx.model.plugin.put(plugin) + plugin_specification = mock.models.create_plugin_specification() interface = mock.models.create_interface( node.service, 'test', 'op', - operation_kwargs=dict(implementation=_operation_mapping(), plugin=plugin) + operation_kwargs=dict(implementation=_operation_mapping(), + plugin_specification=plugin_specification) ) node.interfaces[interface.name] = interface - node.plugins = [plugin] + node.plugin_specifications = [plugin_specification] task = api.task.OperationTask.for_node(node=node, interface_name='test', operation_name='op') graph.add_tasks(task) return graph http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/dd5bfa93/tests/orchestrator/context/test_toolbelt.py ---------------------------------------------------------------------- diff --git a/tests/orchestrator/context/test_toolbelt.py b/tests/orchestrator/context/test_toolbelt.py index f04fd4b..0e35a26 100644 --- a/tests/orchestrator/context/test_toolbelt.py +++ b/tests/orchestrator/context/test_toolbelt.py @@ -132,7 +132,7 @@ def test_relationship_tool_belt(workflow_context, executor): assert isinstance(global_test_holder.get(api.task.OperationTask.NAME_FORMAT.format( type='relationship', - id=relationship.id, + id=relationship.name, interface=interface_name, operation=operation_name )), RelationshipToolBelt) http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/dd5bfa93/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 4f5671b..139d239 100644 --- a/tests/orchestrator/workflows/api/test_task.py +++ b/tests/orchestrator/workflows/api/test_task.py @@ -43,17 +43,20 @@ class TestOperationTask(object): operation_name = 'create' plugin = mock.models.create_plugin('package', '0.1') - plugin.name = 'test_plugin' + ctx.model.node.update(plugin) + + plugin_specification = mock.models.create_plugin_specification('package', '0.1') interface = mock.models.create_interface( ctx.service, interface_name, operation_name, - operation_kwargs=dict(plugin=plugin, implementation='op_path')) + operation_kwargs=dict(plugin_specification=plugin_specification, + implementation='op_path')) node = ctx.model.node.get_by_name(mock.models.DEPENDENT_NODE_NAME) node.interfaces = {interface.name: interface} - node.plugins = [plugin] + node.plugin_specifications = [plugin_specification] ctx.model.node.update(node) inputs = {'test_input': True} max_attempts = 10 @@ -72,7 +75,7 @@ class TestOperationTask(object): assert api_task.name == api.task.OperationTask.NAME_FORMAT.format( type='node', - id=node.id, + id=node.name, interface=interface_name, operation=operation_name ) @@ -90,18 +93,21 @@ class TestOperationTask(object): operation_name = 'preconfigure' plugin = mock.models.create_plugin('package', '0.1') - plugin.name = 'test_plugin' + ctx.model.node.update(plugin) + + plugin_specification = mock.models.create_plugin_specification('package', '0.1') interface = mock.models.create_interface( ctx.service, interface_name, operation_name, - operation_kwargs=dict(plugin=plugin, implementation='op_path') + operation_kwargs=dict(plugin_specification=plugin_specification, + implementation='op_path') ) relationship = ctx.model.relationship.list()[0] relationship.interfaces[interface.name] = interface - relationship.source_node.plugins = [plugin] + relationship.source_node.plugin_specifications = [plugin_specification] inputs = {'test_input': True} max_attempts = 10 retry_interval = 10 @@ -117,7 +123,7 @@ class TestOperationTask(object): assert api_task.name == api.task.OperationTask.NAME_FORMAT.format( type='relationship', - id=relationship.id, + id=relationship.name, interface=interface_name, operation=operation_name ) @@ -134,18 +140,21 @@ class TestOperationTask(object): operation_name = 'preconfigure' plugin = mock.models.create_plugin('package', '0.1') - plugin.name = 'test_plugin' + ctx.model.node.update(plugin) + + plugin_specification = mock.models.create_plugin_specification('package', '0.1') interface = mock.models.create_interface( ctx.service, interface_name, operation_name, - operation_kwargs=dict(plugin=plugin, implementation='op_path') + operation_kwargs=dict(plugin_specification=plugin_specification, + implementation='op_path') ) relationship = ctx.model.relationship.list()[0] relationship.interfaces[interface.name] = interface - relationship.target_node.plugins = [plugin] + relationship.target_node.plugin_specifications = [plugin_specification] inputs = {'test_input': True} max_attempts = 10 retry_interval = 10 @@ -162,7 +171,7 @@ class TestOperationTask(object): assert api_task.name == api.task.OperationTask.NAME_FORMAT.format( type='relationship', - id=relationship.id, + id=relationship.name, interface=interface_name, operation=operation_name ) http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/dd5bfa93/tests/orchestrator/workflows/builtin/test_execute_operation.py ---------------------------------------------------------------------- diff --git a/tests/orchestrator/workflows/builtin/test_execute_operation.py b/tests/orchestrator/workflows/builtin/test_execute_operation.py index 0e5a506..e2a8ef0 100644 --- a/tests/orchestrator/workflows/builtin/test_execute_operation.py +++ b/tests/orchestrator/workflows/builtin/test_execute_operation.py @@ -57,7 +57,7 @@ def test_execute_operation(ctx): assert len(execute_tasks) == 1 assert execute_tasks[0].name == task.OperationTask.NAME_FORMAT.format( type='node', - id=node.id, + id=node.name, interface=interface_name, operation=operation_name ) http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/dd5bfa93/tests/orchestrator/workflows/core/test_task.py ---------------------------------------------------------------------- diff --git a/tests/orchestrator/workflows/core/test_task.py b/tests/orchestrator/workflows/core/test_task.py index d03597d..49f020f 100644 --- a/tests/orchestrator/workflows/core/test_task.py +++ b/tests/orchestrator/workflows/core/test_task.py @@ -83,18 +83,23 @@ class TestOperationTask(object): return api_task, core_task def test_node_operation_task_creation(self, ctx): - storage_plugin = mock.models.create_plugin(package_name='p1', package_version='0.1') - storage_plugin_other = mock.models.create_plugin(package_name='p0', package_version='0.0') - ctx.model.plugin.put(storage_plugin_other) + storage_plugin = mock.models.create_plugin( + package_name='p1', package_version='0.1') + storage_plugin_specification = mock.models.create_plugin_specification( + package_name='p1', package_version='0.1') + storage_plugin_specification_other = mock.models.create_plugin( + package_name='p0', package_version='0.0') ctx.model.plugin.put(storage_plugin) + ctx.model.plugin_specification.put(storage_plugin_specification_other) + ctx.model.plugin_specification.put(storage_plugin_specification) node = ctx.model.node.get_by_name(mock.models.DEPENDENCY_NODE_NAME) node_template = node.node_template - node_template.plugins = [storage_plugin] + node_template.plugin_specifications = [storage_plugin_specification] interface = mock.models.create_interface( node.service, NODE_INTERFACE_NAME, NODE_OPERATION_NAME, - operation_kwargs=dict(plugin=storage_plugin) + operation_kwargs=dict(plugin_specification=storage_plugin_specification) ) node.interfaces[interface.name] = interface ctx.model.node_template.update(node_template) http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/dd5bfa93/tests/resources/service-templates/tosca-simple-1.0/node-cellar/workflows.py ---------------------------------------------------------------------- diff --git a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/workflows.py b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/workflows.py index 4f73c50..94ee824 100644 --- a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/workflows.py +++ b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/workflows.py @@ -20,7 +20,6 @@ def maintenance(ctx, graph, enabled): graph.add_tasks(OperationTask.for_node(node=node, interface_name=INTERFACE_NAME, operation_name=ENABLE_OPERATION_NAME if enabled - else DISABLE_OPERATION_NAME, - dry=True)) + else DISABLE_OPERATION_NAME)) except TaskException: pass http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/dd5bfa93/tests/storage/__init__.py ---------------------------------------------------------------------- diff --git a/tests/storage/__init__.py b/tests/storage/__init__.py index f33205f..e836e2a 100644 --- a/tests/storage/__init__.py +++ b/tests/storage/__init__.py @@ -12,35 +12,17 @@ # 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 os -import platform + from shutil import rmtree from tempfile import mkdtemp from sqlalchemy import ( create_engine, orm, - Column, - Text, - Integer, pool ) - -from aria.modeling import ( - models, - types as modeling_types, - bases -) -from aria import modeling - - -class MockModel(models.aria_declarative_base, bases.ModelMixin): #pylint: disable=abstract-method - __tablename__ = 'mock_model' - model_dict = Column(modeling_types.Dict) - model_list = Column(modeling_types.List) - value = Column(Integer) - name = Column(Text) +from aria.modeling import models class TestFileSystem(object): http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/dd5bfa93/tests/storage/test_instrumentation.py ---------------------------------------------------------------------- diff --git a/tests/storage/test_instrumentation.py b/tests/storage/test_instrumentation.py index 3ef74e4..4188fcd 100644 --- a/tests/storage/test_instrumentation.py +++ b/tests/storage/test_instrumentation.py @@ -17,7 +17,7 @@ import pytest from sqlalchemy import Column, Text, Integer, event from aria.modeling import ( - bases, + mixins, types as modeling_types, models ) @@ -28,7 +28,7 @@ from aria.storage import ( instrumentation ) -from ..storage import release_sqlite_storage, init_inmemory_model_storage +from . import release_sqlite_storage, init_inmemory_model_storage STUB = instrumentation._STUB Value = instrumentation._Value @@ -337,7 +337,7 @@ def storage(): release_sqlite_storage(result) -class _MockModel(bases.ModelMixin): +class _MockModel(mixins.ModelMixin): name = Column(Text) dict1 = Column(modeling_types.Dict) dict2 = Column(modeling_types.Dict) @@ -356,7 +356,7 @@ class MockModel2(_MockModel, models.aria_declarative_base): __tablename__ = 'mock_model_2' -class StrictMockModel(bases.ModelMixin, models.aria_declarative_base): +class StrictMockModel(mixins.ModelMixin, models.aria_declarative_base): __tablename__ = 'strict_mock_model' strict_dict = Column(modeling_types.StrictDict(basestring, basestring)) http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/dd5bfa93/tests/storage/test_model_storage.py ---------------------------------------------------------------------- diff --git a/tests/storage/test_model_storage.py b/tests/storage/test_model_storage.py deleted file mode 100644 index bb778d4..0000000 --- a/tests/storage/test_model_storage.py +++ /dev/null @@ -1,102 +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. - -import pytest - -from aria.storage import ( - ModelStorage, - exceptions, - sql_mapi -) -from aria import (application_model_storage, modeling) -from ..storage import (release_sqlite_storage, init_inmemory_model_storage) - -from . import MockModel - - [email protected] -def storage(): - base_storage = ModelStorage(sql_mapi.SQLAlchemyModelAPI, - initiator=init_inmemory_model_storage) - base_storage.register(MockModel) - yield base_storage - release_sqlite_storage(base_storage) - - [email protected](scope='module', autouse=True) -def module_cleanup(): - modeling.models.aria_declarative_base.metadata.remove(MockModel.__table__) #pylint: disable=no-member - - -def test_storage_base(storage): - with pytest.raises(AttributeError): - storage.non_existent_attribute() - - -def test_model_storage(storage): - mock_model = MockModel(value=0, name='model_name') - storage.mock_model.put(mock_model) - - assert storage.mock_model.get_by_name('model_name') == mock_model - - assert [mm_from_storage for mm_from_storage in storage.mock_model.iter()] == [mock_model] - assert [mm_from_storage for mm_from_storage in storage.mock_model] == [mock_model] - - storage.mock_model.delete(mock_model) - with pytest.raises(exceptions.StorageError): - storage.mock_model.get(mock_model.id) - - -def test_application_storage_factory(): - storage = application_model_storage(sql_mapi.SQLAlchemyModelAPI, - initiator=init_inmemory_model_storage) - - assert storage.service_template - assert storage.node_template - assert storage.group_template - assert storage.policy_template - assert storage.substitution_template - assert storage.substitution_template_mapping - assert storage.requirement_template - assert storage.relationship_template - assert storage.capability_template - assert storage.interface_template - assert storage.operation_template - assert storage.artifact_template - - assert storage.service - assert storage.node - assert storage.group - assert storage.policy - assert storage.substitution - assert storage.substitution_mapping - assert storage.relationship - assert storage.capability - assert storage.interface - assert storage.operation - assert storage.artifact - - assert storage.execution - assert storage.service_update - assert storage.service_update_step - assert storage.service_modification - assert storage.plugin - assert storage.task - - assert storage.parameter - assert storage.type - assert storage.metadata - - release_sqlite_storage(storage)
