Add support of schema versioning for microversion

For API microversion testing, service clients can be
requested with any supported API microversions.
Compute service clients does response validation using response
schema.

To validate the corresponding microversion response with appropriate
schema, we need to add support of versioning in schema.

Each service client having multiple schema for microversions,
needs to define a list of dict with schema versions information.
Based on that information and requested microversion, schema
will be selected.

Example-

from tempest.api_schema.response.compute.v2_1 import xyz as schemav21
from tempest.api_schema.response.compute.v2_2 import xyz as schemav22
from tempest.api_schema.response.compute.v2_10 import abc as schemav210
.
.
.
    schema_versions_info = [
        {'min': None, 'max': '2.1', 'schema': schemav21},
        {'min': '2.2', 'max': '2.9', 'schema': schemav22},
        {'min': '2.10', 'max': None, 'schema': schemav210}]

This can be defined at class level or method level depends on how
schema differ for that service client.

This commits add the logic to select the valid schema for requested API
microversion.

Partially implements blueprint api-microversions-testing-support

Change-Id: I7c87287ca9f6f60a66aab8290031632945c03d59
This commit is contained in:
Ghanshyam 2015-12-17 17:42:08 +09:00 committed by Ghanshyam Mann
parent 3452fdb496
commit 77f3f90348
3 changed files with 121 additions and 0 deletions

View File

@ -181,6 +181,11 @@ class InvalidAPIVersionString(TempestException):
"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 CommandFailed(Exception):
def __init__(self, returncode, cmd, output, stderr):
super(CommandFailed, self).__init__()

View File

@ -14,6 +14,9 @@
from tempest_lib.common import rest_client
from tempest.common import api_version_request
from tempest import exceptions
class BaseComputeClient(rest_client.RestClient):
api_microversion = None
@ -26,3 +29,36 @@ class BaseComputeClient(rest_client.RestClient):
def set_api_microversion(self, microversion):
self.api_microversion = microversion
def get_schema(self, schema_versions_info):
"""Get JSON schema
This method provides the matching schema for requested
microversion (self.api_microversion).
:param schema_versions_info: List of dict which provides schema
information with range of valid versions.
Example -
schema_versions_info = [
{'min': None, 'max': '2.1', 'schema': schemav21},
{'min': '2.2', 'max': '2.9', 'schema': schemav22},
{'min': '2.10', 'max': None, 'schema': schemav210}]
"""
schema = None
version = api_version_request.APIVersionRequest(self.api_microversion)
for items in schema_versions_info:
min_version = api_version_request.APIVersionRequest(items['min'])
max_version = api_version_request.APIVersionRequest(items['max'])
# This is case where self.api_microversion is None, which means
# request without microversion So select base v2.1 schema.
if version.is_null() and items['min'] is None:
schema = items['schema']
break
# else select appropriate schema as per self.api_microversion
elif version.matches(min_version, max_version):
schema = items['schema']
break
if schema is None:
raise exceptions.JSONSchemaNotFound(
version=version.get_string(),
schema_versions_info=schema_versions_info)
return schema

View File

@ -16,6 +16,7 @@ import httplib2
import mock
from tempest_lib.common import rest_client
from tempest import exceptions
from tempest.services.compute.json import base as base_compute_client
from tempest.tests import fake_auth_provider
from tempest.tests.services.compute import base
@ -70,3 +71,82 @@ class TestClientWithMicroversionHeader(base.BaseComputeServiceTest):
'raw_request') as mock_get:
mock_get.side_effect = raw_request
self.client.get('fake_url')
class DummyServiceClient1(base_compute_client.BaseComputeClient):
schema_versions_info = [
{'min': None, 'max': '2.1', 'schema': 'schemav21'},
{'min': '2.2', 'max': '2.9', 'schema': 'schemav22'},
{'min': '2.10', 'max': None, 'schema': 'schemav210'}]
def return_selected_schema(self):
return self.get_schema(self.schema_versions_info)
class TestSchemaVersionsNone(base.BaseComputeServiceTest):
api_microversion = None
expected_schema = 'schemav21'
def setUp(self):
super(TestSchemaVersionsNone, self).setUp()
fake_auth = fake_auth_provider.FakeAuthProvider()
self.client = DummyServiceClient1(fake_auth, 'compute', 'regionOne')
self.client.api_microversion = self.api_microversion
def test_schema(self):
self.assertEqual(self.expected_schema,
self.client.return_selected_schema())
class TestSchemaVersionsV21(TestSchemaVersionsNone):
api_microversion = '2.1'
expected_schema = 'schemav21'
class TestSchemaVersionsV22(TestSchemaVersionsNone):
api_microversion = '2.2'
expected_schema = 'schemav22'
class TestSchemaVersionsV25(TestSchemaVersionsNone):
api_microversion = '2.5'
expected_schema = 'schemav22'
class TestSchemaVersionsV29(TestSchemaVersionsNone):
api_microversion = '2.9'
expected_schema = 'schemav22'
class TestSchemaVersionsV210(TestSchemaVersionsNone):
api_microversion = '2.10'
expected_schema = 'schemav210'
class TestSchemaVersionsLatest(TestSchemaVersionsNone):
api_microversion = 'latest'
expected_schema = 'schemav210'
class DummyServiceClient2(base_compute_client.BaseComputeClient):
schema_versions_info = [
{'min': None, 'max': '2.1', 'schema': 'schemav21'},
{'min': '2.2', 'max': '2.9', 'schema': 'schemav22'}]
def return_selected_schema(self):
return self.get_schema(self.schema_versions_info)
class TestSchemaVersionsNotFound(base.BaseComputeServiceTest):
api_microversion = '2.10'
expected_schema = 'schemav210'
def setUp(self):
super(TestSchemaVersionsNotFound, self).setUp()
fake_auth = fake_auth_provider.FakeAuthProvider()
self.client = DummyServiceClient2(fake_auth, 'compute', 'regionOne')
self.client.api_microversion = self.api_microversion
def test_schema(self):
self.assertRaises(exceptions.JSONSchemaNotFound,
self.client.return_selected_schema)