Skip to content

Commit 9fa6f6e

Browse files
author
Saketram Durbha
committed
refactor Cloud SQL SQL Server samples
* use environment varialbe for proxy connection hostname over hardcoding it * make all environment variables required * include instructions in README for running locally on Windows * make code structure consistent with PostgreSQL and MySQL samples
1 parent b4bbea0 commit 9fa6f6e

File tree

3 files changed

+92
-66
lines changed

3 files changed

+92
-66
lines changed

cloud-sql/sql-server/sqlalchemy/README.md

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,29 +31,48 @@
3131
[instructions](https://cloud.google.com/sql/docs/postgres/connect-external-app#4_if_required_by_your_authentication_method_create_a_service_account).
3232
Download a JSON key to use to authenticate your connection.
3333

34-
1. Use the information noted in the previous steps:
34+
## Running locally
35+
To run this application locally, download and install the `cloud_sql_proxy` by
36+
following the instructions [here](https://cloud.google.com/sql/docs/mysql/sql-proxy#install).
37+
38+
### Linux / MacOS
39+
Use these terminal commands to initialize environment variables:
3540
```bash
3641
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service/account/key.json
3742
export CLOUD_SQL_CONNECTION_NAME='<MY-PROJECT>:<INSTANCE-REGION>:<INSTANCE-NAME>'
3843
export DB_USER='my-db-user'
3944
export DB_PASS='my-db-pass'
4045
export DB_NAME='my_db'
46+
export DB_HOST='127.0.0.1:1433'
4147
```
4248
Note: Saving credentials in environment variables is convenient, but not secure - consider a more
4349
secure solution such as [Cloud KMS](https://cloud.google.com/kms/) to help keep secrets safe.
4450

45-
## Running locally
51+
Then, use the following command to start the proxy in the background using TCP:
52+
```bash
53+
./cloud_sql_proxy -instances=${CLOUD_SQL_CONNECTION_NAME}=tcp:1433 sqlserver -u ${DB_USER} --host 127.0.0.1 &
54+
```
4655

47-
To run this application locally, download and install the `cloud_sql_proxy` by
48-
following the instructions [here](https://cloud.google.com/sql/docs/mysql/sql-proxy#install).
56+
### Windows / PowerShell
57+
Use these PowerShell commands to initialize environment variables:
58+
```powershell
59+
$env:GOOGLE_APPLICATION_CREDENTIALS="<CREDENTIALS_JSON_FILE>"
60+
$env:CLOUD_SQL_CONNECTION_NAME="<MY-PROJECT>:<INSTANCE-REGION>:<INSTANCE-NAME>"
61+
$env:DB_USER="my-db-user"
62+
$env:DB_PASS="my-db-pass"
63+
$env:DB_NAME="my_db"
64+
$env:DB_HOST="127.0.0.1:1433"
65+
```
66+
Note: Saving credentials in environment variables is convenient, but not secure - consider a more
67+
secure solution such as [Cloud KMS](https://cloud.google.com/kms/) to help keep secrets safe.
4968

50-
Then, use the following command to start the proxy in the
51-
background using TCP:
52-
```bash
53-
./cloud_sql_proxy -instances=${CLOUD_SQL_CONNECTION_NAME}=tcp:1433 sqlserver -u ${DB_USER} --host 127.0.0.1
69+
Then use this command to launch the proxy in a separate PowerShell session:
70+
```powershell
71+
Start-Process -filepath "C:\<path to proxy exe>" -ArgumentList "-instances=<MY-PROJECT>:<INSTANCE-REGION>:<INSTANCE-NAME>=tcp:1433 -credential_file=<CREDENTIALS_JSON_FILE>"
5472
```
5573

56-
Next, setup install the requirements into a virtual enviroment:
74+
### Testing the application
75+
Next, setup a virtual environment and install the application's requirements:
5776
```bash
5877
virtualenv --python python3 env
5978
source env/bin/activate

cloud-sql/sql-server/sqlalchemy/app.yaml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ env_variables:
2121
DB_USER: <your-username>
2222
DB_PASS: <your-password>
2323
DB_NAME: <your-db-name>
24-
# Whether the app is deployed or running locally
25-
DEPLOYED: true
24+
DB_HOST: 172.17.0.1:<PORT>
2625

2726
beta_settings:
28-
cloud_sql_instances: <project-name>:<region-name>:<instance-name>=tcp:1433
27+
cloud_sql_instances: <project-name>:<region-name>:<instance-name>=tcp:<PORT>

cloud-sql/sql-server/sqlalchemy/main.py

Lines changed: 62 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -29,60 +29,68 @@
2929

3030
logger = logging.getLogger()
3131

32-
# [START cloud_sql_server_sqlalchemy_create]
33-
# Remember - storing secrets in plaintext is potentially unsafe. Consider using
34-
# something like https://cloud.google.com/kms/ to help keep secrets secret.
35-
db_user = os.environ.get("DB_USER")
36-
db_pass = os.environ.get("DB_PASS")
37-
db_name = os.environ.get("DB_NAME")
38-
39-
# When deployed to GAE Flex for TCP, use "172.17.0.1" to connect
40-
host = "172.17.0.1" if os.environ.get("DEPLOYED") else "127.0.0.1"
41-
42-
# The SQLAlchemy engine will help manage interactions, including automatically
43-
# managing a pool of connections to your database
44-
db = sqlalchemy.create_engine(
45-
# Equivalent URL:
46-
# mssql+pyodbc://<db_user>:<db_pass>@/<host>:<port>/<db_name>?driver=ODBC+Driver+17+for+SQL+Server
47-
sqlalchemy.engine.url.URL(
48-
"mssql+pyodbc",
49-
username=db_user,
50-
password=db_pass,
51-
database=db_name,
52-
host=host,
53-
port=1433,
54-
query={"driver": "ODBC Driver 17 for SQL Server"},
55-
),
56-
# ... Specify additional properties here.
57-
# [START_EXCLUDE]
58-
# [START cloud_sql_server_sqlalchemy_limit]
59-
# Pool size is the maximum number of permanent connections to keep.
60-
pool_size=5,
61-
# Temporarily exceeds the set pool_size if no connections are available.
62-
max_overflow=2,
63-
# The total number of concurrent connections for your application will be
64-
# a total of pool_size and max_overflow.
65-
# [END cloud_sql_server_sqlalchemy_limit]
66-
# [START cloud_sql_server_sqlalchemy_backoff]
67-
# SQLAlchemy automatically uses delays between failed connection attempts,
68-
# but provides no arguments for configuration.
69-
# [END cloud_sql_server_sqlalchemy_backoff]
70-
# [START cloud_sql_server_sqlalchemy_timeout]
71-
# 'pool_timeout' is the maximum number of seconds to wait when retrieving a
72-
# new connection from the pool. After the specified amount of time, an
73-
# exception will be thrown.
74-
pool_timeout=30, # 30 seconds
75-
# [END cloud_sql_server_sqlalchemy_timeout]
76-
# [START cloud_sql_server_sqlalchemy_lifetime]
77-
# 'pool_recycle' is the maximum number of seconds a connection can persist.
78-
# Connections that live longer than the specified amount of time will be
79-
# reestablished
80-
pool_recycle=1800, # 30 minutes
81-
# [END cloud_sql_server_sqlalchemy_lifetime]
82-
echo=True # debug
83-
# [END_EXCLUDE]
84-
)
85-
# [END cloud_sql_server_sqlalchemy_create]
32+
33+
def init_tcp_connection_engine():
34+
# [START cloud_sql_server_sqlalchemy_create_tcp]
35+
# Remember - storing secrets in plaintext is potentially unsafe. Consider using
36+
# something like https://cloud.google.com/kms/ to help keep secrets secret.
37+
db_user = os.environ["DB_USER"]
38+
db_pass = os.environ["DB_PASS"]
39+
db_name = os.environ["DB_NAME"]
40+
41+
# Extract host and port from environment variable DB_HOST
42+
host_args = os.environ["DB_HOST"].split(":")
43+
host, port = host_args[0], int(host_args[1])
44+
45+
# The SQLAlchemy engine will help manage interactions, including automatically
46+
# managing a pool of connections to your database
47+
pool = sqlalchemy.create_engine(
48+
# Equivalent URL:
49+
# mssql+pyodbc://<db_user>:<db_pass>@/<host>:<port>/<db_name>?driver=ODBC+Driver+17+for+SQL+Server
50+
sqlalchemy.engine.url.URL(
51+
"mssql+pyodbc",
52+
username=db_user,
53+
password=db_pass,
54+
database=db_name,
55+
host=host,
56+
port=port,
57+
query={"driver": "ODBC Driver 17 for SQL Server"},
58+
),
59+
# ... Specify additional properties here.
60+
# [START_EXCLUDE]
61+
# [START cloud_sql_server_sqlalchemy_limit]
62+
# Pool size is the maximum number of permanent connections to keep.
63+
pool_size=5,
64+
# Temporarily exceeds the set pool_size if no connections are available.
65+
max_overflow=2,
66+
# The total number of concurrent connections for your application will be
67+
# a total of pool_size and max_overflow.
68+
# [END cloud_sql_server_sqlalchemy_limit]
69+
# [START cloud_sql_server_sqlalchemy_backoff]
70+
# SQLAlchemy automatically uses delays between failed connection attempts,
71+
# but provides no arguments for configuration.
72+
# [END cloud_sql_server_sqlalchemy_backoff]
73+
# [START cloud_sql_server_sqlalchemy_timeout]
74+
# 'pool_timeout' is the maximum number of seconds to wait when retrieving a
75+
# new connection from the pool. After the specified amount of time, an
76+
# exception will be thrown.
77+
pool_timeout=30, # 30 seconds
78+
# [END cloud_sql_server_sqlalchemy_timeout]
79+
# [START cloud_sql_server_sqlalchemy_lifetime]
80+
# 'pool_recycle' is the maximum number of seconds a connection can persist.
81+
# Connections that live longer than the specified amount of time will be
82+
# reestablished
83+
pool_recycle=1800, # 30 minutes
84+
# [END cloud_sql_server_sqlalchemy_lifetime]
85+
echo=True # debug
86+
# [END_EXCLUDE]
87+
)
88+
# [END cloud_sql_server_sqlalchemy_create_tcp]
89+
90+
return pool
91+
92+
93+
db = init_tcp_connection_engine()
8694

8795

8896
@app.before_first_request

0 commit comments

Comments
 (0)