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