Migrated microversion testing framework to tempest/lib
Tempest implements the microversion testing support and that framework and interfaces have been tested by implementing the Compute 2.2 microversion as well as by their unit tests. Those should be stable interfaces so that can be consumed by other projects microversion testing either in tempest or outside tempest. To make them as stable interface, this commit moving that framework and its interfaces to tempest/lib folder. Adding release notes and library doc for those interface. Partially implements blueprint api-microversions-testing-support Change-Id: Icbdcfb4cd5b7fb1029eec035b9e0024be59c8d1f
This commit is contained in:
parent
0d560a9ce4
commit
1f47cf976b
@ -66,3 +66,4 @@ Current Library APIs
|
||||
library/decorators
|
||||
library/rest_client
|
||||
library/utils
|
||||
library/api_microversion_testing
|
||||
|
29
doc/source/library/api_microversion_testing.rst
Normal file
29
doc/source/library/api_microversion_testing.rst
Normal file
@ -0,0 +1,29 @@
|
||||
.. _api_microversion_testing:
|
||||
|
||||
API Microversion Testing Support in Temepst
|
||||
===========================================
|
||||
|
||||
---------------------------------------------
|
||||
Framework to support API Microversion testing
|
||||
---------------------------------------------
|
||||
|
||||
Many of the OpenStack components have implemented API microversions.
|
||||
It is important to tests those microversion in Tempest or external plugins.
|
||||
Tempest now provides stable interfaces to support to test the API microversions.
|
||||
Based on the microversion range coming from the combination of both configuration
|
||||
and each test case, APIs request will be made with selected microversion.
|
||||
|
||||
This document explains the interfaces needed for microversion testing.
|
||||
|
||||
|
||||
The api_version_request module
|
||||
""""""""""""""""""""""""""""""
|
||||
|
||||
.. automodule:: tempest.lib.common.api_version_request
|
||||
:members:
|
||||
|
||||
The api_version_utils module
|
||||
""""""""""""""""""""""""""""
|
||||
|
||||
.. automodule:: tempest.lib.common.api_version_utils
|
||||
:members:
|
@ -0,0 +1,3 @@
|
||||
---
|
||||
features:
|
||||
- Tempest library interface addition(API Microversion testing interfaces).
|
@ -14,7 +14,7 @@
|
||||
|
||||
import fixtures
|
||||
|
||||
from tempest.services.compute.json import base_compute_client
|
||||
from tempest.lib.services.compute import base_compute_client
|
||||
|
||||
|
||||
class APIMicroversionFixture(fixtures.Fixture):
|
||||
|
@ -18,12 +18,12 @@ import time
|
||||
from oslo_log import log as logging
|
||||
|
||||
from tempest.api.compute import api_microversion_fixture
|
||||
from tempest.common import api_version_utils
|
||||
from tempest.common import compute
|
||||
from tempest.common.utils import data_utils
|
||||
from tempest.common import waiters
|
||||
from tempest import config
|
||||
from tempest import exceptions
|
||||
from tempest.lib.common import api_version_utils
|
||||
from tempest.lib import exceptions as lib_exc
|
||||
import tempest.test
|
||||
|
||||
|
@ -176,20 +176,6 @@ class InvalidStructure(TempestException):
|
||||
message = "Invalid structure of table with details"
|
||||
|
||||
|
||||
class InvalidAPIVersionString(TempestException):
|
||||
message = ("API Version String %(version)s is of invalid format. Must "
|
||||
"be of format MajorNum.MinorNum or string 'latest'.")
|
||||
|
||||
|
||||
class JSONSchemaNotFound(TempestException):
|
||||
message = ("JSON Schema for %(version)s is not found in \n"
|
||||
" %(schema_versions_info)s")
|
||||
|
||||
|
||||
class InvalidAPIVersionRange(TempestException):
|
||||
message = ("API Min Version is greater than Max version")
|
||||
|
||||
|
||||
class CommandFailed(Exception):
|
||||
def __init__(self, returncode, cmd, output, stderr):
|
||||
super(CommandFailed, self).__init__()
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
import re
|
||||
|
||||
from tempest import exceptions
|
||||
from tempest.lib import exceptions
|
||||
|
||||
|
||||
# Define the minimum and maximum version of the API across all of the
|
||||
@ -39,6 +39,11 @@ class APIVersionRequest(object):
|
||||
This class provides convenience methods for manipulation
|
||||
and comparison of version numbers that we need to do to
|
||||
implement microversions.
|
||||
|
||||
:param version_string: String representation of APIVersionRequest.
|
||||
Correct format is 'X.Y', where 'X' and 'Y' are int values.
|
||||
None value should be used to create Null APIVersionRequest,
|
||||
which is equal to 0.0
|
||||
"""
|
||||
|
||||
# NOTE: This 'latest' version is a magic number, we assume any
|
||||
@ -47,13 +52,7 @@ class APIVersionRequest(object):
|
||||
latest_ver_minor = 99999
|
||||
|
||||
def __init__(self, version_string=None):
|
||||
"""Create an API version request object.
|
||||
|
||||
:param version_string: String representation of APIVersionRequest.
|
||||
Correct format is 'X.Y', where 'X' and 'Y' are int values.
|
||||
None value should be used to create Null APIVersionRequest,
|
||||
which is equal to 0.0
|
||||
"""
|
||||
"""Create an API version request object."""
|
||||
# NOTE(gmann): 'version_string' as String "None" will be considered as
|
||||
# invalid version string.
|
||||
self.ver_major = 0
|
||||
@ -77,6 +76,12 @@ class APIVersionRequest(object):
|
||||
return ("API Version Request: %s" % self.get_string())
|
||||
|
||||
def is_null(self):
|
||||
"""Checks whether version is null.
|
||||
|
||||
Return True if version object is null otherwise False.
|
||||
|
||||
:returns: boolean
|
||||
"""
|
||||
return self.ver_major == 0 and self.ver_minor == 0
|
||||
|
||||
def _format_type_error(self, other):
|
||||
@ -120,9 +125,9 @@ class APIVersionRequest(object):
|
||||
greater than or equal to the minimum version and less than
|
||||
or equal to the maximum version.
|
||||
|
||||
@param min_version: Minimum acceptable version.
|
||||
@param max_version: Maximum acceptable version.
|
||||
@returns: boolean
|
||||
:param min_version: Minimum acceptable version.
|
||||
:param max_version: Maximum acceptable version.
|
||||
:returns: boolean
|
||||
|
||||
If min_version is null then there is no minimum limit.
|
||||
If max_version is null then there is no maximum limit.
|
@ -14,8 +14,8 @@
|
||||
|
||||
import testtools
|
||||
|
||||
from tempest.common import api_version_request
|
||||
from tempest import exceptions
|
||||
from tempest.lib.common import api_version_request
|
||||
from tempest.lib import exceptions
|
||||
|
||||
|
||||
LATEST_MICROVERSION = 'latest'
|
||||
@ -35,6 +35,20 @@ class BaseMicroversionTest(object):
|
||||
|
||||
def check_skip_with_microversion(test_min_version, test_max_version,
|
||||
cfg_min_version, cfg_max_version):
|
||||
"""Checks API microversions range and returns whether test needs to be skip
|
||||
|
||||
Compare the test and configured microversion range and returns
|
||||
whether test microversion range is out of configured one.
|
||||
This method can be used to skip the test based on configured and test
|
||||
microversion range.
|
||||
|
||||
:param test_min_version: Test Minimum Microversion
|
||||
:param test_max_version: Test Maximum Microversion
|
||||
:param cfg_min_version: Configured Minimum Microversion
|
||||
:param cfg_max_version: Configured Maximum Microversion
|
||||
:returns: boolean
|
||||
"""
|
||||
|
||||
min_version = api_version_request.APIVersionRequest(test_min_version)
|
||||
max_version = api_version_request.APIVersionRequest(test_max_version)
|
||||
config_min_version = api_version_request.APIVersionRequest(cfg_min_version)
|
||||
@ -68,6 +82,16 @@ def check_skip_with_microversion(test_min_version, test_max_version,
|
||||
|
||||
|
||||
def select_request_microversion(test_min_version, cfg_min_version):
|
||||
"""Select microversion from test and configuration.
|
||||
|
||||
Compare requested microversion and return the maximum
|
||||
microversion out of those.
|
||||
|
||||
:param test_min_version: Test Minimum Microversion
|
||||
:param cfg_min_version: Configured Minimum Microversion
|
||||
:returns: Selected microversion string
|
||||
"""
|
||||
|
||||
test_version = api_version_request.APIVersionRequest(test_min_version)
|
||||
cfg_version = api_version_request.APIVersionRequest(cfg_min_version)
|
||||
max_version = cfg_version if cfg_version >= test_version else test_version
|
||||
@ -82,10 +106,10 @@ def assert_version_header_matches_request(api_microversion_header_name,
|
||||
Verify whether microversion is present in response header
|
||||
and with specified 'api_microversion' value.
|
||||
|
||||
@param: api_microversion_header_name: Microversion header name
|
||||
:param api_microversion_header_name: Microversion header name
|
||||
Example- "X-OpenStack-Nova-API-Version"
|
||||
@param: api_microversion: Microversion number like "2.10"
|
||||
@param: response_header: Response header where microversion is
|
||||
:param api_microversion: Microversion number like "2.10"
|
||||
:param response_header: Response header where microversion is
|
||||
expected to be present.
|
||||
"""
|
||||
api_microversion_header_name = api_microversion_header_name.lower()
|
@ -153,6 +153,20 @@ class InvalidStructure(TempestException):
|
||||
message = "Invalid structure of table with details"
|
||||
|
||||
|
||||
class InvalidAPIVersionString(TempestException):
|
||||
message = ("API Version String %(version)s is of invalid format. Must "
|
||||
"be of format MajorNum.MinorNum or string 'latest'.")
|
||||
|
||||
|
||||
class JSONSchemaNotFound(TempestException):
|
||||
message = ("JSON Schema for %(version)s is not found in\n"
|
||||
" %(schema_versions_info)s")
|
||||
|
||||
|
||||
class InvalidAPIVersionRange(TempestException):
|
||||
message = ("The API version range is invalid.")
|
||||
|
||||
|
||||
class BadAltAuth(TempestException):
|
||||
"""Used when trying and failing to change to alt creds.
|
||||
|
||||
|
@ -11,16 +11,30 @@
|
||||
# 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 tempest.lib.common import rest_client
|
||||
|
||||
from tempest.common import api_version_request
|
||||
from tempest.common import api_version_utils
|
||||
from tempest import exceptions
|
||||
from tempest.lib.common import api_version_request
|
||||
from tempest.lib.common import api_version_utils
|
||||
from tempest.lib.common import rest_client
|
||||
from tempest.lib import exceptions
|
||||
|
||||
COMPUTE_MICROVERSION = None
|
||||
|
||||
|
||||
class BaseComputeClient(rest_client.RestClient):
|
||||
"""Base compute service clients class to support microversion.
|
||||
|
||||
This class adds microversion to API request header if same is set
|
||||
and provide interface to select appropriate JSON schema file for
|
||||
response validation.
|
||||
|
||||
:param auth_provider: an auth provider object used to wrap requests in
|
||||
auth
|
||||
:param str service: The service name to use for the catalog lookup
|
||||
:param str region: The region to use for the catalog lookup
|
||||
request with microversion
|
||||
:param kwargs: kwargs required by rest_client.RestClient
|
||||
"""
|
||||
|
||||
api_microversion_header_name = 'X-OpenStack-Nova-API-Version'
|
||||
|
||||
def __init__(self, auth_provider, service, region,
|
||||
@ -50,9 +64,10 @@ class BaseComputeClient(rest_client.RestClient):
|
||||
"""Get JSON schema
|
||||
|
||||
This method provides the matching schema for requested
|
||||
microversion (self.api_microversion).
|
||||
microversion.
|
||||
|
||||
:param schema_versions_info: List of dict which provides schema
|
||||
information with range of valid versions.
|
||||
information with range of valid versions.
|
||||
Example -
|
||||
schema_versions_info = [
|
||||
{'min': None, 'max': '2.1', 'schema': schemav21},
|
@ -18,7 +18,7 @@ from oslo_serialization import jsonutils as json
|
||||
from tempest.api_schema.response.compute.v2_1 import keypairs as schemav21
|
||||
from tempest.api_schema.response.compute.v2_2 import keypairs as schemav22
|
||||
from tempest.lib.common import rest_client
|
||||
from tempest.services.compute.json import base_compute_client
|
||||
from tempest.lib.services.compute import base_compute_client
|
||||
|
||||
|
||||
class KeyPairsClient(base_compute_client.BaseComputeClient):
|
||||
|
@ -12,9 +12,9 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from tempest.common import api_version_request
|
||||
from tempest import exceptions
|
||||
from tempest.tests import base
|
||||
from tempest.lib.common import api_version_request
|
||||
from tempest.lib import exceptions
|
||||
from tempest.tests.lib import base
|
||||
|
||||
|
||||
class APIVersionRequestTests(base.TestCase):
|
@ -14,9 +14,9 @@
|
||||
|
||||
import testtools
|
||||
|
||||
from tempest.common import api_version_utils
|
||||
from tempest import exceptions
|
||||
from tempest.tests import base
|
||||
from tempest.lib.common import api_version_utils
|
||||
from tempest.lib import exceptions
|
||||
from tempest.tests.lib import base
|
||||
|
||||
|
||||
class TestVersionSkipLogic(base.TestCase):
|
@ -16,12 +16,11 @@ import httplib2
|
||||
import mock
|
||||
from oslotest import mockpatch
|
||||
|
||||
from tempest.api.compute import api_microversion_fixture
|
||||
from tempest import exceptions
|
||||
from tempest.lib.common import rest_client
|
||||
from tempest.services.compute.json import base_compute_client
|
||||
from tempest.tests import fake_auth_provider
|
||||
from tempest.tests.services.compute import base
|
||||
from tempest.lib import exceptions
|
||||
from tempest.lib.services.compute import base_compute_client
|
||||
from tempest.tests.lib import fake_auth_provider
|
||||
from tempest.tests.lib.services.compute import base
|
||||
|
||||
|
||||
class TestMicroversionHeaderCheck(base.BaseComputeServiceTest):
|
||||
@ -31,7 +30,11 @@ class TestMicroversionHeaderCheck(base.BaseComputeServiceTest):
|
||||
fake_auth = fake_auth_provider.FakeAuthProvider()
|
||||
self.client = base_compute_client.BaseComputeClient(
|
||||
fake_auth, 'compute', 'regionOne')
|
||||
self.useFixture(api_microversion_fixture.APIMicroversionFixture('2.2'))
|
||||
base_compute_client.COMPUTE_MICROVERSION = '2.2'
|
||||
|
||||
def tearDown(self):
|
||||
super(TestMicroversionHeaderCheck, self).tearDown()
|
||||
base_compute_client.COMPUTE_MICROVERSION = None
|
||||
|
||||
def _check_microverion_header_in_response(self, fake_response):
|
||||
def request(*args, **kwargs):
|
||||
@ -77,8 +80,11 @@ class TestSchemaVersionsNone(base.BaseComputeServiceTest):
|
||||
super(TestSchemaVersionsNone, self).setUp()
|
||||
fake_auth = fake_auth_provider.FakeAuthProvider()
|
||||
self.client = DummyServiceClient1(fake_auth, 'compute', 'regionOne')
|
||||
self.useFixture(api_microversion_fixture.APIMicroversionFixture(
|
||||
self.api_microversion))
|
||||
base_compute_client.COMPUTE_MICROVERSION = self.api_microversion
|
||||
|
||||
def tearDown(self):
|
||||
super(TestSchemaVersionsNone, self).tearDown()
|
||||
base_compute_client.COMPUTE_MICROVERSION = None
|
||||
|
||||
def test_schema(self):
|
||||
self.assertEqual(self.expected_schema,
|
||||
@ -132,8 +138,11 @@ class TestSchemaVersionsNotFound(base.BaseComputeServiceTest):
|
||||
super(TestSchemaVersionsNotFound, self).setUp()
|
||||
fake_auth = fake_auth_provider.FakeAuthProvider()
|
||||
self.client = DummyServiceClient2(fake_auth, 'compute', 'regionOne')
|
||||
self.useFixture(api_microversion_fixture.APIMicroversionFixture(
|
||||
self.api_microversion))
|
||||
base_compute_client.COMPUTE_MICROVERSION = self.api_microversion
|
||||
|
||||
def tearDown(self):
|
||||
super(TestSchemaVersionsNotFound, self).tearDown()
|
||||
base_compute_client.COMPUTE_MICROVERSION = None
|
||||
|
||||
def test_schema(self):
|
||||
self.assertRaises(exceptions.JSONSchemaNotFound,
|
||||
@ -170,7 +179,11 @@ class TestClientWithMicroversionHeader(base.BaseComputeServiceTest):
|
||||
fake_auth = fake_auth_provider.FakeAuthProvider()
|
||||
self.client = base_compute_client.BaseComputeClient(
|
||||
fake_auth, 'compute', 'regionOne')
|
||||
self.useFixture(api_microversion_fixture.APIMicroversionFixture('2.2'))
|
||||
base_compute_client.COMPUTE_MICROVERSION = '2.2'
|
||||
|
||||
def tearDown(self):
|
||||
super(TestClientWithMicroversionHeader, self).tearDown()
|
||||
base_compute_client.COMPUTE_MICROVERSION = None
|
||||
|
||||
def test_microverion_header(self):
|
||||
header = self.client.get_headers()
|
@ -17,7 +17,7 @@ import testtools
|
||||
|
||||
from tempest.api.compute import base as compute_base
|
||||
from tempest import config
|
||||
from tempest import exceptions
|
||||
from tempest.lib import exceptions
|
||||
from tempest.tests import base
|
||||
from tempest.tests import fake_config
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user