Added unit test coverage for verify_project_id

- Cleaned up code path to make it easier to read.
- Added unit test coverage.

Change-Id: I03d98e2ab950247fad73814e2ac03a96cda749b6
This commit is contained in:
Erik Olof Gunnar Andersson 2023-07-29 22:11:43 +02:00
parent fa95018c91
commit f371b1af02
2 changed files with 103 additions and 25 deletions

View File

@ -32,48 +32,58 @@ def verify_project_id(context, project_id):
"""
session = ksa_loading.load_session_from_conf_options(
CONF, 'keystone', auth=context.get_auth_plugin())
adap = ksa_loading.load_adapter_from_conf_options(
CONF, 'keystone', auth=context.get_auth_plugin()
)
adapter = ksa_loading.load_adapter_from_conf_options(
CONF, 'keystone',
session=session, min_version=(3, 0), max_version=(3, 'latest'))
session=session, min_version=(3, 0), max_version=(3, 'latest')
)
try:
resp = adap.get('/projects/%s' % project_id, raise_exc=False)
response = adapter.get('/projects/%s' % project_id, raise_exc=False)
except kse.EndpointNotFound:
LOG.error(
"Keystone identity service version 3.0 was not found. This might "
"be because your endpoint points to the v2.0 versioned endpoint "
"which is not supported. Please fix this.")
'Keystone identity service version 3.0 was not found. This might '
'be because your endpoint points to the v2.0 versioned endpoint '
'which is not supported. Please fix this.'
)
raise exceptions.KeystoneCommunicationFailure(
_("KeystoneV3 endpoint not found"))
_('KeystoneV3 endpoint not found')
)
except kse.ClientException:
# something is wrong, like there isn't a keystone v3 endpoint,
# or nova isn't configured for the interface to talk to it;
# we'll take the pass and default to everything being ok.
LOG.info("Unable to contact keystone to verify project_id")
LOG.info('Unable to contact keystone to verify project_id')
return True
if resp:
if response.ok:
# All is good with this 20x status
return True
elif resp.status_code == 404:
# we got access, and we know this project is not there
raise exceptions.InvalidProject(
_("%s is not a valid project ID.") % project_id)
elif resp.status_code == 403:
elif response.status_code == 403:
# we don't have enough permission to verify this, so default
# to "it's ok".
LOG.info(
"Insufficient permissions for user %(user)s to verify "
"existence of project_id %(pid)s",
{"user": context.user_id, "pid": project_id})
'Insufficient permissions for user %(user)s to verify '
'existence of project_id %(pid)s',
{
'user': context.user_id,
'pid': project_id
}
)
return True
elif response.status_code == 404:
# we got access, and we know this project is not there
raise exceptions.InvalidProject(
_('%s is not a valid project ID.') % project_id
)
else:
LOG.warning(
"Unexpected response from keystone trying to "
"verify project_id %(pid)s - resp: %(code)s %(content)s",
{"pid": project_id,
"code": resp.status_code,
"content": resp.content})
# realize we did something wrong, but move on with a warning
'Unexpected response from keystone trying to '
'verify project_id %(pid)s - response: %(code)s %(content)s',
{
'pid': project_id,
'code': response.status_code,
'content': response.content
}
)
return True

View File

@ -0,0 +1,68 @@
# 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 unittest import mock
from keystoneauth1 import exceptions as kse
import oslotest.base
from designate.common import keystone
from designate import exceptions
class TestVerifyProjectid(oslotest.base.BaseTestCase):
def setUp(self):
super(TestVerifyProjectid, self).setUp()
@mock.patch('keystoneauth1.adapter.Adapter.get')
def test_verify_project_id(self, mock_get):
mock_result = mock.Mock()
mock_result.ok = True
mock_result.status_code = 200
mock_get.return_value = mock_result
self.assertTrue(keystone.verify_project_id(mock.Mock(), '1'))
@mock.patch('keystoneauth1.adapter.Adapter.get')
def test_verify_project_id_request_returns_403(self, mock_get):
mock_result = mock.Mock()
mock_result.ok = False
mock_result.status_code = 403
mock_get.return_value = mock_result
self.assertTrue(keystone.verify_project_id(mock.Mock(), '1'))
@mock.patch('keystoneauth1.adapter.Adapter.get')
def test_verify_project_id_request_returns_404(self, mock_get):
mock_result = mock.Mock()
mock_result.ok = False
mock_result.status_code = 404
mock_get.return_value = mock_result
self.assertRaisesRegex(
exceptions.InvalidProject,
'1 is not a valid project ID.',
keystone.verify_project_id, mock.Mock(), '1'
)
@mock.patch('keystoneauth1.adapter.Adapter.get')
def test_verify_project_id_request_returns_500(self, mock_get):
mock_result = mock.Mock()
mock_result.ok = False
mock_result.status_code = 500
mock_get.return_value = mock_result
self.assertTrue(keystone.verify_project_id(mock.Mock(), '1'))
@mock.patch('keystoneauth1.adapter.Adapter.get')
def test_verify_project_endpoint_not_found(self, mock_get):
mock_get.side_effect = kse.EndpointNotFound
self.assertRaisesRegex(
exceptions.KeystoneCommunicationFailure,
'KeystoneV3 endpoint not found',
keystone.verify_project_id, mock.Mock(), '1'
)