Add "list versions" test for Keystone

"list versions" is an inportant API to know which versions are
supported on clouds. This patch adds the corresponding test for
Keystone API.

Change-Id: Ic4aaa16ac1c15d2b82e3dc90402a5b30d19bcd4e
This commit is contained in:
Ken'ichi Ohmichi
2017-03-03 15:53:46 -08:00
committed by Ken'ichi Ohmichi
parent 5e1543f753
commit da26b16874
9 changed files with 144 additions and 17 deletions

View File

@@ -0,0 +1,6 @@
---
features:
- |
Add versions_client module for identity service.
This new module provides list_versions() method which shows API versions
from Identity service.

View File

@@ -171,6 +171,7 @@ class BaseIdentityV3Test(BaseIdentityTest):
cls.non_admin_users_client = cls.os.users_v3_client
cls.non_admin_token = cls.os.token_v3_client
cls.non_admin_projects_client = cls.os.projects_client
cls.non_admin_versions_client = cls.os.identity_versions_v3_client
class BaseIdentityV3AdminTest(BaseIdentityV3Test):

View File

@@ -21,6 +21,20 @@ from tempest import test
class TestApiDiscovery(base.BaseIdentityV3Test):
"""Tests for API discovery features."""
@decorators.idempotent_id('721f480f-35b6-46c7-846e-047e6acea0dc')
@test.attr(type='smoke')
def test_list_api_versions(self):
# NOTE: Actually this API doesn't depend on v3 API at all, because
# the API operation is "GET /" without v3's endpoint. The reason of
# this test path is just v3 API is CURRENT on Keystone side.
versions = self.non_admin_versions_client.list_versions()
expected_resources = ('id', 'links', 'media-types', 'status',
'updated')
for version in versions['versions']["values"]:
for res in expected_resources:
self.assertIn(res, version)
@test.attr(type='smoke')
@decorators.idempotent_id('b9232f5e-d9e5-4d97-b96c-28d3db4de1bd')
def test_api_version_resources(self):

View File

@@ -225,6 +225,8 @@ class Manager(clients.ServiceClients):
self.credentials_client = self.identity_v3.CredentialsClient(
**params_v3)
self.groups_client = self.identity_v3.GroupsClient(**params_v3)
self.identity_versions_v3_client = self.identity_v3.VersionsClient(
**params_v3)
# Token clients do not use the catalog. They only need default_params.
# They read auth_url, so they should only be set if the corresponding

View File

@@ -23,6 +23,7 @@ import jsonschema
from oslo_log import log as logging
from oslo_serialization import jsonutils as json
import six
from six.moves import urllib
from tempest.lib.common import http
from tempest.lib.common import jsonschema_validator
@@ -915,6 +916,16 @@ class RestClient(object):
msg = ("HTTP response header is invalid (%s)" % ex)
raise exceptions.InvalidHTTPResponseHeader(msg)
def _get_base_version_url(self):
# TODO(oomichi): This method can be used for auth's replace_version().
# So it is nice to have common logic for the maintenance.
endpoint = self.base_url
url = urllib.parse.urlsplit(endpoint)
new_path = re.split(r'(^|/)+v\d+(\.\d+)?', url.path)[0]
url = list(url)
url[2] = new_path + '/'
return urllib.parse.urlunsplit(url)
class ResponseBody(dict):
"""Class that wraps an http response and dict body into a single value.

View File

@@ -12,10 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import re
from oslo_serialization import jsonutils as json
from six.moves import urllib
from tempest.lib.api_schema.response.compute.v2_1 import versions as schema
from tempest.lib.common import rest_client
@@ -24,19 +21,6 @@ from tempest.lib.services.compute import base_compute_client
class VersionsClient(base_compute_client.BaseComputeClient):
def _get_base_version_url(self):
# NOTE: The URL which is got from keystone's catalog contains
# API version and project-id like "/app-name/v2/{project-id}" or
# "/v2/{project-id}", but we need to access the URL which doesn't
# contain API version for getting API versions. For that, here
# should use raw_request() instead of get().
endpoint = self.base_url
url = urllib.parse.urlsplit(endpoint)
new_path = re.split(r'(^|/)+v\d+(\.\d+)?', url.path)[0]
url = list(url)
url[2] = new_path + '/'
return urllib.parse.urlunsplit(url)
def list_versions(self):
version_url = self._get_base_version_url()
resp, body = self.raw_request(version_url, 'GET')

View File

@@ -30,9 +30,10 @@ from tempest.lib.services.identity.v3.services_client import ServicesClient
from tempest.lib.services.identity.v3.token_client import V3TokenClient
from tempest.lib.services.identity.v3.trusts_client import TrustsClient
from tempest.lib.services.identity.v3.users_client import UsersClient
from tempest.lib.services.identity.v3.versions_client import VersionsClient
__all__ = ['CredentialsClient', 'DomainsClient', 'EndPointsClient',
'GroupsClient', 'IdentityClient', 'InheritedRolesClient',
'PoliciesClient', 'ProjectsClient', 'RegionsClient',
'RoleAssignmentsClient', 'RolesClient', 'ServicesClient',
'V3TokenClient', 'TrustsClient', 'UsersClient', ]
'V3TokenClient', 'TrustsClient', 'UsersClient', 'VersionsClient']

View File

@@ -0,0 +1,38 @@
# Copyright 2017 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 time
from oslo_serialization import jsonutils as json
from tempest.lib.common import rest_client
class VersionsClient(rest_client.RestClient):
api_version = "v3"
def list_versions(self):
"""List API versions"""
version_url = self._get_base_version_url()
start = time.time()
resp, body = self.raw_request(version_url, 'GET')
end = time.time()
self._log_request('GET', version_url, resp, secs=(end - start),
resp_body=body)
self._error_checker(resp, body)
self.expected_success(300, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)

View File

@@ -0,0 +1,70 @@
# Copyright 2017 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.services.identity.v3 import versions_client
from tempest.tests.lib import fake_auth_provider
from tempest.tests.lib.services import base
class TestIdentityClient(base.BaseServiceTest):
FAKE_VERSIONS_INFO = {
"versions": {
"values": [
{"status": "stable", "updated": "2017-02-22T00:00:00Z",
"media-types": [
{"base": "application/json", "type":
"application/vnd.openstack.identity-v3+json"}
],
"id": "v3.8",
"links": [
{"href": "https://15.184.67.226/identity_admin/v3/",
"rel": "self"}
]},
{"status": "deprecated", "updated": "2016-08-04T00:00:00Z",
"media-types": [
{"base": "application/json",
"type": "application/vnd.openstack.identity-v2.0+json"}
],
"id": "v2.0",
"links": [
{"href": "https://15.184.67.226/identity_admin/v2.0/",
"rel": "self"},
{"href": "https://docs.openstack.org/",
"type": "text/html", "rel": "describedby"}
]}
]
}
}
def setUp(self):
super(TestIdentityClient, self).setUp()
fake_auth = fake_auth_provider.FakeAuthProvider()
self.client = versions_client.VersionsClient(fake_auth,
'identity',
'regionOne')
def _test_list_versions(self, bytes_body=False):
self.check_service_client_function(
self.client.list_versions,
'tempest.lib.common.rest_client.RestClient.raw_request',
self.FAKE_VERSIONS_INFO,
bytes_body,
300)
def test_list_versions_with_str_body(self):
self._test_list_versions()
def test_list_versions_with_bytes_body(self):
self._test_list_versions(bytes_body=True)