Merge "Add a bit more debugging to the client registry"
diff --git a/releasenotes/notes/add-list-version-to-identity-client-944cb7396088a575.yaml b/releasenotes/notes/add-list-version-to-identity-client-944cb7396088a575.yaml
new file mode 100644
index 0000000..dd66ff5
--- /dev/null
+++ b/releasenotes/notes/add-list-version-to-identity-client-944cb7396088a575.yaml
@@ -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.
diff --git a/requirements.txt b/requirements.txt
index 124da7a..6962e3e 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,7 +1,7 @@
# The order of packages is significant, because pip processes them in the order
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
-pbr>=1.8 # Apache-2.0
+pbr>=2.0.0 # Apache-2.0
cliff>=2.3.0 # Apache-2.0
jsonschema!=2.5.0,<3.0.0,>=2.0.0 # MIT
testtools>=1.4.0 # MIT
@@ -17,7 +17,7 @@
fixtures>=3.0.0 # Apache-2.0/BSD
PyYAML>=3.10.0 # MIT
python-subunit>=0.0.18 # Apache-2.0/BSD
-stevedore>=1.17.1 # Apache-2.0
+stevedore>=1.20.0 # Apache-2.0
PrettyTable<0.8,>=0.7.1 # BSD
os-testr>=0.8.0 # Apache-2.0
urllib3>=1.15.1 # MIT
diff --git a/setup.py b/setup.py
index 782bb21..566d844 100644
--- a/setup.py
+++ b/setup.py
@@ -25,5 +25,5 @@
pass
setuptools.setup(
- setup_requires=['pbr>=1.8'],
+ setup_requires=['pbr>=2.0.0'],
pbr=True)
diff --git a/tempest/api/identity/base.py b/tempest/api/identity/base.py
index 344779c..3c15d8c 100644
--- a/tempest/api/identity/base.py
+++ b/tempest/api/identity/base.py
@@ -178,6 +178,7 @@
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):
diff --git a/tempest/api/identity/v3/test_api_discovery.py b/tempest/api/identity/v3/test_api_discovery.py
index 2eed3c8..177a49d 100644
--- a/tempest/api/identity/v3/test_api_discovery.py
+++ b/tempest/api/identity/v3/test_api_discovery.py
@@ -21,6 +21,20 @@
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):
diff --git a/tempest/clients.py b/tempest/clients.py
index cdd6925..9cb918a 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -225,6 +225,8 @@
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
diff --git a/tempest/lib/common/rest_client.py b/tempest/lib/common/rest_client.py
index f5bff20..3246d6a 100644
--- a/tempest/lib/common/rest_client.py
+++ b/tempest/lib/common/rest_client.py
@@ -23,6 +23,7 @@
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 @@
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.
diff --git a/tempest/lib/services/compute/versions_client.py b/tempest/lib/services/compute/versions_client.py
index b2052c3..75984ec 100644
--- a/tempest/lib/services/compute/versions_client.py
+++ b/tempest/lib/services/compute/versions_client.py
@@ -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 @@
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')
diff --git a/tempest/lib/services/identity/v3/__init__.py b/tempest/lib/services/identity/v3/__init__.py
index 8058d51..88801e7 100644
--- a/tempest/lib/services/identity/v3/__init__.py
+++ b/tempest/lib/services/identity/v3/__init__.py
@@ -30,9 +30,10 @@
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']
diff --git a/tempest/lib/services/identity/v3/versions_client.py b/tempest/lib/services/identity/v3/versions_client.py
new file mode 100644
index 0000000..441ee0d
--- /dev/null
+++ b/tempest/lib/services/identity/v3/versions_client.py
@@ -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)
diff --git a/tempest/tests/lib/services/identity/v3/test_versions_client.py b/tempest/tests/lib/services/identity/v3/test_versions_client.py
new file mode 100644
index 0000000..3bfaf1e
--- /dev/null
+++ b/tempest/tests/lib/services/identity/v3/test_versions_client.py
@@ -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)
diff --git a/test-requirements.txt b/test-requirements.txt
index 936d5aa..13950bd 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -1,7 +1,7 @@
# The order of packages is significant, because pip processes them in the order
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
-hacking>=0.12.0,!=0.13.0,<0.14 # Apache-2.0
+hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0
# needed for doc build
sphinx>=1.5.1 # BSD
oslosphinx>=4.7.0 # Apache-2.0