Separate base microversion client and compute client
To support microversion in service clients, there are some common functionality which can be shared among all projects service client who support microversion. This commit separates the common functionality: - New base microversion client which can be used by any service client for microversion testing. - Base compute client which will be specific to compute service clients. Also adding the microversion header checking in base compute client only as microversion implementation not yet standardize. So projects might have different way of return microversion information in response. Partially implements blueprint api-microversions-testing-support Change-Id: Ic25ab63946264057f3a4365cd1ed13d9a35462db
This commit is contained in:
parent
a1f8713596
commit
bbdb33b1c2
|
@ -69,3 +69,27 @@ def select_request_microversion(test_min_version, cfg_min_version):
|
|||
cfg_version = api_version_request.APIVersionRequest(cfg_min_version)
|
||||
max_version = cfg_version if cfg_version >= test_version else test_version
|
||||
return max_version.get_string()
|
||||
|
||||
|
||||
def assert_version_header_matches_request(api_microversion_header_name,
|
||||
api_microversion,
|
||||
response_header):
|
||||
"""Checks API microversion in resposne header
|
||||
|
||||
Verify whether microversion is present in response header
|
||||
and with specified 'api_microversion' value.
|
||||
|
||||
@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
|
||||
expected to be present.
|
||||
"""
|
||||
api_microversion_header_name = api_microversion_header_name.lower()
|
||||
if (api_microversion_header_name not in response_header or
|
||||
api_microversion != response_header[api_microversion_header_name]):
|
||||
msg = ("Microversion header '%s' with value '%s' does not match in "
|
||||
"response - %s. " % (api_microversion_header_name,
|
||||
api_microversion,
|
||||
response_header))
|
||||
raise exceptions.InvalidHTTPResponseHeader(msg)
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
# Copyright 2016 NEC Corporation. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# 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
|
||||
|
||||
|
||||
class BaseMicroversionClient(rest_client.RestClient):
|
||||
"""Base class to support microversion in service clients
|
||||
|
||||
This class is used to support microversion in service clients.
|
||||
This provides feature to make API request with microversion.
|
||||
Service clients derived from this class will be able to send API
|
||||
request to server with or without microversion.
|
||||
If api_microversion is not set on service client then API request will be
|
||||
normal request without microversion.
|
||||
|
||||
"""
|
||||
def __init__(self, auth_provider, service, region,
|
||||
api_microversion_header_name, **kwargs):
|
||||
"""Base Microversion Client __init__
|
||||
|
||||
: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
|
||||
:param str api_microversion_header_name: The microversion header name
|
||||
to use for sending API
|
||||
request with microversion
|
||||
:param kwargs: kwargs required by rest_client.RestClient
|
||||
"""
|
||||
super(BaseMicroversionClient, self).__init__(
|
||||
auth_provider, service, region, **kwargs)
|
||||
self.api_microversion_header_name = api_microversion_header_name
|
||||
self.api_microversion = None
|
||||
|
||||
def get_headers(self):
|
||||
headers = super(BaseMicroversionClient, self).get_headers()
|
||||
if self.api_microversion:
|
||||
headers[self.api_microversion_header_name] = self.api_microversion
|
||||
return headers
|
||||
|
||||
def set_api_microversion(self, microversion):
|
||||
self.api_microversion = microversion
|
|
@ -12,23 +12,31 @@
|
|||
# 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.services import base_microversion_client
|
||||
|
||||
|
||||
class BaseComputeClient(rest_client.RestClient):
|
||||
api_microversion = None
|
||||
class BaseComputeClient(base_microversion_client.BaseMicroversionClient):
|
||||
|
||||
def get_headers(self):
|
||||
headers = super(BaseComputeClient, self).get_headers()
|
||||
if self.api_microversion:
|
||||
headers['X-OpenStack-Nova-API-Version'] = self.api_microversion
|
||||
return headers
|
||||
def __init__(self, auth_provider, service, region,
|
||||
api_microversion_header_name='X-OpenStack-Nova-API-Version',
|
||||
**kwargs):
|
||||
super(BaseComputeClient, self).__init__(
|
||||
auth_provider, service, region,
|
||||
api_microversion_header_name, **kwargs)
|
||||
|
||||
def set_api_microversion(self, microversion):
|
||||
self.api_microversion = microversion
|
||||
def request(self, method, url, extra_headers=False, headers=None,
|
||||
body=None):
|
||||
resp, resp_body = super(BaseComputeClient, self).request(
|
||||
method, url, extra_headers, headers, body)
|
||||
if self.api_microversion and self.api_microversion != 'latest':
|
||||
api_version_utils.assert_version_header_matches_request(
|
||||
self.api_microversion_header_name,
|
||||
self.api_microversion,
|
||||
resp)
|
||||
return resp, resp_body
|
||||
|
||||
def get_schema(self, schema_versions_info):
|
||||
"""Get JSON schema
|
|
@ -18,10 +18,10 @@ 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.common import service_client
|
||||
from tempest.services.compute.json import base
|
||||
from tempest.services.compute.json import base_compute_client
|
||||
|
||||
|
||||
class KeyPairsClient(base.BaseComputeClient):
|
||||
class KeyPairsClient(base_compute_client.BaseComputeClient):
|
||||
|
||||
schema_versions_info = [{'min': None, 'max': '2.1', 'schema': schemav21},
|
||||
{'min': '2.2', 'max': None, 'schema': schemav22}]
|
||||
|
|
|
@ -219,3 +219,31 @@ class TestSelectRequestMicroversion(base.TestCase):
|
|||
|
||||
def test_both_min_version_equal(self):
|
||||
self._test_request_version('2.3', '2.3', expected_version='2.3')
|
||||
|
||||
|
||||
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}
|
||||
api_version_utils.assert_version_header_matches_request(
|
||||
microversion_header_name, request_microversion, test_respose)
|
||||
|
||||
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'}
|
||||
self.assertRaises(
|
||||
exceptions.InvalidHTTPResponseHeader,
|
||||
api_version_utils.assert_version_header_matches_request,
|
||||
microversion_header_name, request_microversion, test_respose)
|
||||
|
||||
def test_header_not_present(self):
|
||||
microversion_header_name = 'x-openstack-xyz-api-version'
|
||||
request_microversion = '2.1'
|
||||
test_respose = {}
|
||||
self.assertRaises(
|
||||
exceptions.InvalidHTTPResponseHeader,
|
||||
api_version_utils.assert_version_header_matches_request,
|
||||
microversion_header_name, request_microversion, test_respose)
|
||||
|
|
|
@ -13,64 +13,48 @@
|
|||
# under the License.
|
||||
|
||||
import httplib2
|
||||
import mock
|
||||
from oslotest import mockpatch
|
||||
from tempest_lib.common import rest_client
|
||||
|
||||
from tempest import exceptions
|
||||
from tempest.services.compute.json import base as base_compute_client
|
||||
from tempest.services.compute.json import base_compute_client
|
||||
from tempest.tests import fake_auth_provider
|
||||
from tempest.tests.services.compute import base
|
||||
|
||||
|
||||
class TestClientWithoutMicroversionHeader(base.BaseComputeServiceTest):
|
||||
class TestMicroversionHeaderCheck(base.BaseComputeServiceTest):
|
||||
|
||||
def setUp(self):
|
||||
super(TestClientWithoutMicroversionHeader, self).setUp()
|
||||
super(TestMicroversionHeaderCheck, self).setUp()
|
||||
fake_auth = fake_auth_provider.FakeAuthProvider()
|
||||
self.client = base_compute_client.BaseComputeClient(
|
||||
fake_auth, 'compute', 'regionOne')
|
||||
self.client.set_api_microversion('2.2')
|
||||
|
||||
def test_no_microverion_header(self):
|
||||
header = self.client.get_headers()
|
||||
self.assertNotIn('X-OpenStack-Nova-API-Version', header)
|
||||
def _check_microverion_header_in_response(self, fake_response):
|
||||
def request(*args, **kwargs):
|
||||
return (httplib2.Response(fake_response), {})
|
||||
|
||||
def test_no_microverion_header_in_raw_request(self):
|
||||
def raw_request(*args, **kwargs):
|
||||
self.assertNotIn('X-OpenStack-Nova-API-Version', kwargs['headers'])
|
||||
return (httplib2.Response({'status': 200}), {})
|
||||
self.useFixture(mockpatch.PatchObject(
|
||||
rest_client.RestClient,
|
||||
'request',
|
||||
side_effect=request))
|
||||
|
||||
with mock.patch.object(rest_client.RestClient,
|
||||
'raw_request') as mock_get:
|
||||
mock_get.side_effect = raw_request
|
||||
self.client.get('fake_url')
|
||||
def test_correct_microverion_in_response(self):
|
||||
fake_response = {self.client.api_microversion_header_name: '2.2'}
|
||||
self._check_microverion_header_in_response(fake_response)
|
||||
self.client.get('fake_url')
|
||||
|
||||
def test_incorrect_microverion_in_response(self):
|
||||
fake_response = {self.client.api_microversion_header_name: '2.3'}
|
||||
self._check_microverion_header_in_response(fake_response)
|
||||
self.assertRaises(exceptions.InvalidHTTPResponseHeader,
|
||||
self.client.get, 'fake_url')
|
||||
|
||||
class TestClientWithMicroversionHeader(base.BaseComputeServiceTest):
|
||||
|
||||
def setUp(self):
|
||||
super(TestClientWithMicroversionHeader, self).setUp()
|
||||
fake_auth = fake_auth_provider.FakeAuthProvider()
|
||||
self.client = base_compute_client.BaseComputeClient(
|
||||
fake_auth, 'compute', 'regionOne')
|
||||
self.client.api_microversion = '2.2'
|
||||
|
||||
def test_microverion_header(self):
|
||||
header = self.client.get_headers()
|
||||
self.assertIn('X-OpenStack-Nova-API-Version', header)
|
||||
self.assertEqual(self.client.api_microversion,
|
||||
header['X-OpenStack-Nova-API-Version'])
|
||||
|
||||
def test_microverion_header_in_raw_request(self):
|
||||
def raw_request(*args, **kwargs):
|
||||
self.assertIn('X-OpenStack-Nova-API-Version', kwargs['headers'])
|
||||
self.assertEqual(self.client.api_microversion,
|
||||
kwargs['headers']['X-OpenStack-Nova-API-Version'])
|
||||
return (httplib2.Response({'status': 200}), {})
|
||||
|
||||
with mock.patch.object(rest_client.RestClient,
|
||||
'raw_request') as mock_get:
|
||||
mock_get.side_effect = raw_request
|
||||
self.client.get('fake_url')
|
||||
def test_no_microverion_header_in_response(self):
|
||||
self._check_microverion_header_in_response({})
|
||||
self.assertRaises(exceptions.InvalidHTTPResponseHeader,
|
||||
self.client.get, 'fake_url')
|
||||
|
||||
|
||||
class DummyServiceClient1(base_compute_client.BaseComputeClient):
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
# Copyright 2016 NEC Corporation. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import httplib2
|
||||
import mock
|
||||
from tempest_lib.common import rest_client
|
||||
|
||||
from tempest.services import base_microversion_client
|
||||
from tempest.tests import fake_auth_provider
|
||||
from tempest.tests.services.compute import base
|
||||
|
||||
|
||||
class TestClientWithoutMicroversionHeader(base.BaseComputeServiceTest):
|
||||
|
||||
def setUp(self):
|
||||
super(TestClientWithoutMicroversionHeader, self).setUp()
|
||||
fake_auth = fake_auth_provider.FakeAuthProvider()
|
||||
self.client = base_microversion_client.BaseMicroversionClient(
|
||||
fake_auth, 'compute', 'regionOne', 'X-OpenStack-Nova-API-Version')
|
||||
|
||||
def test_no_microverion_header(self):
|
||||
header = self.client.get_headers()
|
||||
self.assertNotIn(self.client.api_microversion_header_name, header)
|
||||
|
||||
def test_no_microverion_header_in_raw_request(self):
|
||||
def raw_request(*args, **kwargs):
|
||||
self.assertNotIn(self.client.api_microversion_header_name,
|
||||
kwargs['headers'])
|
||||
return (httplib2.Response({'status': 200}), {})
|
||||
|
||||
with mock.patch.object(rest_client.RestClient,
|
||||
'raw_request') as mock_get:
|
||||
mock_get.side_effect = raw_request
|
||||
self.client.get('fake_url')
|
||||
|
||||
|
||||
class TestClientWithMicroversionHeader(base.BaseComputeServiceTest):
|
||||
|
||||
def setUp(self):
|
||||
super(TestClientWithMicroversionHeader, self).setUp()
|
||||
fake_auth = fake_auth_provider.FakeAuthProvider()
|
||||
self.client = base_microversion_client.BaseMicroversionClient(
|
||||
fake_auth, 'compute', 'regionOne', 'X-OpenStack-Nova-API-Version')
|
||||
self.client.set_api_microversion('2.2')
|
||||
|
||||
def test_microverion_header(self):
|
||||
header = self.client.get_headers()
|
||||
self.assertIn(self.client.api_microversion_header_name, header)
|
||||
self.assertEqual(self.client.api_microversion,
|
||||
header[self.client.api_microversion_header_name])
|
||||
|
||||
def test_microverion_header_in_raw_request(self):
|
||||
def raw_request(*args, **kwargs):
|
||||
self.assertIn(self.client.api_microversion_header_name,
|
||||
kwargs['headers'])
|
||||
self.assertEqual(
|
||||
self.client.api_microversion,
|
||||
kwargs['headers'][self.client.api_microversion_header_name])
|
||||
return (httplib2.Response({'status': 200}), {})
|
||||
|
||||
with mock.patch.object(rest_client.RestClient,
|
||||
'raw_request') as mock_get:
|
||||
mock_get.side_effect = raw_request
|
||||
self.client.get('fake_url')
|
Loading…
Reference in New Issue