Raising errors from the client instead of ksclient

Consolidates HTTPError types into barbicanclient.exceptions.
Provides a uniform way of external consumers to catch
common exceptions that might occur as a result of normal
client operation.

Fixes bug 1431514

Change-Id: Id65e7da913bb06e2f94a50f44550199dc7f1beb6
This commit is contained in:
John Vrbanac 2015-04-08 17:17:32 -05:00
parent 5ed2e70f9f
commit e06df05a69
10 changed files with 247 additions and 109 deletions

View File

@ -21,6 +21,7 @@ from keystoneclient.auth.base import BaseAuthPlugin
from keystoneclient import session as ks_session
from barbicanclient import containers
from barbicanclient import exceptions
from barbicanclient._i18n import _
from barbicanclient import orders
from barbicanclient import secrets
@ -32,32 +33,6 @@ _DEFAULT_SERVICE_INTERFACE = 'public'
_DEFAULT_API_VERSION = 'v1'
class HTTPError(Exception):
"""Base exception for HTTP errors."""
def __init__(self, message):
super(HTTPError, self).__init__(message)
class HTTPServerError(HTTPError):
"""Raised for 5xx responses from the server."""
pass
class HTTPClientError(HTTPError):
"""Raised for 4xx responses from the server."""
pass
class HTTPAuthError(HTTPError):
"""Raised for 401 Unauthorized responses from the server."""
pass
class _HTTPClient(adapter.Adapter):
def __init__(self, session, project_id=None, **kwargs):
@ -85,11 +60,11 @@ class _HTTPClient(adapter.Adapter):
def request(self, *args, **kwargs):
headers = kwargs.setdefault('headers', {})
headers.update(self._default_headers)
# Set raise_exc=False by default so that we handle request exceptions
kwargs.setdefault('raise_exc', False)
resp = super(_HTTPClient, self).request(*args, **kwargs)
# NOTE(jamielennox): _check_status_code is being completely ignored as
# errors are being raised from session.request. This behaviour is
# enforced by tests. Pass raise_exc=False to request() to make this
# work again.
self._check_status_code(resp)
return resp
@ -113,17 +88,25 @@ class _HTTPClient(adapter.Adapter):
LOG.debug('Response status {0}'.format(status))
if status == 401:
LOG.error('Auth error: {0}'.format(self._get_error_message(resp)))
raise HTTPAuthError('{0}'.format(self._get_error_message(resp)))
raise exceptions.HTTPAuthError(
'{0}'.format(self._get_error_message(resp))
)
if not status or status >= 500:
LOG.error('5xx Server error: {0}'.format(
self._get_error_message(resp)
))
raise HTTPServerError('{0}'.format(self._get_error_message(resp)))
raise exceptions.HTTPServerError(
'{0}'.format(self._get_error_message(resp)),
status
)
if status >= 400:
LOG.error('4xx Client error: {0}'.format(
self._get_error_message(resp)
))
raise HTTPClientError('{0}'.format(self._get_error_message(resp)))
raise exceptions.HTTPClientError(
'{0}'.format(self._get_error_message(resp)),
status
)
def _get_error_message(self, resp):
try:

View File

@ -613,6 +613,9 @@ class ContainerManager(base.BaseEntityManager):
:param secrets: Secrets to populate when creating a Container
:returns: Container
:rtype: :class:`barbicanclient.containers.Container`
:raises barbicanclient.exceptions.HTTPAuthError: 401 Responses
:raises barbicanclient.exceptions.HTTPClientError: 4xx Responses
:raises barbicanclient.exceptions.HTTPServerError: 5xx Responses
"""
return Container(
api=self._api,
@ -634,6 +637,9 @@ class ContainerManager(base.BaseEntityManager):
:param private_key_passphrase: Secret object containing a passphrase
:returns: RSAContainer
:rtype: :class:`barbicanclient.containers.RSAContainer`
:raises barbicanclient.exceptions.HTTPAuthError: 401 Responses
:raises barbicanclient.exceptions.HTTPClientError: 4xx Responses
:raises barbicanclient.exceptions.HTTPServerError: 5xx Responses
"""
return RSAContainer(
api=self._api,
@ -659,6 +665,9 @@ class ContainerManager(base.BaseEntityManager):
:param private_key_passphrase: Secret object containing a passphrase
:returns: CertificateContainer
:rtype: :class:`barbicanclient.containers.CertificateContainer`
:raises barbicanclient.exceptions.HTTPAuthError: 401 Responses
:raises barbicanclient.exceptions.HTTPClientError: 4xx Responses
:raises barbicanclient.exceptions.HTTPServerError: 5xx Responses
"""
return CertificateContainer(
api=self._api,
@ -674,6 +683,9 @@ class ContainerManager(base.BaseEntityManager):
Delete a Container from Barbican
:param container_ref: Full HATEOAS reference to a Container
:raises barbicanclient.exceptions.HTTPAuthError: 401 Responses
:raises barbicanclient.exceptions.HTTPClientError: 4xx Responses
:raises barbicanclient.exceptions.HTTPServerError: 5xx Responses
"""
if not container_ref:
raise ValueError('container_ref is required.')
@ -689,6 +701,9 @@ class ContainerManager(base.BaseEntityManager):
:param name: Name filter for the list
:param type: Type filter for the list
:returns: list of Container metadata objects
:raises barbicanclient.exceptions.HTTPAuthError: 401 Responses
:raises barbicanclient.exceptions.HTTPClientError: 4xx Responses
:raises barbicanclient.exceptions.HTTPServerError: 5xx Responses
"""
LOG.debug('Listing containers - offset {0} limit {1} name {2} type {3}'
.format(offset, limit, name, type))
@ -712,6 +727,9 @@ class ContainerManager(base.BaseEntityManager):
:param name: Name of the consuming service
:param url: URL of the consuming resource
:returns: A container object per the get() method
:raises barbicanclient.exceptions.HTTPAuthError: 401 Responses
:raises barbicanclient.exceptions.HTTPClientError: 4xx Responses
:raises barbicanclient.exceptions.HTTPServerError: 5xx Responses
"""
LOG.debug('Creating consumer registration for container '
'{0} as {1}: {2}'.format(container_ref, name, url))
@ -731,6 +749,9 @@ class ContainerManager(base.BaseEntityManager):
:param container_ref: Full HATEOAS reference to a Container
:param name: Name of the previously consuming service
:param url: URL of the previously consuming resource
:raises barbicanclient.exceptions.HTTPAuthError: 401 Responses
:raises barbicanclient.exceptions.HTTPClientError: 4xx Responses
:raises barbicanclient.exceptions.HTTPServerError: 5xx Responses
"""
LOG.debug('Deleting consumer registration for container '
'{0} as {1}: {2}'.format(container_ref, name, url))

View File

@ -20,3 +20,31 @@ class BarbicanException(Exception):
class PayloadException(BarbicanException):
pass
class HTTPError(Exception):
"""Base exception for HTTP errors."""
def __init__(self, message, status_code=0):
super(HTTPError, self).__init__(message)
self.status_code = status_code
class HTTPServerError(HTTPError):
"""Raised for 5xx responses from the server."""
pass
class HTTPClientError(HTTPError):
"""Raised for 4xx responses from the server."""
pass
class HTTPAuthError(HTTPError):
"""Raised for 401 Unauthorized responses from the server."""
def __init__(self, message, status_code=401):
super(HTTPError, self).__init__(message, status_code)

View File

@ -327,6 +327,9 @@ class OrderManager(base.BaseEntityManager):
:param order_ref: Full HATEOAS reference to an Order
:returns: An instance of the appropriate subtype of Order
:raises barbicanclient.exceptions.HTTPAuthError: 401 Responses
:raises barbicanclient.exceptions.HTTPClientError: 4xx Responses
:raises barbicanclient.exceptions.HTTPServerError: 5xx Responses
"""
LOG.debug("Getting order - Order href: {0}".format(order_ref))
base.validate_ref(order_ref, 'Order')
@ -374,6 +377,9 @@ class OrderManager(base.BaseEntityManager):
:param expiration: The expiration time of the secret in ISO 8601 format
:returns: KeyOrder
:rtype: :class:`barbicanclient.orders.KeyOrder`
:raises barbicanclient.exceptions.HTTPAuthError: 401 Responses
:raises barbicanclient.exceptions.HTTPClientError: 4xx Responses
:raises barbicanclient.exceptions.HTTPServerError: 5xx Responses
"""
return KeyOrder(api=self._api, name=name,
algorithm=algorithm, bit_length=bit_length, mode=mode,
@ -397,6 +403,9 @@ class OrderManager(base.BaseEntityManager):
:param expiration: The expiration time of the secret in ISO 8601 format
:returns: AsymmetricOrder
:rtype: :class:`barbicanclient.orders.AsymmetricOrder`
:raises barbicanclient.exceptions.HTTPAuthError: 401 Responses
:raises barbicanclient.exceptions.HTTPClientError: 4xx Responses
:raises barbicanclient.exceptions.HTTPServerError: 5xx Responses
"""
return AsymmetricOrder(api=self._api, name=name, algorithm=algorithm,
bit_length=bit_length, pass_phrase=pass_phrase,
@ -422,6 +431,9 @@ class OrderManager(base.BaseEntityManager):
:param limit: Max number of orders returned
:param offset: Offset orders to begin list
:returns: list of Order objects
:raises barbicanclient.exceptions.HTTPAuthError: 401 Responses
:raises barbicanclient.exceptions.HTTPClientError: 4xx Responses
:raises barbicanclient.exceptions.HTTPServerError: 5xx Responses
"""
LOG.debug('Listing orders - offset {0} limit {1}'.format(offset,
limit))

View File

@ -396,6 +396,9 @@ class SecretManager(base.BaseEntityManager):
See Launchpad Bug #1419166.
:returns: Secret object retrieved from Barbican
:rtype: :class:`barbicanclient.secrets.Secret`
:raises barbicanclient.exceptions.HTTPAuthError: 401 Responses
:raises barbicanclient.exceptions.HTTPClientError: 4xx Responses
:raises barbicanclient.exceptions.HTTPServerError: 5xx Responses
"""
LOG.debug("Getting secret - Secret href: {0}".format(secret_ref))
base.validate_ref(secret_ref, 'Secret')
@ -428,6 +431,9 @@ class SecretManager(base.BaseEntityManager):
:param expiration: The expiration time of the secret in ISO 8601 format
:returns: A new Secret object
:rtype: :class:`barbicanclient.secrets.Secret`
:raises barbicanclient.exceptions.HTTPAuthError: 401 Responses
:raises barbicanclient.exceptions.HTTPClientError: 4xx Responses
:raises barbicanclient.exceptions.HTTPServerError: 5xx Responses
"""
return Secret(api=self._api, name=name, payload=payload,
payload_content_type=payload_content_type,
@ -440,6 +446,9 @@ class SecretManager(base.BaseEntityManager):
Delete a Secret from Barbican
:param secret_ref: The href for the secret to be deleted
:raises barbicanclient.exceptions.HTTPAuthError: 401 Responses
:raises barbicanclient.exceptions.HTTPClientError: 4xx Responses
:raises barbicanclient.exceptions.HTTPServerError: 5xx Responses
"""
base.validate_ref(secret_ref, 'Secret')
if not secret_ref:
@ -463,6 +472,9 @@ class SecretManager(base.BaseEntityManager):
:returns: list of Secret objects that satisfy the provided filter
criteria.
:rtype: list
:raises barbicanclient.exceptions.HTTPAuthError: 401 Responses
:raises barbicanclient.exceptions.HTTPClientError: 4xx Responses
:raises barbicanclient.exceptions.HTTPServerError: 5xx Responses
"""
LOG.debug('Listing secrets - offset {0} limit {1}'.format(offset,
limit))

View File

@ -19,6 +19,7 @@ from requests_mock.contrib import fixture
import testtools
from barbicanclient import client
from barbicanclient import exceptions
class TestClient(testtools.TestCase):
@ -200,20 +201,20 @@ class WhenTestingCheckStatusCodes(TestClient):
def test_raises_http_auth_error_for_401_response(self):
resp = mock.MagicMock()
resp.status_code = 401
self.assertRaises(client.HTTPAuthError,
self.assertRaises(exceptions.HTTPAuthError,
self.httpclient._check_status_code,
resp)
def test_raises_http_server_error_for_500_response(self):
resp = mock.MagicMock()
resp.status_code = 500
self.assertRaises(client.HTTPServerError,
self.assertRaises(exceptions.HTTPServerError,
self.httpclient._check_status_code, resp)
def test_raises_http_client_error_for_400_response(self):
resp = mock.MagicMock()
resp.status_code = 400
self.assertRaises(client.HTTPClientError,
self.assertRaises(exceptions.HTTPClientError,
self.httpclient._check_status_code, resp)

View File

@ -46,3 +46,9 @@ Containers
.. autoclass:: barbicanclient.containers.CertificateContainer
:members:
Exceptions
==========
.. automodule:: barbicanclient.exceptions
:members:

View File

@ -18,6 +18,8 @@ from functionaltests.client import base
from functionaltests.client.v1.behaviors import container_behaviors
from functionaltests.client.v1.behaviors import secret_behaviors
from barbicanclient import exceptions
create_secret_defaults_data = {
"name": "AES key",
@ -123,10 +125,13 @@ class GenericContainersTestCase(BaseContainersTestCase):
test_model = self.behaviors.create_generic_container(
create_container_defaults_data, secrets=secrets)
e = self.assertRaises(Exception, self.behaviors.store_container,
test_model)
e = self.assertRaises(
exceptions.HTTPClientError,
self.behaviors.store_container,
test_model
)
self.assertEqual(e.http_status, 400)
self.assertEqual(e.status_code, 400)
@testcase.attr('negative')
def test_get_non_existent_container(self):
@ -152,10 +157,13 @@ class GenericContainersTestCase(BaseContainersTestCase):
uuid = 'de305d54-75b4-431b-cccc-eb6b9e546013'
url = base_url + '/containers/' + uuid
e = self.assertRaises(Exception, self.behaviors.get_container,
url)
e = self.assertRaises(
exceptions.HTTPClientError,
self.behaviors.get_container,
url
)
self.assertEqual(e.http_status, 404)
self.assertEqual(e.status_code, 404)
@testcase.attr('negative')
def test_delete_non_existent_container(self):
@ -181,10 +189,13 @@ class GenericContainersTestCase(BaseContainersTestCase):
base_url = self.barbicanclient.secrets._api._base_url
url = base_url + '/containers/' + uuid
e = self.assertRaises(Exception, self.behaviors.get_container,
url)
e = self.assertRaises(
exceptions.HTTPClientError,
self.behaviors.get_container,
url
)
self.assertEqual(e.http_status, 404)
self.assertEqual(e.status_code, 404)
@utils.parameterized_dataset({'0': [0], '1': [1], '50': [50]})
@testcase.attr('positive')
@ -290,10 +301,13 @@ class RSAContainersTestCase(BaseContainersTestCase):
test_model = self.behaviors.create_rsa_container(
no_public_key_rsa_container)
e = self.assertRaises(Exception, self.behaviors.store_container,
test_model)
e = self.assertRaises(
exceptions.HTTPClientError,
self.behaviors.store_container,
test_model
)
self.assertEqual(e.http_status, 400)
self.assertEqual(e.status_code, 400)
@testcase.attr('negative')
def test_create_rsa_no_private_key(self):
@ -309,7 +323,10 @@ class RSAContainersTestCase(BaseContainersTestCase):
test_model = self.behaviors.create_rsa_container(
no_private_key_rsa_container)
e = self.assertRaises(Exception, self.behaviors.store_container,
test_model)
e = self.assertRaises(
exceptions.HTTPClientError,
self.behaviors.store_container,
test_model
)
self.assertEqual(e.http_status, 400)
self.assertEqual(e.status_code, 400)

View File

@ -22,6 +22,8 @@ from functionaltests.client.v1.behaviors import order_behaviors
from functionaltests.client.v1.behaviors import secret_behaviors
from oslo_utils import timeutils
from barbicanclient import exceptions
order_create_key_data = {
"name": "barbican functional test secret name",
"algorithm": "aes",
@ -176,10 +178,14 @@ class OrdersTestCase(base.TestCase):
ref = self.behaviors.base_url + '/orders/' + uuid
# try to get a non-existent order
e = self.assertRaises(Exception, self.behaviors.get_order, ref)
e = self.assertRaises(
exceptions.HTTPClientError,
self.behaviors.get_order,
ref
)
# verify that the order get failed
self.assertEqual(e.http_status, 404)
self.assertEqual(e.status_code, 404)
@testcase.attr('negative')
def test_create_order_nones(self):
@ -187,11 +193,13 @@ class OrdersTestCase(base.TestCase):
test_model = self.behaviors.create_key_order(order_create_nones_data)
e = self.assertRaises(Exception, self.behaviors.store_order,
test_model)
self.assertEqual(e.http_status, 400)
e = self.assertRaises(
exceptions.HTTPClientError,
self.behaviors.store_order,
test_model
)
self.assertEqual(e.status_code, 400)
@testcase.attr('negative')
def test_create_order_empty_entries(self):
@ -204,11 +212,13 @@ class OrdersTestCase(base.TestCase):
test_model.bit_length = ""
test_model.payload_content_type = ""
e = self.assertRaises(Exception, self.behaviors.store_order,
test_model)
self.assertEqual(e.http_status, 400)
e = self.assertRaises(
exceptions.HTTPClientError,
self.behaviors.store_order,
test_model
)
self.assertEqual(e.status_code, 400)
@testcase.attr('negative')
def test_create_order_defaults_oversized_strings(self):
@ -219,10 +229,13 @@ class OrdersTestCase(base.TestCase):
test_model.algorithm = base.TestCase.oversized_field
test_model.mode = base.TestCase.oversized_field
e = self.assertRaises(Exception, self.behaviors.store_order,
test_model)
e = self.assertRaises(
exceptions.HTTPClientError,
self.behaviors.store_order,
test_model
)
self.assertEqual(e.http_status, 400)
self.assertEqual(e.status_code, 400)
@utils.parameterized_dataset({
'8': [8],
@ -265,9 +278,12 @@ class OrdersTestCase(base.TestCase):
test_model = self.behaviors.create_key_order(order_create_key_data)
test_model.bit_length = bit_length
e = self.assertRaises(Exception, self.behaviors.store_order,
test_model)
self.assertEqual(e.http_status, 400)
e = self.assertRaises(
exceptions.HTTPClientError,
self.behaviors.store_order,
test_model
)
self.assertEqual(e.status_code, 400)
@utils.parameterized_dataset({
'alphanumeric': ['1f34ds'],
@ -296,10 +312,13 @@ class OrdersTestCase(base.TestCase):
test_model = self.behaviors.create_key_order(order_create_key_data)
test_model.name = name
e = self.assertRaises(Exception, self.behaviors.store_order,
test_model)
e = self.assertRaises(
exceptions.HTTPClientError,
self.behaviors.store_order,
test_model
)
self.assertEqual(e.http_status, 400)
self.assertEqual(e.status_code, 400)
@utils.parameterized_dataset({
'cbc': ['cbc']
@ -325,9 +344,12 @@ class OrdersTestCase(base.TestCase):
test_model = self.behaviors.create_key_order(order_create_key_data)
test_model.mode = mode
e = self.assertRaises(Exception, self.behaviors.store_order,
test_model)
self.assertEqual(e.http_status, 400)
e = self.assertRaises(
exceptions.HTTPClientError,
self.behaviors.store_order,
test_model
)
self.assertEqual(e.status_code, 400)
@utils.parameterized_dataset({
'aes': ['aes']
@ -354,10 +376,13 @@ class OrdersTestCase(base.TestCase):
test_model = self.behaviors.create_key_order(order_create_key_data)
test_model.algorithm = algorithm
e = self.assertRaises(Exception, self.behaviors.store_order,
test_model)
e = self.assertRaises(
exceptions.HTTPClientError,
self.behaviors.store_order,
test_model
)
self.assertEqual(e.http_status, 400)
self.assertEqual(e.status_code, 400)
# TODO(tdink) Add empty after Launchpad 1420444 is resolved
@utils.parameterized_dataset({
@ -390,10 +415,13 @@ class OrdersTestCase(base.TestCase):
test_model = self.behaviors.create_key_order(order_create_key_data)
test_model.payload_content_type = pct
e = self.assertRaises(Exception, self.behaviors.store_order,
test_model)
e = self.assertRaises(
exceptions.HTTPClientError,
self.behaviors.store_order,
test_model
)
self.assertEqual(e.http_status, 400)
self.assertEqual(e.status_code, 400)
@utils.parameterized_dataset({
'negative_five_long_expire': {
@ -442,7 +470,10 @@ class OrdersTestCase(base.TestCase):
test_model = self.behaviors.create_key_order(order_create_key_data)
test_model.expiration = timestamp
e = self.assertRaises(Exception, self.behaviors.store_order,
test_model)
e = self.assertRaises(
exceptions.HTTPClientError,
self.behaviors.store_order,
test_model
)
self.assertEqual(e.http_status, 400)
self.assertEqual(e.status_code, 400)

View File

@ -136,10 +136,13 @@ class SecretsTestCase(base.TestCase):
uuid = 'de20ad54-85b4-421b-adb2-eb7b9e546013'
url = self.behaviors.base_url + '/secrets/' + uuid
e = self.assertRaises(Exception, self.behaviors.delete_secret,
url)
e = self.assertRaises(
exceptions.HTTPClientError,
self.behaviors.delete_secret,
url
)
self.assertEqual(e.http_status, 404)
self.assertEqual(e.status_code, 404)
@testcase.attr('negative')
def test_secret_create_nones_content_type(self):
@ -197,9 +200,12 @@ class SecretsTestCase(base.TestCase):
secret_create_defaults_data)
test_model.expiration = '2000-01-10T14:58:52.546795'
e = self.assertRaises(Exception, self.behaviors.store_secret,
test_model)
self.assertEqual(e.http_status, 400)
e = self.assertRaises(
exceptions.HTTPClientError,
self.behaviors.store_secret,
test_model
)
self.assertEqual(e.status_code, 400)
@testcase.attr('negative')
def test_secret_create_emptystrings(self):
@ -227,9 +233,12 @@ class SecretsTestCase(base.TestCase):
secret_create_defaults_data)
test_model.payload = str(self.oversized_payload)
e = self.assertRaises(Exception, self.behaviors.store_secret,
test_model)
self.assertEqual(e.http_status, 413)
e = self.assertRaises(
exceptions.HTTPClientError,
self.behaviors.store_secret,
test_model
)
self.assertEqual(e.status_code, 413)
@utils.parameterized_dataset({
'alphanumeric': ['1f34ds'],
@ -265,10 +274,13 @@ class SecretsTestCase(base.TestCase):
secret_create_defaults_data)
test_model.name = name
e = self.assertRaises(Exception, self.behaviors.store_secret,
test_model)
e = self.assertRaises(
exceptions.HTTPClientError,
self.behaviors.store_secret,
test_model
)
self.assertEqual(e.http_status, 400)
self.assertEqual(e.status_code, 400)
@utils.parameterized_dataset({
'aes': ['aes']
@ -299,10 +311,13 @@ class SecretsTestCase(base.TestCase):
# We are currently testing for exception with http_code
# launchpad bug 1431514 will address the change to this functionality
e = self.assertRaises(Exception, self.behaviors.store_secret,
test_model)
e = self.assertRaises(
exceptions.HTTPClientError,
self.behaviors.store_secret,
test_model
)
self.assertEqual(e.http_status, 400)
self.assertEqual(e.status_code, 400)
@utils.parameterized_dataset({
'512': [512],
@ -341,10 +356,13 @@ class SecretsTestCase(base.TestCase):
secret_create_defaults_data)
test_model.bit_length = bit_length
e = self.assertRaises(Exception, self.behaviors.store_secret,
test_model)
e = self.assertRaises(
exceptions.HTTPClientError,
self.behaviors.store_secret,
test_model
)
self.assertEqual(e.http_status, 400)
self.assertEqual(e.status_code, 400)
@utils.parameterized_dataset({
'cbc': ['cbc']
@ -374,10 +392,13 @@ class SecretsTestCase(base.TestCase):
secret_create_defaults_data)
test_model.mode = mode
e = self.assertRaises(Exception, self.behaviors.store_secret,
test_model)
e = self.assertRaises(
exceptions.HTTPClientError,
self.behaviors.store_secret,
test_model
)
self.assertEqual(e.http_status, 400)
self.assertEqual(e.status_code, 400)
@utils.parameterized_dataset({
'text_content_type_none_encoding': {
@ -491,10 +512,13 @@ class SecretsTestCase(base.TestCase):
test_model.payload_content_type = kwargs[
'payload_content_type']
e = self.assertRaises(Exception, self.behaviors.store_secret,
test_model)
e = self.assertRaises(
exceptions.HTTPClientError,
self.behaviors.store_secret,
test_model
)
self.assertEqual(e.http_status, 400)
self.assertEqual(e.status_code, 400)
@utils.parameterized_dataset({
'max_payload_string': [base.TestCase.max_sized_payload]
@ -599,10 +623,13 @@ class SecretsTestCase(base.TestCase):
secret_create_defaults_data)
test_model.expiration = timestamp
e = self.assertRaises(Exception, self.behaviors.store_secret,
test_model)
e = self.assertRaises(
exceptions.HTTPClientError,
self.behaviors.store_secret,
test_model
)
self.assertEqual(e.http_status, 400)
self.assertEqual(e.status_code, 400)
@utils.parameterized_dataset({
'alphanumeric': ['1f34ds'],