######### # Copyright (c) 2016 GigaSpaces Technologies Ltd. All rights reserved # # Licensed 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. """Test the functions related to retrieving relationship information. Functions under test are mostly inside openstack_plugin_common: get_relationships_by_openstack_type get_connected_nodes_by_openstack_type get_openstack_ids_of_connected_nodes_by_openstack_type get_single_connected_node_by_openstack_type """ import uuid from unittest import TestCase from neutron_plugin.network import NETWORK_OPENSTACK_TYPE from cloudify.exceptions import NonRecoverableError from cloudify.mocks import ( MockCloudifyContext, MockNodeContext, MockNodeInstanceContext, MockRelationshipContext, MockRelationshipSubjectContext, ) from openstack_plugin_common import ( OPENSTACK_ID_PROPERTY, OPENSTACK_TYPE_PROPERTY, get_openstack_id_of_single_connected_node_by_openstack_type, get_openstack_ids_of_connected_nodes_by_openstack_type, get_relationships_by_openstack_type, get_single_connected_node_by_openstack_type, ) class RelationshipsTestBase(TestCase): def _make_vm_ctx_with_relationships(self, rel_specs, properties=None): """Prepare a mock CloudifyContext from the given relationship spec. rel_specs is an ordered collection of relationship specs - dicts with the keys "node" and "instance" used to construct the MockNodeContext and the MockNodeInstanceContext, and optionally a "type" key. Examples: [ {}, {"node": {"id": 5}}, { "type": "some_type", "instance": { "id": 3, "runtime_properties":{} } } ] """ if properties is None: properties = {} relationships = [] for rel_spec in rel_specs: node = rel_spec.get('node', {}) node_id = node.pop('id', uuid.uuid4().hex) instance = rel_spec.get('instance', {}) instance_id = instance.pop('id', '{0}_{1}'.format( node_id, uuid.uuid4().hex)) if 'properties' not in node: node['properties'] = {} node_ctx = MockNodeContext(id=node_id, **node) instance_ctx = MockNodeInstanceContext(id=instance_id, **instance) rel_subject_ctx = MockRelationshipSubjectContext( node=node_ctx, instance=instance_ctx) rel_type = rel_spec.get('type') rel_ctx = MockRelationshipContext(target=rel_subject_ctx, type=rel_type) relationships.append(rel_ctx) return MockCloudifyContext(node_id='vm', properties=properties, relationships=relationships) class TestGettingRelatedResources(RelationshipsTestBase): def test_get_relationships_finds_all_by_type(self): """get_relationships_by_openstack_type returns all rels that match.""" rel_specs = [{ 'instance': { 'id': instance_id, 'runtime_properties': { OPENSTACK_TYPE_PROPERTY: NETWORK_OPENSTACK_TYPE } } } for instance_id in range(3)] rel_specs.append({ 'instance': { 'runtime_properties': { OPENSTACK_TYPE_PROPERTY: 'something else' } } }) ctx = self._make_vm_ctx_with_relationships(rel_specs) filtered = get_relationships_by_openstack_type(ctx, NETWORK_OPENSTACK_TYPE) self.assertEqual(3, len(filtered)) def test_get_ids_of_nodes_by_type(self): rel_spec = { 'instance': { 'runtime_properties': { OPENSTACK_TYPE_PROPERTY: NETWORK_OPENSTACK_TYPE, OPENSTACK_ID_PROPERTY: 'the node id' } } } ctx = self._make_vm_ctx_with_relationships([rel_spec]) ids = get_openstack_ids_of_connected_nodes_by_openstack_type( ctx, NETWORK_OPENSTACK_TYPE) self.assertEqual(['the node id'], ids) class TestGetSingleByID(RelationshipsTestBase): def _make_instances(self, ids): """Mock a context with relationships to instances with given ids.""" rel_specs = [{ 'node': { 'id': node_id }, 'instance': { 'runtime_properties': { OPENSTACK_TYPE_PROPERTY: NETWORK_OPENSTACK_TYPE, OPENSTACK_ID_PROPERTY: node_id } } } for node_id in ids] return self._make_vm_ctx_with_relationships(rel_specs) def test_get_single_id(self): ctx = self._make_instances(['the node id']) found_id = get_openstack_id_of_single_connected_node_by_openstack_type( ctx, NETWORK_OPENSTACK_TYPE) self.assertEqual('the node id', found_id) def test_get_single_id_two_found(self): ctx = self._make_instances([0, 1]) self.assertRaises( NonRecoverableError, get_openstack_id_of_single_connected_node_by_openstack_type, ctx, NETWORK_OPENSTACK_TYPE) def test_get_single_id_two_found_if_exists_true(self): ctx = self._make_instances([0, 1]) try: get_openstack_id_of_single_connected_node_by_openstack_type( ctx, NETWORK_OPENSTACK_TYPE, if_exists=True) except NonRecoverableError as e: self.assertIn(NETWORK_OPENSTACK_TYPE, e.message) else: self.fail() def test_get_single_id_if_exists_none_found(self): ctx = self._make_instances([]) found = get_openstack_id_of_single_connected_node_by_openstack_type( ctx, NETWORK_OPENSTACK_TYPE, if_exists=True) self.assertIsNone(found) def test_get_single_id_none_found(self): rel_spec = [] ctx = self._make_vm_ctx_with_relationships(rel_spec) self.assertRaises( NonRecoverableError, get_openstack_id_of_single_connected_node_by_openstack_type, ctx, NETWORK_OPENSTACK_TYPE) def test_get_single_node(self): ctx = self._make_instances(['the node id']) found_node = get_single_connected_node_by_openstack_type( ctx, NETWORK_OPENSTACK_TYPE) self.assertEqual('the node id', found_node.id) def test_get_single_node_two_found(self): ctx = self._make_instances([0, 1]) self.assertRaises( NonRecoverableError, get_single_connected_node_by_openstack_type, ctx, NETWORK_OPENSTACK_TYPE) def test_get_single_node_two_found_if_exists(self): ctx = self._make_instances([0, 1]) self.assertRaises( NonRecoverableError, get_single_connected_node_by_openstack_type, ctx, NETWORK_OPENSTACK_TYPE, if_exists=True) def test_get_single_node_if_exists_none_found(self): ctx = self._make_instances([]) found = get_single_connected_node_by_openstack_type( ctx, NETWORK_OPENSTACK_TYPE, if_exists=True) self.assertIsNone(found) def test_get_single_node_none_found(self): ctx = self._make_instances([]) self.assertRaises( NonRecoverableError, get_single_connected_node_by_openstack_type, ctx, NETWORK_OPENSTACK_TYPE)