Merge "switch to the newly created opensuse-15 nodeset"
diff --git a/.gitignore b/.gitignore
index 06a2281..9767e52 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,9 @@
+# Don't add patterns to exclude files created by preferred personal tools
+# (editors, IDEs, your operating system itself even). These should instead be
+# maintained outside the repository, for example in a ~/.gitignore file added
+# with:
+#
+# git config --global core.excludesfile '~/.gitignore'
AUTHORS
ChangeLog
*.pyc
diff --git a/.zuul.yaml b/.zuul.yaml
index 191d407..2bcbc85 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -413,6 +413,16 @@
c-bak: false
- job:
+ name: tempest-full-train
+ parent: tempest-full
+ override-checkout: stable/train
+
+- job:
+ name: tempest-full-train-py3
+ parent: tempest-full-py3
+ override-checkout: stable/train
+
+- job:
name: tempest-full-stein
parent: tempest-full
override-checkout: stable/stein
@@ -630,6 +640,10 @@
- tempest-full-py3-ipv6:
voting: false
irrelevant-files: *tempest-irrelevant-files
+ - tempest-full-train:
+ irrelevant-files: *tempest-irrelevant-files
+ - tempest-full-train-py3:
+ irrelevant-files: *tempest-irrelevant-files
- tempest-full-stein:
irrelevant-files: *tempest-irrelevant-files
- tempest-full-stein-py3:
@@ -739,6 +753,8 @@
irrelevant-files: *tempest-irrelevant-files
periodic-stable:
jobs:
+ - tempest-full-train
+ - tempest-full-train-py3
- tempest-full-stein
- tempest-full-stein-py3
- tempest-full-rocky
diff --git a/REVIEWING.rst b/REVIEWING.rst
index 498ce66..e07e358 100644
--- a/REVIEWING.rst
+++ b/REVIEWING.rst
@@ -183,6 +183,9 @@
* the project's PTL +1's the change
* the patch does not affect any other project's testing gates
* the patch does not cause any negative side effects
+ * If fixing and removing the faulty plugin (which leads to fail
+ voting ``tempest-tox-plugin-sanity-check`` job) and unblock the
+ tempest gate
Note that such a policy should be used judiciously, as we should strive to
have two +2's on each patch set, prior to approval.
diff --git a/releasenotes/notes/fix-1847749-2670b1d4f6097a1a.yaml b/releasenotes/notes/fix-1847749-2670b1d4f6097a1a.yaml
new file mode 100644
index 0000000..4842f63
--- /dev/null
+++ b/releasenotes/notes/fix-1847749-2670b1d4f6097a1a.yaml
@@ -0,0 +1,6 @@
+---
+fixes:
+ - |
+ Bug#1847749. This provides the workaround of Skip Exception raised instead of skipping
+ the CLI tests. If you are running Tempest with stestr > 2.5.0 then use this fix.
+ Ref- https://github.com/testing-cabal/testtools/issues/272
diff --git a/releasenotes/notes/fix-credential-logging-98089c897d801355.yaml b/releasenotes/notes/fix-credential-logging-98089c897d801355.yaml
new file mode 100644
index 0000000..9534a72
--- /dev/null
+++ b/releasenotes/notes/fix-credential-logging-98089c897d801355.yaml
@@ -0,0 +1,9 @@
+---
+features:
+ - |
+ A new kwarg, ``log_req_body``, was added to the
+ ``tempest.lib.common.rest_client.RestClient`` method ``raw_request()``.
+ This kwarg takes in a string which will be used in place of the request
+ body, which is logged by default. The intent of this option is to be used
+ for security reasons to avoid logging sensitive information that are part
+ of request bodies.
diff --git a/releasenotes/notes/tempest-train-release-a2ed0743a5eadeb6.yaml b/releasenotes/notes/tempest-train-release-a2ed0743a5eadeb6.yaml
new file mode 100644
index 0000000..960b0b2
--- /dev/null
+++ b/releasenotes/notes/tempest-train-release-a2ed0743a5eadeb6.yaml
@@ -0,0 +1,17 @@
+---
+prelude: |
+ This release is to tag the Tempest for OpenStack Train release.
+ This release marks the start of Train release support in Tempest.
+ After this release, Tempest will support below OpenStack Releases:
+
+ * Train
+ * Stein
+ * Rocky
+ * Queens
+
+ Current development of Tempest is for OpenStack Ussuri development
+ cycle. Every Tempest commit is also tested against master during
+ the Ussuri cycle. However, this does not necessarily mean that using
+ Tempest as of this tag will work against a Ussuri (or future release)
+ cloud.
+ To be on safe side, use this tag to test the OpenStack Train release.
diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst
index 1d0d914..43c102c 100644
--- a/releasenotes/source/index.rst
+++ b/releasenotes/source/index.rst
@@ -6,6 +6,7 @@
:maxdepth: 1
unreleased
+ v22.0.0
v21.0.0
v20.0.0
v19.0.0
diff --git a/releasenotes/source/v22.0.0.rst b/releasenotes/source/v22.0.0.rst
new file mode 100644
index 0000000..519b081
--- /dev/null
+++ b/releasenotes/source/v22.0.0.rst
@@ -0,0 +1,6 @@
+=====================
+v22.0.0 Release Notes
+=====================
+
+.. release-notes:: 22.0.0 Release Notes
+ :version: 22.0.0
diff --git a/tempest/api/image/v2/test_images.py b/tempest/api/image/v2/test_images.py
index c938cee..5a27a43 100644
--- a/tempest/api/image/v2/test_images.py
+++ b/tempest/api/image/v2/test_images.py
@@ -57,6 +57,13 @@
self.assertIn('status', image)
self.assertEqual('queued', image['status'])
+ # NOTE: This Glance API returns different status codes for image
+ # condition. In this empty data case, Glance should return 204,
+ # so here should check the status code.
+ image_file = self.client.show_image_file(image['id'])
+ self.assertEqual(0, len(image_file.data))
+ self.assertEqual(204, image_file.response.status)
+
# Now try uploading an image file
file_content = data_utils.random_bytes()
image_file = six.BytesIO(file_content)
@@ -115,17 +122,6 @@
visibility='private')
self.assertEqual('queued', image['status'])
- # NOTE: This Glance API returns different status codes for image
- # condition. In this empty data case, Glance should return 204,
- # so here should check the status code.
- image_file = self.client.show_image_file(image['id'])
- self.assertEqual(0, len(image_file.data))
- self.assertEqual(204, image_file.response.status)
-
- # Now try uploading an image file
- image_file = six.BytesIO(data_utils.random_bytes())
- self.client.store_image_file(image['id'], image_file)
-
# Update Image
new_image_name = data_utils.rand_name('new-image')
self.client.update_image(image['id'], [
diff --git a/tempest/api/volume/admin/test_volume_pools.py b/tempest/api/volume/admin/test_volume_pools.py
index d389c26..744bc01 100644
--- a/tempest/api/volume/admin/test_volume_pools.py
+++ b/tempest/api/volume/admin/test_volume_pools.py
@@ -24,6 +24,7 @@
def _assert_pools(self, with_detail=False):
cinder_pools = self.admin_scheduler_stats_client.list_pools(
detail=with_detail)['pools']
+ self.assertNotEmpty(cinder_pools, "no cinder pools listed.")
self.assertIn('name', cinder_pools[0])
if with_detail:
self.assertIn(CONF.volume.vendor_name,
diff --git a/tempest/api/volume/test_versions.py b/tempest/api/volume/test_versions.py
index b4d48db..b602032 100644
--- a/tempest/api/volume/test_versions.py
+++ b/tempest/api/volume/test_versions.py
@@ -27,3 +27,15 @@
# with JSON-Schema validation. It is enough to just call
# the API here.
self.versions_client.list_versions()
+
+ @decorators.idempotent_id('7f755ae2-caa9-4049-988c-331d8f7a579f')
+ def test_show_version(self):
+ # NOTE: The version data is checked on service client side
+ # with JSON-Schema validation. So we will loop through each
+ # version and call show version.
+ versions = self.versions_client.list_versions()['versions']
+ for version_dict in versions:
+ version = version_dict['id']
+ major_version = version.split('.')[0]
+ response = self.versions_client.show_version(major_version)
+ self.assertEqual(version, response['versions'][0]['id'])
diff --git a/tempest/api/volume/test_volumes_backup.py b/tempest/api/volume/test_volumes_backup.py
index 6ce5d3e..c178272 100644
--- a/tempest/api/volume/test_volumes_backup.py
+++ b/tempest/api/volume/test_volumes_backup.py
@@ -50,7 +50,6 @@
'available')
return restored_volume
- @decorators.skip_because(bug="1483434")
@testtools.skipIf(CONF.volume.storage_protocol == 'ceph',
'ceph does not support arbitrary container names')
@decorators.idempotent_id('a66eb488-8ee1-47d4-8e9f-575a095728c6')
diff --git a/tempest/lib/base.py b/tempest/lib/base.py
index 3be55c0..74ae77c 100644
--- a/tempest/lib/base.py
+++ b/tempest/lib/base.py
@@ -14,11 +14,29 @@
# under the License.
import os
+import sys
import fixtures
+import pkg_resources
import testtools
+def _handle_skip_exception():
+ try:
+ stestr_version = pkg_resources.parse_version(
+ pkg_resources.get_distribution("stestr").version)
+ stestr_min = pkg_resources.parse_version('2.5.0')
+ new_stestr = (stestr_version >= stestr_min)
+ import unittest
+ import unittest2
+ if sys.version_info >= (3, 5) and new_stestr:
+ testtools.TestCase.skipException = unittest.case.SkipTest
+ else:
+ testtools.TestCase.skipException = unittest2.case.SkipTest
+ except Exception:
+ pass
+
+
class BaseTestCase(testtools.testcase.WithAttributes, testtools.TestCase):
setUpClassCalled = False
@@ -33,6 +51,18 @@
if hasattr(super(BaseTestCase, cls), 'setUpClass'):
super(BaseTestCase, cls).setUpClass()
cls.setUpClassCalled = True
+ # TODO(gmann): cls.handle_skip_exception is really workaround for
+ # testtools bug- https://github.com/testing-cabal/testtools/issues/272
+ # stestr which is used by Tempest internally to run the test switch
+ # the customize test runner(which use stdlib unittest) for >=py3.5
+ # else testtools.run.- https://github.com/mtreinish/stestr/pull/265
+ # These two test runner are not compatible due to skip exception
+ # handling(due to unittest2). testtools.run treat unittestt.SkipTest
+ # as error and stdlib unittest treat unittest2.case.SkipTest raised
+ # by testtools.TestCase.skipException.
+ # The below workaround can be removed once testtools fix issue# 272.
+ cls.orig_skip_exception = testtools.TestCase.skipException
+ _handle_skip_exception()
@classmethod
def tearDownClass(cls):
@@ -40,6 +70,7 @@
super(BaseTestCase, cls).tearDownClass()
def setUp(self):
+ testtools.TestCase.skipException = self.orig_skip_exception
super(BaseTestCase, self).setUp()
if not self.setUpClassCalled:
raise RuntimeError("setUpClass does not calls the super's "
diff --git a/tempest/lib/common/rest_client.py b/tempest/lib/common/rest_client.py
index f076727..431a0a0 100644
--- a/tempest/lib/common/rest_client.py
+++ b/tempest/lib/common/rest_client.py
@@ -547,24 +547,17 @@
req_url, req_headers, req_body = self.auth_provider.auth_request(
method, url, headers, body, self.filters)
- # Do the actual request, and time it
- start = time.time()
- self._log_request_start(method, req_url)
resp, resp_body = self.raw_request(
req_url, method, headers=req_headers, body=req_body,
chunked=chunked
)
- end = time.time()
- self._log_request(method, req_url, resp, secs=(end - start),
- req_headers=req_headers, req_body=req_body,
- resp_body=resp_body)
-
# Verify HTTP response codes
self.response_checker(method, resp, resp_body)
return resp, resp_body
- def raw_request(self, url, method, headers=None, body=None, chunked=False):
+ def raw_request(self, url, method, headers=None, body=None, chunked=False,
+ log_req_body=None):
"""Send a raw HTTP request without the keystone catalog or auth
This method sends a HTTP request in the same manner as the request()
@@ -580,14 +573,29 @@
explicitly requires no headers use an empty dict.
:param str body: Body to send with the request
:param bool chunked: sends the body with chunked encoding
+ :param str log_req_body: Whether to log the request body or not.
+ It is default to None which means request
+ body is safe to log otherwise pass any string
+ you want to log in place of request body.
+ For example: '<omitted>'
:rtype: tuple
:return: a tuple with the first entry containing the response headers
and the second the response body
"""
if headers is None:
headers = self.get_headers()
- return self.http_obj.request(url, method, headers=headers,
- body=body, chunked=chunked)
+ # Do the actual request, and time it
+ start = time.time()
+ self._log_request_start(method, url)
+ resp, resp_body = self.http_obj.request(
+ url, method, headers=headers,
+ body=body, chunked=chunked)
+ end = time.time()
+ req_body = body if log_req_body is None else log_req_body
+ self._log_request(method, url, resp, secs=(end - start),
+ req_headers=headers, req_body=req_body,
+ resp_body=resp_body)
+ return resp, resp_body
def request(self, method, url, extra_headers=False, headers=None,
body=None, chunked=False):
diff --git a/tempest/lib/services/compute/versions_client.py b/tempest/lib/services/compute/versions_client.py
index 8fbb136..c6e1783 100644
--- a/tempest/lib/services/compute/versions_client.py
+++ b/tempest/lib/services/compute/versions_client.py
@@ -12,8 +12,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import time
-
from oslo_serialization import jsonutils as json
from tempest.lib.api_schema.response.compute.v2_1 import versions as schema
@@ -26,11 +24,7 @@
def list_versions(self):
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)
body = json.loads(body)
diff --git a/tempest/lib/services/identity/v2/token_client.py b/tempest/lib/services/identity/v2/token_client.py
index 458c862..9f10f58 100644
--- a/tempest/lib/services/identity/v2/token_client.py
+++ b/tempest/lib/services/identity/v2/token_client.py
@@ -105,9 +105,8 @@
headers = self.get_headers(accept_type="json")
resp, resp_body = self.raw_request(url, method,
- headers=headers, body=body)
- self._log_request(method, url, resp, req_headers=headers,
- req_body='<omitted>', resp_body=resp_body)
+ headers=headers, body=body,
+ log_req_body='<omitted>')
if resp.status in [401, 403]:
resp_body = json.loads(resp_body)
diff --git a/tempest/lib/services/identity/v3/token_client.py b/tempest/lib/services/identity/v3/token_client.py
index d591f03..6956297 100644
--- a/tempest/lib/services/identity/v3/token_client.py
+++ b/tempest/lib/services/identity/v3/token_client.py
@@ -160,10 +160,8 @@
headers = self.get_headers(accept_type="json")
resp, resp_body = self.raw_request(url, method,
- headers=headers, body=body)
- self._log_request(method, url, resp, req_headers=headers,
- req_body='<omitted>', resp_body=resp_body)
-
+ headers=headers, body=body,
+ log_req_body='<omitted>')
if resp.status in [401, 403]:
resp_body = json.loads(resp_body)
raise exceptions.Unauthorized(resp_body['error']['message'])
diff --git a/tempest/lib/services/identity/v3/versions_client.py b/tempest/lib/services/identity/v3/versions_client.py
index 441ee0d..f3a8986 100644
--- a/tempest/lib/services/identity/v3/versions_client.py
+++ b/tempest/lib/services/identity/v3/versions_client.py
@@ -12,8 +12,6 @@
# 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
@@ -26,11 +24,7 @@
"""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)
diff --git a/tempest/lib/services/image/v2/versions_client.py b/tempest/lib/services/image/v2/versions_client.py
index 1adc466..1b7f806 100644
--- a/tempest/lib/services/image/v2/versions_client.py
+++ b/tempest/lib/services/image/v2/versions_client.py
@@ -12,8 +12,6 @@
# 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
@@ -26,11 +24,7 @@
"""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)
diff --git a/tempest/lib/services/volume/v1/backups_client.py b/tempest/lib/services/volume/v1/backups_client.py
index edc5dda..2289253 100644
--- a/tempest/lib/services/volume/v1/backups_client.py
+++ b/tempest/lib/services/volume/v1/backups_client.py
@@ -83,6 +83,9 @@
def import_backup(self, **kwargs):
"""Import backup metadata record."""
+ # TODO(linanbj): Current api-site doesn't contain this API description.
+ # After fixing the api-site, we need to fix here also for putting the
+ # link to api-site.
post_body = json.dumps({'backup-record': kwargs})
resp, body = self.post("backups/import_record", post_body)
body = json.loads(body)
diff --git a/tempest/lib/services/volume/v3/versions_client.py b/tempest/lib/services/volume/v3/versions_client.py
index fc8e92f..aa6c867 100644
--- a/tempest/lib/services/volume/v3/versions_client.py
+++ b/tempest/lib/services/volume/v3/versions_client.py
@@ -12,8 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-import os
-import time
+from six.moves.urllib.parse import urljoin
from oslo_serialization import jsonutils as json
@@ -33,14 +32,10 @@
"""
version_url = self._get_base_version_url()
- start = time.time()
resp, body = self.raw_request(version_url, 'GET')
- end = time.time()
# NOTE: We need a raw_request() here instead of request() call because
# "list API versions" API doesn't require an authentication and we can
# skip it with raw_request() call.
- self._log_request('GET', version_url, resp, secs=(end - start),
- resp_body=body)
self._error_checker(resp, body)
body = json.loads(body)
@@ -50,13 +45,18 @@
def show_version(self, version):
"""Show API version details
+ Use raw_request in order to have access to the endpoints minus
+ version and project in order to add version only back.
+
For a full list of available parameters, please refer to the official
API reference:
https://docs.openstack.org/api-ref/block-storage/v3/#show-api-v3-details
"""
- version_url = os.path.join(self._get_base_version_url(), version)
- resp, body = self.get(version_url)
+ version_url = urljoin(self._get_base_version_url(), version + '/')
+ resp, body = self.raw_request(version_url, 'GET',
+ {'X-Auth-Token': self.token})
+ self._error_checker(resp, body)
body = json.loads(body)
self.validate_response(schema.volume_api_version_details, resp, body)
return rest_client.ResponseBody(resp, body)
diff --git a/tempest/test.py b/tempest/test.py
index 85000b6..f383bc1 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -27,6 +27,7 @@
from tempest.common import credentials_factory as credentials
from tempest.common import utils
from tempest import config
+from tempest.lib import base as lib_base
from tempest.lib.common import fixed_network
from tempest.lib.common import profiler
from tempest.lib.common import validation_resources as vr
@@ -148,11 +149,25 @@
if hasattr(super(BaseTestCase, cls), 'setUpClass'):
super(BaseTestCase, cls).setUpClass()
# All the configuration checks that may generate a skip
- cls.skip_checks()
- if not cls.__skip_checks_called:
- raise RuntimeError("skip_checks for %s did not call the super's "
- "skip_checks" % cls.__name__)
+ # TODO(gmann): cls.handle_skip_exception is really workaround for
+ # testtools bug- https://github.com/testing-cabal/testtools/issues/272
+ # stestr which is used by Tempest internally to run the test switch
+ # the customize test runner(which use stdlib unittest) for >=py3.5
+ # else testtools.run.- https://github.com/mtreinish/stestr/pull/265
+ # These two test runner are not compatible due to skip exception
+ # handling(due to unittest2). testtools.run treat unittestt.SkipTest
+ # as error and stdlib unittest treat unittest2.case.SkipTest raised
+ # by testtools.TestCase.skipException.
+ # The below workaround can be removed once testtools fix issue# 272.
+ orig_skip_exception = testtools.TestCase.skipException
+ lib_base._handle_skip_exception()
try:
+ cls.skip_checks()
+
+ if not cls.__skip_checks_called:
+ raise RuntimeError(
+ "skip_checks for %s did not call the super's "
+ "skip_checks" % cls.__name__)
# Allocation of all required credentials and client managers
cls._teardowns.append(('credentials', cls.clear_credentials))
cls.setup_credentials()
@@ -173,6 +188,8 @@
six.reraise(etype, value, trace)
finally:
del trace # to avoid circular refs
+ finally:
+ testtools.TestCase.skipException = orig_skip_exception
@classmethod
def tearDownClass(cls):
diff --git a/tempest/tests/lib/fake_identity.py b/tempest/tests/lib/fake_identity.py
index 8bae34f..9d7b0fd 100644
--- a/tempest/tests/lib/fake_identity.py
+++ b/tempest/tests/lib/fake_identity.py
@@ -192,7 +192,7 @@
def _fake_v3_response(self, uri, method="GET", body=None, headers=None,
- redirections=5, connection_type=None):
+ redirections=5, connection_type=None, log_req_body=None):
fake_headers = {
"x-subject-token": TOKEN
}
@@ -202,7 +202,7 @@
def _fake_v3_response_domain_scope(self, uri, method="GET", body=None,
headers=None, redirections=5,
- connection_type=None):
+ connection_type=None, log_req_body=None):
fake_headers = {
"status": "201",
"x-subject-token": TOKEN
@@ -213,7 +213,7 @@
def _fake_v3_response_no_scope(self, uri, method="GET", body=None,
headers=None, redirections=5,
- connection_type=None):
+ connection_type=None, log_req_body=None):
fake_headers = {
"status": "201",
"x-subject-token": TOKEN
@@ -223,7 +223,7 @@
def _fake_v2_response(self, uri, method="GET", body=None, headers=None,
- redirections=5, connection_type=None):
+ redirections=5, connection_type=None, log_req_body=None):
return (fake_http.fake_http_response({}, status=200),
json.dumps(IDENTITY_V2_RESPONSE))
diff --git a/tempest/tests/lib/services/identity/v2/test_token_client.py b/tempest/tests/lib/services/identity/v2/test_token_client.py
index a592ada..5b4e210 100644
--- a/tempest/tests/lib/services/identity/v2/test_token_client.py
+++ b/tempest/tests/lib/services/identity/v2/test_token_client.py
@@ -86,6 +86,9 @@
with mock.patch.object(token_client_v2, 'raw_request') as mock_raw_r:
mock_raw_r.return_value = response, body
resp, body = token_client_v2.request('GET', 'fake_uri')
+ mock_raw_r.assert_called_once_with('fake_uri', 'GET',
+ headers=mock.ANY, body=None,
+ log_req_body='<omitted>')
self.assertIsInstance(body, dict)
def test_request_with_bytes_body(self):
diff --git a/tempest/tests/lib/services/identity/v3/test_projects_client.py b/tempest/tests/lib/services/identity/v3/test_projects_client.py
index 6ffbcde..d26de06 100644
--- a/tempest/tests/lib/services/identity/v3/test_projects_client.py
+++ b/tempest/tests/lib/services/identity/v3/test_projects_client.py
@@ -62,7 +62,8 @@
"/0c4e939acacf4376bdcd1129f1a054ad"
},
"name": "admin",
- "parent_id": None
+ "parent_id": None,
+ "tags": []
},
{
"is_domain": False,
@@ -75,7 +76,8 @@
"/0cbd49cbf76d405d9c86562e1d579bd3"
},
"name": "demo",
- "parent_id": None
+ "parent_id": None,
+ "tags": []
},
{
"is_domain": False,
@@ -88,7 +90,8 @@
"/2db68fed84324f29bb73130c6c2094fb"
},
"name": "swifttenanttest2",
- "parent_id": None
+ "parent_id": None,
+ "tags": []
},
{
"is_domain": False,
@@ -101,7 +104,8 @@
"/3d594eb0f04741069dbbb521635b21c7"
},
"name": "service",
- "parent_id": None
+ "parent_id": None,
+ "tags": []
}
]
}
diff --git a/tempest/tests/lib/services/identity/v3/test_token_client.py b/tempest/tests/lib/services/identity/v3/test_token_client.py
index a9c58df..656e10a 100644
--- a/tempest/tests/lib/services/identity/v3/test_token_client.py
+++ b/tempest/tests/lib/services/identity/v3/test_token_client.py
@@ -136,6 +136,9 @@
mock_raw_r.return_value = (
fake_identity._fake_v3_response(None, None))
resp, body = token_client_v3.request('GET', 'fake_uri')
+ mock_raw_r.assert_called_once_with('fake_uri', 'GET',
+ headers=mock.ANY, body=None,
+ log_req_body='<omitted>')
self.assertIsInstance(body, dict)
diff --git a/tempest/tests/lib/services/identity/v3/test_users_client.py b/tempest/tests/lib/services/identity/v3/test_users_client.py
index 5b572f5..c0dfdae 100644
--- a/tempest/tests/lib/services/identity/v3/test_users_client.py
+++ b/tempest/tests/lib/services/identity/v3/test_users_client.py
@@ -25,6 +25,11 @@
'enabled': True,
'name': 'Tempest User',
'password': 'TempestPassword',
+ "description": "Tempest User",
+ "email": "TempestUser@example.com",
+ "options": {
+ "ignore_password_expiry": True
+ }
}
}
@@ -104,6 +109,38 @@
]
}
+ FAKE_PROJECT_LIST = {
+ "links": {
+ "self": "http://example.com/identity/v3/users/313233/projects",
+ "previous": None,
+ "next": None
+ },
+ "projects": [
+ {
+ "description": "description of this project",
+ "domain_id": "161718",
+ "enabled": True,
+ "id": "456788",
+ "links": {
+ "self": "http://example.com/identity/v3/projects/456788"
+ },
+ "name": "a project name",
+ "parent_id": "212223"
+ },
+ {
+ "description": "description of this project",
+ "domain_id": "161718",
+ "enabled": True,
+ "id": "456789",
+ "links": {
+ "self": "http://example.com/identity/v3/projects/456789"
+ },
+ "name": "another domain",
+ "parent_id": "212223"
+ },
+ ]
+ }
+
def setUp(self):
super(TestUsersClient, self).setUp()
fake_auth = fake_auth_provider.FakeAuthProvider()
@@ -155,6 +192,15 @@
user_id='817fb3c23fd7465ba6d7fe1b1320121d',
)
+ def _test_list_user_projects(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_user_projects,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_PROJECT_LIST,
+ bytes_body,
+ user_id='817fb3c23fd7465ba6d7fe1b1320121d',
+ )
+
def test_create_user_with_string_body(self):
self._test_create_user()
@@ -185,6 +231,12 @@
def test_list_user_groups_with_bytes_body(self):
self._test_list_user_groups(bytes_body=True)
+ def test_list_user_projects_with_string_body(self):
+ self._test_list_user_projects()
+
+ def test_list_user_projects_with_bytes_body(self):
+ self._test_list_user_projects(bytes_body=True)
+
def test_delete_user(self):
self.check_service_client_function(
self.client.delete_user,
diff --git a/tempest/tests/lib/services/volume/v3/test_versions_client.py b/tempest/tests/lib/services/volume/v3/test_versions_client.py
index b9abd45..575cae3 100644
--- a/tempest/tests/lib/services/volume/v3/test_versions_client.py
+++ b/tempest/tests/lib/services/volume/v3/test_versions_client.py
@@ -97,6 +97,14 @@
'volume',
'regionOne')
+ def _test_get_base_version_url(self, url, expected_base_url):
+ fake_auth = fake_auth_provider.FakeAuthProvider(fake_base_url=url)
+ client = versions_client.VersionsClient(fake_auth,
+ 'volume',
+ 'regionOne')
+ self.assertEqual(expected_base_url,
+ client._get_base_version_url())
+
def _test_list_versions(self, bytes_body=False):
self.check_service_client_function(
self.client.list_versions,
@@ -105,22 +113,30 @@
bytes_body,
300)
+ def _test_show_version(self, version, bytes_body=False):
+ self.check_service_client_function(
+ self.client.show_version,
+ 'tempest.lib.common.rest_client.RestClient.raw_request',
+ self.FAKE_VERSION_DETAILS,
+ bytes_body,
+ 200, version=version)
+
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)
- def _test_show_version(self, bytes_body=False):
- self.check_service_client_function(
- self.client.show_version,
- 'tempest.lib.common.rest_client.RestClient.get',
- self.FAKE_VERSION_DETAILS,
- bytes_body,
- 200, version='v3')
-
def test_show_version_details_with_str_body(self):
- self._test_show_version()
+ self._test_show_version('v3')
def test_show_version_details_with_bytes_body(self):
- self._test_show_version(bytes_body=True)
+ self._test_show_version('v3', bytes_body=True)
+
+ def test_get_base_version_url_app_name(self):
+ self._test_get_base_version_url('https://bar.org/volume/v1/123',
+ 'https://bar.org/volume/')
+ self._test_get_base_version_url('https://bar.org/volume/v2/123',
+ 'https://bar.org/volume/')
+ self._test_get_base_version_url('https://bar.org/volume/v3/123',
+ 'https://bar.org/volume/')
diff --git a/tempest/tests/lib/services/volume/v3/test_volumes_client.py b/tempest/tests/lib/services/volume/v3/test_volumes_client.py
index 1250536..56c1a35 100644
--- a/tempest/tests/lib/services/volume/v3/test_volumes_client.py
+++ b/tempest/tests/lib/services/volume/v3/test_volumes_client.py
@@ -24,27 +24,25 @@
FAKE_VOLUME_SUMMARY = {
"volume-summary": {
- "total_size": 20,
- "total_count": 5
+ "total_size": 4,
+ "total_count": 4,
+ "metadata": {
+ "key1": ["value1", "value2"],
+ "key2": ["value2"]
+ }
}
}
FAKE_VOLUME_METADATA_ITEM = {
"meta": {
- "key1": "value1"
+ "name": "metadata1"
}
}
FAKE_VOLUME_IMAGE_METADATA = {
"metadata": {
- "container_format": "bare",
- "min_ram": "0",
- "disk_format": "raw",
- "image_name": "xly-ubuntu16-server",
- "image_id": "3e087b0c-10c5-4255-b147-6e8e9dbad6fc",
- "checksum": "008f5d22fe3cb825d714da79607a90f9",
- "min_disk": "0",
- "size": "8589934592"
+ "key1": "value1",
+ "key2": "value2"
}
}
diff --git a/tempest/tests/lib/test_base.py b/tempest/tests/lib/test_base.py
index 27cda1a..2c16e1c 100644
--- a/tempest/tests/lib/test_base.py
+++ b/tempest/tests/lib/test_base.py
@@ -48,6 +48,7 @@
@classmethod
def setUpClass(cls): # noqa
"""Simulate absence of super() call."""
+ cls.orig_skip_exception = cls.skipException
def setUp(self):
try:
diff --git a/tempest/tests/test_test.py b/tempest/tests/test_test.py
index fc50736..49fd010 100644
--- a/tempest/tests/test_test.py
+++ b/tempest/tests/test_test.py
@@ -532,13 +532,14 @@
# If a skip condition is hit in the test, no credentials or resource
# is provisioned / cleaned-up
self.mocks['skip_checks'].side_effect = (
- testtools.testcase.TestSkipped())
+ testtools.TestCase.skipException())
suite = unittest.TestSuite((self.test,))
log = []
result = LoggingTestResult(log)
suite.run(result)
# If we trigger a skip condition, teardown is not invoked at all
- self.assertEqual(self.SETUP_FIXTURES[:2],
+ self.assertEqual((self.SETUP_FIXTURES[:2] +
+ [self.TEARDOWN_FIXTURES[0]]),
self.test.fixtures_invoked)
def test_skip_credentials_fails(self):
diff --git a/tools/generate-tempest-plugins-list.py b/tools/generate-tempest-plugins-list.py
index 255487e..64adcbe 100644
--- a/tools/generate-tempest-plugins-list.py
+++ b/tools/generate-tempest-plugins-list.py
@@ -35,8 +35,6 @@
# TODO(masayukig): Some of these can be removed from BLACKLIST in the future
# when the patches are merged.
BLACKLIST = [
- 'openstack/barbican-tempest-plugin',
- # https://review.opendev.org/#/c/634631/
'x/gce-api', # It looks gce-api doesn't support python3 yet.
'x/group-based-policy', # It looks this doesn't support python3 yet.
'x/intel-nfv-ci-tests', # https://review.opendev.org/#/c/634640/