From 2b31ea8dbbca512898d1256eb1b0df78c950b369 Mon Sep 17 00:00:00 2001 From: Quan Pham Date: Wed, 10 Jul 2024 09:53:30 -0400 Subject: [PATCH] Added dummy identity provider to remove Keystone dependency during testing The identity provider used by `esi_leap` is now abstracted with a `BaseIDP` ABC, and implemented by two subclasses: A `KeystoneIDP` class which mostly copied the code from `common/keystone.py`, and `DummyIDP` which mocks a real IDP The IDP used by `esi_leap` can be set by overriding the `idp_type` CONF value like so: CONF.set_override( "idp_type", "dummy_idp", group="esi" ) As a consequence of abstracting the IDP, `common/keystone.py` has been removed. All references to `common/keystone.py` and the functions defined in it has been appropriately changed. New unit tests have been added for the keystone and dummy IDP clients --- esi_leap/api/controllers/v1/event.py | 6 +- esi_leap/api/controllers/v1/lease.py | 10 +- esi_leap/api/controllers/v1/node.py | 12 +- esi_leap/api/controllers/v1/offer.py | 8 +- esi_leap/api/controllers/v1/utils.py | 12 +- esi_leap/common/{keystone.py => idp.py} | 36 ++--- esi_leap/common/idp_clients/__init__.py | 0 esi_leap/common/idp_clients/baseIDP.py | 23 +++ esi_leap/common/idp_clients/dummyIDP.py | 40 ++++++ esi_leap/common/idp_clients/keystoneIDP.py | 36 +++++ esi_leap/conf/__init__.py | 2 + esi_leap/conf/esi.py | 23 +++ esi_leap/db/sqlalchemy/api.py | 4 +- esi_leap/tests/api/base.py | 1 + .../tests/api/controllers/v1/test_event.py | 6 +- .../tests/api/controllers/v1/test_lease.py | 26 ++-- .../tests/api/controllers/v1/test_node.py | 12 +- .../tests/api/controllers/v1/test_offer.py | 20 +-- .../tests/api/controllers/v1/test_utils.py | 20 +-- esi_leap/tests/base.py | 1 + esi_leap/tests/common/test_idp.py | 131 ++++++++++++++++++ esi_leap/tests/common/test_keystone.py | 88 ------------ esi_leap/tests/db/sqlalchemy/test_api.py | 2 +- 23 files changed, 346 insertions(+), 173 deletions(-) rename esi_leap/common/{keystone.py => idp.py} (64%) create mode 100644 esi_leap/common/idp_clients/__init__.py create mode 100644 esi_leap/common/idp_clients/baseIDP.py create mode 100644 esi_leap/common/idp_clients/dummyIDP.py create mode 100644 esi_leap/common/idp_clients/keystoneIDP.py create mode 100644 esi_leap/conf/esi.py create mode 100644 esi_leap/tests/common/test_idp.py delete mode 100644 esi_leap/tests/common/test_keystone.py diff --git a/esi_leap/api/controllers/v1/event.py b/esi_leap/api/controllers/v1/event.py index d8aa5ae4..9dee5bb2 100644 --- a/esi_leap/api/controllers/v1/event.py +++ b/esi_leap/api/controllers/v1/event.py @@ -21,7 +21,7 @@ from esi_leap.api.controllers import types from esi_leap.api.controllers.v1 import utils from esi_leap.common import exception -from esi_leap.common import keystone +from esi_leap.common import idp import esi_leap.conf from esi_leap.objects import event as event_obj from esi_leap.resource_objects import get_resource_object @@ -82,9 +82,7 @@ def get_all( lessee_or_owner_id = cdict["project_id"] if lessee_or_owner_id is not None: - lessee_or_owner_id = keystone.get_project_uuid_from_ident( - lessee_or_owner_id - ) + lessee_or_owner_id = idp.get_project_uuid_from_ident(lessee_or_owner_id) if resource_uuid is not None: if resource_type is None: diff --git a/esi_leap/api/controllers/v1/lease.py b/esi_leap/api/controllers/v1/lease.py index 1898396b..cf9c95fe 100644 --- a/esi_leap/api/controllers/v1/lease.py +++ b/esi_leap/api/controllers/v1/lease.py @@ -26,7 +26,7 @@ from esi_leap.common import constants from esi_leap.common import exception from esi_leap.common import ironic -from esi_leap.common import keystone +from esi_leap.common import idp from esi_leap.common import statuses import esi_leap.conf from esi_leap.objects import lease as lease_obj @@ -120,10 +120,10 @@ def get_all( cdict = request.to_policy_values() if project_id is not None: - project_id = keystone.get_project_uuid_from_ident(project_id) + project_id = idp.get_project_uuid_from_ident(project_id) if owner_id is not None: - owner_id = keystone.get_project_uuid_from_ident(owner_id) + owner_id = idp.get_project_uuid_from_ident(owner_id) if resource_uuid is not None: if resource_type is None: @@ -156,7 +156,7 @@ def get_all( with concurrent.futures.ThreadPoolExecutor() as executor: f1 = executor.submit(ironic.get_node_list) - f2 = executor.submit(keystone.get_project_list) + f2 = executor.submit(idp.get_project_list) node_list = f1.result() project_list = f2.result() @@ -196,7 +196,7 @@ def post(self, new_lease): lease_dict["resource_uuid"] = resource.get_uuid() if "project_id" in lease_dict: - lease_dict["project_id"] = keystone.get_project_uuid_from_ident( + lease_dict["project_id"] = idp.get_project_uuid_from_ident( lease_dict["project_id"] ) diff --git a/esi_leap/api/controllers/v1/node.py b/esi_leap/api/controllers/v1/node.py index 55d2c6f1..366bdc27 100644 --- a/esi_leap/api/controllers/v1/node.py +++ b/esi_leap/api/controllers/v1/node.py @@ -21,7 +21,7 @@ from esi_leap.api.controllers import base from esi_leap.api.controllers import types from esi_leap.common import ironic -from esi_leap.common import keystone +from esi_leap.common import idp from esi_leap.common import statuses import esi_leap.conf from esi_leap.objects import lease as lease_obj @@ -83,9 +83,9 @@ def get_all(self, resource_class=None, owner=None, lessee=None): context = pecan.request.context if owner is not None: - owner = keystone.get_project_uuid_from_ident(owner) + owner = idp.get_project_uuid_from_ident(owner) if lessee is not None: - lessee = keystone.get_project_uuid_from_ident(lessee) + lessee = idp.get_project_uuid_from_ident(lessee) filter_args = { "resource_class": resource_class, @@ -99,7 +99,7 @@ def get_all(self, resource_class=None, owner=None, lessee=None): with concurrent.futures.ThreadPoolExecutor() as executor: filter_args = {k: v for k, v in filter_args.items() if v is not None} f1 = executor.submit(ironic.get_node_list, context, **filter_args) - f2 = executor.submit(keystone.get_project_list) + f2 = executor.submit(idp.get_project_list) nodes = f1.result() project_list = f2.result() @@ -139,8 +139,8 @@ def get_all(self, resource_class=None, owner=None, lessee=None): resource_class=node.resource_class, properties=ironic.get_condensed_properties(node.properties), maintenance=str(node.maintenance), - owner=keystone.get_project_name(node.owner, project_list), - lessee=keystone.get_project_name(node.lessee, project_list), + owner=idp.get_project_name(node.owner, project_list), + lessee=idp.get_project_name(node.lessee, project_list), future_offers=f_offer_uuids, future_leases=f_lease_uuids, ) diff --git a/esi_leap/api/controllers/v1/offer.py b/esi_leap/api/controllers/v1/offer.py index ca2296c0..50ab2fb1 100644 --- a/esi_leap/api/controllers/v1/offer.py +++ b/esi_leap/api/controllers/v1/offer.py @@ -26,7 +26,7 @@ from esi_leap.api.controllers.v1 import utils from esi_leap.common import exception from esi_leap.common import ironic -from esi_leap.common import keystone +from esi_leap.common import idp from esi_leap.common import statuses import esi_leap.conf from esi_leap.objects import lease as lease_obj @@ -124,7 +124,7 @@ def get_all( utils.policy_authorize("esi_leap:offer:get_all", cdict, cdict) if project_id is not None: - project_id = keystone.get_project_uuid_from_ident(project_id) + project_id = idp.get_project_uuid_from_ident(project_id) if resource_uuid is not None: if resource_type is None: @@ -193,7 +193,7 @@ def get_all( node_list = None with concurrent.futures.ThreadPoolExecutor() as executor: f1 = executor.submit(ironic.get_node_list) - f2 = executor.submit(keystone.get_project_list) + f2 = executor.submit(idp.get_project_list) node_list = f1.result() project_list = f2.result() @@ -231,7 +231,7 @@ def post(self, new_offer): offer_dict["resource_uuid"] = resource.get_uuid() if "lessee_id" in offer_dict: - offer_dict["lessee_id"] = keystone.get_project_uuid_from_ident( + offer_dict["lessee_id"] = idp.get_project_uuid_from_ident( offer_dict["lessee_id"] ) diff --git a/esi_leap/api/controllers/v1/utils.py b/esi_leap/api/controllers/v1/utils.py index 25d3e892..ec7f1070 100644 --- a/esi_leap/api/controllers/v1/utils.py +++ b/esi_leap/api/controllers/v1/utils.py @@ -16,7 +16,7 @@ import datetime from esi_leap.common import exception -from esi_leap.common import keystone +from esi_leap.common import idp from esi_leap.common import policy from esi_leap.objects import lease as lease_obj from esi_leap.objects import offer as offer_obj @@ -148,7 +148,7 @@ def check_offer_lessee(cdict, offer): if offer.lessee_id is None or offer.project_id == project_id: return - if offer.lessee_id not in keystone.get_parent_project_id_tree(project_id): + if offer.lessee_id not in idp.get_parent_project_id_tree(project_id): resource_policy_authorize( "esi_leap:offer:offer_admin", cdict, cdict, "offer", offer.uuid ) @@ -159,8 +159,8 @@ def offer_get_dict_with_added_info(offer, project_list=None, node_list=None): o = offer.to_dict() o["availabilities"] = offer.get_availabilities() - o["project"] = keystone.get_project_name(offer.project_id, project_list) - o["lessee"] = keystone.get_project_name(offer.lessee_id, project_list) + o["project"] = idp.get_project_name(offer.project_id, project_list) + o["lessee"] = idp.get_project_name(offer.lessee_id, project_list) o["resource"] = resource.get_name(node_list) o["resource_class"] = resource.get_resource_class(node_list) o["resource_properties"] = resource.get_properties(node_list) @@ -171,8 +171,8 @@ def lease_get_dict_with_added_info(lease, project_list=None, node_list=None): resource = lease.resource_object() lease_dict = lease.to_dict() - lease_dict["project"] = keystone.get_project_name(lease.project_id, project_list) - lease_dict["owner"] = keystone.get_project_name(lease.owner_id, project_list) + lease_dict["project"] = idp.get_project_name(lease.project_id, project_list) + lease_dict["owner"] = idp.get_project_name(lease.owner_id, project_list) lease_dict["resource"] = resource.get_name(node_list) lease_dict["resource_class"] = resource.get_resource_class(node_list) lease_dict["resource_properties"] = resource.get_properties(node_list) diff --git a/esi_leap/common/keystone.py b/esi_leap/common/idp.py similarity index 64% rename from esi_leap/common/keystone.py rename to esi_leap/common/idp.py index 464b95c4..fd1a190f 100644 --- a/esi_leap/common/keystone.py +++ b/esi_leap/common/idp.py @@ -10,38 +10,40 @@ # License for the specific language governing permissions and limitations # under the License. -from keystoneauth1 import loading as ks_loading -from keystoneclient import client as keystone_client from oslo_utils import uuidutils from esi_leap.common import exception import esi_leap.conf +from esi_leap.common.idp_clients import baseIDP +from esi_leap.common.idp_clients import keystoneIDP # noqa: F401 +from esi_leap.common.idp_clients import dummyIDP # noqa: F401 CONF = esi_leap.conf.CONF -_cached_keystone_client = None +IDP_TYPE_MAP = {idp.idp_type: idp for idp in baseIDP.BaseIDP.__subclasses__()} +_cached_idp_client = None _cached_project_list = None -def get_keystone_client(): - global _cached_keystone_client - if _cached_keystone_client is not None: - return _cached_keystone_client +def get_idp_client(): + global _cached_idp_client + if _cached_idp_client is not None: + return _cached_idp_client - auth_plugin = ks_loading.load_auth_from_conf_options(CONF, "keystone") - sess = ks_loading.load_session_from_conf_options(CONF, "keystone", auth=auth_plugin) - cli = keystone_client.Client(session=sess) - _cached_keystone_client = cli + # Get Client config option + idp_type = CONF.esi.idp_type + cli = IDP_TYPE_MAP[idp_type]() + _cached_idp_client = cli return cli def get_parent_project_id_tree(project_id): - ks_client = get_keystone_client() - project = ks_client.projects.get(project_id) + idp = get_idp_client() + project = idp.get_projects(project_id) project_ids = [project.id] while project.parent_id is not None: - project = ks_client.projects.get(project.parent_id) + project = idp.get_projects(project.parent_id) project_ids.append(project.id) return project_ids @@ -50,7 +52,7 @@ def get_project_uuid_from_ident(project_ident): if uuidutils.is_uuid_like(project_ident): return project_ident else: - projects = get_keystone_client().projects.list(name=project_ident) + projects = get_idp_client().list_projects(name=project_ident) if len(projects) > 0: # projects have unique names return projects[0].id @@ -58,13 +60,13 @@ def get_project_uuid_from_ident(project_ident): def get_project_list(): - return get_keystone_client().projects.list() + return get_idp_client().list_projects() def get_project_name(project_id, project_list=None): if project_id: if project_list is None: - project = get_keystone_client().projects.get(project_id) + project = get_idp_client().get_projects(project_id) else: project = next( (p for p in project_list if getattr(p, "id") == project_id), None diff --git a/esi_leap/common/idp_clients/__init__.py b/esi_leap/common/idp_clients/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/esi_leap/common/idp_clients/baseIDP.py b/esi_leap/common/idp_clients/baseIDP.py new file mode 100644 index 00000000..8d0af9ce --- /dev/null +++ b/esi_leap/common/idp_clients/baseIDP.py @@ -0,0 +1,23 @@ +# 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. + +import abc + + +class BaseIDP(abc.ABC): + @abc.abstractmethod + def get_projects(self, project_id): + pass + + @abc.abstractmethod + def list_projects(self, **kwargs): + pass diff --git a/esi_leap/common/idp_clients/dummyIDP.py b/esi_leap/common/idp_clients/dummyIDP.py new file mode 100644 index 00000000..42696c5f --- /dev/null +++ b/esi_leap/common/idp_clients/dummyIDP.py @@ -0,0 +1,40 @@ +# 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. + +from keystoneclient.v3.projects import Project +from keystoneclient.v3.projects import ProjectManager +from keystoneclient.v3.users import User +from keystoneclient.v3.users import UserManager + +from esi_leap.common.idp_clients import baseIDP + + +class DummyIDP(baseIDP.BaseIDP): + idp_type = "dummy_idp" + dummy_project_dict = {} + dummy_user_dict = {} + + def get_projects(self, project_id): + return self.dummy_project_dict[project_id] + + def list_projects(self, **kwargs): + return [project for project in self.dummy_project_dict.values()] + + def add_project(self, id, name, parent_id): + self.dummy_project_dict[id] = Project( + ProjectManager, {"id": id, "name": name, "parent_id": parent_id} + ) + + def add_user(self, id, name, project_id): + self.dummy_user_dict[id] = User( + UserManager, {"id": id, "name": name, "project_id": project_id} + ) diff --git a/esi_leap/common/idp_clients/keystoneIDP.py b/esi_leap/common/idp_clients/keystoneIDP.py new file mode 100644 index 00000000..315eac86 --- /dev/null +++ b/esi_leap/common/idp_clients/keystoneIDP.py @@ -0,0 +1,36 @@ +# 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. + +from keystoneauth1 import loading as ks_loading +from keystoneclient import client as keystone_client + +from esi_leap.common.idp_clients import baseIDP +import esi_leap.conf + +CONF = esi_leap.conf.CONF + + +class KeystoneIDP(baseIDP.BaseIDP): + idp_type = "keystone_idp" + + def __init__(self) -> None: + auth_plugin = ks_loading.load_auth_from_conf_options(CONF, "keystone") + sess = ks_loading.load_session_from_conf_options( + CONF, "keystone", auth=auth_plugin + ) + self.cli = keystone_client.Client(session=sess) + + def get_projects(self, project_id): + return self.cli.projects.get(project_id) + + def list_projects(self, **kwargs): + return self.cli.projects.list(**kwargs) diff --git a/esi_leap/conf/__init__.py b/esi_leap/conf/__init__.py index 9b731101..10a2bdff 100644 --- a/esi_leap/conf/__init__.py +++ b/esi_leap/conf/__init__.py @@ -13,6 +13,7 @@ from esi_leap.conf import api from esi_leap.conf import dummy_node +from esi_leap.conf import esi from esi_leap.conf import ironic from esi_leap.conf import keystone from esi_leap.conf import netconf @@ -33,3 +34,4 @@ notification.register_opts(CONF) pecan.register_opts(CONF) serialconsoleproxy.register_opts(CONF) +esi.register_opts(CONF) diff --git a/esi_leap/conf/esi.py b/esi_leap/conf/esi.py new file mode 100644 index 00000000..9e0e894c --- /dev/null +++ b/esi_leap/conf/esi.py @@ -0,0 +1,23 @@ +# 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. + +from oslo_config import cfg + +opts = [ + cfg.StrOpt("idp_type", default="keystone_idp"), +] + +api_group = cfg.OptGroup("esi", title="ESI Options") + + +def register_opts(conf): + conf.register_opts(opts, group=api_group) diff --git a/esi_leap/db/sqlalchemy/api.py b/esi_leap/db/sqlalchemy/api.py index 0b2106a6..50def7ff 100644 --- a/esi_leap/db/sqlalchemy/api.py +++ b/esi_leap/db/sqlalchemy/api.py @@ -23,7 +23,7 @@ from esi_leap.common import constants from esi_leap.common import exception -from esi_leap.common import keystone +from esi_leap.common import idp from esi_leap.common import statuses from esi_leap.db.sqlalchemy import models @@ -129,7 +129,7 @@ def offer_get_all(filters): query = query.filter((models.Offer.status.in_(status))) if lessee_id: - lessee_id_list = keystone.get_parent_project_id_tree(lessee_id) + lessee_id_list = idp.get_parent_project_id_tree(lessee_id) query = query.filter( or_( models.Offer.project_id == lessee_id, diff --git a/esi_leap/tests/api/base.py b/esi_leap/tests/api/base.py index 50ec4244..f029c85c 100644 --- a/esi_leap/tests/api/base.py +++ b/esi_leap/tests/api/base.py @@ -29,6 +29,7 @@ def setUp(self): super(APITestCase, self).setUp() CONF.set_override("auth_enable", False, group="pecan") + CONF.set_override("idp_type", "dummy_idp", group="esi") self.app = pecan.testing.load_test_app(dict(app.get_pecan_config())) diff --git a/esi_leap/tests/api/controllers/v1/test_event.py b/esi_leap/tests/api/controllers/v1/test_event.py index ecbd10da..2b3c6ef5 100644 --- a/esi_leap/tests/api/controllers/v1/test_event.py +++ b/esi_leap/tests/api/controllers/v1/test_event.py @@ -36,7 +36,7 @@ def setUp(self): super(TestEventsController, self).setUp() @mock.patch("esi_leap.api.controllers.v1.utils.policy_authorize") - @mock.patch("esi_leap.common.keystone.get_project_uuid_from_ident") + @mock.patch("esi_leap.common.idp.get_project_uuid_from_ident") @mock.patch("esi_leap.api.controllers.v1.event.get_resource_object") @mock.patch("esi_leap.objects.event.Event.get_all") def test_get_all(self, mock_ega, mock_gro, mock_gpufi, mock_pa): @@ -55,7 +55,7 @@ def test_get_all(self, mock_ega, mock_gro, mock_gpufi, mock_pa): self.assertEqual(data["events"][0]["id"], 1) @mock.patch("esi_leap.api.controllers.v1.utils.policy_authorize") - @mock.patch("esi_leap.common.keystone.get_project_uuid_from_ident") + @mock.patch("esi_leap.common.idp.get_project_uuid_from_ident") @mock.patch("esi_leap.api.controllers.v1.event.get_resource_object") @mock.patch("esi_leap.objects.event.Event.get_all") def test_get_all_not_admin(self, mock_ega, mock_gro, mock_gpufi, mock_pa): @@ -75,7 +75,7 @@ def test_get_all_not_admin(self, mock_ega, mock_gro, mock_gpufi, mock_pa): self.assertEqual(data["events"][0]["id"], 1) @mock.patch("esi_leap.api.controllers.v1.utils.policy_authorize") - @mock.patch("esi_leap.common.keystone.get_project_uuid_from_ident") + @mock.patch("esi_leap.common.idp.get_project_uuid_from_ident") @mock.patch("esi_leap.api.controllers.v1.event.get_resource_object") @mock.patch("esi_leap.objects.event.Event.get_all") def test_get_all_resource_filter(self, mock_ega, mock_gro, mock_gpufi, mock_pa): diff --git a/esi_leap/tests/api/controllers/v1/test_lease.py b/esi_leap/tests/api/controllers/v1/test_lease.py index 65ed03d6..ea087286 100644 --- a/esi_leap/tests/api/controllers/v1/test_lease.py +++ b/esi_leap/tests/api/controllers/v1/test_lease.py @@ -67,7 +67,7 @@ def test_empty(self): self.assertEqual([], data["leases"]) @mock.patch("esi_leap.common.ironic.get_node_list") - @mock.patch("esi_leap.common.keystone.get_project_list") + @mock.patch("esi_leap.common.idp.get_project_list") @mock.patch("esi_leap.api.controllers.v1.utils." "lease_get_dict_with_added_info") @mock.patch("esi_leap.objects.lease.Lease.get_all") def test_one(self, mock_ga, mock_lgdwai, mock_gpl, mock_gnl): @@ -85,7 +85,7 @@ def test_one(self, mock_ga, mock_lgdwai, mock_gpl, mock_gnl): @mock.patch("esi_leap.api.controllers.v1.utils." "lease_get_dict_with_added_info") @mock.patch("esi_leap.api.controllers.v1.lease.get_resource_object") - @mock.patch("esi_leap.common.keystone.get_project_uuid_from_ident") + @mock.patch("esi_leap.common.idp.get_project_uuid_from_ident") @mock.patch("oslo_utils.uuidutils.generate_uuid") @mock.patch("esi_leap.api.controllers.v1.utils.check_resource_admin") @mock.patch("esi_leap.objects.lease.Lease.create") @@ -133,7 +133,7 @@ def test_post( @mock.patch("esi_leap.api.controllers.v1.utils." "lease_get_dict_with_added_info") @mock.patch("esi_leap.api.controllers.v1.lease.get_resource_object") - @mock.patch("esi_leap.common.keystone.get_project_uuid_from_ident") + @mock.patch("esi_leap.common.idp.get_project_uuid_from_ident") @mock.patch("oslo_utils.uuidutils.generate_uuid") @mock.patch("esi_leap.api.controllers.v1.utils.check_resource_admin") @mock.patch("esi_leap.objects.lease.Lease.create") @@ -181,7 +181,7 @@ def test_post_default_resource_type( @mock.patch("esi_leap.api.controllers.v1.utils." "lease_get_dict_with_added_info") @mock.patch("esi_leap.api.controllers.v1.utils." "check_resource_lease_admin") @mock.patch("esi_leap.api.controllers.v1.lease.get_resource_object") - @mock.patch("esi_leap.common.keystone.get_project_uuid_from_ident") + @mock.patch("esi_leap.common.idp.get_project_uuid_from_ident") @mock.patch("oslo_utils.uuidutils.generate_uuid") @mock.patch("esi_leap.api.controllers.v1.utils.check_resource_admin") @mock.patch("esi_leap.objects.lease.Lease.create") @@ -241,7 +241,7 @@ def test_post_non_admin_parent_lease( @mock.patch("esi_leap.api.controllers.v1.utils." "check_resource_lease_admin") @mock.patch("esi_leap.api.controllers.v1.lease.get_resource_object") - @mock.patch("esi_leap.common.keystone.get_project_uuid_from_ident") + @mock.patch("esi_leap.common.idp.get_project_uuid_from_ident") @mock.patch("oslo_utils.uuidutils.generate_uuid") @mock.patch("esi_leap.api.controllers.v1.utils.check_resource_admin") @mock.patch("esi_leap.objects.lease.Lease.create") @@ -334,7 +334,7 @@ def test_patch_end_time_and_more(self, mock_clpar, mock_lease_update, mock_lgdwa self.assertEqual(http_client.INTERNAL_SERVER_ERROR, request.status_int) @mock.patch("esi_leap.common.ironic.get_node_list") - @mock.patch("esi_leap.common.keystone.get_project_list") + @mock.patch("esi_leap.common.idp.get_project_list") @mock.patch("esi_leap.api.controllers.v1.utils." "lease_get_dict_with_added_info") @mock.patch( "esi_leap.api.controllers.v1.lease.LeasesController." @@ -368,9 +368,9 @@ def test_get_nofilters( self.assertEqual(2, mock_lgdwai.call_count) @mock.patch("esi_leap.common.ironic.get_node_list") - @mock.patch("esi_leap.common.keystone.get_project_list") + @mock.patch("esi_leap.common.idp.get_project_list") @mock.patch("esi_leap.api.controllers.v1.utils." "lease_get_dict_with_added_info") - @mock.patch("esi_leap.common.keystone.get_project_uuid_from_ident") + @mock.patch("esi_leap.common.idp.get_project_uuid_from_ident") @mock.patch( "esi_leap.api.controllers.v1.lease.LeasesController." "_lease_get_all_authorize_filters" @@ -404,9 +404,9 @@ def test_get_project_filter( self.assertEqual(2, mock_lgdwai.call_count) @mock.patch("esi_leap.common.ironic.get_node_list") - @mock.patch("esi_leap.common.keystone.get_project_list") + @mock.patch("esi_leap.common.idp.get_project_list") @mock.patch("esi_leap.api.controllers.v1.utils." "lease_get_dict_with_added_info") - @mock.patch("esi_leap.common.keystone.get_project_uuid_from_ident") + @mock.patch("esi_leap.common.idp.get_project_uuid_from_ident") @mock.patch( "esi_leap.api.controllers.v1.lease.LeasesController." "_lease_get_all_authorize_filters" @@ -442,7 +442,7 @@ def test_get_owner_filter( self.assertEqual(2, mock_lgdwai.call_count) @mock.patch("esi_leap.common.ironic.get_node_list") - @mock.patch("esi_leap.common.keystone.get_project_list") + @mock.patch("esi_leap.common.idp.get_project_list") @mock.patch("esi_leap.api.controllers.v1.utils." "lease_get_dict_with_added_info") @mock.patch("esi_leap.api.controllers.v1.lease.get_resource_object") @mock.patch( @@ -480,7 +480,7 @@ def test_get_resource_filter( self.assertEqual(2, mock_lgdwai.call_count) @mock.patch("esi_leap.common.ironic.get_node_list") - @mock.patch("esi_leap.common.keystone.get_project_list") + @mock.patch("esi_leap.common.idp.get_project_list") @mock.patch("esi_leap.api.controllers.v1.utils." "lease_get_dict_with_added_info") @mock.patch( "esi_leap.api.controllers.v1.lease.LeasesController." @@ -546,7 +546,7 @@ def _get_lease_response(lease, use_datetime=False): self.assertEqual(response, expected_resp) @mock.patch("esi_leap.common.ironic.get_node_list") - @mock.patch("esi_leap.common.keystone.get_project_list") + @mock.patch("esi_leap.common.idp.get_project_list") @mock.patch("esi_leap.api.controllers.v1.utils." "lease_get_dict_with_added_info") @mock.patch("esi_leap.api.controllers.v1.lease.get_resource_object") @mock.patch( diff --git a/esi_leap/tests/api/controllers/v1/test_node.py b/esi_leap/tests/api/controllers/v1/test_node.py index d3217484..1e7bb62f 100644 --- a/esi_leap/tests/api/controllers/v1/test_node.py +++ b/esi_leap/tests/api/controllers/v1/test_node.py @@ -59,7 +59,7 @@ def setUp(self): @mock.patch("esi_leap.common.ironic.get_node_list") @mock.patch("esi_leap.objects.offer.Offer.get_all") @mock.patch("esi_leap.objects.lease.Lease.get_all") - @mock.patch("esi_leap.common.keystone.get_project_list") + @mock.patch("esi_leap.common.idp.get_project_list") def test_get_all(self, mock_gpl, mock_lga, mock_oga, mock_gnl): fake_node = FakeIronicNode() fake_project = FakeProject() @@ -94,7 +94,7 @@ def test_get_all(self, mock_gpl, mock_lga, mock_oga, mock_gnl): self.assertEqual(data["nodes"][0]["future_leases"], ["fake-future-lease-uuid"]) @mock.patch("esi_leap.common.ironic.get_node_list") - @mock.patch("esi_leap.common.keystone.get_project_list") + @mock.patch("esi_leap.common.idp.get_project_list") def test_get_all_resource_class_filter(self, mock_gpl, mock_gnl): fake_node = FakeIronicNode() fake_project = FakeProject() @@ -109,8 +109,8 @@ def test_get_all_resource_class_filter(self, mock_gpl, mock_gnl): self.assertEqual(data["nodes"][0]["resource_class"], "baremetal") @mock.patch("esi_leap.common.ironic.get_node_list") - @mock.patch("esi_leap.common.keystone.get_project_list") - @mock.patch("esi_leap.common.keystone.get_project_uuid_from_ident") + @mock.patch("esi_leap.common.idp.get_project_list") + @mock.patch("esi_leap.common.idp.get_project_uuid_from_ident") def test_get_all_owner_filter(self, mock_get_project_uuid, mock_gpl, mock_gnl): fake_node = FakeIronicNode() fake_project = FakeProject() @@ -127,8 +127,8 @@ def test_get_all_owner_filter(self, mock_get_project_uuid, mock_gpl, mock_gnl): self.assertEqual(data["nodes"][0]["owner"], fake_project.name) @mock.patch("esi_leap.common.ironic.get_node_list") - @mock.patch("esi_leap.common.keystone.get_project_list") - @mock.patch("esi_leap.common.keystone.get_project_uuid_from_ident") + @mock.patch("esi_leap.common.idp.get_project_list") + @mock.patch("esi_leap.common.idp.get_project_uuid_from_ident") def test_get_all_lesse_filter(self, mock_get_project_uuid, mock_gpl, mock_gnl): fake_node = FakeIronicNode() fake_project = FakeProject() diff --git a/esi_leap/tests/api/controllers/v1/test_offer.py b/esi_leap/tests/api/controllers/v1/test_offer.py index c88e1df2..e6c0037e 100644 --- a/esi_leap/tests/api/controllers/v1/test_offer.py +++ b/esi_leap/tests/api/controllers/v1/test_offer.py @@ -196,7 +196,7 @@ def test_post_default_resource_type( self.assertEqual(http_client.CREATED, request.status_int) @mock.patch("esi_leap.api.controllers.v1.offer.get_resource_object") - @mock.patch("esi_leap.common.keystone.get_project_uuid_from_ident") + @mock.patch("esi_leap.common.idp.get_project_uuid_from_ident") @mock.patch("oslo_utils.uuidutils.generate_uuid") @mock.patch("esi_leap.api.controllers.v1.utils.check_resource_admin") @mock.patch("esi_leap.objects.offer.Offer.create") @@ -360,7 +360,7 @@ def test_post_non_admin_no_parent_lease( self.assertEqual(http_client.FORBIDDEN, request.status_int) @mock.patch("esi_leap.common.ironic.get_node_list") - @mock.patch("esi_leap.common.keystone.get_project_list") + @mock.patch("esi_leap.common.idp.get_project_list") @mock.patch("esi_leap.api.controllers.v1.utils." "offer_get_dict_with_added_info") @mock.patch("esi_leap.objects.offer.Offer.get_all") def test_get_nofilters(self, mock_get_all, mock_ogdwai, mock_gpl, mock_gnl): @@ -389,7 +389,7 @@ def test_get_nofilters(self, mock_get_all, mock_ogdwai, mock_gpl, mock_gnl): self.assertEqual(request, expected_resp) @mock.patch("esi_leap.common.ironic.get_node_list") - @mock.patch("esi_leap.common.keystone.get_project_list") + @mock.patch("esi_leap.common.idp.get_project_list") @mock.patch("esi_leap.api.controllers.v1.utils." "offer_get_dict_with_added_info") @mock.patch("esi_leap.objects.offer.Offer.get_all") def test_get_any_status(self, mock_get_all, mock_ogdwai, mock_gpl, mock_gnl): @@ -418,7 +418,7 @@ def test_get_any_status(self, mock_get_all, mock_ogdwai, mock_gpl, mock_gnl): self.assertEqual(request, expected_resp) @mock.patch("esi_leap.common.ironic.get_node_list") - @mock.patch("esi_leap.common.keystone.get_project_list") + @mock.patch("esi_leap.common.idp.get_project_list") @mock.patch("esi_leap.api.controllers.v1.utils." "offer_get_dict_with_added_info") @mock.patch("esi_leap.objects.offer.Offer.get_all") def test_get_status_filter(self, mock_get_all, mock_ogdwai, mock_gpl, mock_gnl): @@ -447,8 +447,8 @@ def test_get_status_filter(self, mock_get_all, mock_ogdwai, mock_gpl, mock_gnl): self.assertEqual(request, expected_resp) @mock.patch("esi_leap.common.ironic.get_node_list") - @mock.patch("esi_leap.common.keystone.get_project_list") - @mock.patch("esi_leap.common.keystone.get_project_uuid_from_ident") + @mock.patch("esi_leap.common.idp.get_project_list") + @mock.patch("esi_leap.common.idp.get_project_uuid_from_ident") @mock.patch("esi_leap.api.controllers.v1.utils." "offer_get_dict_with_added_info") @mock.patch("esi_leap.objects.offer.Offer.get_all") def test_get_project_filter( @@ -484,7 +484,7 @@ def test_get_project_filter( self.assertEqual(request, expected_resp) @mock.patch("esi_leap.common.ironic.get_node_list") - @mock.patch("esi_leap.common.keystone.get_project_list") + @mock.patch("esi_leap.common.idp.get_project_list") @mock.patch("esi_leap.api.controllers.v1.offer.get_resource_object") @mock.patch("esi_leap.api.controllers.v1.utils." "offer_get_dict_with_added_info") @mock.patch("esi_leap.objects.offer.Offer.get_all") @@ -524,7 +524,7 @@ def test_get_resource_filter( self.assertEqual(request, expected_resp) @mock.patch("esi_leap.common.ironic.get_node_list") - @mock.patch("esi_leap.common.keystone.get_project_list") + @mock.patch("esi_leap.common.idp.get_project_list") @mock.patch("esi_leap.api.controllers.v1.utils." "offer_get_dict_with_added_info") @mock.patch("esi_leap.objects.offer.Offer.get_all") def test_get_resource_class_filter( @@ -558,7 +558,7 @@ def test_get_resource_class_filter( self.assertEqual(request, expected_resp) @mock.patch("esi_leap.common.ironic.get_node_list") - @mock.patch("esi_leap.common.keystone.get_project_list") + @mock.patch("esi_leap.common.idp.get_project_list") @mock.patch("esi_leap.api.controllers.v1.offer.get_resource_object") @mock.patch("esi_leap.api.controllers.v1.utils." "offer_get_dict_with_added_info") @mock.patch("esi_leap.objects.offer.Offer.get_all") @@ -596,7 +596,7 @@ def test_get_resource_filter_default_resource_type( self.assertEqual(request, expected_resp) @mock.patch("esi_leap.common.ironic.get_node_list") - @mock.patch("esi_leap.common.keystone.get_project_list") + @mock.patch("esi_leap.common.idp.get_project_list") @mock.patch("esi_leap.api.controllers.v1.utils." "offer_get_dict_with_added_info") @mock.patch("esi_leap.objects.offer.Offer.get_all") @mock.patch("esi_leap.api.controllers.v1.utils.policy_authorize") diff --git a/esi_leap/tests/api/controllers/v1/test_utils.py b/esi_leap/tests/api/controllers/v1/test_utils.py index bc89fd61..d383bfe4 100644 --- a/esi_leap/tests/api/controllers/v1/test_utils.py +++ b/esi_leap/tests/api/controllers/v1/test_utils.py @@ -25,7 +25,7 @@ from esi_leap.objects import lease from esi_leap.objects import offer from esi_leap.resource_objects.fake_node import FakeNode - +from esi_leap.conf import CONF admin_ctx = ctx.RequestContext(project_id="adminid", roles=["admin"]) @@ -488,8 +488,12 @@ def test_check_lease_policy(self, mock_get_lease, mock_authorize): class TestOfferLesseeUtils(testtools.TestCase): + def setUp(self): + super(TestOfferLesseeUtils, self).setUp() + CONF.set_override("idp_type", "dummy_idp", group="esi") + @mock.patch("esi_leap.api.controllers.v1.utils.policy_authorize") - @mock.patch("esi_leap.common.keystone.get_parent_project_id_tree") + @mock.patch("esi_leap.common.idp.get_parent_project_id_tree") def test_check_offer_lessee_no_lessee_id(self, mock_gppit, mock_authorize): utils.check_offer_lessee(lessee_ctx.to_policy_values(), test_offer) @@ -497,7 +501,7 @@ def test_check_offer_lessee_no_lessee_id(self, mock_gppit, mock_authorize): assert not mock_gppit.called @mock.patch.object(policy, "authorize", spec=True) - @mock.patch("esi_leap.common.keystone.get_parent_project_id_tree") + @mock.patch("esi_leap.common.idp.get_parent_project_id_tree") def test_check_offer_lessee_owner_match(self, mock_gppit, mock_authorize): utils.check_offer_lessee( owner_ctx.to_policy_values(), test_offer_lessee_no_match @@ -507,7 +511,7 @@ def test_check_offer_lessee_owner_match(self, mock_gppit, mock_authorize): assert not mock_gppit.called @mock.patch("esi_leap.api.controllers.v1.utils.policy_authorize") - @mock.patch("esi_leap.common.keystone.get_parent_project_id_tree") + @mock.patch("esi_leap.common.idp.get_parent_project_id_tree") def test_check_offer_lessee_admin(self, mock_gppit, mock_authorize): mock_authorize.return_value = True mock_gppit.return_value = [admin_ctx.project_id] @@ -524,7 +528,7 @@ def test_check_offer_lessee_admin(self, mock_gppit, mock_authorize): mock_gppit.assert_called_once_with(admin_ctx.project_id) @mock.patch("esi_leap.api.controllers.v1.utils.policy_authorize") - @mock.patch("esi_leap.common.keystone.get_parent_project_id_tree") + @mock.patch("esi_leap.common.idp.get_parent_project_id_tree") def test_check_offer_lessee_non_admin_match(self, mock_gppit, mock_authorize): mock_gppit.return_value = [lessee_ctx.project_id, "lesseeidparent"] @@ -534,7 +538,7 @@ def test_check_offer_lessee_non_admin_match(self, mock_gppit, mock_authorize): mock_gppit.assert_called_once_with(lessee_ctx.project_id) @mock.patch("esi_leap.api.controllers.v1.utils.policy_authorize") - @mock.patch("esi_leap.common.keystone.get_parent_project_id_tree") + @mock.patch("esi_leap.common.idp.get_parent_project_id_tree") def test_check_offer_lessee_non_admin_no_match(self, mock_gppit, mock_authorize): mock_authorize.side_effect = exception.HTTPResourceForbidden( resource_type="offer", resource=test_offer_lessee_no_match.uuid @@ -628,7 +632,7 @@ def test_resource_policy_authorize_exception(self, mock_authorize): class TestOfferGetDictWithAddedInfoUtils(testtools.TestCase): - @mock.patch("esi_leap.common.keystone.get_project_name") + @mock.patch("esi_leap.common.idp.get_project_name") @mock.patch("esi_leap.objects.offer.Offer.get_availabilities") def test_offer_get_dict_with_added_info(self, mock_get_availabilities, mock_gpn): mock_get_availabilities.return_value = [] @@ -685,7 +689,7 @@ def setUp(self): ) @mock.patch("esi_leap.resource_objects.fake_node.FakeNode.get_name") - @mock.patch("esi_leap.common.keystone.get_project_name") + @mock.patch("esi_leap.common.idp.get_project_name") @mock.patch("esi_leap.objects.lease.get_resource_object") def test_lease_get_dict_with_added_info(self, mock_gro, mock_gpn, mock_gn): mock_gro.return_value = FakeNode("111") diff --git a/esi_leap/tests/base.py b/esi_leap/tests/base.py index d4967313..d5d42bf1 100644 --- a/esi_leap/tests/base.py +++ b/esi_leap/tests/base.py @@ -74,6 +74,7 @@ class DBTestCase(TestCase): def setUp(self): super(DBTestCase, self).setUp() CONF.set_override("connection", "sqlite://", group="database") + CONF.set_override("idp_type", "dummy_idp", group="esi") self.db_api = db_api.get_instance() diff --git a/esi_leap/tests/common/test_idp.py b/esi_leap/tests/common/test_idp.py new file mode 100644 index 00000000..7585f7e3 --- /dev/null +++ b/esi_leap/tests/common/test_idp.py @@ -0,0 +1,131 @@ +# 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. + +import mock + +from esi_leap.common import exception as e +from esi_leap.common import idp +from esi_leap.common.idp_clients import dummyIDP, keystoneIDP +from esi_leap.tests import base + + +class FakeProject(object): + def __init__(self): + self.id = "uuid" + self.name = "name" + + +class IDPTestCase(base.TestCase): + @mock.patch("oslo_utils.uuidutils.is_uuid_like") + def test_get_project_uuid_from_ident_uuid(self, mock_iul): + mock_iul.return_value = True + + project_uuid = idp.get_project_uuid_from_ident("uuid") + + mock_iul.assert_called_once_with("uuid") + self.assertEqual("uuid", project_uuid) + + @mock.patch.object(idp, "get_idp_client", autospec=True) + @mock.patch("oslo_utils.uuidutils.is_uuid_like") + def test_get_project_uuid_from_ident_name(self, mock_iul, mock_keystone): + mock_iul.return_value = False + mock_keystone.return_value.list_projects.return_value = [FakeProject()] + + project_uuid = idp.get_project_uuid_from_ident("name") + + mock_iul.assert_called_once_with("name") + self.assertEqual("uuid", project_uuid) + mock_keystone.return_value.list_projects.assert_called_once_with(name="name") + + @mock.patch.object(idp, "get_idp_client", autospec=True) + @mock.patch("oslo_utils.uuidutils.is_uuid_like") + def test_get_project_uuid_from_ident_name_no_match(self, mock_iul, mock_keystone): + mock_iul.return_value = False + mock_keystone.return_value.list_projects.return_value = [] + + self.assertRaises(e.ProjectNoSuchName, idp.get_project_uuid_from_ident, "name") + + mock_iul.assert_called_once_with("name") + mock_keystone.return_value.list_projects.assert_called_once_with(name="name") + + @mock.patch.object(idp, "get_idp_client", autospec=True) + def test_get_project_name_no_list(self, mock_keystone): + mock_keystone.return_value.get_projects.return_value = FakeProject() + + project_name = idp.get_project_name("12345") + + self.assertEqual("name", project_name) + + @mock.patch.object(idp, "get_idp_client", autospec=True) + def test_get_project_name_list(self, mock_keystone): + project_list = [FakeProject()] + project_name = idp.get_project_name("uuid", project_list) + + self.assertEqual("name", project_name) + + @mock.patch.object(idp, "get_idp_client", autospec=True) + def test_get_project_name_list_no_match(self, mock_keystone): + project_list = [FakeProject()] + project_name = idp.get_project_name("uuid2", project_list) + + self.assertEqual("", project_name) + + @mock.patch.object(idp, "get_idp_client", autospec=True) + def test_get_project_name_none(self, mock_keystone): + project_list = [FakeProject()] + project_name = idp.get_project_name(None, project_list) + + self.assertEqual("", project_name) + + +class KeystoneIDPTestCase(base.TestCase): + @mock.patch("keystoneclient.client.Client") + def test_get_projects(self, mock_kc): + test_keystone_idp = keystoneIDP.KeystoneIDP() + + test_keystone_idp.get_projects(1) + test_keystone_idp.cli.projects.get.assert_called_once_with(1) + + @mock.patch("keystoneclient.client.Client") + def test_list_projects(self, mock_kc): + test_keystone_idp = keystoneIDP.KeystoneIDP() + + test_keystone_idp.list_projects(foo="foo", bar=None) + test_keystone_idp.cli.projects.list.assert_called_once_with(foo="foo", bar=None) + + +class DummyIDPTestCase(base.TestCase): + def setUp(self): + super().setUp() + + dummy_idp = dummyIDP.DummyIDP() + dummy_idp.add_project(1, "P1", None) + dummy_idp.add_project(2, "P2", None) + dummy_idp.add_project(3, "P3", 1) + + self.dummy_idp = dummy_idp + + def test_get_projects(self): + project = self.dummy_idp.get_projects(1) + self.assertEqual([project.id, project.name, project.parent_id], [1, "P1", None]) + + project = self.dummy_idp.get_projects(3) + self.assertEqual([project.id, project.name, project.parent_id], [3, "P3", 1]) + + def test_list_projects(self): + project_list = self.dummy_idp.list_projects() + self.assertEqual(len(project_list), 3) + project_2 = project_list[1] + + self.assertEqual( + [project_2.id, project_2.name, project_2.parent_id], [2, "P2", None] + ) diff --git a/esi_leap/tests/common/test_keystone.py b/esi_leap/tests/common/test_keystone.py deleted file mode 100644 index ae4ada15..00000000 --- a/esi_leap/tests/common/test_keystone.py +++ /dev/null @@ -1,88 +0,0 @@ -# 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. - -import mock - -from esi_leap.common import exception as e -from esi_leap.common import keystone -from esi_leap.tests import base - - -class FakeProject(object): - def __init__(self): - self.id = "uuid" - self.name = "name" - - -class KeystoneTestCase(base.TestCase): - @mock.patch("oslo_utils.uuidutils.is_uuid_like") - def test_get_project_uuid_from_ident_uuid(self, mock_iul): - mock_iul.return_value = True - - project_uuid = keystone.get_project_uuid_from_ident("uuid") - - mock_iul.assert_called_once_with("uuid") - self.assertEqual("uuid", project_uuid) - - @mock.patch.object(keystone, "get_keystone_client", autospec=True) - @mock.patch("oslo_utils.uuidutils.is_uuid_like") - def test_get_project_uuid_from_ident_name(self, mock_iul, mock_keystone): - mock_iul.return_value = False - mock_keystone.return_value.projects.list.return_value = [FakeProject()] - - project_uuid = keystone.get_project_uuid_from_ident("name") - - mock_iul.assert_called_once_with("name") - self.assertEqual("uuid", project_uuid) - mock_keystone.return_value.projects.list.assert_called_once_with(name="name") - - @mock.patch.object(keystone, "get_keystone_client", autospec=True) - @mock.patch("oslo_utils.uuidutils.is_uuid_like") - def test_get_project_uuid_from_ident_name_no_match(self, mock_iul, mock_keystone): - mock_iul.return_value = False - mock_keystone.return_value.projects.list.return_value = [] - - self.assertRaises( - e.ProjectNoSuchName, keystone.get_project_uuid_from_ident, "name" - ) - - mock_iul.assert_called_once_with("name") - mock_keystone.return_value.projects.list.assert_called_once_with(name="name") - - @mock.patch.object(keystone, "get_keystone_client", autospec=True) - def test_get_project_name_no_list(self, mock_keystone): - mock_keystone.return_value.projects.get.return_value = FakeProject() - - project_name = keystone.get_project_name("12345") - - self.assertEqual("name", project_name) - - @mock.patch.object(keystone, "get_keystone_client", autospec=True) - def test_get_project_name_list(self, mock_keystone): - project_list = [FakeProject()] - project_name = keystone.get_project_name("uuid", project_list) - - self.assertEqual("name", project_name) - - @mock.patch.object(keystone, "get_keystone_client", autospec=True) - def test_get_project_name_list_no_match(self, mock_keystone): - project_list = [FakeProject()] - project_name = keystone.get_project_name("uuid2", project_list) - - self.assertEqual("", project_name) - - @mock.patch.object(keystone, "get_keystone_client", autospec=True) - def test_get_project_name_none(self, mock_keystone): - project_list = [FakeProject()] - project_name = keystone.get_project_name(None, project_list) - - self.assertEqual("", project_name) diff --git a/esi_leap/tests/db/sqlalchemy/test_api.py b/esi_leap/tests/db/sqlalchemy/test_api.py index 9754e84e..5890012e 100644 --- a/esi_leap/tests/db/sqlalchemy/test_api.py +++ b/esi_leap/tests/db/sqlalchemy/test_api.py @@ -501,7 +501,7 @@ def test_offer_get_all(self): (o1.to_dict(), o2.to_dict()), (res[0].to_dict(), res[1].to_dict()) ) - @mock.patch("esi_leap.common.keystone.get_parent_project_id_tree") + @mock.patch("esi_leap.common.idp.get_parent_project_id_tree") def test_offer_get_all_lessee_filter(self, mock_gppit): mock_gppit.return_value = ["12345", "67890"]