-
Notifications
You must be signed in to change notification settings - Fork 8
feat: Replace aiohttp.ClientSession with AlloyDBAdminAsyncClient #416
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
8fdc7d7
72a4814
2bcd203
2d1493a
65e3397
c498957
364c5b1
32cb0b5
edf3372
a3e3bda
a3800ba
9560e2d
4c22d48
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -18,10 +18,13 @@ | |||
import logging | ||||
from typing import Optional, TYPE_CHECKING | ||||
|
||||
import aiohttp | ||||
from cryptography import x509 | ||||
from google.api_core.client_options import ClientOptions | ||||
from google.api_core.gapic_v1.client_info import ClientInfo | ||||
from google.auth.credentials import TokenState | ||||
from google.auth.transport import requests | ||||
import google.cloud.alloydb_v1beta as v1beta | ||||
from google.protobuf import duration_pb2 | ||||
|
||||
from google.cloud.alloydb.connector.connection_info import ConnectionInfo | ||||
from google.cloud.alloydb.connector.version import __version__ as version | ||||
|
@@ -55,7 +58,7 @@ def __init__( | |||
alloydb_api_endpoint: str, | ||||
quota_project: Optional[str], | ||||
credentials: Credentials, | ||||
client: Optional[aiohttp.ClientSession] = None, | ||||
client: Optional[v1beta.AlloyDBAdminAsyncClient] = None, | ||||
driver: Optional[str] = None, | ||||
user_agent: Optional[str] = None, | ||||
) -> None: | ||||
|
@@ -72,23 +75,28 @@ def __init__( | |||
A credentials object created from the google-auth Python library. | ||||
Must have the AlloyDB Admin scopes. For more info check out | ||||
https://google-auth.readthedocs.io/en/latest/. | ||||
client (aiohttp.ClientSession): Async client used to make requests to | ||||
AlloyDB APIs. | ||||
client (v1beta.AlloyDBAdminAsyncClient): Async client used to make | ||||
requests to AlloyDB APIs. | ||||
Optional, defaults to None and creates new client. | ||||
driver (str): Database driver to be used by the client. | ||||
""" | ||||
user_agent = _format_user_agent(driver, user_agent) | ||||
headers = { | ||||
"x-goog-api-client": user_agent, | ||||
"User-Agent": user_agent, | ||||
"Content-Type": "application/json", | ||||
} | ||||
if quota_project: | ||||
headers["x-goog-user-project"] = quota_project | ||||
|
||||
self._client = client if client else aiohttp.ClientSession(headers=headers) | ||||
self._client = ( | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. does this still need to be lazy initialized? This was required for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What do you mean by "lazy initialized"? How is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @rhatgadkar-goog In the Connector initialization, the client is first set to
If it is not then you can improve performance of the first connect call by properly initializing client in Connector init. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't believe the Why do you think that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We need access to the So we can't initialize the We could move the Is it alright to move There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We do NOT want to move There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, I see. For the same argument of not having
What do you think about this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Need to check if something similar to this is possible with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is related to #205. So I'm adding this feature request to that issue |
||||
client | ||||
if client | ||||
else v1beta.AlloyDBAdminAsyncClient( | ||||
credentials=credentials, | ||||
client_options=ClientOptions( | ||||
api_endpoint=alloydb_api_endpoint, | ||||
quota_project_id=quota_project, | ||||
), | ||||
client_info=ClientInfo( | ||||
user_agent=user_agent, | ||||
), | ||||
) | ||||
) | ||||
self._credentials = credentials | ||||
self._alloydb_api_endpoint = alloydb_api_endpoint | ||||
# asyncpg does not currently support using metadata exchange | ||||
# only use metadata exchange for pg8000 driver | ||||
self._use_metadata = True if driver == "pg8000" else False | ||||
|
@@ -118,35 +126,21 @@ async def _get_metadata( | |||
Returns: | ||||
dict: IP addresses of the AlloyDB instance. | ||||
""" | ||||
headers = { | ||||
"Authorization": f"Bearer {self._credentials.token}", | ||||
} | ||||
parent = ( | ||||
f"projects/{project}/locations/{region}/clusters/{cluster}/instances/{name}" | ||||
) | ||||
|
||||
url = f"{self._alloydb_api_endpoint}/{API_VERSION}/projects/{project}/locations/{region}/clusters/{cluster}/instances/{name}/connectionInfo" | ||||
|
||||
resp = await self._client.get(url, headers=headers) | ||||
# try to get response json for better error message | ||||
try: | ||||
resp_dict = await resp.json() | ||||
if resp.status >= 400: | ||||
# if detailed error message is in json response, use as error message | ||||
message = resp_dict.get("error", {}).get("message") | ||||
if message: | ||||
resp.reason = message | ||||
# skip, raise_for_status will catch all errors in finally block | ||||
except Exception: | ||||
pass | ||||
finally: | ||||
resp.raise_for_status() | ||||
req = v1beta.GetConnectionInfoRequest(parent=parent) | ||||
resp = await self._client.get_connection_info(request=req) | ||||
|
||||
# Remove trailing period from PSC DNS name. | ||||
psc_dns = resp_dict.get("pscDnsName") | ||||
psc_dns = resp.psc_dns_name | ||||
if psc_dns: | ||||
psc_dns = psc_dns.rstrip(".") | ||||
|
||||
return { | ||||
"PRIVATE": resp_dict.get("ipAddress"), | ||||
"PUBLIC": resp_dict.get("publicIpAddress"), | ||||
"PRIVATE": resp.ip_address, | ||||
"PUBLIC": resp.public_ip_address, | ||||
"PSC": psc_dns, | ||||
} | ||||
|
||||
|
@@ -175,34 +169,17 @@ async def _get_client_certificate( | |||
tuple[str, list[str]]: tuple containing the CA certificate | ||||
and certificate chain for the AlloyDB instance. | ||||
""" | ||||
headers = { | ||||
"Authorization": f"Bearer {self._credentials.token}", | ||||
} | ||||
|
||||
url = f"{self._alloydb_api_endpoint}/{API_VERSION}/projects/{project}/locations/{region}/clusters/{cluster}:generateClientCertificate" | ||||
|
||||
data = { | ||||
"publicKey": pub_key, | ||||
"certDuration": "3600s", | ||||
"useMetadataExchange": self._use_metadata, | ||||
} | ||||
|
||||
resp = await self._client.post(url, headers=headers, json=data) | ||||
# try to get response json for better error message | ||||
try: | ||||
resp_dict = await resp.json() | ||||
if resp.status >= 400: | ||||
# if detailed error message is in json response, use as error message | ||||
message = resp_dict.get("error", {}).get("message") | ||||
if message: | ||||
resp.reason = message | ||||
# skip, raise_for_status will catch all errors in finally block | ||||
except Exception: | ||||
pass | ||||
finally: | ||||
resp.raise_for_status() | ||||
|
||||
return (resp_dict["caCert"], resp_dict["pemCertificateChain"]) | ||||
parent = f"projects/{project}/locations/{region}/clusters/{cluster}" | ||||
dur = duration_pb2.Duration() | ||||
dur.seconds = 3600 | ||||
req = v1beta.GenerateClientCertificateRequest( | ||||
parent=parent, | ||||
cert_duration=dur, | ||||
public_key=pub_key, | ||||
use_metadata_exchange=self._use_metadata, | ||||
) | ||||
resp = await self._client.generate_client_certificate(request=req) | ||||
return (resp.ca_cert, resp.pem_certificate_chain) | ||||
|
||||
async def get_connection_info( | ||||
self, | ||||
|
@@ -267,9 +244,3 @@ async def get_connection_info( | |||
ip_addrs, | ||||
expiration, | ||||
) | ||||
|
||||
async def close(self) -> None: | ||||
"""Close AlloyDBClient gracefully.""" | ||||
logger.debug("Waiting for connector's http client to close") | ||||
await self._client.close() | ||||
logger.debug("Closed connector's http client") |
Uh oh!
There was an error while loading. Please reload this page.