Merge "Add compare header version function to tempest.lib"

This commit is contained in:
Jenkins 2017-09-01 07:37:27 +00:00 committed by Gerrit Code Review
commit a07642783d
5 changed files with 182 additions and 9 deletions

View File

@ -0,0 +1,15 @@
---
features:
- |
Add a new function called ``compare_version_header_to_response`` to
``tempest.lib.common.api_version_utils``, which compares the API
micoversion in the response header to another microversion using the
comparators defined in
``tempest.lib.common.api_version_request.APIVersionRequest``.
It is now possible to determine how to retrieve an attribute from a
response body of an API call, depending on the returned microversion.
Add a new exception type called ``InvalidParam`` to
``tempest.lib.exceptions``, allowing the possibility of raising an
exception if an invalid parameter is passed to a library function.

View File

@ -23,6 +23,7 @@ from tempest.common import utils
from tempest.common.utils.linux import remote_client
from tempest.common import waiters
from tempest import config
from tempest.lib.common import api_version_utils
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
@ -369,7 +370,11 @@ class ServerActionsTestJSON(base.BaseV2ComputeTest):
"been successful as it should have been "
"deleted during rotation.", oldest_backup)
image1_id = data_utils.parse_image_id(resp['location'])
if api_version_utils.compare_version_header_to_response(
"OpenStack-API-Version", "compute 2.45", resp, "lt"):
image1_id = resp['image_id']
else:
image1_id = data_utils.parse_image_id(resp['location'])
self.addCleanup(_clean_oldest_backup, image1_id)
waiters.wait_for_image_status(glance_client,
image1_id, 'active')
@ -380,7 +385,11 @@ class ServerActionsTestJSON(base.BaseV2ComputeTest):
backup_type='daily',
rotation=2,
name=backup2).response
image2_id = data_utils.parse_image_id(resp['location'])
if api_version_utils.compare_version_header_to_response(
"OpenStack-API-Version", "compute 2.45", resp, "lt"):
image2_id = resp['image_id']
else:
image2_id = data_utils.parse_image_id(resp['location'])
self.addCleanup(glance_client.delete_image, image2_id)
waiters.wait_for_image_status(glance_client,
image2_id, 'active')
@ -419,7 +428,11 @@ class ServerActionsTestJSON(base.BaseV2ComputeTest):
backup_type='daily',
rotation=2,
name=backup3).response
image3_id = data_utils.parse_image_id(resp['location'])
if api_version_utils.compare_version_header_to_response(
"OpenStack-API-Version", "compute 2.45", resp, "lt"):
image3_id = resp['image_id']
else:
image3_id = data_utils.parse_image_id(resp['location'])
self.addCleanup(glance_client.delete_image, image3_id)
# the first back up should be deleted
waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')

View File

@ -12,6 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
from oslo_log import log as logging
import testtools
from tempest.lib.common import api_version_request
@ -19,6 +20,7 @@ from tempest.lib import exceptions
LATEST_MICROVERSION = 'latest'
LOG = logging.getLogger(__name__)
class BaseMicroversionTest(object):
@ -120,3 +122,60 @@ def assert_version_header_matches_request(api_microversion_header_name,
api_microversion,
response_header))
raise exceptions.InvalidHTTPResponseHeader(msg)
def compare_version_header_to_response(api_microversion_header_name,
api_microversion,
response_header,
operation='eq'):
"""Compares API microversion in response header to ``api_microversion``.
Compare the ``api_microversion`` value in response header if microversion
header is present in response, otherwise return false.
To make this function work for APIs which do not return microversion
header in response (example compute v2.0), this function does *not* raise
InvalidHTTPResponseHeader.
:param api_microversion_header_name: Microversion header name. Example:
'Openstack-Api-Version'.
:param api_microversion: Microversion number. Example:
* '2.10' for the old-style header name, 'X-OpenStack-Nova-API-Version'
* 'Compute 2.10' for the new-style header name, 'Openstack-Api-Version'
:param response_header: Response header where microversion is
expected to be present.
:param operation: The boolean operation to use to compare the
``api_microversion`` to the microversion in ``response_header``.
Can be 'lt', 'eq', 'gt', 'le', 'ne', 'ge'. Default is 'eq'. The
operation type should be based on the order of the arguments:
``api_microversion`` <operation> ``response_header`` microversion.
:returns: True if the comparison is logically true, else False if the
comparison is logically false or if ``api_microversion_header_name`` is
missing in the ``response_header``.
:raises InvalidParam: If the operation is not lt, eq, gt, le, ne or ge.
"""
api_microversion_header_name = api_microversion_header_name.lower()
if api_microversion_header_name not in response_header:
return False
op = getattr(api_version_request.APIVersionRequest,
'__%s__' % operation, None)
if op is None:
msg = ("Operation %s is invalid. Valid options include: lt, eq, gt, "
"le, ne, ge." % operation)
LOG.debug(msg)
raise exceptions.InvalidParam(invalid_param=msg)
# Remove "volume" from "volume <microversion>", for example, so that the
# microversion can be converted to `APIVersionRequest`.
api_version = api_microversion.split(' ')[-1]
resp_version = response_header[api_microversion_header_name].split(' ')[-1]
if not op(
api_version_request.APIVersionRequest(api_version),
api_version_request.APIVersionRequest(resp_version)):
return False
return True

View File

@ -276,3 +276,7 @@ class DeleteErrorException(TempestException):
class InvalidTestResource(TempestException):
message = "%(name)s is not a valid %(type)s, or the name is ambiguous"
class InvalidParam(TempestException):
message = ("Invalid Parameter passed: %(invalid_param)s")

View File

@ -92,24 +92,106 @@ class TestMicroversionHeaderMatches(base.TestCase):
def test_header_matches(self):
microversion_header_name = 'x-openstack-xyz-api-version'
request_microversion = '2.1'
test_respose = {microversion_header_name: request_microversion}
test_response = {microversion_header_name: request_microversion}
api_version_utils.assert_version_header_matches_request(
microversion_header_name, request_microversion, test_respose)
microversion_header_name, request_microversion, test_response)
def test_header_does_not_match(self):
microversion_header_name = 'x-openstack-xyz-api-version'
request_microversion = '2.1'
test_respose = {microversion_header_name: '2.2'}
test_response = {microversion_header_name: '2.2'}
self.assertRaises(
exceptions.InvalidHTTPResponseHeader,
api_version_utils.assert_version_header_matches_request,
microversion_header_name, request_microversion, test_respose)
microversion_header_name, request_microversion, test_response)
def test_header_not_present(self):
microversion_header_name = 'x-openstack-xyz-api-version'
request_microversion = '2.1'
test_respose = {}
test_response = {}
self.assertRaises(
exceptions.InvalidHTTPResponseHeader,
api_version_utils.assert_version_header_matches_request,
microversion_header_name, request_microversion, test_respose)
microversion_header_name, request_microversion, test_response)
def test_compare_versions_less_than(self):
microversion_header_name = 'x-openstack-xyz-api-version'
request_microversion = '2.2'
test_response = {microversion_header_name: '2.1'}
self.assertFalse(
api_version_utils.compare_version_header_to_response(
microversion_header_name, request_microversion, test_response,
"lt"))
def test_compare_versions_less_than_equal(self):
microversion_header_name = 'x-openstack-xyz-api-version'
request_microversion = '2.2'
test_response = {microversion_header_name: '2.1'}
self.assertFalse(
api_version_utils.compare_version_header_to_response(
microversion_header_name, request_microversion, test_response,
"le"))
def test_compare_versions_greater_than_equal(self):
microversion_header_name = 'x-openstack-xyz-api-version'
request_microversion = '2.1'
test_response = {microversion_header_name: '2.2'}
self.assertFalse(
api_version_utils.compare_version_header_to_response(
microversion_header_name, request_microversion, test_response,
"ge"))
def test_compare_versions_greater_than(self):
microversion_header_name = 'x-openstack-xyz-api-version'
request_microversion = '2.1'
test_response = {microversion_header_name: '2.2'}
self.assertFalse(
api_version_utils.compare_version_header_to_response(
microversion_header_name, request_microversion, test_response,
"gt"))
def test_compare_versions_equal(self):
microversion_header_name = 'x-openstack-xyz-api-version'
request_microversion = '2.11'
test_response = {microversion_header_name: '2.1'}
self.assertFalse(
api_version_utils.compare_version_header_to_response(
microversion_header_name, request_microversion, test_response,
"eq"))
def test_compare_versions_not_equal(self):
microversion_header_name = 'x-openstack-xyz-api-version'
request_microversion = '2.1'
test_response = {microversion_header_name: '2.1'}
self.assertFalse(
api_version_utils.compare_version_header_to_response(
microversion_header_name, request_microversion, test_response,
"ne"))
def test_compare_versions_with_name_in_microversion(self):
microversion_header_name = 'x-openstack-xyz-api-version'
request_microversion = 'volume 3.1'
test_response = {microversion_header_name: 'volume 3.1'}
self.assertTrue(
api_version_utils.compare_version_header_to_response(
microversion_header_name, request_microversion, test_response,
"eq"))
def test_compare_versions_invalid_operation(self):
microversion_header_name = 'x-openstack-xyz-api-version'
request_microversion = '2.1'
test_response = {microversion_header_name: '2.1'}
self.assertRaises(
exceptions.InvalidParam,
api_version_utils.compare_version_header_to_response,
microversion_header_name, request_microversion, test_response,
"foo")
def test_compare_versions_header_not_present(self):
microversion_header_name = 'x-openstack-xyz-api-version'
request_microversion = '2.1'
test_response = {}
self.assertFalse(
api_version_utils.compare_version_header_to_response(
microversion_header_name, request_microversion, test_response,
"eq"))