Skip to content

Commit 1725249

Browse files
authored
Handle DevStack service catalog correctly (#167)
* Handle catalog urls with prefixes correctly * Handle Cinder catalog service type alias
1 parent e82e29c commit 1725249

File tree

2 files changed

+29
-4
lines changed

2 files changed

+29
-4
lines changed

capi_janitor/openstack/openstack.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ class AuthenticationError(Exception):
2222
def __init__(self, user):
2323
super().__init__(f"failed to authenticate as user: {user}")
2424

25+
class CatalogError(Exception):
26+
"""
27+
Raised when an unknown catalog service type is requested.
28+
"""
29+
def __init__(self, name):
30+
super().__init__(f"service type {name} not found in OpenStack service catalog")
31+
2532

2633
class Auth(httpx.Auth):
2734
"""
@@ -128,13 +135,17 @@ class Client(rest.AsyncClient):
128135
Client for OpenStack APIs.
129136
"""
130137
def __init__(self, /, base_url, prefix = None, **kwargs):
131-
# Extract the path part of the base_url
138+
# Extract the path part of the base_url
132139
url = urllib.parse.urlsplit(base_url)
133140
# Initialise the client with the scheme/host
134141
super().__init__(base_url = f"{url.scheme}://{url.netloc}", **kwargs)
135-
# If another prefix is not given, use the path from the base URL as the prefix
142+
# If another prefix is not given, use the path from the base URL as the prefix,
143+
# otherwise combine the prefixes and remove duplicates path sections.
136144
# This ensures things like pagination work nicely without duplicating the prefix
137-
self._prefix = prefix or url.path
145+
if prefix:
146+
self._prefix = "/".join([url.path.rstrip("/"), prefix.lstrip("/").lstrip(url.path)])
147+
else:
148+
self._prefix = url.path
138149

139150
def __aenter__(self):
140151
# Prevent individual clients from being used in a context manager

capi_janitor/openstack/operator.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,21 @@ async def purge_openstack_resources(
203203

204204
# Delete volumes and snapshots associated with PVCs, unless requested
205205
# otherwise via the annotation
206-
volumeapi = cloud.api_client("volumev3")
206+
# NOTE(sd109): DevStack uses 'block-storage' as the Cinder service
207+
# type in the catalog which is technically correct and volumev3 is just
208+
# a historically valid alias, see:
209+
# - https://docs.openstack.org/keystone/latest/contributor/service-catalog.html
210+
# - https://service-types.openstack.org/service-types.json
211+
# TODO: Make use of https://opendev.org/openstack/os-service-types to improve
212+
# service type alias handling?
213+
try:
214+
volumeapi = cloud.api_client("volumev3")
215+
except KeyError:
216+
try:
217+
volumeapi = cloud.api_client("block-storage")
218+
except KeyError:
219+
raise openstack.CatalogError("volumev3 or block-storage")
220+
207221
snapshots_detail = volumeapi.resource("snapshots/detail")
208222
snapshots = volumeapi.resource("snapshots")
209223
check_snapshots = False

0 commit comments

Comments
 (0)