From 32b83078194f40e0d3445d95cf04ce97091fd229 Mon Sep 17 00:00:00 2001 From: Brian Rosmaita Date: Thu, 15 Mar 2018 20:32:40 -0400 Subject: [PATCH] Split glanceclient functional tests Prepare for the Image API v1 to be removed from glance during Rocky by splitting the functional tests that hit v1 from the tests that hit v2. Introduce a new job that runs the functional-v1 tests against a devstack running glance stable/queens, and configure this job for both check and gate for the glanceclient. The v2 functional tests continue to be run for both check and gate against a devstack running glance master. Change-Id: Ifa98ada26a84e4cca3ea8c98173f61a6174cca27 --- .zuul.yaml | 48 +++++++++++- glanceclient/tests/functional/base.py | 3 +- glanceclient/tests/functional/v1/__init__.py | 0 .../functional/v1/test_readonly_glance.py | 73 +++++++++++++++++++ glanceclient/tests/functional/v2/__init__.py | 0 .../functional/{ => v2}/test_http_headers.py | 0 .../{ => v2}/test_readonly_glance.py | 15 ---- tools/fix_ca_bundle.sh | 4 +- tox.ini | 15 +++- 9 files changed, 136 insertions(+), 22 deletions(-) create mode 100644 glanceclient/tests/functional/v1/__init__.py create mode 100644 glanceclient/tests/functional/v1/test_readonly_glance.py create mode 100644 glanceclient/tests/functional/v2/__init__.py rename glanceclient/tests/functional/{ => v2}/test_http_headers.py (100%) rename glanceclient/tests/functional/{ => v2}/test_readonly_glance.py (86%) diff --git a/.zuul.yaml b/.zuul.yaml index 2a784b92..e386d54e 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -1,16 +1,54 @@ +- job: + name: glanceclient-dsvm-functional-v1 + parent: devstack-tox-functional + description: | + Devstack-based functional tests for glanceclient + against the Image API v1. + + The Image API v1 is removed from glance in Rocky, but + is still supported by glanceclient until the S cycle, + so we test it against glance stable/queens. + + THIS JOB SHOULD BE REMOVED AT THE BEGINNING OF THE S + CYCLE. + override-checkout: stable/queens + required-projects: + - name: openstack/python-glanceclient + override-checkout: master + timeout: 4200 + vars: + tox_envlist: functional-v1 + devstack_localrc: + GLANCE_V1_ENABLED: true + devstack_services: + # turn off ceilometer + ceilometer-acentral: false + ceilometer-acompute: false + ceilometer-alarm-evaluator: false + ceilometer-alarm-notifier: false + ceilometer-anotification: false + ceilometer-api: false + ceilometer-collector: false + # turn on swift + s-account: true + s-container: true + s-object: true + s-proxy: true + # Hardcode glanceclient path so the job can be run on glance patches + zuul_work_dir: src/git.openstack.org/openstack/python-glanceclient + - job: name: glanceclient-dsvm-functional parent: devstack-tox-functional description: | - devstack-based functional tests for glanceclient + Devstack-based functional tests for glanceclient. + + These test glanceclient against Image API v2 only. required-projects: - openstack/python-glanceclient timeout: 4200 vars: devstack_localrc: - # TODO(rosmaita): remove when glanceclient tests no longer - # use the Images v1 API - GLANCE_V1_ENABLED: true LIBS_FROM_GIT: python-glanceclient devstack_services: # turn off ceilometer @@ -39,9 +77,11 @@ - project: check: jobs: + - glanceclient-dsvm-functional-v1 - glanceclient-dsvm-functional - glanceclient-dsvm-functional-identity-v3-only: voting: false gate: jobs: + - glanceclient-dsvm-functional-v1 - glanceclient-dsvm-functional diff --git a/glanceclient/tests/functional/base.py b/glanceclient/tests/functional/base.py index 0efc0792..578dc395 100644 --- a/glanceclient/tests/functional/base.py +++ b/glanceclient/tests/functional/base.py @@ -48,9 +48,10 @@ class ClientTestBase(base.ClientTestBase): def _get_clients(self): self.creds = credentials().get_auth_args() + venv_name = os.environ.get('OS_TESTENV_NAME', 'functional') cli_dir = os.environ.get( 'OS_GLANCECLIENT_EXEC_DIR', - os.path.join(os.path.abspath('.'), '.tox/functional/bin')) + os.path.join(os.path.abspath('.'), '.tox/%s/bin' % venv_name)) return base.CLIClient( username=self.creds['username'], diff --git a/glanceclient/tests/functional/v1/__init__.py b/glanceclient/tests/functional/v1/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/glanceclient/tests/functional/v1/test_readonly_glance.py b/glanceclient/tests/functional/v1/test_readonly_glance.py new file mode 100644 index 00000000..122c61b1 --- /dev/null +++ b/glanceclient/tests/functional/v1/test_readonly_glance.py @@ -0,0 +1,73 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import re + +from tempest.lib import exceptions + +from glanceclient.tests.functional import base + + +class SimpleReadOnlyGlanceClientTest(base.ClientTestBase): + + """Read only functional python-glanceclient tests. + + This only exercises client commands that are read only. + """ + + def test_list_v1(self): + out = self.glance('--os-image-api-version 1 image-list') + endpoints = self.parser.listing(out) + self.assertTableStruct(endpoints, [ + 'ID', 'Name', 'Disk Format', 'Container Format', + 'Size', 'Status']) + + def test_fake_action(self): + self.assertRaises(exceptions.CommandFailed, + self.glance, + 'this-does-not-exist') + + def test_member_list_v1(self): + tenant_name = '--tenant-id %s' % self.creds['project_name'] + out = self.glance('--os-image-api-version 1 member-list', + params=tenant_name) + endpoints = self.parser.listing(out) + self.assertTableStruct(endpoints, + ['Image ID', 'Member ID', 'Can Share']) + + def test_help(self): + help_text = self.glance('--os-image-api-version 1 help') + lines = help_text.split('\n') + self.assertFirstLineStartsWith(lines, 'usage: glance') + + commands = [] + cmds_start = lines.index('Positional arguments:') + cmds_end = lines.index('Optional arguments:') + command_pattern = re.compile('^ {4}([a-z0-9\-\_]+)') + for line in lines[cmds_start:cmds_end]: + match = command_pattern.match(line) + if match: + commands.append(match.group(1)) + commands = set(commands) + wanted_commands = {'bash-completion', 'help', + 'image-create', 'image-delete', + 'image-download', 'image-list', + 'image-show', 'image-update', + 'member-create', 'member-delete', + 'member-list'} + self.assertEqual(commands, wanted_commands) + + def test_version(self): + self.glance('', flags='--version') + + def test_debug_list(self): + self.glance('--os-image-api-version 1 image-list', flags='--debug') diff --git a/glanceclient/tests/functional/v2/__init__.py b/glanceclient/tests/functional/v2/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/glanceclient/tests/functional/test_http_headers.py b/glanceclient/tests/functional/v2/test_http_headers.py similarity index 100% rename from glanceclient/tests/functional/test_http_headers.py rename to glanceclient/tests/functional/v2/test_http_headers.py diff --git a/glanceclient/tests/functional/test_readonly_glance.py b/glanceclient/tests/functional/v2/test_readonly_glance.py similarity index 86% rename from glanceclient/tests/functional/test_readonly_glance.py rename to glanceclient/tests/functional/v2/test_readonly_glance.py index ccd49d63..c024303a 100644 --- a/glanceclient/tests/functional/test_readonly_glance.py +++ b/glanceclient/tests/functional/v2/test_readonly_glance.py @@ -24,13 +24,6 @@ class SimpleReadOnlyGlanceClientTest(base.ClientTestBase): This only exercises client commands that are read only. """ - def test_list_v1(self): - out = self.glance('--os-image-api-version 1 image-list') - endpoints = self.parser.listing(out) - self.assertTableStruct(endpoints, [ - 'ID', 'Name', 'Disk Format', 'Container Format', - 'Size', 'Status']) - def test_list_v2(self): out = self.glance('--os-image-api-version 2 image-list') endpoints = self.parser.listing(out) @@ -41,14 +34,6 @@ class SimpleReadOnlyGlanceClientTest(base.ClientTestBase): self.glance, 'this-does-not-exist') - def test_member_list_v1(self): - tenant_name = '--tenant-id %s' % self.creds['project_name'] - out = self.glance('--os-image-api-version 1 member-list', - params=tenant_name) - endpoints = self.parser.listing(out) - self.assertTableStruct(endpoints, - ['Image ID', 'Member ID', 'Can Share']) - def test_member_list_v2(self): try: # NOTE(flwang): If set disk-format and container-format, Jenkins diff --git a/tools/fix_ca_bundle.sh b/tools/fix_ca_bundle.sh index 8e3dba20..cd35d8da 100755 --- a/tools/fix_ca_bundle.sh +++ b/tools/fix_ca_bundle.sh @@ -6,10 +6,12 @@ # assumptions: # - devstack is running # - the devstack tls-proxy service is running +# - the environment var OS_TESTENV_NAME is set in tox.ini (defaults +# to 'functional' # # This code based on a function in devstack lib/tls function set_ca_bundle { - local python_cmd='.tox/functional/bin/python' + local python_cmd=".tox/${OS_TESTENV_NAME:-functional}/bin/python" local capath=$($python_cmd -c $'try:\n from requests import certs\n print (certs.where())\nexcept ImportError: pass') # of course, each distro keeps the CA store in a different location local fedora_CA='/etc/pki/tls/certs/ca-bundle.crt' diff --git a/tox.ini b/tox.ini index e6915cce..d50c8ee2 100644 --- a/tox.ini +++ b/tox.ini @@ -30,7 +30,20 @@ warnerror = True # See glanceclient/tests/functional/README.rst # for information on running the functional tests. setenv = - OS_TEST_PATH = ./glanceclient/tests/functional + OS_TEST_PATH = ./glanceclient/tests/functional/v2 + OS_TESTENV_NAME = {envname} +whitelist_externals = + bash +commands = + bash tools/fix_ca_bundle.sh + python setup.py testr --testr-args='{posargs}' + +[testenv:functional-v1] +# TODO(rosmaita): remove this testenv at the beginning +# of the 'S' cycle +setenv = + OS_TEST_PATH = ./glanceclient/tests/functional/v1 + OS_TESTENV_NAME = {envname} whitelist_externals = bash commands =