Skip to content
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 24 additions & 7 deletions capi_janitor/openstack/openstack.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,11 +153,12 @@ class Cloud:
"""
Object for interacting with OpenStack clouds.
"""
def __init__(self, auth, transport, interface):
def __init__(self, auth, transport, interface, region = None):
self._auth = auth
self._transport = transport
self._interface = interface
self._endpoints = {}
self._region = region
# A map of api name to client
self._clients = {}

Expand All @@ -174,11 +175,7 @@ async def __aenter__(self):
else:
raise
self._endpoints = {
entry["type"]: next(
ep["url"]
for ep in entry["endpoints"]
if ep["interface"] == self._interface
)
entry["type"]: self._service_endpoint(entry)["url"]
for entry in response.json()["catalog"]
if len(entry["endpoints"]) > 0
}
Expand Down Expand Up @@ -221,6 +218,25 @@ def api_client(self, name, prefix = None):
)
return self._clients[name]

def _service_endpoint(self, endpoints):
"""
Filters the target cloud's catalog endpoints to find the relevant entry.
"""
iface_endpoints = [ep for ep in endpoints if ep["interface"] == self._interface]
# If there's no region_name field in the clouds.yaml we use the first endpoint which
# matches the interface name for consistent behaviour with the OpenStack CLI.
if not self._region:
return iface_endpoints[0]
# Otherwise, further filter by region name
region_endpoints = [ep for ep in iface_endpoints if ep["region"] == self._region]
if len(region_endpoints) != 1:
raise Exception(
"Failed to find a unique catalog endpoints for"
f" interface {region_endpoints[0]['interface']}"
f" and region {region_endpoints[0]['region']}"
)
return region_endpoints[0]

@classmethod
def from_clouds(cls, clouds, cloud, cacert):
config = clouds["clouds"][cloud]
Expand All @@ -232,10 +248,11 @@ def from_clouds(cls, clouds, cloud, cacert):
config["auth"]["application_credential_id"],
config["auth"]["application_credential_secret"]
)
region = config.get("region_name")
# Create a default context using the verification from the config
context = httpx.create_ssl_context(verify = config.get("verify", True))
# If a cacert was given, load it into the context
if cacert is not None:
context.load_verify_locations(cadata = cacert)
transport = httpx.AsyncHTTPTransport(verify = context)
return cls(auth, transport, config.get("interface", "public"))
return cls(auth, transport, config.get("interface", "public"), region)
Loading