From 9606fc25cc8a13d28a526066a01a95024ec0e970 Mon Sep 17 00:00:00 2001 From: Jack Wotherspoon Date: Wed, 3 May 2023 13:24:55 -0400 Subject: [PATCH] chore(cloudsql): update samples to gen2 functions and v2 proxy (#9854) * chore(cloudsql): update samples to gen2 Cloud Functions * chore: update samples to v2 proxy * chore: address PR comments --- cloud-sql/mysql/sqlalchemy/README.md | 352 ++++++++++++++---- cloud-sql/mysql/sqlalchemy/app.flexible.yaml | 4 +- cloud-sql/mysql/sqlalchemy/app.standard.yaml | 4 +- cloud-sql/mysql/sqlalchemy/deployment.yaml | 11 +- cloud-sql/mysql/sqlalchemy/main.py | 3 + cloud-sql/mysql/sqlalchemy/requirements.txt | 1 + cloud-sql/postgres/sqlalchemy/README.md | 350 +++++++++++++---- .../postgres/sqlalchemy/app.flexible.yaml | 4 +- .../postgres/sqlalchemy/app.standard.yaml | 4 +- cloud-sql/postgres/sqlalchemy/deployment.yaml | 11 +- cloud-sql/postgres/sqlalchemy/main.py | 3 + .../postgres/sqlalchemy/requirements.txt | 1 + cloud-sql/sql-server/sqlalchemy/README.md | 182 ++++----- .../sql-server/sqlalchemy/app.flexible.yaml | 2 +- .../sql-server/sqlalchemy/app.standard.yaml | 4 +- .../sql-server/sqlalchemy/deployment.yaml | 11 +- cloud-sql/sql-server/sqlalchemy/main.py | 3 + .../sql-server/sqlalchemy/requirements.txt | 1 + 18 files changed, 695 insertions(+), 256 deletions(-) diff --git a/cloud-sql/mysql/sqlalchemy/README.md b/cloud-sql/mysql/sqlalchemy/README.md index d28a72c18c31..7ccada71b169 100644 --- a/cloud-sql/mysql/sqlalchemy/README.md +++ b/cloud-sql/mysql/sqlalchemy/README.md @@ -1,76 +1,293 @@ -# Connecting to Cloud SQL - MySQL +# Connecting to Cloud SQL - mysql + +This demo application can be used to connect to Cloud SQL in two different ways: + +1. [The Cloud SQL Python Connector](https://github.com/GoogleCloudPlatform/cloud-sql-python-connector) (recommended) + +2. [The Cloud SQL Auth Proxy](https://github.com/GoogleCloudPlatform/cloud-sql-proxy) + +Using the Cloud SQL Python Connector library is recommended over the Cloud SQL Auth +Proxy as it provides all the same functionality and features but as a native +Python package. See [cloud-sql-python-connector package](https://pypi.org/project/cloud-sql-python-connector/). ## Before you begin -1. If you haven't already, set up a Python Development Environment by following the [python setup guide](https://cloud.google.com/python/setup) and +1. If you haven't already, set up a Python Development Environment by following the [python setup guide](https://cloud.google.com/python/setup) and [create a project](https://cloud.google.com/resource-manager/docs/creating-managing-projects#creating_a_project). -1. Create a 2nd Gen Cloud SQL Instance by following these -[instructions](https://cloud.google.com/sql/docs/mysql/create-instance). Note the connection string, -database user, and database password that you create. +1. Create a 2nd Gen Cloud SQL Instance by following these +[instructions](https://cloud.google.com/sql/docs/mysql/create-instance). Note the connection +string, database user, and database password that you create. -1. Create a database for your application by following these +1. Create a database for your application by following these [instructions](https://cloud.google.com/sql/docs/mysql/create-manage-databases). Note the database -name. +name. -1. Create a service account with the 'Cloud SQL Client' permissions by following these +1. Create a service account with the 'Cloud SQL Client' permissions by following these [instructions](https://cloud.google.com/sql/docs/mysql/connect-external-app#4_if_required_by_your_authentication_method_create_a_service_account). -Download a JSON key to use to authenticate your connection. +Download a JSON key to use to authenticate your connection. + +## Cloud SQL Python Connector Usage + +### Run App Locally + +To run the demo application locally using the Cloud SQL Python Connector, set +environment variables and install dependencies as shown below. + +Note: The `INSTANCE_CONNECTION_NAME` for your instance can be found on the +**Overview** page for your instance in the +[Google Cloud console](https://console.cloud.google.com/sql) or by running +the following command: + +```sh +gcloud sql instances describe --format='value(connectionName)' +``` + +#### Linux / Mac OS + +Use these terminal commands to initialize environment variables: + +```bash +export GOOGLE_APPLICATION_CREDENTIALS='/path/to/service/account/key.json' +export INSTANCE_CONNECTION_NAME='::' +export DB_USER='' +export DB_PASS='' +export DB_NAME='' +``` + +Note: Saving credentials in environment variables is convenient, but not secure - consider a more +secure solution such as [Secret Manager](https://cloud.google.com/secret-manager/docs/overview) to +help keep secrets safe. + +#### Windows/PowerShell + +Use these PowerShell commands to initialize environment variables: + +```powershell +$env:GOOGLE_APPLICATION_CREDENTIALS="/path/to/service/account/key.json" +$env:INSTANCE_CONNECTION_NAME="::" +$env:DB_USER="" +$env:DB_PASS="" +$env:DB_NAME="" +``` + +Note: Saving credentials in environment variables is convenient, but not secure - consider a more +secure solution such as [Secret Manager](https://cloud.google.com/secret-manager/docs/overview) to +help keep secrets safe. + +#### Install Dependencies + +Next, install the requirements into a virtual environment: + +```bash +virtualenv --python python3 env +source env/bin/activate +pip install -r requirements.txt +``` + +#### Test the Application + +Finally, start the application: + +```bash +python app.py +``` + +Navigate towards `http://127.0.0.1:8080` to verify your application is running correctly. + +### Deploy to App Engine Standard + +To run on GAE-Standard, create an App Engine project by following the setup with these +[instructions](https://cloud.google.com/appengine/docs/standard/python3/quickstart#before-you-begin). + +Update `app.standard.yaml` with the correct values to pass the environment +variables into the runtime. Your `app.standard.yaml` file should look like this: + +Note: If you want to connect to Cloud SQL over Private IP, add the additional +env variable `PRIVATE_IP: True` below. + +```yaml +runtime: python310 +entrypoint: gunicorn -b :$PORT app:app + +env_variables: + INSTANCE_CONNECTION_NAME: :: + DB_USER: + DB_PASS: + DB_NAME: +``` + +Note: Saving credentials in environment variables is convenient, but not secure - consider a more +secure solution such as [Secret Manager](https://cloud.google.com/secret-manager/docs/overview) to +help keep secrets safe. + +Next, the following command will deploy the application to your Google Cloud project: + +```bash +gcloud app deploy app.standard.yaml +``` + +### Deploy to App Engine Flexible + +To run on GAE-Flexible, create an App Engine project by following the setup for these +[instructions](https://cloud.google.com/appengine/docs/flexible/python/quickstart#before-you-begin). + +First, update `app.flexible.yaml` with the correct values to pass the environment +variables into the runtime. Your `app.flexible.yaml` file should look like this: -## Running locally +Note: If you want to connect to Cloud SQL over Private IP, add the additional +env variable `PRIVATE_IP: True` below. -To run this application locally, download and install the `cloud_sql_proxy` by -following the instructions -[here](https://cloud.google.com/sql/docs/mysql/sql-proxy#install). +```yaml +runtime: custom +env: flex +entrypoint: gunicorn -b :$PORT app:app + +env_variables: + INSTANCE_CONNECTION_NAME: :: + DB_USER: + DB_PASS: + DB_NAME: +``` + +Note: Saving credentials in environment variables is convenient, but not secure - consider a more +secure solution such as [Secret Manager](https://cloud.google.com/secret-manager/docs/overview) to +help keep secrets safe. + +Next, the following command will deploy the application to your Google Cloud project: + +```bash +gcloud app deploy app.flexible.yaml +``` + +### Deploy to Cloud Run + +See the [Cloud Run documentation](https://cloud.google.com/sql/docs/mysql/connect-run) +for more details on connecting a Cloud Run service to Cloud SQL. + +Note: If you want to connect to Cloud SQL over Private IP, add the additional +env variable `--set-env-vars PRIVATE_IP=True` and +flag `--vpc-connector ` below. + +```sh +gcloud run deploy cloud-sql-demo \ + --allow-unauthenticated \ + --set-env-vars INSTANCE_CONNECTION_NAME='::' \ + --set-env-vars DB_USER='' \ + --set-env-vars DB_PASS='' \ + --set-env-vars DB_NAME='' +``` + +Navigate your browser to the URL output at the end of the deployment process +to view the demo app! + +It is recommended to use the [Secret Manager integration](https://cloud.google.com/run/docs/configuring/secrets) for Cloud Run instead +of using environment variables for the SQL configuration. The service injects the SQL credentials from +Secret Manager at runtime via an environment variable. + +Create secrets via the command line: + +```sh +echo -n $INSTANCE_CONNECTION_NAME | \ + gcloud secrets create [INSTANCE_CONNECTION_NAME_SECRET] --data-file=- +``` + +Deploy the service to Cloud Run specifying the env var name and secret name: + +```sh +gcloud run deploy cloud-sql-demo \ + --allow-unauthenticated \ + --update-secrets INSTANCE_CONNECTION_NAME=[INSTANCE_CONNECTION_NAME_SECRET]:latest,\ + DB_USER=[DB_USER_SECRET]:latest, \ + DB_PASS=[DB_PASS_SECRET]:latest, \ + DB_NAME=[DB_NAME_SECRET]:latest +``` + +### Deploy to Cloud Functions + +To deploy the service to [Cloud Functions](https://cloud.google.com/functions/docs) run the following command: + +Note: If you want to connect to Cloud SQL over Private IP, add the additional +env variable `--set-env-vars PRIVATE_IP=True` and +flag `--vpc-connector ` below. + +```sh +gcloud functions deploy votes --gen2 --runtime python310 --trigger-http \ + --allow-unauthenticated \ + --entry-point votes \ + --region \ + --set-env-vars INSTANCE_CONNECTION_NAME=:: \ + --set-env-vars DB_USER=$DB_USER \ + --set-env-vars DB_PASS=$DB_PASS \ + --set-env-vars DB_NAME=$DB_NAME +``` + +Take note of the URL output at the end of the deployment process to view your function! + +## Cloud SQL Auth Proxy Usage + +### Running locally + +To run this application locally, download and install the `cloud-sql-proxy` by +following the instructions [here](https://cloud.google.com/sql/docs/mysql/sql-proxy#install). Instructions are provided below for using the proxy with a TCP connection or a Unix Domain Socket. On Linux or Mac OS you can use either option, but on Windows the proxy currently requires a TCP connection. -### Launch proxy with TCP +#### Launch proxy with TCP To run the sample locally with a TCP connection, set environment variables and launch the proxy as shown below. -#### Linux / Mac OS +##### Linux / Mac OS + Use these terminal commands to initialize environment variables: + ```bash -export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service/account/key.json +export GOOGLE_APPLICATION_CREDENTIALS='/path/to/service/account/key.json' export INSTANCE_HOST='127.0.0.1' export DB_PORT='3306' export DB_USER='' export DB_PASS='' export DB_NAME='' ``` + Note: Saving credentials in environment variables is convenient, but not secure - consider a more secure solution such as [Secret Manager](https://cloud.google.com/secret-manager/docs/overview) to help keep secrets safe. Then use this command to launch the proxy in the background: + ```bash -./cloud_sql_proxy -instances=::=tcp:3306 -credential_file=$GOOGLE_APPLICATION_CREDENTIALS & +./cloud-sql-proxy :: & ``` -#### Windows/PowerShell +##### Windows/PowerShell + Use these PowerShell commands to initialize environment variables: + ```powershell -$env:GOOGLE_APPLICATION_CREDENTIALS="" +$env:GOOGLE_APPLICATION_CREDENTIALS="/path/to/service/account/key.json" $env:INSTANCE_HOST="127.0.0.1" $env:DB_PORT="3306" $env:DB_USER="" $env:DB_PASS="" $env:DB_NAME="" ``` + Note: Saving credentials in environment variables is convenient, but not secure - consider a more secure solution such as [Secret Manager](https://cloud.google.com/secret-manager/docs/overview) to help keep secrets safe. Then use this command to launch the proxy in a separate PowerShell session: + ```powershell -Start-Process -filepath "C:\" -ArgumentList "-instances=::=tcp:3306 -credential_file=" +Start-Process -filepath "C:\" -ArgumentList "::" ``` -### Launch proxy with Unix Domain Socket +#### Launch proxy with Unix Domain Socket + NOTE: this option is currently only supported on Linux and Mac OS. Windows users should use the [Launch proxy with TCP](#launch-proxy-with-tcp) option. @@ -83,25 +300,29 @@ sudo chown -R $USER /cloudsql ``` Use these terminal commands to initialize other environment variables as well: + ```bash -export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service/account/key.json -export INSTANCE_UNIX_SOCKET='./cloudsql/::' +export GOOGLE_APPLICATION_CREDENTIALS='/path/to/service/account/key.json' +export INSTANCE_UNIX_SOCKET='/cloudsql/::' export DB_USER='' export DB_PASS='' export DB_NAME='' ``` + Note: Saving credentials in environment variables is convenient, but not secure - consider a more secure solution such as [Secret Manager](https://cloud.google.com/secret-manager/docs/overview) to help keep secrets safe. Then use this command to launch the proxy in the background: + ```bash -./cloud_sql_proxy -dir=./cloudsql --instances=:: --credential_file=$GOOGLE_APPLICATION_CREDENTIALS & +./cloud-sql-proxy --unix-socket /cloudsql :: & ``` -### Testing the application +#### Testing the application Next, setup install the requirements into a virtual environment: + ```bash virtualenv --python python3 env source env/bin/activate @@ -109,18 +330,19 @@ pip install -r requirements.txt ``` Finally, start the application: + ```bash python app.py ``` Navigate towards `http://127.0.0.1:8080` to verify your application is running correctly. -## Deploy to App Engine Standard +### Deploy to App Engine Standard -To run on GAE-Standard, create an App Engine project by following the setup for these +To run on GAE-Standard, create an App Engine project by following the setup for these [instructions](https://cloud.google.com/appengine/docs/standard/python3/quickstart#before-you-begin). -First, update `app.standard.yaml` with the correct values to pass the environment +First, update `app.standard.yaml` with the correct values to pass the environment variables into the runtime. Your `app.standard.yaml` file should look like this: ```yaml @@ -128,7 +350,7 @@ runtime: python37 entrypoint: gunicorn -b :$PORT app:app env_variables: - INSTANCE_UNIX_SOCKET: /cloudsql/:: + INSTANCE_UNIX_SOCKET: /cloudsql/:: DB_USER: DB_PASS: DB_NAME: @@ -144,12 +366,12 @@ Next, the following command will deploy the application to your Google Cloud pro gcloud app deploy app.standard.yaml ``` -## Deploy to App Engine Flexible +### Deploy to App Engine Flexible -To run on GAE-Flexible, create an App Engine project by following the setup for these +To run on GAE-Flexible, create an App Engine project by following the setup for these [instructions](https://cloud.google.com/appengine/docs/flexible/python/quickstart#before-you-begin). -First, update `app.flexible.yaml` with the correct values to pass the environment +First, update `app.flexible.yaml` with the correct values to pass the environment variables into the runtime. Your `app.flexible.yaml` file should look like this: ```yaml @@ -158,13 +380,13 @@ env: flex entrypoint: gunicorn -b :$PORT app:app env_variables: - INSTANCE_UNIX_SOCKET: /cloudsql/:: + INSTANCE_UNIX_SOCKET: /cloudsql/:: DB_USER: DB_PASS: DB_NAME: beta_settings: - cloud_sql_instances: :: + cloud_sql_instances: :: ``` Note: Saving credentials in environment variables is convenient, but not secure - consider a more @@ -177,72 +399,58 @@ Next, the following command will deploy the application to your Google Cloud pro gcloud app deploy app.flexible.yaml ``` -## Deploy to Cloud Run +### Deploy to Cloud Run See the [Cloud Run documentation](https://cloud.google.com/sql/docs/mysql/connect-run) for more details on connecting a Cloud Run service to Cloud SQL. -1. Build the container image: - ```sh -gcloud builds submit --tag gcr.io//run-mysql -``` - -2. Deploy the service to Cloud Run: - -```sh -gcloud run deploy run-mysql --image gcr.io//run-mysql \ - --add-cloudsql-instances '::' \ - --set-env-vars INSTANCE_UNIX_SOCKET='/cloudsql/::' \ +gcloud run deploy cloud-sql-demo \ + --add-cloudsql-instances '::' \ + --set-env-vars INSTANCE_UNIX_SOCKET='/cloudsql/::' \ --set-env-vars DB_USER='' \ --set-env-vars DB_PASS='' \ --set-env-vars DB_NAME='' ``` -Take note of the URL output at the end of the deployment process. - -Replace environment variables with the correct values for your Cloud SQL -instance configuration. +Navigate your browser to the URL output at the end of the deployment process +to view the demo app! It is recommended to use the [Secret Manager integration](https://cloud.google.com/run/docs/configuring/secrets) for Cloud Run instead of using environment variables for the SQL configuration. The service injects the SQL credentials from Secret Manager at runtime via an environment variable. Create secrets via the command line: + ```sh echo -n $INSTANCE_UNIX_SOCKET | \ gcloud secrets create [INSTANCE_UNIX_SOCKET_SECRET] --data-file=- ``` Deploy the service to Cloud Run specifying the env var name and secret name: + ```sh -gcloud beta run deploy SERVICE --image gcr.io//run-sql \ - --add-cloudsql-instances :: \ - --update-secrets INSTANCE_UNIX_SOCKET=[INSTANCE_UNIX_SOCKET_SECRET]:latest,\ - DB_USER=[DB_USER_SECRET]:latest, \ - DB_PASS=[DB_PASS_SECRET]:latest, \ - DB_NAME=[DB_NAME_SECRET]:latest +gcloud run deploy cloud-sql-demo \ + --add-cloudsql-instances :: \ + --update-secrets INSTANCE_UNIX_SOCKET=[INSTANCE_UNIX_SOCKET_SECRET]:latest,\ + DB_USER=[DB_USER_SECRET]:latest, \ + DB_PASS=[DB_PASS_SECRET]:latest, \ + DB_NAME=[DB_NAME_SECRET]:latest ``` -3. Navigate your browser to the URL noted in step 2. - -For more details about using Cloud Run see http://cloud.run. -Review other [Python on Cloud Run samples](../../../run/). - -## Deploy to Cloud Functions +### Deploy to Cloud Functions To deploy the service to [Cloud Functions](https://cloud.google.com/functions/docs) run the following command: ```sh -gcloud functions deploy votes --runtime python39 --trigger-http --allow-unauthenticated \ ---set-env-vars INSTANCE_UNIX_SOCKET=/cloudsql/:: \ ---set-env-vars DB_USER=$DB_USER \ ---set-env-vars DB_PASS=$DB_PASS \ - --set-env-vars DB_NAME=$DB_NAME +gcloud functions deploy votes --gen2 --runtime python310 --trigger-http \ + --allow-unauthenticated \ + --entry-point votes \ + --region \ + --set-env-vars INSTANCE_UNIX_SOCKET=/cloudsql/:: \ + --set-env-vars DB_USER=$DB_USER \ + --set-env-vars DB_PASS=$DB_PASS \ + --set-env-vars DB_NAME=$DB_NAME ``` -Take note of the URL output at the end of the deployment process or run the following to view your function: - -```sh -gcloud app browse -``` +Take note of the URL output at the end of the deployment process to view your function! diff --git a/cloud-sql/mysql/sqlalchemy/app.flexible.yaml b/cloud-sql/mysql/sqlalchemy/app.flexible.yaml index 98229510b48e..595b8a636dde 100644 --- a/cloud-sql/mysql/sqlalchemy/app.flexible.yaml +++ b/cloud-sql/mysql/sqlalchemy/app.flexible.yaml @@ -21,10 +21,10 @@ entrypoint: gunicorn -b :$PORT app:app # Cloud Secret Manager (https://cloud.google.com/secret-manager) to help # keep secrets safe. env_variables: - INSTANCE_UNIX_SOCKET: /cloudsql/:: + INSTANCE_UNIX_SOCKET: /cloudsql/:: DB_USER: DB_PASS: DB_NAME: beta_settings: - cloud_sql_instances: :: + cloud_sql_instances: :: diff --git a/cloud-sql/mysql/sqlalchemy/app.standard.yaml b/cloud-sql/mysql/sqlalchemy/app.standard.yaml index a8e64b396f93..394ffa96457c 100644 --- a/cloud-sql/mysql/sqlalchemy/app.standard.yaml +++ b/cloud-sql/mysql/sqlalchemy/app.standard.yaml @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -runtime: python37 +runtime: python310 entrypoint: gunicorn -b :$PORT app:app # Note: Saving credentials in environment variables is convenient, but not @@ -20,7 +20,7 @@ entrypoint: gunicorn -b :$PORT app:app # Cloud Secret Manager (https://cloud.google.com/secret-manager) to help # keep secrets safe. env_variables: - INSTANCE_UNIX_SOCKET: /cloudsql/:: + INSTANCE_UNIX_SOCKET: /cloudsql/:: DB_USER: DB_PASS: DB_NAME: diff --git a/cloud-sql/mysql/sqlalchemy/deployment.yaml b/cloud-sql/mysql/sqlalchemy/deployment.yaml index fe51e7c53afb..dd9cd1c684d3 100644 --- a/cloud-sql/mysql/sqlalchemy/deployment.yaml +++ b/cloud-sql/mysql/sqlalchemy/deployment.yaml @@ -61,18 +61,17 @@ spec: # This uses the latest version of the Cloud SQL proxy # It is recommended to use a specific version for production environments. # See: https://github.com/GoogleCloudPlatform/cloudsql-proxy - image: gcr.io/cloudsql-docker/gce-proxy:latest - command: - - "/cloud_sql_proxy" - + image: gcr.io/cloud-sql-connectors/cloud-sql-proxy:latest + args: # If connecting from a VPC-native GKE cluster, you can use the # following flag to have the proxy connect over private IP - # - "-ip_address_types=PRIVATE" + # - "--private-ip" # tcp should be set to the port the proxy should listen on # and should match the DB_PORT value set above. # Defaults: MySQL: 3306, Postgres: 5432, SQLServer: 1433 - - "-instances==tcp:3306" + - "--port=3306" + - "" securityContext: # The default Cloud SQL proxy image runs as the # "nonroot" user and group (uid: 65532) by default. diff --git a/cloud-sql/mysql/sqlalchemy/main.py b/cloud-sql/mysql/sqlalchemy/main.py index 9330ea19a7fd..84b7d9005751 100644 --- a/cloud-sql/mysql/sqlalchemy/main.py +++ b/cloud-sql/mysql/sqlalchemy/main.py @@ -14,6 +14,8 @@ from flask import render_template, Response +import functions_framework + from app import get_index_context, init_connection_pool, migrate_db, save_vote ############ TABS vs. SPACES App for Cloud Functions ############ @@ -24,6 +26,7 @@ migrate_db(db) +@functions_framework.http def votes(request): if request.method == "GET": context = get_index_context(db) diff --git a/cloud-sql/mysql/sqlalchemy/requirements.txt b/cloud-sql/mysql/sqlalchemy/requirements.txt index 103fd6a1165e..478588719cbd 100644 --- a/cloud-sql/mysql/sqlalchemy/requirements.txt +++ b/cloud-sql/mysql/sqlalchemy/requirements.txt @@ -3,3 +3,4 @@ SQLAlchemy==2.0.12 PyMySQL==1.0.3 gunicorn==20.1.0 cloud-sql-python-connector==1.2.2 +functions-framework==3.3.0 diff --git a/cloud-sql/postgres/sqlalchemy/README.md b/cloud-sql/postgres/sqlalchemy/README.md index d0f5be289824..7a81a3622e83 100644 --- a/cloud-sql/postgres/sqlalchemy/README.md +++ b/cloud-sql/postgres/sqlalchemy/README.md @@ -1,75 +1,293 @@ # Connecting to Cloud SQL - Postgres +This demo application can be used to connect to Cloud SQL in two different ways: + +1. [The Cloud SQL Python Connector](https://github.com/GoogleCloudPlatform/cloud-sql-python-connector) (recommended) + +2. [The Cloud SQL Auth Proxy](https://github.com/GoogleCloudPlatform/cloud-sql-proxy) + +Using the Cloud SQL Python Connector library is recommended over the Cloud SQL Auth +Proxy as it provides all the same functionality and features but as a native +Python package. See [cloud-sql-python-connector package](https://pypi.org/project/cloud-sql-python-connector/). + ## Before you begin -1. If you haven't already, set up a Python Development Environment by following the [python setup guide](https://cloud.google.com/python/setup) and +1. If you haven't already, set up a Python Development Environment by following the [python setup guide](https://cloud.google.com/python/setup) and [create a project](https://cloud.google.com/resource-manager/docs/creating-managing-projects#creating_a_project). -1. Create a 2nd Gen Cloud SQL Instance by following these -[instructions](https://cloud.google.com/sql/docs/postgres/create-instance). Note the connection +1. Create a 2nd Gen Cloud SQL Instance by following these +[instructions](https://cloud.google.com/sql/docs/postgres/create-instance). Note the connection string, database user, and database password that you create. -1. Create a database for your application by following these +1. Create a database for your application by following these [instructions](https://cloud.google.com/sql/docs/postgres/create-manage-databases). Note the database -name. +name. -1. Create a service account with the 'Cloud SQL Client' permissions by following these +1. Create a service account with the 'Cloud SQL Client' permissions by following these [instructions](https://cloud.google.com/sql/docs/postgres/connect-external-app#4_if_required_by_your_authentication_method_create_a_service_account). -Download a JSON key to use to authenticate your connection. +Download a JSON key to use to authenticate your connection. + +## Cloud SQL Python Connector Usage + +### Run App Locally + +To run the demo application locally using the Cloud SQL Python Connector, set +environment variables and install dependencies as shown below. + +Note: The `INSTANCE_CONNECTION_NAME` for your instance can be found on the +**Overview** page for your instance in the +[Google Cloud console](https://console.cloud.google.com/sql) or by running +the following command: + +```sh +gcloud sql instances describe --format='value(connectionName)' +``` + +#### Linux / Mac OS + +Use these terminal commands to initialize environment variables: + +```bash +export GOOGLE_APPLICATION_CREDENTIALS='/path/to/service/account/key.json' +export INSTANCE_CONNECTION_NAME='::' +export DB_USER='' +export DB_PASS='' +export DB_NAME='' +``` + +Note: Saving credentials in environment variables is convenient, but not secure - consider a more +secure solution such as [Secret Manager](https://cloud.google.com/secret-manager/docs/overview) to +help keep secrets safe. + +#### Windows/PowerShell + +Use these PowerShell commands to initialize environment variables: + +```powershell +$env:GOOGLE_APPLICATION_CREDENTIALS="/path/to/service/account/key.json" +$env:INSTANCE_CONNECTION_NAME="::" +$env:DB_USER="" +$env:DB_PASS="" +$env:DB_NAME="" +``` + +Note: Saving credentials in environment variables is convenient, but not secure - consider a more +secure solution such as [Secret Manager](https://cloud.google.com/secret-manager/docs/overview) to +help keep secrets safe. -## Running locally +#### Install Dependencies -To run this application locally, download and install the `cloud_sql_proxy` by +Next, install the requirements into a virtual environment: + +```bash +virtualenv --python python3 env +source env/bin/activate +pip install -r requirements.txt +``` + +#### Test the Application + +Finally, start the application: + +```bash +python app.py +``` + +Navigate towards `http://127.0.0.1:8080` to verify your application is running correctly. + +### Deploy to App Engine Standard + +To run on GAE-Standard, create an App Engine project by following the setup with these +[instructions](https://cloud.google.com/appengine/docs/standard/python3/quickstart#before-you-begin). + +Update `app.standard.yaml` with the correct values to pass the environment +variables into the runtime. Your `app.standard.yaml` file should look like this: + +Note: If you want to connect to Cloud SQL over Private IP, add the additional +env variable `PRIVATE_IP: True` below. + +```yaml +runtime: python310 +entrypoint: gunicorn -b :$PORT app:app + +env_variables: + INSTANCE_CONNECTION_NAME: :: + DB_USER: + DB_PASS: + DB_NAME: +``` + +Note: Saving credentials in environment variables is convenient, but not secure - consider a more +secure solution such as [Secret Manager](https://cloud.google.com/secret-manager/docs/overview) to +help keep secrets safe. + +Next, the following command will deploy the application to your Google Cloud project: + +```bash +gcloud app deploy app.standard.yaml +``` + +### Deploy to App Engine Flexible + +To run on GAE-Flexible, create an App Engine project by following the setup for these +[instructions](https://cloud.google.com/appengine/docs/flexible/python/quickstart#before-you-begin). + +First, update `app.flexible.yaml` with the correct values to pass the environment +variables into the runtime. Your `app.flexible.yaml` file should look like this: + +Note: If you want to connect to Cloud SQL over Private IP, add the additional +env variable `PRIVATE_IP: True` below. + +```yaml +runtime: custom +env: flex +entrypoint: gunicorn -b :$PORT app:app + +env_variables: + INSTANCE_CONNECTION_NAME: :: + DB_USER: + DB_PASS: + DB_NAME: +``` + +Note: Saving credentials in environment variables is convenient, but not secure - consider a more +secure solution such as [Secret Manager](https://cloud.google.com/secret-manager/docs/overview) to +help keep secrets safe. + +Next, the following command will deploy the application to your Google Cloud project: + +```bash +gcloud app deploy app.flexible.yaml +``` + +### Deploy to Cloud Run + +See the [Cloud Run documentation](https://cloud.google.com/sql/docs/postgres/connect-run) +for more details on connecting a Cloud Run service to Cloud SQL. + +Note: If you want to connect to Cloud SQL over Private IP, add the additional +env variable `--set-env-vars PRIVATE_IP=True` and +flag `--vpc-connector ` below. + +```sh +gcloud run deploy cloud-sql-demo \ + --allow-unauthenticated \ + --set-env-vars INSTANCE_CONNECTION_NAME='::' \ + --set-env-vars DB_USER='' \ + --set-env-vars DB_PASS='' \ + --set-env-vars DB_NAME='' +``` + +Navigate your browser to the URL output at the end of the deployment process +to view the demo app! + +It is recommended to use the [Secret Manager integration](https://cloud.google.com/run/docs/configuring/secrets) for Cloud Run instead +of using environment variables for the SQL configuration. The service injects the SQL credentials from +Secret Manager at runtime via an environment variable. + +Create secrets via the command line: + +```sh +echo -n $INSTANCE_CONNECTION_NAME | \ + gcloud secrets create [INSTANCE_CONNECTION_NAME_SECRET] --data-file=- +``` + +Deploy the service to Cloud Run specifying the env var name and secret name: + +```sh +gcloud run deploy cloud-sql-demo \ + --allow-unauthenticated \ + --update-secrets INSTANCE_CONNECTION_NAME=[INSTANCE_CONNECTION_NAME_SECRET]:latest,\ + DB_USER=[DB_USER_SECRET]:latest, \ + DB_PASS=[DB_PASS_SECRET]:latest, \ + DB_NAME=[DB_NAME_SECRET]:latest +``` + +### Deploy to Cloud Functions + +To deploy the service to [Cloud Functions](https://cloud.google.com/functions/docs) run the following command: + +Note: If you want to connect to Cloud SQL over Private IP, add the additional +env variable `--set-env-vars PRIVATE_IP=True` and +flag `--vpc-connector ` below. + +```sh +gcloud functions deploy votes --gen2 --runtime python310 --trigger-http \ + --allow-unauthenticated \ + --entry-point votes \ + --region \ + --set-env-vars INSTANCE_CONNECTION_NAME=:: \ + --set-env-vars DB_USER=$DB_USER \ + --set-env-vars DB_PASS=$DB_PASS \ + --set-env-vars DB_NAME=$DB_NAME +``` + +Take note of the URL output at the end of the deployment process to view your function! + +## Cloud SQL Auth Proxy Usage + +### Running locally + +To run this application locally, download and install the `cloud-sql-proxy` by following the instructions [here](https://cloud.google.com/sql/docs/postgres/sql-proxy#install). Instructions are provided below for using the proxy with a TCP connection or a Unix Domain Socket. On Linux or Mac OS you can use either option, but on Windows the proxy currently requires a TCP connection. -### Launch proxy with TCP +#### Launch proxy with TCP To run the sample locally with a TCP connection, set environment variables and launch the proxy as shown below. -#### Linux / Mac OS +##### Linux / Mac OS + Use these terminal commands to initialize environment variables: + ```bash -export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service/account/key.json +export GOOGLE_APPLICATION_CREDENTIALS='/path/to/service/account/key.json' export INSTANCE_HOST='127.0.0.1' export DB_PORT='5432' export DB_USER='' export DB_PASS='' export DB_NAME='' ``` + Note: Saving credentials in environment variables is convenient, but not secure - consider a more secure solution such as [Secret Manager](https://cloud.google.com/secret-manager/docs/overview) to help keep secrets safe. Then use this command to launch the proxy in the background: + ```bash -./cloud_sql_proxy -instances=::=tcp:5432 -credential_file=$GOOGLE_APPLICATION_CREDENTIALS & +./cloud-sql-proxy :: & ``` -#### Windows/PowerShell +##### Windows/PowerShell + Use these PowerShell commands to initialize environment variables: + ```powershell -$env:GOOGLE_APPLICATION_CREDENTIALS="" +$env:GOOGLE_APPLICATION_CREDENTIALS="/path/to/service/account/key.json" $env:INSTANCE_HOST="127.0.0.1" $env:DB_PORT="5432" $env:DB_USER="" $env:DB_PASS="" $env:DB_NAME="" ``` + Note: Saving credentials in environment variables is convenient, but not secure - consider a more secure solution such as [Secret Manager](https://cloud.google.com/secret-manager/docs/overview) to help keep secrets safe. Then use this command to launch the proxy in a separate PowerShell session: + ```powershell -Start-Process -filepath "C:\" -ArgumentList "-instances=::=tcp:5432 -credential_file=" +Start-Process -filepath "C:\" -ArgumentList "::" ``` -### Launch proxy with Unix Domain Socket +#### Launch proxy with Unix Domain Socket + NOTE: this option is currently only supported on Linux and Mac OS. Windows users should use the [Launch proxy with TCP](#launch-proxy-with-tcp) option. @@ -77,29 +295,34 @@ To use a Unix socket, you'll need to create a directory and give write access to the proxy. For example: ```bash -sudo mkdir /path/to/the/new/directory -sudo chown -R $USER /path/to/the/new/directory +sudo mkdir /cloudsql +sudo chown -R $USER /cloudsql ``` Use these terminal commands to initialize other environment variables as well: + ```bash -export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service/account/key.json -export INSTANCE_UNIX_SOCKET='./cloudsql/::' +export GOOGLE_APPLICATION_CREDENTIALS='/path/to/service/account/key.json' +export INSTANCE_UNIX_SOCKET='/cloudsql/::' export DB_USER='' export DB_PASS='' export DB_NAME='' ``` + Note: Saving credentials in environment variables is convenient, but not secure - consider a more secure solution such as [Secret Manager](https://cloud.google.com/secret-manager/docs/overview) to help keep secrets safe. Then use this command to launch the proxy in the background: + ```bash -./cloud_sql_proxy -dir=./cloudsql --instances=:: --credential_file=$GOOGLE_APPLICATION_CREDENTIALS & +./cloud-sql-proxy --unix-socket /cloudsql :: & ``` -### Testing the application +#### Testing the application + Next, setup install the requirements into a virtual environment: + ```bash virtualenv --python python3 env source env/bin/activate @@ -107,18 +330,19 @@ pip install -r requirements.txt ``` Finally, start the application: + ```bash python app.py ``` Navigate towards `http://127.0.0.1:8080` to verify your application is running correctly. -## Deploy to App Engine Standard +### Deploy to App Engine Standard -To run on GAE-Standard, create an App Engine project by following the setup for these +To run on GAE-Standard, create an App Engine project by following the setup for these [instructions](https://cloud.google.com/appengine/docs/standard/python3/quickstart#before-you-begin). -First, update `app.standard.yaml` with the correct values to pass the environment +First, update `app.standard.yaml` with the correct values to pass the environment variables into the runtime. Your `app.standard.yaml` file should look like this: ```yaml @@ -126,7 +350,7 @@ runtime: python37 entrypoint: gunicorn -b :$PORT app:app env_variables: - INSTANCE_UNIX_SOCKET: /cloudsql/:: + INSTANCE_UNIX_SOCKET: /cloudsql/:: DB_USER: DB_PASS: DB_NAME: @@ -142,12 +366,12 @@ Next, the following command will deploy the application to your Google Cloud pro gcloud app deploy app.standard.yaml ``` -## Deploy to App Engine Flexible +### Deploy to App Engine Flexible -To run on GAE-Flexible, create an App Engine project by following the setup for these +To run on GAE-Flexible, create an App Engine project by following the setup for these [instructions](https://cloud.google.com/appengine/docs/flexible/python/quickstart#before-you-begin). -First, update `app.flexible.yaml` with the correct values to pass the environment +First, update `app.flexible.yaml` with the correct values to pass the environment variables into the runtime. Your `app.flexible.yaml` file should look like this: ```yaml @@ -156,13 +380,13 @@ env: flex entrypoint: gunicorn -b :$PORT app:app env_variables: - INSTANCE_UNIX_SOCKET: /cloudsql/:: + INSTANCE_UNIX_SOCKET: /cloudsql/:: DB_USER: DB_PASS: DB_NAME: beta_settings: - cloud_sql_instances: :: + cloud_sql_instances: :: ``` Note: Saving credentials in environment variables is convenient, but not secure - consider a more @@ -175,72 +399,58 @@ Next, the following command will deploy the application to your Google Cloud pro gcloud app deploy app.flexible.yaml ``` -## Deploy to Cloud Run +### Deploy to Cloud Run See the [Cloud Run documentation](https://cloud.google.com/sql/docs/postgres/connect-run) for more details on connecting a Cloud Run service to Cloud SQL. -1. Build the container image: - ```sh -gcloud builds submit --tag gcr.io/[YOUR_PROJECT_ID]/run-sql -``` - -2. Deploy the service to Cloud Run: - -```sh -gcloud run deploy run-sql --image gcr.io/[YOUR_PROJECT_ID]/run-sql \ - --add-cloudsql-instances '::' \ - --set-env-vars INSTANCE_UNIX_SOCKET='/cloudsql/::' \ +gcloud run deploy cloud-sql-demo \ + --add-cloudsql-instances '::' \ + --set-env-vars INSTANCE_UNIX_SOCKET='/cloudsql/::' \ --set-env-vars DB_USER='' \ --set-env-vars DB_PASS='' \ --set-env-vars DB_NAME='' ``` -Take note of the URL output at the end of the deployment process. - -Replace environment variables with the correct values for your Cloud SQL -instance configuration. +Navigate your browser to the URL output at the end of the deployment process +to view the demo app! It is recommended to use the [Secret Manager integration](https://cloud.google.com/run/docs/configuring/secrets) for Cloud Run instead of using environment variables for the SQL configuration. The service injects the SQL credentials from Secret Manager at runtime via an environment variable. Create secrets via the command line: + ```sh echo -n $INSTANCE_UNIX_SOCKET | \ gcloud secrets create [INSTANCE_UNIX_SOCKET_SECRET] --data-file=- ``` Deploy the service to Cloud Run specifying the env var name and secret name: + ```sh -gcloud beta run deploy SERVICE --image gcr.io/[YOUR_PROJECT_ID]/run-sql \ - --add-cloudsql-instances :: \ - --update-secrets INSTANCE_UNIX_SOCKET=[INSTANCE_UNIX_SOCKET_SECRET]:latest,\ - DB_USER=[DB_USER_SECRET]:latest, \ - DB_PASS=[DB_PASS_SECRET]:latest, \ - DB_NAME=[DB_NAME_SECRET]:latest +gcloud run deploy cloud-sql-demo \ + --add-cloudsql-instances :: \ + --update-secrets INSTANCE_UNIX_SOCKET=[INSTANCE_UNIX_SOCKET_SECRET]:latest,\ + DB_USER=[DB_USER_SECRET]:latest, \ + DB_PASS=[DB_PASS_SECRET]:latest, \ + DB_NAME=[DB_NAME_SECRET]:latest ``` -3. Navigate your browser to the URL noted in step 2. - -For more details about using Cloud Run see http://cloud.run. -Review other [Python on Cloud Run samples](../../../run/). - -## Deploy to Cloud Functions +### Deploy to Cloud Functions To deploy the service to [Cloud Functions](https://cloud.google.com/functions/docs) run the following command: ```sh -gcloud functions deploy votes --runtime python39 --trigger-http --allow-unauthenticated \ ---set-env-vars INSTANCE_UNIX_SOCKET=/cloudsql/:: \ ---set-env-vars DB_USER=$DB_USER \ ---set-env-vars DB_PASS=$DB_PASS \ - --set-env-vars DB_NAME=$DB_NAME +gcloud functions deploy votes --gen2 --runtime python310 --trigger-http \ + --allow-unauthenticated \ + --entry-point votes \ + --region \ + --set-env-vars INSTANCE_UNIX_SOCKET=/cloudsql/:: \ + --set-env-vars DB_USER=$DB_USER \ + --set-env-vars DB_PASS=$DB_PASS \ + --set-env-vars DB_NAME=$DB_NAME ``` -Take note of the URL output at the end of the deployment process or run the following to view your function: - -```sh -gcloud app browse -``` +Take note of the URL output at the end of the deployment process to view your function! diff --git a/cloud-sql/postgres/sqlalchemy/app.flexible.yaml b/cloud-sql/postgres/sqlalchemy/app.flexible.yaml index 98229510b48e..595b8a636dde 100644 --- a/cloud-sql/postgres/sqlalchemy/app.flexible.yaml +++ b/cloud-sql/postgres/sqlalchemy/app.flexible.yaml @@ -21,10 +21,10 @@ entrypoint: gunicorn -b :$PORT app:app # Cloud Secret Manager (https://cloud.google.com/secret-manager) to help # keep secrets safe. env_variables: - INSTANCE_UNIX_SOCKET: /cloudsql/:: + INSTANCE_UNIX_SOCKET: /cloudsql/:: DB_USER: DB_PASS: DB_NAME: beta_settings: - cloud_sql_instances: :: + cloud_sql_instances: :: diff --git a/cloud-sql/postgres/sqlalchemy/app.standard.yaml b/cloud-sql/postgres/sqlalchemy/app.standard.yaml index a8e64b396f93..394ffa96457c 100644 --- a/cloud-sql/postgres/sqlalchemy/app.standard.yaml +++ b/cloud-sql/postgres/sqlalchemy/app.standard.yaml @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -runtime: python37 +runtime: python310 entrypoint: gunicorn -b :$PORT app:app # Note: Saving credentials in environment variables is convenient, but not @@ -20,7 +20,7 @@ entrypoint: gunicorn -b :$PORT app:app # Cloud Secret Manager (https://cloud.google.com/secret-manager) to help # keep secrets safe. env_variables: - INSTANCE_UNIX_SOCKET: /cloudsql/:: + INSTANCE_UNIX_SOCKET: /cloudsql/:: DB_USER: DB_PASS: DB_NAME: diff --git a/cloud-sql/postgres/sqlalchemy/deployment.yaml b/cloud-sql/postgres/sqlalchemy/deployment.yaml index 18489d02ff24..48a6fb86deea 100644 --- a/cloud-sql/postgres/sqlalchemy/deployment.yaml +++ b/cloud-sql/postgres/sqlalchemy/deployment.yaml @@ -61,18 +61,17 @@ spec: # This uses the latest version of the Cloud SQL proxy # It is recommended to use a specific version for production environments. # See: https://github.com/GoogleCloudPlatform/cloudsql-proxy - image: gcr.io/cloudsql-docker/gce-proxy:latest - command: - - "/cloud_sql_proxy" - + image: gcr.io/cloud-sql-connectors/cloud-sql-proxy:latest + args: # If connecting from a VPC-native GKE cluster, you can use the # following flag to have the proxy connect over private IP - # - "-ip_address_types=PRIVATE" + # - "--private-ip" # tcp should be set to the port the proxy should listen on # and should match the DB_PORT value set above. # Defaults: MySQL: 3306, Postgres: 5432, SQLServer: 1433 - - "-instances==tcp:5432" + - "--port=5432" + - "" securityContext: # The default Cloud SQL proxy image runs as the # "nonroot" user and group (uid: 65532) by default. diff --git a/cloud-sql/postgres/sqlalchemy/main.py b/cloud-sql/postgres/sqlalchemy/main.py index 9330ea19a7fd..84b7d9005751 100644 --- a/cloud-sql/postgres/sqlalchemy/main.py +++ b/cloud-sql/postgres/sqlalchemy/main.py @@ -14,6 +14,8 @@ from flask import render_template, Response +import functions_framework + from app import get_index_context, init_connection_pool, migrate_db, save_vote ############ TABS vs. SPACES App for Cloud Functions ############ @@ -24,6 +26,7 @@ migrate_db(db) +@functions_framework.http def votes(request): if request.method == "GET": context = get_index_context(db) diff --git a/cloud-sql/postgres/sqlalchemy/requirements.txt b/cloud-sql/postgres/sqlalchemy/requirements.txt index 3502cd942b32..74b0b620386c 100644 --- a/cloud-sql/postgres/sqlalchemy/requirements.txt +++ b/cloud-sql/postgres/sqlalchemy/requirements.txt @@ -3,3 +3,4 @@ pg8000==1.29.4 SQLAlchemy==2.0.12 cloud-sql-python-connector==1.2.2 gunicorn==20.1.0 +functions-framework==3.3.0 diff --git a/cloud-sql/sql-server/sqlalchemy/README.md b/cloud-sql/sql-server/sqlalchemy/README.md index 2259f7c77d83..2b76a56f6072 100644 --- a/cloud-sql/sql-server/sqlalchemy/README.md +++ b/cloud-sql/sql-server/sqlalchemy/README.md @@ -1,99 +1,117 @@ # Connecting to Cloud SQL - SQL Server +This demo application can be used to connect to Cloud SQL in two different ways: + +1. [The Cloud SQL Python Connector](https://github.com/GoogleCloudPlatform/cloud-sql-python-connector) (recommended) + +2. [The Cloud SQL Auth Proxy](https://github.com/GoogleCloudPlatform/cloud-sql-proxy) + +Using the Cloud SQL Python Connector library is recommended over the Cloud SQL Auth +Proxy as it provides all the same functionality and features but as a native +Python package. See [cloud-sql-python-connector package](https://pypi.org/project/cloud-sql-python-connector/). + ## Before you begin -1. If you haven't already, set up a Python Development Environment by following the [python setup guide](https://cloud.google.com/python/setup) and +1. If you haven't already, set up a Python Development Environment by following the [python setup guide](https://cloud.google.com/python/setup) and [create a project](https://cloud.google.com/resource-manager/docs/creating-managing-projects#creating_a_project). -2. Create a 2nd Gen Cloud SQL Instance by following these -[instructions](https://cloud.google.com/sql/docs/sqlserver/create-instance). Note the connection string, -database user, and database password that you create. +1. Create a 2nd Gen Cloud SQL Instance by following these +[instructions](https://cloud.google.com/sql/docs/sqlserver/create-instance). Note the connection +string, database user, and database password that you create. -3. Create a database for your application by following these +1. Create a database for your application by following these [instructions](https://cloud.google.com/sql/docs/sqlserver/create-manage-databases). Note the database -name. +name. -4. Create a service account with the 'Cloud SQL Client' permissions by following these +1. Create a service account with the 'Cloud SQL Client' permissions by following these [instructions](https://cloud.google.com/sql/docs/sqlserver/connect-external-app#4_if_required_by_your_authentication_method_create_a_service_account). -Download a JSON key to use to authenticate your connection. +Download a JSON key to use to authenticate your connection. -## Running locally +## Cloud SQL Python Connector Usage -To run this application locally, download and install the `cloud_sql_proxy` by -following the instructions [here](https://cloud.google.com/sql/docs/sqlserver/sql-proxy#install). +### Run App Locally -### Launch proxy with TCP +To run the demo application locally using the Cloud SQL Python Connector, set +environment variables and install dependencies as shown below. -To run the sample locally with a TCP connection, set environment variables and launch the proxy as -shown below. +Note: The `INSTANCE_CONNECTION_NAME` for your instance can be found on the +**Overview** page for your instance in the +[Google Cloud console](https://console.cloud.google.com/sql) or by running +the following command: + +```sh +gcloud sql instances describe --format='value(connectionName)' +``` + +#### Linux / Mac OS -### Linux / MacOS Use these terminal commands to initialize environment variables: + ```bash -export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service/account/key.json -export INSTANCE_HOST='127.0.0.1' -export DB_PORT='1433' -export DB_USER='' +export GOOGLE_APPLICATION_CREDENTIALS='/path/to/service/account/key.json' +export INSTANCE_CONNECTION_NAME='::' +export DB_USER='' export DB_PASS='' export DB_NAME='' ``` + Note: Saving credentials in environment variables is convenient, but not secure - consider a more secure solution such as [Secret Manager](https://cloud.google.com/secret-manager/docs/overview) to help keep secrets safe. -Then, use the following command to start the proxy in the background using TCP: -```bash -./cloud_sql_proxy -instances=::=tcp:1433 -credential_file=$GOOGLE_APPLICATION_CREDENTIALS & -``` +#### Windows/PowerShell -### Windows / PowerShell Use these PowerShell commands to initialize environment variables: + ```powershell $env:GOOGLE_APPLICATION_CREDENTIALS="/path/to/service/account/key.json" -$env:INSTANCE_HOST="127.0.0.1" -$env:DB_PORT="1433" +$env:INSTANCE_CONNECTION_NAME="::" $env:DB_USER="" $env:DB_PASS="" -$env:DB_NAME="" -ArgumentList "-instances=::=tcp:1433 -credential_file=/path/to/service/account/key.json" -``` +#### Install Dependencies -### Testing the application +Next, install the requirements into a virtual environment: -Next, setup a virtual environment and install the application's requirements: ```bash virtualenv --python python3 env source env/bin/activate pip install -r requirements.txt ``` +#### Test the Application + Finally, start the application: + ```bash python app.py ``` Navigate towards `http://127.0.0.1:8080` to verify your application is running correctly. -## Deploy to App Engine Standard +### Deploy to App Engine Standard -To run on GAE-Standard, create an App Engine project by following the setup for these +To run on GAE-Standard, create an App Engine project by following the setup with these [instructions](https://cloud.google.com/appengine/docs/standard/python3/quickstart#before-you-begin). -First, update `app.standard.yaml` with the correct values to pass the environment +Update `app.standard.yaml` with the correct values to pass the environment variables into the runtime. Your `app.standard.yaml` file should look like this: +Note: If you want to connect to Cloud SQL over Private IP, add the additional +env variable `PRIVATE_IP: True` below. + ```yaml -runtime: python37 +runtime: python310 entrypoint: gunicorn -b :$PORT app:app + env_variables: - INSTANCE_CONNECTION_NAME: :: + INSTANCE_CONNECTION_NAME: :: DB_USER: DB_PASS: DB_NAME: @@ -109,26 +127,27 @@ Next, the following command will deploy the application to your Google Cloud pro gcloud app deploy app.standard.yaml ``` -## Deploy to App Engine Flexible +### Deploy to App Engine Flexible -To run on GAE-Flexible, create an App Engine project by following the setup for these +To run on GAE-Flexible, create an App Engine project by following the setup for these [instructions](https://cloud.google.com/appengine/docs/flexible/python/quickstart#before-you-begin). -First, update `app.flexible.yaml` with the correct values to pass the environment +First, update `app.flexible.yaml` with the correct values to pass the environment variables into the runtime. Your `app.flexible.yaml` file should look like this: +Note: If you want to connect to Cloud SQL over Private IP, add the additional +env variable `PRIVATE_IP: True` below. + ```yaml runtime: custom env: flex entrypoint: gunicorn -b :$PORT app:app + env_variables: - INSTANCE_HOST: '172.17.0.1' - DB_PORT: '1433' + INSTANCE_CONNECTION_NAME: :: DB_USER: DB_PASS: DB_NAME: -beta_settings: - cloud_sql_instances: ::=tcp:1433 ``` Note: Saving credentials in environment variables is convenient, but not secure - consider a more @@ -141,73 +160,66 @@ Next, the following command will deploy the application to your Google Cloud pro gcloud app deploy app.flexible.yaml ``` -## Deploy to Cloud Run +### Deploy to Cloud Run See the [Cloud Run documentation](https://cloud.google.com/sql/docs/sqlserver/connect-run) for more details on connecting a Cloud Run service to Cloud SQL. -1. Build the container image: +Note: If you want to connect to Cloud SQL over Private IP, add the additional +env variable `--set-env-vars PRIVATE_IP=True` and +flag `--vpc-connector ` below. ```sh -gcloud builds submit --tag gcr.io//run-sqlserver -``` - -2. Deploy the service to Cloud Run: - -```sh -gcloud run deploy run-sqlserver --image gcr.io//run-sqlserver \ - --add-cloudsql-instances '::' \ - --set-env-vars INSTANCE_CONNECTION_NAME='::' \ +gcloud run deploy cloud-sql-demo \ + --allow-unauthenticated \ + --set-env-vars INSTANCE_CONNECTION_NAME='::' \ --set-env-vars DB_USER='' \ --set-env-vars DB_PASS='' \ --set-env-vars DB_NAME='' ``` -Take note of the URL output at the end of the deployment process. - -Replace environment variables with the correct values for your Cloud SQL -instance configuration. +Navigate your browser to the URL output at the end of the deployment process +to view the demo app! It is recommended to use the [Secret Manager integration](https://cloud.google.com/run/docs/configuring/secrets) for Cloud Run instead of using environment variables for the SQL configuration. The service injects the SQL credentials from Secret Manager at runtime via an environment variable. Create secrets via the command line: + ```sh -echo -n $DB_PASS | \ - gcloud secrets create [DB_PASS_SECRET] --data-file=- +echo -n $INSTANCE_CONNECTION_NAME | \ + gcloud secrets create [INSTANCE_CONNECTION_NAME_SECRET] --data-file=- ``` Deploy the service to Cloud Run specifying the env var name and secret name: + ```sh -gcloud beta run deploy SERVICE --image gcr.io//run-sql \ - --add-cloudsql-instances :: \ - --update-secrets INSTANCE_CONNECTION_NAME=[INSTANCE_CONNECTION_NAME_SECRET]:latest, \ - DB_PORT-[DB_PORT_SECRET]:latest, \ - DB_USER=[DB_USER_SECRET]:latest, \ - DB_PASS=[DB_PASS_SECRET]:latest, \ - DB_NAME=[DB_NAME_SECRET]:latest +gcloud run deploy cloud-sql-demo \ + --allow-unauthenticated \ + --update-secrets INSTANCE_CONNECTION_NAME=[INSTANCE_CONNECTION_NAME_SECRET]:latest,\ + DB_USER=[DB_USER_SECRET]:latest, \ + DB_PASS=[DB_PASS_SECRET]:latest, \ + DB_NAME=[DB_NAME_SECRET]:latest ``` -3. Navigate your browser to the URL noted in step 2. - -For more details about using Cloud Run see http://cloud.run. -Review other [Python on Cloud Run samples](../../../run/). - -## Deploy to Cloud Functions +### Deploy to Cloud Functions To deploy the service to [Cloud Functions](https://cloud.google.com/functions/docs) run the following command: -```sh -gcloud functions deploy votes --runtime python39 --trigger-http --allow-unauthenticated \ ---set-env-vars INSTANCE_CONNECTION_NAME=:: \ ---set-env-vars DB_USER=$DB_USER \ ---set-env-vars DB_PASS=$DB_PASS \ ---set-env-vars DB_NAME=$DB_NAME -``` - -Take note of the URL output at the end of the deployment process or run the following to view your function: +Note: If you want to connect to Cloud SQL over Private IP, add the additional +env variable `--set-env-vars PRIVATE_IP=True` and +flag `--vpc-connector ` below. ```sh -gcloud app browse +gcloud functions deploy votes --gen2 --runtime python310 --trigger-http \ + --allow-unauthenticated \ + --entry-point votes \ + --region \ + --set-env-vars INSTANCE_CONNECTION_NAME=:: \ + --set-env-vars DB_USER=$DB_USER \ + --set-env-vars DB_PASS=$DB_PASS \ + --set-env-vars DB_NAME=$DB_NAME ``` + +Take note of the URL output at the end of the deployment process to view your function! diff --git a/cloud-sql/sql-server/sqlalchemy/app.flexible.yaml b/cloud-sql/sql-server/sqlalchemy/app.flexible.yaml index 24edbc08952c..365e76abcd90 100644 --- a/cloud-sql/sql-server/sqlalchemy/app.flexible.yaml +++ b/cloud-sql/sql-server/sqlalchemy/app.flexible.yaml @@ -28,4 +28,4 @@ env_variables: DB_NAME: beta_settings: - cloud_sql_instances: ::=tcp:1433 + cloud_sql_instances: ::=tcp:1433 diff --git a/cloud-sql/sql-server/sqlalchemy/app.standard.yaml b/cloud-sql/sql-server/sqlalchemy/app.standard.yaml index 68b9466b5940..e51e0cb5f40a 100644 --- a/cloud-sql/sql-server/sqlalchemy/app.standard.yaml +++ b/cloud-sql/sql-server/sqlalchemy/app.standard.yaml @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -runtime: python37 +runtime: python310 entrypoint: gunicorn -b :$PORT app:app # Note: Saving credentials in environment variables is convenient, but not @@ -20,7 +20,7 @@ entrypoint: gunicorn -b :$PORT app:app # Cloud Secret Manager (https://cloud.google.com/secret-manager) to help # keep secrets safe. env_variables: - INSTANCE_CONNECTION_NAME: :: + INSTANCE_CONNECTION_NAME: :: DB_USER: DB_PASS: DB_NAME: diff --git a/cloud-sql/sql-server/sqlalchemy/deployment.yaml b/cloud-sql/sql-server/sqlalchemy/deployment.yaml index 5ee86ff01f7e..470728022ffc 100644 --- a/cloud-sql/sql-server/sqlalchemy/deployment.yaml +++ b/cloud-sql/sql-server/sqlalchemy/deployment.yaml @@ -65,18 +65,17 @@ spec: # This uses the latest version of the Cloud SQL proxy # It is recommended to use a specific version for production environments. # See: https://github.com/GoogleCloudPlatform/cloudsql-proxy - image: gcr.io/cloudsql-docker/gce-proxy:latest - command: - - "/cloud_sql_proxy" - + image: gcr.io/cloud-sql-connectors/cloud-sql-proxy:latest + args: # If connecting from a VPC-native GKE cluster, you can use the # following flag to have the proxy connect over private IP - # - "-ip_address_types=PRIVATE" + # - "--private-ip" # tcp should be set to the port the proxy should listen on # and should match the DB_PORT value set above. # Defaults: MySQL: 3306, Postgres: 5432, SQLServer: 1433 - - "-instances==tcp:1433" + - "--port=1433" + - "" securityContext: # The default Cloud SQL proxy image runs as the # "nonroot" user and group (uid: 65532) by default. diff --git a/cloud-sql/sql-server/sqlalchemy/main.py b/cloud-sql/sql-server/sqlalchemy/main.py index f76dfce45f52..fb2dc20b6193 100644 --- a/cloud-sql/sql-server/sqlalchemy/main.py +++ b/cloud-sql/sql-server/sqlalchemy/main.py @@ -14,6 +14,8 @@ from flask import render_template, Response +import functions_framework + from app import get_index_context, init_connection_pool, migrate_db, save_vote ############ TABS vs. SPACES App for Cloud Functions ############ @@ -24,6 +26,7 @@ migrate_db(db) +@functions_framework.http def votes(request): if request.method == "GET": context = get_index_context(db) diff --git a/cloud-sql/sql-server/sqlalchemy/requirements.txt b/cloud-sql/sql-server/sqlalchemy/requirements.txt index 9f8f10aad230..ac05a0d4d7a2 100644 --- a/cloud-sql/sql-server/sqlalchemy/requirements.txt +++ b/cloud-sql/sql-server/sqlalchemy/requirements.txt @@ -5,3 +5,4 @@ pyopenssl==23.1.1 SQLAlchemy==2.0.12 cloud-sql-python-connector==1.2.2 sqlalchemy-pytds==0.3.5 +functions-framework==3.3.0