infrastructure/movie-search-app/connect_tcp.py (58 lines of code) (raw):

# Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # TODO (https://github.com/GoogleCloudPlatform/python-docs-samples/issues/8253): remove old region tags # [START cloud_sql_postgres_sqlalchemy_connect_tcp] # [START cloud_sql_postgres_sqlalchemy_sslcerts] # [START cloud_sql_postgres_sqlalchemy_connect_tcp_sslcerts] import os import ssl import logging import sqlalchemy def connect_tcp_socket() -> sqlalchemy.engine.base.Engine: """Initializes a TCP connection pool for a PostgreSQL instance of Postgres.""" # Note: Saving credentials in environment variables is convenient, but not # secure - consider a more secure solution such as # Cloud Secret Manager (https://cloud.google.com/secret-manager) to help # keep secrets safe. if os.environ.get("INSTANCE_HOST"): db_host = os.environ[ "INSTANCE_HOST" ] # e.g. '127.0.0.1' ('172.17.0.1' if deployed to GAE Flex) else: db_host = "127.0.0.1" logging.warning(("INSTANCE_HOST is not set using default: %s", db_host)) if os.environ.get("DB_PORT"): db_port = os.environ["DB_PORT"] # e.g. '5432' else: db_port = "5432" logging.warning(("DB_PORT is not set using default: %s", db_port)) if os.environ.get("DB_USER"): db_user = os.environ["DB_USER"] # e.g. 'my-db-user' else: db_user = "movies_owner" logging.warning(("DB_USER is not set using default: %s", db_user)) if os.environ.get("DB_PASS"): db_pass = os.environ["DB_PASS"] # e.g. 'my-db-password' else: db_pass = "password" logging.warning(("DB_PASS is not set using default: %s", db_pass)) if os.environ.get("DB_NAME"): db_name = os.environ["DB_NAME"] # e.g. 'my-database' else: db_name = "movies" logging.warning(("DB_NAME is not set using default: %s", db_name)) # [END cloud_sql_postgres_sqlalchemy_connect_tcp] connect_args = {} # For deployments that connect directly to a PostgreSQL instance without # using the PostgreSQL Proxy, configuring SSL certificates will ensure the # connection is encrypted. if os.environ.get("DB_ROOT_CERT"): db_root_cert = os.environ["DB_ROOT_CERT"] # e.g. '/path/to/my/server-ca.pem' db_cert = os.environ["DB_CERT"] # e.g. '/path/to/my/client-cert.pem' db_key = os.environ["DB_KEY"] # e.g. '/path/to/my/client-key.pem' ssl_context = ssl.SSLContext() ssl_context.verify_mode = ssl.CERT_REQUIRED ssl_context.load_verify_locations(db_root_cert) ssl_context.load_cert_chain(db_cert, db_key) connect_args["ssl_context"] = ssl_context # [START cloud_sql_postgres_sqlalchemy_connect_tcp] pool = sqlalchemy.create_engine( # Equivalent URL: # postgresql+pg8000://<db_user>:<db_pass>@<db_host>:<db_port>/<db_name> sqlalchemy.engine.url.URL.create( drivername="postgresql+pg8000", username=db_user, password=db_pass, host=db_host, port=db_port, database=db_name, ), # [END cloud_sql_postgres_sqlalchemy_connect_tcp] connect_args=connect_args, # [START cloud_sql_postgres_sqlalchemy_connect_tcp] # [START_EXCLUDE] # [START cloud_sql_postgres_sqlalchemy_limit] # Pool size is the maximum number of permanent connections to keep. pool_size=5, # Temporarily exceeds the set pool_size if no connections are available. max_overflow=2, # The total number of concurrent connections for your application will be # a total of pool_size and max_overflow. # [END cloud_sql_postgres_sqlalchemy_limit] # [START cloud_sql_postgres_sqlalchemy_backoff] # SQLAlchemy automatically uses delays between failed connection attempts, # but provides no arguments for configuration. # [END cloud_sql_postgres_sqlalchemy_backoff] # [START cloud_sql_postgres_sqlalchemy_timeout] # 'pool_timeout' is the maximum number of seconds to wait when retrieving a # new connection from the pool. After the specified amount of time, an # exception will be thrown. pool_timeout=30, # 30 seconds # [END cloud_sql_postgres_sqlalchemy_timeout] # [START cloud_sql_postgres_sqlalchemy_lifetime] # 'pool_recycle' is the maximum number of seconds a connection can persist. # Connections that live longer than the specified amount of time will be # re-established pool_recycle=1800, # 30 minutes # [END cloud_sql_postgres_sqlalchemy_lifetime] # [END_EXCLUDE] ) return pool # [END cloud_sql_postgres_sqlalchemy_connect_tcp_sslcerts] # [END cloud_sql_postgres_sqlalchemy_sslcerts] # [END cloud_sql_postgres_sqlalchemy_connect_tcp]