Add keystone exceptions wrapper for openstack clients
* Added decorator which wraps keystone exceptions * Added unit tests with no auth_token and with heat client cached Change-Id: If42efe5f6806b12e7aabfd943150917a0b8f7618
This commit is contained in:
@@ -16,6 +16,7 @@ from heatclient import client as heatclient
|
|||||||
from keystoneclient.v2_0 import client as ksclient
|
from keystoneclient.v2_0 import client as ksclient
|
||||||
from oslo.config import cfg
|
from oslo.config import cfg
|
||||||
|
|
||||||
|
from solum.common import exception
|
||||||
from solum.openstack.common.gettextutils import _
|
from solum.openstack.common.gettextutils import _
|
||||||
from solum.openstack.common import log as logging
|
from solum.openstack.common import log as logging
|
||||||
|
|
||||||
@@ -77,6 +78,7 @@ class OpenStackClients(object):
|
|||||||
def _get_client_option(self, client, option):
|
def _get_client_option(self, client, option):
|
||||||
return getattr(getattr(cfg.CONF, '%s_client' % client), option)
|
return getattr(getattr(cfg.CONF, '%s_client' % client), option)
|
||||||
|
|
||||||
|
@exception.wrap_keystone_exception
|
||||||
def heat(self):
|
def heat(self):
|
||||||
if self._heat:
|
if self._heat:
|
||||||
return self._heat
|
return self._heat
|
||||||
|
|||||||
@@ -20,8 +20,10 @@ Includes decorator for re-raising Solum-type exceptions.
|
|||||||
|
|
||||||
import functools
|
import functools
|
||||||
import pecan
|
import pecan
|
||||||
|
import sys
|
||||||
import wsme
|
import wsme
|
||||||
|
|
||||||
|
from keystoneclient import exceptions as keystone_exceptions
|
||||||
from oslo.config import cfg
|
from oslo.config import cfg
|
||||||
import six
|
import six
|
||||||
|
|
||||||
@@ -30,6 +32,7 @@ from solum.openstack.common import excutils
|
|||||||
from solum.openstack.common.gettextutils import _
|
from solum.openstack.common.gettextutils import _
|
||||||
from solum.openstack.common import log as logging
|
from solum.openstack.common import log as logging
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
exc_log_opts = [
|
exc_log_opts = [
|
||||||
@@ -96,6 +99,25 @@ def wrap_controller_exception(func):
|
|||||||
return wrapped
|
return wrapped
|
||||||
|
|
||||||
|
|
||||||
|
def wrap_keystone_exception(func):
|
||||||
|
"""This decorator wraps keystone exception by throwing Solum specific
|
||||||
|
exceptions.
|
||||||
|
"""
|
||||||
|
@functools.wraps(func)
|
||||||
|
def wrapped(*args, **kw):
|
||||||
|
try:
|
||||||
|
return func(*args, **kw)
|
||||||
|
except keystone_exceptions.AuthorizationFailure:
|
||||||
|
raise AuthorizationFailure(
|
||||||
|
client=func.__name__, message="reason: %s" % sys.exc_info()[1])
|
||||||
|
except keystone_exceptions.ClientException:
|
||||||
|
raise AuthorizationFailure(
|
||||||
|
client=func.__name__,
|
||||||
|
message="unexpected keystone client error occurred: %s"
|
||||||
|
% sys.exc_info()[1])
|
||||||
|
return wrapped
|
||||||
|
|
||||||
|
|
||||||
class SolumException(Exception):
|
class SolumException(Exception):
|
||||||
"""Base Solum Exception
|
"""Base Solum Exception
|
||||||
|
|
||||||
@@ -152,3 +174,7 @@ class ResourceExists(SolumException):
|
|||||||
class NotImplemented(SolumException):
|
class NotImplemented(SolumException):
|
||||||
msg_fmt = _("The requested operation is not implemented.")
|
msg_fmt = _("The requested operation is not implemented.")
|
||||||
code = 501
|
code = 501
|
||||||
|
|
||||||
|
|
||||||
|
class AuthorizationFailure(SolumException):
|
||||||
|
msg_fmt = _("%(client)s connection failed. %(message)s")
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import mock
|
|||||||
|
|
||||||
from heatclient import client as heatclient
|
from heatclient import client as heatclient
|
||||||
from solum.common import clients
|
from solum.common import clients
|
||||||
|
from solum.common import exception
|
||||||
from solum.tests import base
|
from solum.tests import base
|
||||||
|
|
||||||
|
|
||||||
@@ -37,3 +38,31 @@ class ClientsTest(base.BaseTestCase):
|
|||||||
cert_file=None, token='3bcc3d3a03f44e3d8377f9247b0ad155',
|
cert_file=None, token='3bcc3d3a03f44e3d8377f9247b0ad155',
|
||||||
auth_url='keystone_url', ca_file=None, key_file=None,
|
auth_url='keystone_url', ca_file=None, key_file=None,
|
||||||
password=None, insecure=False)
|
password=None, insecure=False)
|
||||||
|
|
||||||
|
def test_clients_heat_noauth(self):
|
||||||
|
con = mock.MagicMock()
|
||||||
|
con.auth_token = None
|
||||||
|
con.tenant = "b363706f891f48019483f8bd6503c54b"
|
||||||
|
auth_url = mock.PropertyMock(name="auth_url",
|
||||||
|
return_value="keystone_url")
|
||||||
|
type(con).auth_url = auth_url
|
||||||
|
con.get_url_for = mock.Mock(name="get_url_for")
|
||||||
|
con.get_url_for.return_value = "url_from_keystone"
|
||||||
|
obj = clients.OpenStackClients(con)
|
||||||
|
obj._heat = None
|
||||||
|
self.assertRaises(exception.AuthorizationFailure, obj.heat)
|
||||||
|
|
||||||
|
def test_clients_heat_cached(self):
|
||||||
|
con = mock.MagicMock()
|
||||||
|
con.tenant = "b363706f891f48019483f8bd6503c54b"
|
||||||
|
con.auth_token = "3bcc3d3a03f44e3d8377f9247b0ad155"
|
||||||
|
auth_url = mock.PropertyMock(name="auth_url",
|
||||||
|
return_value="keystone_url")
|
||||||
|
type(con).auth_url = auth_url
|
||||||
|
con.get_url_for = mock.Mock(name="get_url_for")
|
||||||
|
con.get_url_for.return_value = "url_from_keystone"
|
||||||
|
obj = clients.OpenStackClients(con)
|
||||||
|
obj._heat = None
|
||||||
|
heat = obj.heat()
|
||||||
|
heat_cached = obj.heat()
|
||||||
|
self.assertEqual(heat, heat_cached)
|
||||||
|
|||||||
Reference in New Issue
Block a user