From 49f8e17d3a44737734a50feb9193fae6ede0cada Mon Sep 17 00:00:00 2001 From: Stuart McLaren Date: Wed, 9 Jul 2014 15:29:17 +0000 Subject: [PATCH] Also run v2 functional tests with registry Currently the v2 functional tests are run without the v2 registry enabled. This means that bugs which are only seen when the v2 registry is enabled may not be caught by the gate (eg #1308419, #1339775). Here we enable some basic functional testing (eg image life cycle) with the v2 registry enabled (in addition to the existing direct-to-database mode). This should help prevent some types of bugs being introduced. There is a plan to move some functional tests into tempest, at which point these additional tests can be removed in favour of equivalent tempest tests. Change-Id: I774a277673390650874aad4334b28d1a872ea93f --- glance/tests/functional/__init__.py | 6 +++ .../tests/functional/v2/registry_data_api.py | 52 +++++++++++++++++++ glance/tests/functional/v2/test_images.py | 49 ++++++++++++++++- glance/tests/functional/v2/test_tasks.py | 10 +++- 4 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 glance/tests/functional/v2/registry_data_api.py diff --git a/glance/tests/functional/__init__.py b/glance/tests/functional/__init__.py index 5a09fc054e..301f38ec56 100644 --- a/glance/tests/functional/__init__.py +++ b/glance/tests/functional/__init__.py @@ -320,6 +320,8 @@ class ApiServer(Server): default_sql_connection = 'sqlite:////%s/tests.sqlite' % self.test_dir self.sql_connection = os.environ.get('GLANCE_TEST_SQL_CONNECTION', default_sql_connection) + self.data_api = kwargs.get("data_api", + "glance.db.sqlalchemy.api") self.user_storage_quota = '0' self.lock_path = self.test_dir @@ -369,6 +371,7 @@ image_cache_driver = %(image_cache_driver)s policy_file = %(policy_file)s policy_default_rule = %(policy_default_rule)s db_auto_create = False +data_api = %(data_api)s sql_connection = %(sql_connection)s show_image_direct_url = %(show_image_direct_url)s show_multiple_locations = %(show_multiple_locations)s @@ -499,6 +502,9 @@ pipeline = unauthenticated-context registryapp [pipeline:glance-registry-fakeauth] pipeline = fakeauth context registryapp +[pipeline:glance-registry-trusted-auth] +pipeline = context registryapp + [app:registryapp] paste.app_factory = glance.registry.api:API.factory diff --git a/glance/tests/functional/v2/registry_data_api.py b/glance/tests/functional/v2/registry_data_api.py new file mode 100644 index 0000000000..0ba9ef6808 --- /dev/null +++ b/glance/tests/functional/v2/registry_data_api.py @@ -0,0 +1,52 @@ +# Copyright 2014 Hewlett-Packard Development Company, L.P. +# 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 glance.db.registry.api import * # noqa +from glance.common.rpc import RPCClient +from glance.registry.client.v2 import api +from glance.registry.client.v2 import client + + +def patched_bulk_request(self, commands): + # We add some auth headers which are typically + # added by keystone. This is required when testing + # without keystone, otherwise the tests fail. + # We use the 'trusted-auth' deployment flavour + # for testing so that these headers are interpreted + # as expected (ie the same way as if keystone was + # present) + body = self._serializer.to_json(commands) + headers = {"X-Identity-Status": "Confirmed", 'X-Roles': 'member'} + if self.context.user is not None: + headers['X-User-Id'] = self.context.user + if self.context.tenant is not None: + headers['X-Tenant-Id'] = self.context.tenant + response = super(RPCClient, self).do_request('POST', + self.base_path, + body, + headers=headers) + return self._deserializer.from_json(response.read()) + + +def client_wrapper(func): + def call(context): + reg_client = func(context) + reg_client.context = context + return reg_client + return call + +client.RegistryClient.bulk_request = patched_bulk_request + +api.get_registry_client = client_wrapper(api.get_registry_client) diff --git a/glance/tests/functional/v2/test_images.py b/glance/tests/functional/v2/test_images.py index ea0bb31c2f..02a2e27034 100644 --- a/glance/tests/functional/v2/test_images.py +++ b/glance/tests/functional/v2/test_images.py @@ -38,7 +38,7 @@ class TestImages(functional.FunctionalTest): super(TestImages, self).setUp() self.cleanup() self.api_server.deployment_flavor = 'noauth' - self.start_servers(**self.__dict__.copy()) + self.api_server.data_api = 'glance.db.sqlalchemy.api' def _url(self, path): return 'http://127.0.0.1:%d%s' % (self.api_port, path) @@ -56,6 +56,7 @@ class TestImages(functional.FunctionalTest): def test_image_lifecycle(self): # Image list should be empty + self.start_servers(**self.__dict__.copy()) path = self._url('/v2/images') response = requests.get(path, headers=self._headers()) self.assertEqual(200, response.status_code) @@ -511,6 +512,7 @@ class TestImages(functional.FunctionalTest): self.stop_servers() def test_permissions(self): + self.start_servers(**self.__dict__.copy()) # Create an image that belongs to TENANT1 path = self._url('/v2/images') headers = self._headers({'Content-Type': 'application/json'}) @@ -1454,6 +1456,7 @@ class TestImages(functional.FunctionalTest): self.stop_servers() def test_tag_lifecycle(self): + self.start_servers(**self.__dict__.copy()) # Create an image with a tag - duplicate should be ignored path = self._url('/v2/images') headers = self._headers({'Content-Type': 'application/json'}) @@ -1633,6 +1636,7 @@ class TestImages(functional.FunctionalTest): def test_images_container(self): # Image list should be empty and no next link should be present + self.start_servers(**self.__dict__.copy()) path = self._url('/v2/images') response = requests.get(path, headers=self._headers()) self.assertEqual(200, response.status_code) @@ -1813,6 +1817,7 @@ class TestImages(functional.FunctionalTest): self.stop_servers() def test_update_locations(self): + self.start_servers(**self.__dict__.copy()) # Create an image path = self._url('/v2/images') headers = self._headers({'content-type': 'application/json'}) @@ -1850,6 +1855,14 @@ class TestImages(functional.FunctionalTest): self.assertEqual(image['size'], 6) +class TestImagesWithRegistry(TestImages): + def setUp(self): + super(TestImagesWithRegistry, self).setUp() + self.api_server.data_api = ( + 'glance.tests.functional.v2.registry_data_api') + self.registry_server.deployment_flavor = 'trusted-auth' + + class TestImageDirectURLVisibility(functional.FunctionalTest): def setUp(self): @@ -2051,6 +2064,14 @@ class TestImageDirectURLVisibility(functional.FunctionalTest): self.stop_servers() +class TestImageDirectURLVisibilityWithRegistry(TestImageDirectURLVisibility): + def setUp(self): + super(TestImageDirectURLVisibilityWithRegistry, self).setUp() + self.api_server.data_api = ( + 'glance.tests.functional.v2.registry_data_api') + self.registry_server.deployment_flavor = 'trusted-auth' + + class TestImageLocationSelectionStrategy(functional.FunctionalTest): def setUp(self): @@ -2205,6 +2226,15 @@ class TestImageLocationSelectionStrategy(functional.FunctionalTest): self.stop_servers() +class TestImageLocationSelectionStrategyWithRegistry( + TestImageLocationSelectionStrategy): + def setUp(self): + super(TestImageLocationSelectionStrategyWithRegistry, self).setUp() + self.api_server.data_api = ( + 'glance.tests.functional.v2.registry_data_api') + self.registry_server.deployment_flavor = 'trusted-auth' + + class TestImageMembers(functional.FunctionalTest): def setUp(self): @@ -2506,12 +2536,21 @@ class TestImageMembers(functional.FunctionalTest): self.stop_servers() +class TestImageMembersWithRegistry(TestImageMembers): + def setUp(self): + super(TestImageMembersWithRegistry, self).setUp() + self.api_server.data_api = ( + 'glance.tests.functional.v2.registry_data_api') + self.registry_server.deployment_flavor = 'trusted-auth' + + class TestQuotas(functional.FunctionalTest): def setUp(self): super(TestQuotas, self).setUp() self.cleanup() self.api_server.deployment_flavor = 'noauth' + self.registry_server.deployment_flavor = 'trusted-auth' self.user_storage_quota = 100 self.start_servers(**self.__dict__.copy()) @@ -2580,3 +2619,11 @@ class TestQuotas(functional.FunctionalTest): yield 'x' * (self.user_storage_quota + 1) self._upload_image_test(data_gen(), 413) + + +class TestQuotasWithRegistry(TestQuotas): + def setUp(self): + super(TestQuotasWithRegistry, self).setUp() + self.api_server.data_api = ( + 'glance.tests.functional.v2.registry_data_api') + self.registry_server.deployment_flavor = 'trusted-auth' diff --git a/glance/tests/functional/v2/test_tasks.py b/glance/tests/functional/v2/test_tasks.py index c4f3167746..1dd37b73a1 100644 --- a/glance/tests/functional/v2/test_tasks.py +++ b/glance/tests/functional/v2/test_tasks.py @@ -37,7 +37,6 @@ class TestTasks(functional.FunctionalTest): self.cleanup() self.file_path = self._stash_file() self.api_server.deployment_flavor = 'noauth' - self.start_servers(**self.__dict__.copy()) def _url(self, path): return 'http://127.0.0.1:%d%s' % (self.api_port, path) @@ -64,6 +63,7 @@ class TestTasks(functional.FunctionalTest): return 'file://%s' % file_path def test_task_lifecycle(self): + self.start_servers(**self.__dict__.copy()) # Task list should be empty path = self._url('/v2/tasks') response = requests.get(path, headers=self._headers()) @@ -138,3 +138,11 @@ class TestTasks(functional.FunctionalTest): self.assertEqual('GET', response.headers.get('Allow')) self.stop_servers() + + +class TestTasksWithRegistry(TestTasks): + def setUp(self): + super(TestTasksWithRegistry, self).setUp() + self.api_server.data_api = ( + 'glance.tests.functional.v2.registry_data_api') + self.registry_server.deployment_flavor = 'trusted-auth'