From 0dea14df865249d96b79f139392e119f3dd9a61d Mon Sep 17 00:00:00 2001 From: Bartosz Zurkowski Date: Fri, 6 Jul 2018 21:01:54 +0200 Subject: [PATCH] Create base class for client to avoid code duplication Implementing listing or showing resource in every client leads to a lot of duplicated code. This change adds a base client class which implements common helpers. Removes "Database" prefix from class names and "db" infix from method signatures for alignment with standards from the rest of the community. Also, adds doseq option by URL encoding to handle sequence field values. Change-Id: I580405e2cb8a15e5735ae413ad2186c620f018bc Co-Authored-By: Przemyslaw Godek Co-Authored-By: Krzysztof Opasiak Signed-off-by: Bartosz Zurkowski --- .../services/database/json/base_client.py | 47 +++++++++++++++++++ .../services/database/json/flavors_client.py | 25 ++++------ .../services/database/json/limits_client.py | 18 +++---- .../services/database/json/versions_client.py | 21 +++------ .../tests/api/database/base.py | 6 +-- .../api/database/flavors/test_flavors.py | 10 ++-- .../database/flavors/test_flavors_negative.py | 2 +- .../tests/api/database/limits/test_limits.py | 2 +- .../api/database/versions/test_versions.py | 2 +- 9 files changed, 79 insertions(+), 54 deletions(-) create mode 100644 trove_tempest_plugin/services/database/json/base_client.py diff --git a/trove_tempest_plugin/services/database/json/base_client.py b/trove_tempest_plugin/services/database/json/base_client.py new file mode 100644 index 0000000..30b43be --- /dev/null +++ b/trove_tempest_plugin/services/database/json/base_client.py @@ -0,0 +1,47 @@ +# Copyright 2018 Samsung Electronics +# 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 six.moves.urllib import parse as urllib + +from tempest.lib.common import rest_client + + +class BaseClient(rest_client.RestClient): + + def show_resource(self, uri, expected_status_code=200, **fields): + if fields: + # Encode provided dict of fields into a series of key=value pairs + # separated by '&' characters. + # + # The field value can be a sequence. Setting option doseq to True + # enforces producing individual key-value pair for each element of + # the sequence under the same key. + # + # e.g. {'foo': 'bar', 'baz': ['test1', 'test2']} + # => foo=bar&baz=test1&baz=test2 + uri += '?' + urllib.urlencode(fields, doseq=True) + resp, body = self.get(uri) + self.expected_success(expected_status_code, resp.status) + body = json.loads(body) + return rest_client.ResponseBody(resp, body) + + def list_resources(self, uri, expected_status_code=200, **filters): + if filters: + uri += '?' + urllib.urlencode(filters, doseq=True) + resp, body = self.get(uri) + self.expected_success(expected_status_code, resp.status) + body = json.loads(body) + return rest_client.ResponseBody(resp, body) diff --git a/trove_tempest_plugin/services/database/json/flavors_client.py b/trove_tempest_plugin/services/database/json/flavors_client.py index 95ecfdc..4580f23 100644 --- a/trove_tempest_plugin/services/database/json/flavors_client.py +++ b/trove_tempest_plugin/services/database/json/flavors_client.py @@ -13,25 +13,16 @@ # License for the specific language governing permissions and limitations # under the License. -from oslo_serialization import jsonutils as json -from six.moves import urllib -from tempest.lib.common import rest_client +from trove_tempest_plugin.services.database.json import base_client -class DatabaseFlavorsClient(rest_client.RestClient): +class FlavorsClient(base_client.BaseClient): - def list_db_flavors(self, params=None): - url = 'flavors' - if params: - url += '?%s' % urllib.parse.urlencode(params) + uri = '/flavors' - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - return rest_client.ResponseBody(resp, body) + def list_flavors(self): + return self.list_resources(self.uri) - def show_db_flavor(self, db_flavor_id): - resp, body = self.get("flavors/%s" % db_flavor_id) - self.expected_success(200, resp.status) - body = json.loads(body) - return rest_client.ResponseBody(resp, body) + def show_flavor(self, flavor_id): + uri = '%s/%s' % (self.uri, flavor_id) + return self.show_resource(uri) diff --git a/trove_tempest_plugin/services/database/json/limits_client.py b/trove_tempest_plugin/services/database/json/limits_client.py index 23164a8..e36b105 100644 --- a/trove_tempest_plugin/services/database/json/limits_client.py +++ b/trove_tempest_plugin/services/database/json/limits_client.py @@ -13,19 +13,13 @@ # License for the specific language governing permissions and limitations # under the License. -from oslo_serialization import jsonutils as json -from six.moves.urllib import parse as urllib -from tempest.lib.common import rest_client +from trove_tempest_plugin.services.database.json import base_client -class DatabaseLimitsClient(rest_client.RestClient): +class LimitsClient(base_client.BaseClient): - def list_db_limits(self, params=None): + uri = '/limits' + + def list_limits(self): """List all limits.""" - url = 'limits' - if params: - url += '?%s' % urllib.urlencode(params) - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - return rest_client.ResponseBody(resp, body) + return self.list_resources(self.uri) diff --git a/trove_tempest_plugin/services/database/json/versions_client.py b/trove_tempest_plugin/services/database/json/versions_client.py index d7154f2..b20a472 100644 --- a/trove_tempest_plugin/services/database/json/versions_client.py +++ b/trove_tempest_plugin/services/database/json/versions_client.py @@ -13,25 +13,18 @@ # License for the specific language governing permissions and limitations # under the License. -from oslo_serialization import jsonutils as json -from six.moves.urllib import parse as urllib -from tempest.lib.common import rest_client +from trove_tempest_plugin.services.database.json import base_client -class DatabaseVersionsClient(rest_client.RestClient): +class VersionsClient(base_client.BaseClient): + + uri = '' def __init__(self, auth_provider, service, region, **kwargs): - super(DatabaseVersionsClient, self).__init__( + super(VersionsClient, self).__init__( auth_provider, service, region, **kwargs) self.skip_path() - def list_db_versions(self, params=None): + def list_versions(self): """List all versions.""" - url = '' - if params: - url += '?%s' % urllib.urlencode(params) - - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - return rest_client.ResponseBody(resp, body) + return self.list_resources(self.uri) diff --git a/trove_tempest_plugin/tests/api/database/base.py b/trove_tempest_plugin/tests/api/database/base.py index 842ac72..7dd4174 100644 --- a/trove_tempest_plugin/tests/api/database/base.py +++ b/trove_tempest_plugin/tests/api/database/base.py @@ -48,18 +48,18 @@ class BaseDatabaseTest(tempest.test.BaseTestCase): 'build_timeout': CONF.compute.build_timeout } default_params_with_timeout_values.update(default_params) - cls.database_flavors_client = flavors_client.DatabaseFlavorsClient( + cls.database_flavors_client = flavors_client.FlavorsClient( cls.os_primary.auth_provider, CONF.database.catalog_type, CONF.identity.region, **default_params_with_timeout_values) cls.os_flavors_client = cls.os_primary.flavors_client - cls.database_limits_client = limits_client.DatabaseLimitsClient( + cls.database_limits_client = limits_client.LimitsClient( cls.os_primary.auth_provider, CONF.database.catalog_type, CONF.identity.region, **default_params_with_timeout_values) - cls.database_versions_client = versions_client.DatabaseVersionsClient( + cls.database_versions_client = versions_client.VersionsClient( cls.os_primary.auth_provider, CONF.database.catalog_type, CONF.identity.region, diff --git a/trove_tempest_plugin/tests/api/database/flavors/test_flavors.py b/trove_tempest_plugin/tests/api/database/flavors/test_flavors.py index f6154d8..9b9069a 100644 --- a/trove_tempest_plugin/tests/api/database/flavors/test_flavors.py +++ b/trove_tempest_plugin/tests/api/database/flavors/test_flavors.py @@ -31,7 +31,7 @@ class DatabaseFlavorsTest(base.BaseDatabaseTest): @decorators.idempotent_id('c94b825e-0132-4686-8049-8a4a2bc09525') def test_get_db_flavor(self): # The expected flavor details should be returned - flavor = (self.client.show_db_flavor(self.db_flavor_ref) + flavor = (self.client.show_flavor(self.db_flavor_ref) ['flavor']) self.assertEqual(self.db_flavor_ref, str(flavor['id'])) self.assertIn('ram', flavor) @@ -41,10 +41,10 @@ class DatabaseFlavorsTest(base.BaseDatabaseTest): @testtools.attr('smoke') @decorators.idempotent_id('685025d6-0cec-4673-8a8d-995cb8e0d3bb') def test_list_db_flavors(self): - flavor = (self.client.show_db_flavor(self.db_flavor_ref) + flavor = (self.client.show_flavor(self.db_flavor_ref) ['flavor']) # List of all flavors should contain the expected flavor - flavors = self.client.list_db_flavors()['flavors'] + flavors = self.client.list_flavors()['flavors'] self.assertIn(flavor, flavors) def _check_values(self, names, db_flavor, os_flavor, in_db=True): @@ -62,7 +62,7 @@ class DatabaseFlavorsTest(base.BaseDatabaseTest): @decorators.idempotent_id('afb2667f-4ec2-4925-bcb7-313fdcffb80d') @utils.services('compute') def test_compare_db_flavors_with_os(self): - db_flavors = self.client.list_db_flavors()['flavors'] + db_flavors = self.client.list_flavors()['flavors'] os_flavors = (self.os_flavors_client.list_flavors(detail=True) ['flavors']) self.assertEqual(len(os_flavors), len(db_flavors), @@ -70,7 +70,7 @@ class DatabaseFlavorsTest(base.BaseDatabaseTest): (os_flavors, db_flavors)) for os_flavor in os_flavors: db_flavor =\ - self.client.show_db_flavor(os_flavor['id'])['flavor'] + self.client.show_flavor(os_flavor['id'])['flavor'] if db_flavor['id']: self.assertIn('id', db_flavor) self.assertEqual(str(db_flavor['id']), str(os_flavor['id']), diff --git a/trove_tempest_plugin/tests/api/database/flavors/test_flavors_negative.py b/trove_tempest_plugin/tests/api/database/flavors/test_flavors_negative.py index 2bbd0a4..6d5aa19 100644 --- a/trove_tempest_plugin/tests/api/database/flavors/test_flavors_negative.py +++ b/trove_tempest_plugin/tests/api/database/flavors/test_flavors_negative.py @@ -33,4 +33,4 @@ class DatabaseFlavorsNegativeTest(base.BaseDatabaseTest): def test_get_non_existent_db_flavor(self): # flavor details are not returned for non-existent flavors self.assertRaises(lib_exc.NotFound, - self.client.show_db_flavor, -1) + self.client.show_flavor, -1) diff --git a/trove_tempest_plugin/tests/api/database/limits/test_limits.py b/trove_tempest_plugin/tests/api/database/limits/test_limits.py index 02c28f9..6441a81 100644 --- a/trove_tempest_plugin/tests/api/database/limits/test_limits.py +++ b/trove_tempest_plugin/tests/api/database/limits/test_limits.py @@ -31,7 +31,7 @@ class DatabaseLimitsTest(base.BaseDatabaseTest): def test_absolute_limits(self): # Test to verify if all absolute limit parameters are # present when verb is ABSOLUTE - limits = self.client.list_db_limits()['limits'] + limits = self.client.list_limits()['limits'] expected_abs_limits = ['max_backups', 'max_volumes', 'max_instances', 'verb'] absolute_limit = [l for l in limits diff --git a/trove_tempest_plugin/tests/api/database/versions/test_versions.py b/trove_tempest_plugin/tests/api/database/versions/test_versions.py index f12da1a..c22f257 100644 --- a/trove_tempest_plugin/tests/api/database/versions/test_versions.py +++ b/trove_tempest_plugin/tests/api/database/versions/test_versions.py @@ -29,7 +29,7 @@ class DatabaseVersionsTest(base.BaseDatabaseTest): @testtools.attr('smoke') @decorators.idempotent_id('6952cd77-90cd-4dca-bb60-8e2c797940cf') def test_list_db_versions(self): - versions = self.client.list_db_versions()['versions'] + versions = self.client.list_versions()['versions'] self.assertTrue(len(versions) > 0, "No database versions found") # List of all versions should contain the current version, and there # should only be one 'current' version