Skip to content

Commit ac4b80b

Browse files
committed
authv1: Modernize returned service catalog
Keystone has only been returning v3 catalogs for a while now, so many client libraries have dropped support for the old v2 catalogs. We should switch to the new format so we stop causing KeyErrors like File ".../cliff/formatters/table.py", line 109, in add_rows table.add_row(_format_row(first_row)) ^^^^^^^^^^^^^^^^^^^^^^ File ".../cliff/formatters/table.py", line 38, in _format_row r = r.human_readable() ^^^^^^^^^^^^^^^^^^ File ".../openstackclient/identity/v3/catalog.py", line 37, in human_readable ret += " {}: {}\n".format(ep['interface'], ep['url']) ~~^^^^^^^^^^^^^ KeyError: 'interface' (Previously seen while trying to run `openstack catalog show` with latest python-openstackclient/osc-lib/openstacksdk -- but this used to work!) Change-Id: Ie8726b97e1dde7d7bfd8e4215af6af52e1fd870e Signed-off-by: Tim Burke <tim.burke@gmail.com>
1 parent 0c73602 commit ac4b80b

6 files changed

Lines changed: 74 additions & 6 deletions

File tree

swiftclient/authv1.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,15 @@ def catalog(self):
7070
# openstackclient wants this for the `catalog list` and
7171
# `catalog show` commands
7272
endpoints = [{
73+
'interface': 'public',
7374
'region': 'default',
74-
'publicURL': self._storage_url,
75+
'url': self._storage_url,
7576
}]
7677
if self.storage_url != self._storage_url:
7778
endpoints.insert(0, {
79+
'interface': 'public',
7880
'region': 'override',
79-
'publicURL': self.storage_url,
81+
'url': self.storage_url,
8082
})
8183

8284
return [
@@ -89,8 +91,9 @@ def catalog(self):
8991
'name': 'auth',
9092
'type': 'identity',
9193
'endpoints': [{
94+
'interface': 'public',
9295
'region': 'default',
93-
'publicURL': self.auth_url,
96+
'url': self.auth_url,
9497
}],
9598
}
9699
]
@@ -151,6 +154,8 @@ def __init__(self, auth_url, storage_url, account, username, auth_token,
151154
self._expires = None
152155
# following is used by openstackclient
153156
self.project_id = None
157+
self.domain_id = 'default'
158+
self.system_scoped = False
154159

155160
@property
156161
def expires(self):

swiftclient/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,7 @@ def get_auth_keystone(auth_url, user, key, os_options, **kwargs):
577577

578578
filter_kwargs = {}
579579
service_type = os_options.get('service_type') or 'object-store'
580-
endpoint_type = os_options.get('endpoint_type') or 'publicURL'
580+
endpoint_type = os_options.get('endpoint_type') or 'public'
581581
if os_options.get('region_name'):
582582
filter_kwargs['attr'] = 'region'
583583
filter_kwargs['filter_value'] = os_options['region_name']

test-requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ python-keystoneclient>=0.7.0
55
keystoneauth1>=3.4.0 # Apache-2.0
66
stestr>=2.0.0,!=3.0.0 # Apache-2.0
77
openstacksdk>=0.11.0 # Apache-2.0
8+
python-openstackclient>=3.12.0 # Apache-2.0
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Copyright (c) 2025 NVIDIA
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12+
# implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
import os
17+
import subprocess
18+
import unittest
19+
20+
from . import TEST_CONFIG
21+
22+
23+
class TestOpenStackClient(unittest.TestCase):
24+
@classmethod
25+
def setUpClass(cls):
26+
# NB: Only runs for v1 auth, to exercise our keystoneauth plugin
27+
cls.skip_tests = (TEST_CONFIG is None or
28+
TEST_CONFIG['auth_version'] != '1')
29+
cls.env = {
30+
'OS_AUTH_TYPE': 'v1password',
31+
'OS_AUTH_URL': TEST_CONFIG['auth_url'] or '',
32+
'OS_USERNAME': TEST_CONFIG['account_username'] or '',
33+
'OS_PASSWORD': TEST_CONFIG['password'] or '',
34+
'OS_CACERT': TEST_CONFIG['cacert'] or '',
35+
}
36+
if 'PATH' in os.environ:
37+
cls.env['PATH'] = os.environ['PATH']
38+
39+
def setUp(self):
40+
if self.skip_tests:
41+
raise unittest.SkipTest('SKIPPING V1-AUTH TESTS')
42+
43+
def _run(self, *args):
44+
subprocess.run(args, env=self.env, check=True)
45+
46+
def test_token_issue(self):
47+
self._run('openstack', 'token', 'issue')
48+
49+
def test_catalog_list(self):
50+
self._run('openstack', 'catalog', 'list')
51+
52+
def test_catalog_show(self):
53+
self._run('openstack', 'catalog', 'show', 'swift')
54+
self._run('openstack', 'catalog', 'show', 'object-store')
55+
self._run('openstack', 'catalog', 'show', 'auth')
56+
57+
def test_account_show(self):
58+
self._run('openstack', 'object', 'store', 'account', 'show')
59+
# If account show works and the openstacksdk tests work, presumably
60+
# container/object commands work, too
61+
62+
# service list? endpoint list?

test/unit/test_authv1.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ def test_get_access(self):
163163
self.assertEqual('object-store', catalog[0].get('type'))
164164
self.assertIn('endpoints', catalog[0])
165165
self.assertIn(self.storage_url, [
166-
e.get('publicURL') for e in catalog[0]['endpoints']])
166+
e.get('url') for e in catalog[0]['endpoints']])
167167

168168
def test_get_access_with_expiry(self):
169169
auth_plugin = authv1.PasswordPlugin(**self.options)

test/unit/test_shell.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3365,7 +3365,7 @@ class TestKeystoneOptions(MockHttpTest):
33653365
# options that are given default values in code if missing from CLI
33663366
defaults = {'auth-version': '2.0',
33673367
'service-type': 'object-store',
3368-
'endpoint-type': 'publicURL'}
3368+
'endpoint-type': 'public'}
33693369

33703370
def _build_os_opts(self, keys):
33713371
os_opts = {}

0 commit comments

Comments
 (0)