Skip to content

Commit 544ad59

Browse files
committed
Refine endpoint filtering behaviour
1 parent bb3c59f commit 544ad59

File tree

1 file changed

+26
-18
lines changed

1 file changed

+26
-18
lines changed

capi_janitor/openstack/openstack.py

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,10 @@ class Auth(httpx.Auth):
2727
"""
2828
Authenticator class for OpenStack connections.
2929
"""
30-
def __init__(self, auth_url, application_credential_id, application_credential_secret, region_name):
30+
def __init__(self, auth_url, application_credential_id, application_credential_secret):
3131
self.url = auth_url
3232
self._application_credential_id = application_credential_id
3333
self._application_credential_secret = application_credential_secret
34-
self.region_name = region_name
3534
self._token = None
3635
self._user_id = None
3736
self._lock = asyncio.Lock()
@@ -154,11 +153,12 @@ class Cloud:
154153
"""
155154
Object for interacting with OpenStack clouds.
156155
"""
157-
def __init__(self, auth, transport, interface):
156+
def __init__(self, auth, transport, interface, region = None):
158157
self._auth = auth
159158
self._transport = transport
160159
self._interface = interface
161160
self._endpoints = {}
161+
self._region = region
162162
# A map of api name to client
163163
self._clients = {}
164164

@@ -175,18 +175,7 @@ async def __aenter__(self):
175175
else:
176176
raise
177177
self._endpoints = {
178-
entry["type"]: next(
179-
ep["url"]
180-
for ep in entry["endpoints"]
181-
if (
182-
ep["interface"] == self._interface
183-
# NOTE(scott): Entrypoint has 'region_id' and 'region'
184-
# fields whereas app cred has a 'region_name' field.
185-
# This code assumes that app cred 'region_name' maps
186-
# to catalog entry 'region' rather than 'region_id'.
187-
and ep["region"] == self._auth.region_name
188-
)
189-
)
178+
entry["type"]: self._service_endpoint(entry)["url"]
190179
for entry in response.json()["catalog"]
191180
if len(entry["endpoints"]) > 0
192181
}
@@ -229,6 +218,25 @@ def api_client(self, name, prefix = None):
229218
)
230219
return self._clients[name]
231220

221+
def _service_endpoint(self, endpoints):
222+
"""
223+
Filters the target cloud's catalog endpoints to find the relevant entry.
224+
"""
225+
iface_endpoints = [ep for ep in endpoints if ep["interface"] == self._interface]
226+
# If there's no region_name field in the clouds.yaml we use the first endpoint which
227+
# matches the interface name for consistent behaviour with the OpenStack CLI.
228+
if not self._region:
229+
return iface_endpoints[0]
230+
# Otherwise, further filter by region name
231+
region_endpoints = [ep for ep in iface_endpoints if ep["region"] == self._region]
232+
if len(region_endpoints) != 1:
233+
raise Exception(
234+
"Failed to find a unique catalog endpoints for"
235+
f" interface {region_endpoints[0]['interface']}"
236+
f" and region {region_endpoints[0]['region']}"
237+
)
238+
return region_endpoints[0]
239+
232240
@classmethod
233241
def from_clouds(cls, clouds, cloud, cacert):
234242
config = clouds["clouds"][cloud]
@@ -238,13 +246,13 @@ def from_clouds(cls, clouds, cloud, cacert):
238246
auth = Auth(
239247
auth_url,
240248
config["auth"]["application_credential_id"],
241-
config["auth"]["application_credential_secret"],
242-
config["region_name"]
249+
config["auth"]["application_credential_secret"]
243250
)
251+
region = config.get("region_name")
244252
# Create a default context using the verification from the config
245253
context = httpx.create_ssl_context(verify = config.get("verify", True))
246254
# If a cacert was given, load it into the context
247255
if cacert is not None:
248256
context.load_verify_locations(cadata = cacert)
249257
transport = httpx.AsyncHTTPTransport(verify = context)
250-
return cls(auth, transport, config.get("interface", "public"))
258+
return cls(auth, transport, config.get("interface", "public"), region)

0 commit comments

Comments
 (0)