Merge "Add additional roles method to v3 roles client."
diff --git a/doc/source/configuration.rst b/doc/source/configuration.rst
index 18269bf..2314222 100644
--- a/doc/source/configuration.rst
+++ b/doc/source/configuration.rst
@@ -9,6 +9,8 @@
config file which explains the purpose of each individual option. You can see
the sample config file here: :ref:`tempest-sampleconf`
+.. _tempest_cred_provider_conf:
+
Test Credentials
----------------
@@ -232,6 +234,9 @@
Enabling Remote Access to Created Servers
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. _tempest_conf_network_allocation:
+
Network Creation/Usage for Servers
""""""""""""""""""""""""""""""""""
When Tempest creates servers for testing, some tests require being able to
diff --git a/doc/source/index.rst b/doc/source/index.rst
index 896cd98..1264ecc 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -67,7 +67,8 @@
HACKING
REVIEWING
microversion_testing
- test-removal
+ test_removal
+ write_tests
-------
Plugins
diff --git a/doc/source/plugin.rst b/doc/source/plugin.rst
index 6b30825..b3af92f 100644
--- a/doc/source/plugin.rst
+++ b/doc/source/plugin.rst
@@ -1,3 +1,5 @@
+.. _tempest_plugin:
+
=============================
Tempest Test Plugin Interface
=============================
diff --git a/doc/source/test-removal.rst b/doc/source/test_removal.rst
similarity index 100%
rename from doc/source/test-removal.rst
rename to doc/source/test_removal.rst
diff --git a/doc/source/write_tests.rst b/doc/source/write_tests.rst
new file mode 100644
index 0000000..768bf0f
--- /dev/null
+++ b/doc/source/write_tests.rst
@@ -0,0 +1,243 @@
+.. _tempest_test_writing:
+
+Tempest Test Writing Guide
+==========================
+
+This guide serves as a starting point for developers working on writing new
+Tempest tests. At a high level tests in Tempest are just tests that conform to
+the standard python `unit test`_ framework. But there are several aspects of
+that are unique to tempest and it's role as an integration test suite running
+against a real cloud.
+
+.. _unit test: https://docs.python.org/3.6/library/unittest.html
+
+.. note:: This guide is for writing tests in the tempest repository. While many
+ parts of this guide are also applicable to tempest plugins, not all
+ the APIs mentioned are considered stable or recommended for use in
+ plugins. Please refer to :ref:`tempest_plugin` for details about
+ writing plugins
+
+
+Adding a New TestCase
+=====================
+
+The base unit of testing in Tempest is the `TestCase`_ (also called the test
+class). Each TestCase contains test methods which are the individual tests that
+will be executed by the test runner. But, the TestCase is the smallest self
+contained unit for tests from the tempest perspective. It's also the level at
+which tempest is parallel safe. In other words, multiple TestCases can be
+executed in parallel, but individual test methods in the same TestCase can not.
+Also, all test methods within a TestCase are assumed to be executed serially. As
+such you can use the test case to store variables that are shared between
+methods.
+
+.. _TestCase: https://docs.python.org/3.6/library/unittest.html#unittest.TestCase
+
+In standard unittest the lifecycle of a TestCase can be described in the
+following phases:
+
+ #. setUpClass
+ #. setUp
+ #. Test Execution
+ #. tearDown
+ #. doCleanups
+ #. tearDownClass
+
+setUpClass
+----------
+
+The setUpClass phase is the first phase executed by the test runner and is used
+to perform any setup required for all the test methods to be executed. In
+Tempest this is a very important step and will automatically do the necessary
+setup for interacting with the configured cloud.
+
+To accomplish this you do **not** define a setUpClass function, instead there
+are a number of predefined phases to setUpClass that are used. The phases are:
+
+ * skip_checks
+ * setup_credentials
+ * setup_clients
+ * resource_setup
+
+which is executed in that order. An example of a TestCase which defines all
+of these would be::
+
+ from tempest import config
+ from tempest import test
+
+ CONF = config.CONF
+
+
+ class TestExampleCase(test.BaseTestCase):
+
+ @classmethod
+ def skip_checks(cls):
+ """This section is used to evaluate config early and skip all test
+ methods based on these checks
+ """
+ super(TestExampleCase, cls).skip_checks()
+ if not CONF.section.foo
+ cls.skip('A helpful message')
+
+ @classmethod
+ def setup_credentials(cls):
+ """This section is used to do any manual credential allocation and also
+ in the case of dynamic credentials to override the default network
+ resource creation/auto allocation
+ """
+ # This call is used to tell the credential allocator to not create any
+ # network resources for this test case. It also enables selective
+ # creation of other neutron resources. NOTE: it must go before the
+ # super call
+ cls.set_network_resources()
+ super(TestExampleCase, cls).setup_credentials()
+
+ @classmethod
+ def setup_clients(cls):
+ """This section is used to setup client aliases from the manager object
+ or to initialize any additional clients. Except in a few very
+ specific situations you should not need to use this.
+ """
+ super(TestExampleCase, cls).setup_clients()
+ cls.servers_client = cls.os.servers_client
+
+ @classmethod
+ def resource_setup(cls):
+ """This section is used to create any resources or objects which are
+ going to be used and shared by **all** test methods in the
+ TestCase. Note then anything created in this section must also be
+ destroyed in the corresponding resource_cleanup() method (which will
+ be run during tearDownClass())
+ """
+ super(TestExampleCase, cls).resource_setup()
+ cls.shared_server = cls.servers_client.create_server(...)
+
+
+Allocating Credentials
+''''''''''''''''''''''
+
+Since Tempest tests are all about testing a running cloud, every test will need
+credentials to be able to make API requests against the cloud. Since this is
+critical to operation and, when running in parallel, easy to make a mistake,
+the base TestCase class will automatically allocate a regular user for each
+TestCase during the setup_credentials() phase. During this process it will also
+initialize a client manager object using those credentials, which will be your
+entry point into interacting with the cloud. For more details on how credentials
+are allocated the :ref:`tempest_cred_provider_conf` section of the Tempest
+Configuration Guide provides more details on the operation of this.
+
+There are some cases when you need more than a single set of credentials, or
+credentials with a more specialized set of roles. To accomplish this you have
+to set a class variable ``credentials`` on the TestCase directly. For example::
+
+ from tempest import test
+
+ class TestExampleAdmin(test.BaseTestCase):
+
+ credentials = ['primary', 'admin']
+
+ @classmethod
+ def skip_checks(cls):
+ ...
+
+In this example the ``TestExampleAdmin`` TestCase will allocate 2 sets of
+credentials, one regular user and one admin user. The corresponding manager
+objects will be set as class variables cls.os and cls.os_adm respectively. You
+can also allocate a second user by putting **'alt'** in the list too. A set of
+alt credentials are the same as primary but can be used for tests cases that
+need a second user/project.
+
+You can also specify credentials with specific roles assigned. This is useful
+for cases where there are specific RBAC requirements hard coded into an API.
+The canonical example of this are swift tests which often want to test swift's
+concepts of operator and reseller_admin. An actual example from tempest on how
+to do this is::
+
+ class PublicObjectTest(base.BaseObjectTest):
+
+ credentials = [['operator', CONF.object_storage.operator_role],
+ ['operator_alt', CONF.object_storage.operator_role]]
+
+ @classmethod
+ def setup_credentials(cls):
+ super(PublicObjectTest, cls).setup_credentials()
+ ...
+
+In this case the manager objects will be set to ``cls.os_roles_operator`` and
+``cls.os_roles_operator_alt`` respectively.
+
+
+There is no limit to how many credentials you can allocate in this manner,
+however in almost every case you should **not** need more than 3 sets of
+credentials per test case.
+
+To figure out the mapping of manager objects set on the TestCase and the
+requested credentials you can reference:
+
++-------------------+---------------------+
+| Credentials Entry | Manager Variable |
++===================+=====================+
+| primary | cls.os |
++-------------------+---------------------+
+| admin | cls.os_adm |
++-------------------+---------------------+
+| alt | cls.os_alt |
++-------------------+---------------------+
+| [$label, $role] | cls.os_roles_$label |
++-------------------+---------------------+
+
+By default cls.os is available since it is allocated in the base tempest test
+class. (located in tempest/test.py) If your TestCase inherits from a different
+direct parent class (it'll still inherit from the BaseTestCase, just not
+directly) be sure to check if that class overrides allocated credentials.
+
+Dealing with Network Allocation
+'''''''''''''''''''''''''''''''
+
+When neutron is enabled and a testing requires networking this isn't normally
+automatically setup when a tenant is created. Since tempest needs isolated
+tenants to function properly it also needs to handle network allocation. By
+default the base test class will allocate a network, subnet, and router
+automatically. (this depends on the configured credential provider, for more
+details see: :ref:`tempest_conf_network_allocation`) However, there are
+situations where you do no need all of these resources allocated. (or your
+TestCase inherits from a class that overrides the default in tempest/test.py)
+There is a class level mechanism to override this allocation and specify which
+resources you need. To do this you need to call `cls.set_network_resources()`
+in the `setup_credentials()` method before the `super()`. For example::
+
+ from tempest import test
+
+
+ class TestExampleCase(test.BaseTestCase):
+
+ @classmethod
+ def setup_credentials(cls):
+ cls.set_network_resources(network=True, subnet=True, router=False)
+ super(TestExampleCase, cls).setup_credentials()
+
+There are 2 quirks with the usage here. First for the set_network_resources
+function to work properly it **must be called before super()**. This is so
+that children classes' settings are always used instead of a parent classes'.
+The other quirk here is that if you do not want to allocate any network
+resources for your test class simply call `set_network_resources()` without
+any arguments. For example::
+
+ from tempest import test
+
+
+ class TestExampleCase(test.BaseTestCase):
+
+ @classmethod
+ def setup_credentials(cls):
+ cls.set_network_resources()
+ super(TestExampleCase, cls).setup_credentials()
+
+This will not allocate any networking resources. This is because by default all
+the arguments default to False.
+
+It's also worth pointing out that it is common for base test classes for
+different services (and scenario tests) to override this setting. When
+inheriting from classes other than the base TestCase in tempest/test.py it is
+worth checking the immediate parent for what is set to determine if your
+class needs to override that setting.
diff --git a/releasenotes/notes/add-OAUTH-Consumer-Client-tempest-tests-db1df7aae4a9fd4e.yaml b/releasenotes/notes/add-OAUTH-Consumer-Client-tempest-tests-db1df7aae4a9fd4e.yaml
new file mode 100644
index 0000000..6b45666
--- /dev/null
+++ b/releasenotes/notes/add-OAUTH-Consumer-Client-tempest-tests-db1df7aae4a9fd4e.yaml
@@ -0,0 +1,3 @@
+---
+features:
+ - Add a new client to handle the OAUTH consumers feature from the identity API.
diff --git a/requirements.txt b/requirements.txt
index 92825a7..7c934c2 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -10,7 +10,7 @@
testrepository>=0.0.18 # Apache-2.0/BSD
oslo.concurrency>=3.8.0 # Apache-2.0
oslo.config>=3.22.0 # Apache-2.0
-oslo.log>=3.11.0 # Apache-2.0
+oslo.log>=3.22.0 # Apache-2.0
oslo.serialization>=1.10.0 # Apache-2.0
oslo.utils>=3.20.0 # Apache-2.0
six>=1.9.0 # MIT
diff --git a/tempest/api/compute/servers/test_list_server_filters.py b/tempest/api/compute/servers/test_list_server_filters.py
index 12eb5e1..1ad153a 100644
--- a/tempest/api/compute/servers/test_list_server_filters.py
+++ b/tempest/api/compute/servers/test_list_server_filters.py
@@ -48,23 +48,25 @@
cls.fixed_network_name = None
network_kwargs = fixed_network.set_networks_kwarg(network)
cls.s1_name = data_utils.rand_name(cls.__name__ + '-instance')
- cls.s1 = cls.create_test_server(name=cls.s1_name,
- wait_until='ACTIVE',
- **network_kwargs)
+ cls.s1 = cls.create_test_server(name=cls.s1_name, **network_kwargs)
cls.s2_name = data_utils.rand_name(cls.__name__ + '-instance')
# If image_ref_alt is "" or None then we still want to boot a server
# but we rely on `testtools.skipUnless` decorator to actually skip
# the irrelevant tests.
cls.s2 = cls.create_test_server(
- name=cls.s2_name, image_id=cls.image_ref_alt or cls.image_ref,
- wait_until='ACTIVE')
+ name=cls.s2_name, image_id=cls.image_ref_alt or cls.image_ref)
cls.s3_name = data_utils.rand_name(cls.__name__ + '-instance')
cls.s3 = cls.create_test_server(name=cls.s3_name,
flavor=cls.flavor_ref_alt,
wait_until='ACTIVE')
+ waiters.wait_for_server_status(cls.client, cls.s1['id'],
+ 'ACTIVE')
+ waiters.wait_for_server_status(cls.client, cls.s2['id'],
+ 'ACTIVE')
+
@decorators.idempotent_id('05e8a8e7-9659-459a-989d-92c2f501f4ba')
@testtools.skipUnless(CONF.compute.image_ref != CONF.compute.image_ref_alt,
"Need distinct images to run this test")
diff --git a/tempest/api/identity/admin/v3/test_oauth_consumers.py b/tempest/api/identity/admin/v3/test_oauth_consumers.py
new file mode 100644
index 0000000..f06fb8f
--- /dev/null
+++ b/tempest/api/identity/admin/v3/test_oauth_consumers.py
@@ -0,0 +1,91 @@
+# Copyright 2017 AT&T 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.api.identity import base
+from tempest.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
+from tempest.lib import decorators
+from tempest.lib import exceptions as exceptions
+
+
+class OAUTHConsumersV3Test(base.BaseIdentityV3AdminTest):
+
+ def _create_consumer(self):
+ """Creates a consumer with a random description."""
+ description = data_utils.rand_name('test_create_consumer')
+ consumer = self.oauth_consumers_client.create_consumer(
+ description)['consumer']
+ # cleans up created consumers after tests
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.oauth_consumers_client.delete_consumer,
+ consumer['id'])
+ return consumer
+
+ @decorators.idempotent_id('c8307ea6-a86c-47fd-ae7b-5b3b2caca76d')
+ def test_create_and_show_consumer(self):
+ """Tests to make sure that a consumer with parameters is made"""
+ consumer = self._create_consumer()
+ # fetch created consumer from client
+ fetched_consumer = self.oauth_consumers_client.show_consumer(
+ consumer['id'])['consumer']
+ # assert that the fetched consumer matches the created one and
+ # has all parameters
+ for key in ['description', 'id', 'links']:
+ self.assertEqual(consumer[key], fetched_consumer[key])
+
+ @decorators.idempotent_id('fdfa1b7f-2a31-4354-b2c7-f6ae20554f93')
+ def test_delete_consumer(self):
+ """Tests the delete function."""
+ consumer = self._create_consumer()
+ # fetch consumer from client to confirm it exists
+ fetched_consumer = self.oauth_consumers_client.show_consumer(
+ consumer['id'])['consumer']
+ self.assertEqual(consumer['id'], fetched_consumer['id'])
+ # delete existing consumer
+ self.oauth_consumers_client.delete_consumer(consumer['id'])
+ # check that consumer no longer exists
+ self.assertRaises(exceptions.NotFound,
+ self.oauth_consumers_client.show_consumer,
+ consumer['id'])
+
+ @decorators.idempotent_id('080a9b1a-c009-47c0-9979-5305bf72e3dc')
+ def test_update_consumer(self):
+ """Tests the update functionality"""
+ # create a new consumer to update
+ consumer = self._create_consumer()
+ # create new description
+ new_description = data_utils.rand_name('test_update_consumer')
+ # update consumer
+ self.oauth_consumers_client.update_consumer(consumer['id'],
+ new_description)
+ # check that the same consumer now has the new description
+ updated_consumer = self.oauth_consumers_client.show_consumer(
+ consumer['id'])['consumer']
+ self.assertEqual(new_description, updated_consumer['description'])
+
+ @decorators.idempotent_id('09ca50de-78f2-4ffb-ac71-f2254036b2b8')
+ def test_list_consumers(self):
+ """Test for listing consumers"""
+ # create two consumers to populate list
+ new_consumer_one = self._create_consumer()
+ new_consumer_two = self._create_consumer()
+ # fetch the list of consumers
+ consumer_list = self.oauth_consumers_client \
+ .list_consumers()['consumers']
+ # add fetched consumer ids to a list
+ id_list = [consumer['id'] for consumer in consumer_list]
+ # check if created consumers are in the list
+ self.assertIn(new_consumer_one['id'], id_list)
+ self.assertIn(new_consumer_two['id'], id_list)
diff --git a/tempest/api/identity/base.py b/tempest/api/identity/base.py
index 9339d3c..8317535 100644
--- a/tempest/api/identity/base.py
+++ b/tempest/api/identity/base.py
@@ -212,6 +212,7 @@
cls.groups_client = cls.os_adm.groups_client
cls.projects_client = cls.os_adm.projects_client
cls.role_assignments = cls.os_admin.role_assignments_client
+ cls.oauth_consumers_client = cls.os_adm.oauth_consumers_client
if CONF.identity.admin_domain_scope:
# NOTE(andreaf) When keystone policy requires it, the identity
# admin clients for these tests shall use 'domain' scoped tokens.
diff --git a/tempest/api/volume/admin/v2/test_backends_capabilities.py b/tempest/api/volume/admin/test_backends_capabilities.py
similarity index 100%
rename from tempest/api/volume/admin/v2/test_backends_capabilities.py
rename to tempest/api/volume/admin/test_backends_capabilities.py
diff --git a/tempest/api/volume/admin/v2/test_snapshot_manage.py b/tempest/api/volume/admin/test_snapshot_manage.py
similarity index 100%
rename from tempest/api/volume/admin/v2/test_snapshot_manage.py
rename to tempest/api/volume/admin/test_snapshot_manage.py
diff --git a/tempest/api/volume/admin/v3/test_user_messages.py b/tempest/api/volume/admin/test_user_messages.py
similarity index 96%
rename from tempest/api/volume/admin/v3/test_user_messages.py
rename to tempest/api/volume/admin/test_user_messages.py
index 991397a..20c3538 100755
--- a/tempest/api/volume/admin/v3/test_user_messages.py
+++ b/tempest/api/volume/admin/test_user_messages.py
@@ -13,7 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-from tempest.api.volume.v3 import base
+from tempest.api.volume import base
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
@@ -33,7 +33,8 @@
'links']
-class UserMessagesTest(base.VolumesV3AdminTest):
+class UserMessagesTest(base.BaseVolumeAdminTest):
+ _api_version = 3
min_microversion = '3.3'
max_microversion = 'latest'
diff --git a/tempest/api/volume/admin/v2/test_volume_manage.py b/tempest/api/volume/admin/test_volume_manage.py
similarity index 96%
rename from tempest/api/volume/admin/v2/test_volume_manage.py
rename to tempest/api/volume/admin/test_volume_manage.py
index f983490..a039085 100644
--- a/tempest/api/volume/admin/v2/test_volume_manage.py
+++ b/tempest/api/volume/admin/test_volume_manage.py
@@ -22,11 +22,11 @@
CONF = config.CONF
-class VolumeManageAdminV2Test(base.BaseVolumeAdminTest):
+class VolumeManageAdminTest(base.BaseVolumeAdminTest):
@classmethod
def skip_checks(cls):
- super(VolumeManageAdminV2Test, cls).skip_checks()
+ super(VolumeManageAdminTest, cls).skip_checks()
if not CONF.volume_feature_enabled.manage_volume:
raise cls.skipException("Manage volume tests are disabled")
diff --git a/tempest/api/volume/admin/v2/test_volume_pools.py b/tempest/api/volume/admin/test_volume_pools.py
similarity index 100%
rename from tempest/api/volume/admin/v2/test_volume_pools.py
rename to tempest/api/volume/admin/test_volume_pools.py
diff --git a/tempest/api/volume/admin/v2/test_volume_type_access.py b/tempest/api/volume/admin/test_volume_type_access.py
similarity index 100%
rename from tempest/api/volume/admin/v2/test_volume_type_access.py
rename to tempest/api/volume/admin/test_volume_type_access.py
diff --git a/tempest/api/volume/admin/v2/test_volumes_list.py b/tempest/api/volume/admin/test_volumes_list.py
similarity index 100%
rename from tempest/api/volume/admin/v2/test_volumes_list.py
rename to tempest/api/volume/admin/test_volumes_list.py
diff --git a/tempest/api/volume/admin/v2/__init__.py b/tempest/api/volume/admin/v2/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tempest/api/volume/admin/v2/__init__.py
+++ /dev/null
diff --git a/tempest/api/volume/admin/v3/__init__.py b/tempest/api/volume/admin/v3/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tempest/api/volume/admin/v3/__init__.py
+++ /dev/null
diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py
index 2f719c8..0cd5ec7 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -13,9 +13,11 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest.api.volume import api_microversion_fixture
from tempest.common import compute
from tempest.common import waiters
from tempest import config
+from tempest.lib.common import api_version_utils
from tempest.lib.common.utils import data_utils
from tempest.lib.common.utils import test_utils
from tempest.lib import exceptions
@@ -24,7 +26,8 @@
CONF = config.CONF
-class BaseVolumeTest(tempest.test.BaseTestCase):
+class BaseVolumeTest(api_version_utils.BaseMicroversionTest,
+ tempest.test.BaseTestCase):
"""Base test case class for all Cinder API tests."""
_api_version = 2
@@ -49,6 +52,10 @@
msg = ("Invalid Cinder API version (%s)" % cls._api_version)
raise exceptions.InvalidConfiguration(msg)
+ api_version_utils.check_skip_with_microversion(
+ cls.min_microversion, cls.max_microversion,
+ CONF.volume.min_microversion, CONF.volume.max_microversion)
+
@classmethod
def setup_credentials(cls):
cls.set_network_resources()
@@ -68,10 +75,21 @@
cls.availability_zone_client = (
cls.os.volume_v2_availability_zone_client)
cls.volume_limits_client = cls.os.volume_v2_limits_client
+ cls.messages_client = cls.os.volume_v3_messages_client
+ cls.versions_client = cls.os.volume_v3_versions_client
+
+ def setUp(self):
+ super(BaseVolumeTest, self).setUp()
+ self.useFixture(api_microversion_fixture.APIMicroversionFixture(
+ self.request_microversion))
@classmethod
def resource_setup(cls):
super(BaseVolumeTest, cls).resource_setup()
+ cls.request_microversion = (
+ api_version_utils.select_request_microversion(
+ cls.min_microversion,
+ CONF.volume.min_microversion))
cls.snapshots = []
cls.volumes = []
@@ -240,6 +258,8 @@
cls.os_adm.volume_capabilities_v2_client
cls.admin_scheduler_stats_client = \
cls.os_adm.volume_scheduler_stats_v2_client
+ cls.admin_messages_client = cls.os_adm.volume_v3_messages_client
+ cls.admin_volume_types_client = cls.os_adm.volume_types_v2_client
@classmethod
def resource_setup(cls):
diff --git a/tempest/api/volume/v2/test_image_metadata.py b/tempest/api/volume/test_image_metadata.py
similarity index 100%
rename from tempest/api/volume/v2/test_image_metadata.py
rename to tempest/api/volume/test_image_metadata.py
diff --git a/tempest/api/volume/v3/test_versions.py b/tempest/api/volume/test_versions.py
similarity index 90%
rename from tempest/api/volume/v3/test_versions.py
rename to tempest/api/volume/test_versions.py
index 20f1657..76f2a99 100644
--- a/tempest/api/volume/v3/test_versions.py
+++ b/tempest/api/volume/test_versions.py
@@ -12,12 +12,14 @@
# License for the specific language governing permissions and limitations
# under the License.
-from tempest.api.volume.v3 import base
+from tempest.api.volume import base
from tempest.lib import decorators
from tempest import test
-class VersionsTest(base.VolumesV3Test):
+class VersionsTest(base.BaseVolumeTest):
+
+ _api_version = 3
@decorators.idempotent_id('77838fc4-b49b-4c64-9533-166762517369')
@test.attr(type='smoke')
diff --git a/tempest/api/volume/test_volumes_backup.py b/tempest/api/volume/test_volumes_backup.py
index f6fd86e..925beee 100644
--- a/tempest/api/volume/test_volumes_backup.py
+++ b/tempest/api/volume/test_volumes_backup.py
@@ -66,7 +66,8 @@
description = data_utils.rand_name("volume-backup-description")
backup = self.create_backup(volume_id=volume['id'],
name=backup_name,
- description=description)
+ description=description,
+ container='container')
self.assertEqual(backup_name, backup['name'])
waiters.wait_for_volume_resource_status(self.volumes_client,
volume['id'], 'available')
@@ -75,6 +76,7 @@
backup = self.backups_client.show_backup(backup['id'])['backup']
self.assertEqual(backup_name, backup['name'])
self.assertEqual(description, backup['description'])
+ self.assertEqual('container', backup['container'])
# Get all backups with detail
backups = self.backups_client.list_backups(
diff --git a/tempest/api/volume/test_volumes_snapshots_negative.py b/tempest/api/volume/test_volumes_snapshots_negative.py
index 6e6cd35..2e30d04 100644
--- a/tempest/api/volume/test_volumes_snapshots_negative.py
+++ b/tempest/api/volume/test_volumes_snapshots_negative.py
@@ -68,3 +68,17 @@
self.assertRaises(lib_exc.BadRequest,
self.snapshots_client.list_snapshots,
limit='invalid')
+
+ @test.attr(type=['negative'])
+ @decorators.idempotent_id('27b5f37f-bf69-4e8c-986e-c44f3d6819b8')
+ def test_list_snapshots_invalid_param_sort(self):
+ self.assertRaises(lib_exc.BadRequest,
+ self.snapshots_client.list_snapshots,
+ sort_key='invalid')
+
+ @test.attr(type=['negative'])
+ @decorators.idempotent_id('b68deeda-ca79-4a32-81af-5c51179e553a')
+ def test_list_snapshots_invalid_param_marker(self):
+ self.assertRaises(lib_exc.NotFound,
+ self.snapshots_client.list_snapshots,
+ marker=data_utils.rand_uuid())
diff --git a/tempest/api/volume/v2/test_volumes_snapshots_negative.py b/tempest/api/volume/v2/test_volumes_snapshots_negative.py
deleted file mode 100644
index 42ae859..0000000
--- a/tempest/api/volume/v2/test_volumes_snapshots_negative.py
+++ /dev/null
@@ -1,46 +0,0 @@
-# Copyright 2017 Red Hat, Inc.
-# 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.api.volume import base
-from tempest import config
-from tempest.lib.common.utils import data_utils
-from tempest.lib import decorators
-from tempest.lib import exceptions as lib_exc
-from tempest import test
-
-CONF = config.CONF
-
-
-class VolumesSnapshotNegativeTest(base.BaseVolumeTest):
-
- @classmethod
- def skip_checks(cls):
- super(VolumesSnapshotNegativeTest, cls).skip_checks()
- if not CONF.volume_feature_enabled.snapshot:
- raise cls.skipException("Cinder volume snapshots are disabled")
-
- @test.attr(type=['negative'])
- @decorators.idempotent_id('27b5f37f-bf69-4e8c-986e-c44f3d6819b8')
- def test_list_snapshots_invalid_param_sort(self):
- self.assertRaises(lib_exc.BadRequest,
- self.snapshots_client.list_snapshots,
- sort_key='invalid')
-
- @test.attr(type=['negative'])
- @decorators.idempotent_id('b68deeda-ca79-4a32-81af-5c51179e553a')
- def test_list_snapshots_invalid_param_marker(self):
- self.assertRaises(lib_exc.NotFound,
- self.snapshots_client.list_snapshots,
- marker=data_utils.rand_uuid())
diff --git a/tempest/api/volume/v3/__init__.py b/tempest/api/volume/v3/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tempest/api/volume/v3/__init__.py
+++ /dev/null
diff --git a/tempest/api/volume/v3/base.py b/tempest/api/volume/v3/base.py
deleted file mode 100644
index 7f76e6f..0000000
--- a/tempest/api/volume/v3/base.py
+++ /dev/null
@@ -1,66 +0,0 @@
-# Copyright 2016 Andrew Kerr
-# 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.api.volume import api_microversion_fixture
-from tempest.api.volume import base
-from tempest import config
-from tempest.lib.common import api_version_utils
-
-CONF = config.CONF
-
-
-class VolumesV3Test(api_version_utils.BaseMicroversionTest,
- base.BaseVolumeTest):
- """Base test case class for all v3 Cinder API tests."""
-
- _api_version = 3
-
- @classmethod
- def skip_checks(cls):
- super(VolumesV3Test, cls).skip_checks()
- api_version_utils.check_skip_with_microversion(
- cls.min_microversion, cls.max_microversion,
- CONF.volume.min_microversion, CONF.volume.max_microversion)
-
- @classmethod
- def resource_setup(cls):
- super(VolumesV3Test, cls).resource_setup()
- cls.request_microversion = (
- api_version_utils.select_request_microversion(
- cls.min_microversion,
- CONF.volume.min_microversion))
-
- @classmethod
- def setup_clients(cls):
- super(VolumesV3Test, cls).setup_clients()
- cls.messages_client = cls.os.volume_v3_messages_client
- cls.versions_client = cls.os.volume_v3_versions_client
-
- def setUp(self):
- super(VolumesV3Test, self).setUp()
- self.useFixture(api_microversion_fixture.APIMicroversionFixture(
- self.request_microversion))
-
-
-class VolumesV3AdminTest(VolumesV3Test,
- base.BaseVolumeAdminTest):
- """Base test case class for all v3 Volume Admin API tests."""
-
- credentials = ['primary', 'admin']
-
- @classmethod
- def setup_clients(cls):
- super(VolumesV3AdminTest, cls).setup_clients()
- cls.admin_messages_client = cls.os_adm.volume_v3_messages_client
- cls.admin_volume_types_client = cls.os_adm.volume_types_v2_client
diff --git a/tempest/clients.py b/tempest/clients.py
index 49a046a..71c3d41 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -229,6 +229,8 @@
self.groups_client = self.identity_v3.GroupsClient(**params_v3)
self.identity_versions_v3_client = self.identity_v3.VersionsClient(
**params_v3)
+ self.oauth_consumers_client = self.identity_v3.OAUTHConsumerClient(
+ **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/common/waiters.py b/tempest/common/waiters.py
index 3e5600c..9c83c99 100644
--- a/tempest/common/waiters.py
+++ b/tempest/common/waiters.py
@@ -261,16 +261,16 @@
time.sleep(client.build_interval)
-def wait_for_interface_status(client, server, port_id, status):
+def wait_for_interface_status(client, server_id, port_id, status):
"""Waits for an interface to reach a given status."""
- body = (client.show_interface(server, port_id)
+ body = (client.show_interface(server_id, port_id)
['interfaceAttachment'])
interface_status = body['port_state']
start = int(time.time())
while(interface_status != status):
time.sleep(client.build_interval)
- body = (client.show_interface(server, port_id)
+ body = (client.show_interface(server_id, port_id)
['interfaceAttachment'])
interface_status = body['port_state']
diff --git a/tempest/config.py b/tempest/config.py
index ef67e7d..35eb187 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -505,7 +505,7 @@
"users can specify."),
cfg.ListOpt('disk_formats',
default=['ami', 'ari', 'aki', 'vhd', 'vmdk', 'raw', 'qcow2',
- 'vdi', 'iso'],
+ 'vdi', 'iso', 'vhdx'],
help="A list of image's disk formats "
"users can specify.")
]
diff --git a/tempest/lib/api_schema/response/compute/v2_1/servers.py b/tempest/lib/api_schema/response/compute/v2_1/servers.py
index 4c4b5eb..33a7757 100644
--- a/tempest/lib/api_schema/response/compute/v2_1/servers.py
+++ b/tempest/lib/api_schema/response/compute/v2_1/servers.py
@@ -100,8 +100,10 @@
'id': {'type': 'string'},
'links': parameter_types.links
},
- 'additionalProperties': False,
- 'required': ['id', 'links']
+ # NOTE(gmann): This will be empty object if there is no
+ # flavor info present in DB. This can happen when flavor info is
+ # deleted after server creation.
+ 'additionalProperties': False
},
'fault': {
'type': 'object',
diff --git a/tempest/lib/cmd/check_uuid.py b/tempest/lib/cmd/check_uuid.py
index eafde44..e911776 100755
--- a/tempest/lib/cmd/check_uuid.py
+++ b/tempest/lib/cmd/check_uuid.py
@@ -29,7 +29,7 @@
DECORATOR_MODULE = 'decorators'
DECORATOR_NAME = 'idempotent_id'
DECORATOR_IMPORT = 'tempest.%s' % DECORATOR_MODULE
-IMPORT_LINE = 'from tempest import %s' % DECORATOR_MODULE
+IMPORT_LINE = 'from tempest.lib import %s' % DECORATOR_MODULE
DECORATOR_TEMPLATE = "@%s.%s('%%s')" % (DECORATOR_MODULE,
DECORATOR_NAME)
UNIT_TESTS_EXCLUDE = 'tempest.tests'
diff --git a/tempest/lib/services/identity/v3/__init__.py b/tempest/lib/services/identity/v3/__init__.py
index 88801e7..1489b50 100644
--- a/tempest/lib/services/identity/v3/__init__.py
+++ b/tempest/lib/services/identity/v3/__init__.py
@@ -20,6 +20,8 @@
from tempest.lib.services.identity.v3.identity_client import IdentityClient
from tempest.lib.services.identity.v3.inherited_roles_client import \
InheritedRolesClient
+from tempest.lib.services.identity.v3.oauth_consumers_client import \
+ OAUTHConsumerClient
from tempest.lib.services.identity.v3.policies_client import PoliciesClient
from tempest.lib.services.identity.v3.projects_client import ProjectsClient
from tempest.lib.services.identity.v3.regions_client import RegionsClient
@@ -36,4 +38,5 @@
'GroupsClient', 'IdentityClient', 'InheritedRolesClient',
'PoliciesClient', 'ProjectsClient', 'RegionsClient',
'RoleAssignmentsClient', 'RolesClient', 'ServicesClient',
- 'V3TokenClient', 'TrustsClient', 'UsersClient', 'VersionsClient']
+ 'V3TokenClient', 'TrustsClient', 'UsersClient', 'VersionsClient',
+ 'OAUTHConsumerClient']
diff --git a/tempest/lib/services/identity/v3/oauth_consumers_client.py b/tempest/lib/services/identity/v3/oauth_consumers_client.py
new file mode 100644
index 0000000..582c9e0
--- /dev/null
+++ b/tempest/lib/services/identity/v3/oauth_consumers_client.py
@@ -0,0 +1,95 @@
+# Copyright 2017 AT&T 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 oslo_serialization import jsonutils as json
+
+from tempest.lib.common import rest_client
+
+
+class OAUTHConsumerClient(rest_client.RestClient):
+ api_version = "v3"
+
+ def create_consumer(self, description=None):
+ """Creates a consumer.
+
+ :param str description: Optional field to add notes about the consumer
+
+ For more information, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v3-ext/#create-consumer
+ """
+ post_body = {"description": description}
+ post_body = json.dumps({'consumer': post_body})
+ resp, body = self.post('OS-OAUTH1/consumers', post_body)
+ self.expected_success(201, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def delete_consumer(self, consumer_id):
+ """Deletes a consumer.
+
+ :param str consumer_id: The ID of the consumer that will be deleted
+
+ For more information, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v3-ext/#delete-consumer
+ """
+ resp, body = self.delete('OS-OAUTH1/consumers/%s' % consumer_id)
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def update_consumer(self, consumer_id, description=None):
+ """Updates a consumer.
+
+ :param str consumer_id: The ID of the consumer that will be updated
+ :param str description: Optional field to add notes about the consumer
+
+ For more information, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v3-ext/#update-consumers
+ """
+ post_body = {"description": description}
+ post_body = json.dumps({'consumer': post_body})
+ resp, body = self.patch('OS-OAUTH1/consumers/%s' % consumer_id,
+ post_body)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def show_consumer(self, consumer_id):
+ """Show consumer details.
+
+ :param str consumer_id: The ID of the consumer that will be shown
+
+ For more information, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v3-ext/#show-consumer-details
+ """
+ resp, body = self.get('OS-OAUTH1/consumers/%s' % consumer_id)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def list_consumers(self):
+ """List all consumers.
+
+ For more information, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v3-ext/#list-consumers
+ """
+ resp, body = self.get('OS-OAUTH1/consumers')
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/lib/services/volume/v2/snapshots_client.py b/tempest/lib/services/volume/v2/snapshots_client.py
index 2bdf1b1..983ed89 100644
--- a/tempest/lib/services/volume/v2/snapshots_client.py
+++ b/tempest/lib/services/volume/v2/snapshots_client.py
@@ -27,7 +27,8 @@
For a full list of available parameters, please refer to the official
API reference:
- http://developer.openstack.org/api-ref/block-storage/v2/#list-snapshots-v2
+ http://developer.openstack.org/api-ref/block-storage/v2/#list-snapshots-with-details
+ http://developer.openstack.org/api-ref/block-storage/v2/#list-snapshots
"""
url = 'snapshots'
if detail:
@@ -45,7 +46,7 @@
For a full list of available parameters, please refer to the official
API reference:
- http://developer.openstack.org/api-ref/block-storage/v2/#show-snapshot-v2
+ http://developer.openstack.org/api-ref/block-storage/v2/#show-snapshot-details
"""
url = "snapshots/%s" % snapshot_id
resp, body = self.get(url)
@@ -71,7 +72,7 @@
For a full list of available parameters, please refer to the official
API reference:
- http://developer.openstack.org/api-ref/block-storage/v2/#update-snapshot-v2
+ http://developer.openstack.org/api-ref/block-storage/v2/#update-snapshot
"""
put_body = json.dumps({'snapshot': kwargs})
resp, body = self.put('snapshots/%s' % snapshot_id, put_body)
@@ -84,7 +85,7 @@
For a full list of available parameters, please refer to the official
API reference:
- http://developer.openstack.org/api-ref/block-storage/v2/#delete-snapshot-v2
+ http://developer.openstack.org/api-ref/block-storage/v2/#delete-snapshot
"""
resp, body = self.delete("snapshots/%s" % snapshot_id)
self.expected_success(202, resp.status)
@@ -136,7 +137,7 @@
For a full list of available parameters, please refer to the official
API reference:
- http://developer.openstack.org/api-ref/block-storage/v2/#show-snapshot-metadata-v2
+ http://developer.openstack.org/api-ref/block-storage/v2/#show-snapshot-metadata
"""
url = "snapshots/%s/metadata" % snapshot_id
resp, body = self.get(url)
@@ -149,7 +150,7 @@
For a full list of available parameters, please refer to the official
API reference:
- http://developer.openstack.org/api-ref/block-storage/v2/#update-snapshot-metadata-v2
+ http://developer.openstack.org/api-ref/block-storage/v2/#update-snapshot-metadata
"""
put_body = json.dumps(kwargs)
url = "snapshots/%s/metadata" % snapshot_id
diff --git a/tempest/lib/services/volume/v2/types_client.py b/tempest/lib/services/volume/v2/types_client.py
index 31597d7..5d30615 100644
--- a/tempest/lib/services/volume/v2/types_client.py
+++ b/tempest/lib/services/volume/v2/types_client.py
@@ -41,7 +41,7 @@
For a full list of available parameters, please refer to the official
API reference:
- http://developer.openstack.org/api-ref/block-storage/v2/#list-volume-types-v2
+ http://developer.openstack.org/api-ref/block-storage/v2/#list-volume-types
"""
url = 'types'
if params:
@@ -57,7 +57,7 @@
For a full list of available parameters, please refer to the official
API reference:
- http://developer.openstack.org/api-ref/block-storage/v2/#show-volume-type-v2
+ http://developer.openstack.org/api-ref/block-storage/v2/#show-volume-type-details
"""
url = "types/%s" % volume_type_id
resp, body = self.get(url)
@@ -70,7 +70,7 @@
For a full list of available parameters, please refer to the official
API reference:
- http://developer.openstack.org/api-ref/block-storage/v2/#create-volume-type-v2
+ http://developer.openstack.org/api-ref/block-storage/v2/#create-volume-type
"""
post_body = json.dumps({'volume_type': kwargs})
resp, body = self.post('types', post_body)
@@ -83,7 +83,7 @@
For a full list of available parameters, please refer to the official
API reference:
- http://developer.openstack.org/api-ref/block-storage/v2/#delete-volume-type-v2
+ http://developer.openstack.org/api-ref/block-storage/v2/#delete-volume-type
"""
resp, body = self.delete("types/%s" % volume_type_id)
self.expected_success(202, resp.status)
@@ -138,7 +138,7 @@
For a full list of available parameters, please refer to the official
API reference:
- http://developer.openstack.org/api-ref/block-storage/v2/#update-volume-type-v2
+ http://developer.openstack.org/api-ref/block-storage/v2/#update-volume-type
"""
put_body = json.dumps({'volume_type': kwargs})
resp, body = self.put('types/%s' % volume_type_id, put_body)
@@ -156,7 +156,7 @@
updated value.
For a full list of available parameters, please refer to the official
API reference:
- http://developer.openstack.org/api-ref/block-storage/v2/#update-volume-type-extra-specs-v2
+ http://developer.openstack.org/api-ref/block-storage/v2/#update-extra-specs-for-a-volume-type
"""
url = "types/%s/extra_specs/%s" % (volume_type_id, extra_spec_name)
put_body = json.dumps(extra_specs)
@@ -170,7 +170,7 @@
For a full list of available parameters, please refer to the official
API reference:
- http://developer.openstack.org/api-ref/block-storage/v2/#add-type-access-v2
+ http://developer.openstack.org/api-ref/block-storage/v2/#add-private-volume-type-access
"""
post_body = json.dumps({'addProjectAccess': kwargs})
url = 'types/%s/action' % volume_type_id
@@ -183,7 +183,7 @@
For a full list of available parameters, please refer to the official
API reference:
- http://developer.openstack.org/api-ref/block-storage/v2/#remove-type-access-v2
+ http://developer.openstack.org/api-ref/block-storage/v2/#remove-private-volume-type-access
"""
post_body = json.dumps({'removeProjectAccess': kwargs})
url = 'types/%s/action' % volume_type_id
@@ -196,7 +196,7 @@
For a full list of available parameters, please refer to the official
API reference:
- http://developer.openstack.org/api-ref/block-storage/v2/#list-type-access-v2
+ http://developer.openstack.org/api-ref/block-storage/v2/#list-private-volume-type-access-details
"""
url = 'types/%s/os-volume-type-access' % volume_type_id
resp, body = self.get(url)
diff --git a/tempest/lib/services/volume/v2/volumes_client.py b/tempest/lib/services/volume/v2/volumes_client.py
index f59abb7..72823c0 100644
--- a/tempest/lib/services/volume/v2/volumes_client.py
+++ b/tempest/lib/services/volume/v2/volumes_client.py
@@ -106,7 +106,7 @@
For a full list of available parameters, please refer to the official
API reference:
- http://developer.openstack.org/api-ref/block-storage/v2/#attach-volume
+ http://developer.openstack.org/api-ref/block-storage/v2/#attach-volume-to-server
"""
post_body = json.dumps({'os-attach': kwargs})
url = 'volumes/%s/action' % (volume_id)
@@ -163,7 +163,7 @@
For a full list of available parameters, please refer to the official
API reference:
- http://developer.openstack.org/api-ref/block-storage/v2/#extend-volume
+ http://developer.openstack.org/api-ref/block-storage/v2/#extend-volume-size
"""
post_body = json.dumps({'os-extend': kwargs})
url = 'volumes/%s/action' % (volume_id)
@@ -176,7 +176,7 @@
For a full list of available parameters, please refer to the official
API reference:
- http://developer.openstack.org/api-ref/block-storage/v2/#reset-volume-status
+ http://developer.openstack.org/api-ref/block-storage/v2/#reset-volume-statuses
"""
post_body = json.dumps({'os-reset_status': kwargs})
resp, body = self.post('volumes/%s/action' % volume_id, post_body)
@@ -307,7 +307,7 @@
For a full list of available parameters, please refer to the official
API reference:
- http://developer.openstack.org/api-ref/block-storage/v2/#update-volume-image-metadata
+ http://developer.openstack.org/api-ref/block-storage/v2/#set-image-metadata-for-volume
"""
post_body = json.dumps({'os-set_image_metadata': {'metadata': kwargs}})
url = "volumes/%s/action" % (volume_id)
@@ -344,7 +344,7 @@
For a full list of available parameters, please refer to the official
API reference:
- http://developer.openstack.org/api-ref/block-storage/v2/#show_backend_capabilities
+ http://developer.openstack.org/api-ref/block-storage/v2/#show-back-end-capabilities
"""
url = 'capabilities/%s' % host
resp, body = self.get(url)
diff --git a/tempest/tests/lib/services/identity/v3/test_oauth_consumers_client.py b/tempest/tests/lib/services/identity/v3/test_oauth_consumers_client.py
new file mode 100644
index 0000000..8d53792
--- /dev/null
+++ b/tempest/tests/lib/services/identity/v3/test_oauth_consumers_client.py
@@ -0,0 +1,160 @@
+# Copyright 2017 AT&T 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 oauth_consumers_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestOAUTHConsumerClient(base.BaseServiceTest):
+ FAKE_CREATE_CONSUMER = {
+ "consumer": {
+ 'description': 'A fake description 1'
+ }
+
+ }
+
+ FAKE_CONSUMER_INFO = {
+ "consumer": {
+ 'id': '6392c7d3b7a2062e09a07aa377',
+ 'links': {
+ 'self': 'http://example.com/identity/v3/' +
+ 'OS-OAUTH1/consumers/g6f2l9'
+ },
+ 'description': 'A description that is fake'
+ }
+
+ }
+
+ FAKE_LIST_CONSUMERS = {
+ 'links': {
+ 'self': 'http://example.com/identity/v3/OS-OAUTH1/consumers/',
+ 'next': None,
+ 'previous': None
+ },
+ 'consumers': [
+ {
+ 'id': '6392c7d3b7a2062e09a07aa377',
+ 'links': {
+ 'self': 'http://example.com/identity/v3/' +
+ 'OS-OAUTH1/consumers/6b9f2g5'
+ },
+ 'description': 'A description that is fake'
+ },
+ {
+ 'id': '677a855c9e3eb3a3954b36aca6',
+ 'links': {
+ 'self': 'http://example.com/identity/v3/' +
+ 'OS-OAUTH1/consumers/6a9f2366'
+ },
+ 'description': 'A very fake description 2'
+ },
+ {
+ 'id': '9d3ac57b08d65e07826b5e506',
+ 'links': {
+ 'self': 'http://example.com/identity/v3/' +
+ 'OS-OAUTH1/consumers/626b5e506'
+ },
+ 'description': 'A very fake description 3'
+ },
+ {
+ 'id': 'b522d163b1a18e928aca9y426',
+ 'links': {
+ 'self': 'http://example.com/identity/v3/' +
+ 'OS-OAUTH1/consumers/g7ca9426'
+ },
+ 'description': 'A very fake description 4'
+ },
+ {
+ 'id': 'b7e47321b5ef9051f93c2049e',
+ 'links': {
+ 'self': 'http://example.com/identity/v3/' +
+ 'OS-OAUTH1/consumers/23d82049e'
+ },
+ 'description': 'A very fake description 5'
+ }
+ ]
+ }
+
+ def setUp(self):
+ super(TestOAUTHConsumerClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = oauth_consumers_client.OAUTHConsumerClient(fake_auth,
+ 'identity',
+ 'regionOne')
+
+ def _test_create_consumer(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.create_consumer,
+ 'tempest.lib.common.rest_client.RestClient.post',
+ self.FAKE_CREATE_CONSUMER,
+ bytes_body,
+ description=self.FAKE_CREATE_CONSUMER["consumer"]["description"],
+ status=201)
+
+ def _test_show_consumer(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.show_consumer,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_CONSUMER_INFO,
+ bytes_body,
+ consumer_id="6392c7d3b7a2062e09a07aa377")
+
+ def _test_list_consumers(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_consumers,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_LIST_CONSUMERS,
+ bytes_body)
+
+ def _test_update_consumer(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.update_consumer,
+ 'tempest.lib.common.rest_client.RestClient.patch',
+ self.FAKE_CONSUMER_INFO,
+ bytes_body,
+ consumer_id="6392c7d3b7a2062e09a07aa377")
+
+ def test_create_consumer_with_str_body(self):
+ self._test_create_consumer()
+
+ def test_create_consumer_with_bytes_body(self):
+ self._test_create_consumer(bytes_body=True)
+
+ def test_show_consumer_with_str_body(self):
+ self._test_show_consumer()
+
+ def test_show_consumer_with_bytes_body(self):
+ self._test_show_consumer(bytes_body=True)
+
+ def test_list_consumers_with_str_body(self):
+ self._test_list_consumers()
+
+ def test_list_consumers_with_bytes_body(self):
+ self._test_list_consumers(bytes_body=True)
+
+ def test_update_consumer_with_str_body(self):
+ self._test_update_consumer()
+
+ def test_update_consumer_with_bytes_body(self):
+ self._test_update_consumer(bytes_body=True)
+
+ def test_delete_consumer(self):
+ self.check_service_client_function(
+ self.client.delete_consumer,
+ 'tempest.lib.common.rest_client.RestClient.delete',
+ {},
+ consumer_id="6392c7d3b7a2062e09a07aa377",
+ status=204)
diff --git a/tox.ini b/tox.ini
index b3052eb..892f834 100644
--- a/tox.ini
+++ b/tox.ini
@@ -36,7 +36,6 @@
commands = oslo-config-generator --config-file tempest/cmd/config-generator.tempest.conf
[testenv:cover]
-setenv = OS_TEST_PATH=./tempest/tests
commands = python setup.py testr --coverage --testr-arg='tempest\.tests {posargs}'
[testenv:all]