0
votes

UPDATE:

I re-forked the GoogleCloudPlatform example project and tried again. Suddenly, it's working.

Half of my problem had to do with the fact that my target project uses Flask-SQLAlchemy. For that, I needed to use the MySQLdb dialect as shown in this answer: https://stackoverflow.com/a/10900826/4455571

I'm still not sure why I couldn't get the GoogleCloudPlatform example to work the first time and why it suddenly started working after I re-forked.

Original post:

I am trying to connect a container running on Cloud Run to Cloud SQL using the following guide: https://cloud.google.com/sql/docs/mysql/connect-run?hl=en_US

I have made sure to do the following:

  • Enable the API for my project
  • Add the "Cloud SQL Client" role to my service account [email protected]

However, the connection fails with the following error:

File "/usr/local/lib/python3.8/site-packages/pymysql/connections.py", line 630, in connect raise exc sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (2003, "Can't connect to MySQL server on 'localhost' ([Errno 2] No such File or directory)")

I made a second attempt using the sample code from GitHub: https://github.com/GoogleCloudPlatform/python-docs-samples/tree/master/cloud-sql/mysql/sqlalchemy

These are the steps I followed:

  1. Mirrored the repository and made it private
  2. Edited app.yaml to add my credentials similar to the following (I didn't wrap the values in quotes - should I?):
env_variables:
  CLOUD_SQL_CONNECTION_NAME: my-project-270323:us-central1:database
  DB_USER: root
  DB_PASS: areallygreatpassword
  DB_NAME: database
  1. Connected the repo to Cloud Build and triggered a new build
  2. Deployed my container in a new service on Cloud Run making sure to select by database under Connections > Cloud SQL connections

I get the same error. What am I doing wrong?

EDIT

Here's the full error dump:

Traceback (most recent call last):()
File "/usr/local/lib/python3.8/site-packages/flask/app.py", line 2446, in wsgi_app response = self.full_dispatch_request()()
File "/usr/local/lib/python3.8/site-packages/flask/app.py", line 1944, in full_dispatch_request self.try_trigger_before_first_request_functions()()
File "/usr/local/lib/python3.8/site-packages/flask/app.py", line 1992, in try_trigger_before_first_request_functions func()()
File "/app/main.py", line 81, in create_tables with db.connect() as conn:()
File "/usr/local/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 2209, in connect return self._connection_cls(self, **kwargs)()
File "/usr/local/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 103, in __init__ else engine.raw_connection()()
File "/usr/local/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 2306, in raw_connection return self._wrap_pool_connect(()
File "/usr/local/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 2279, in _wrap_pool_connect Connection._handle_dbapi_exception_noconnection(()
File "/usr/local/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1547, in _handle_dbapi_exception_noconnection util.raise_from_cause(sqlalchemy_exception, exc_info)()
File "/usr/local/lib/python3.8/site-packages/sqlalchemy/util/compat.py", line 398, in raise_from_cause reraise(type(exception), exception, tb=exc_tb, cause=cause)()
File "/usr/local/lib/python3.8/site-packages/sqlalchemy/util/compat.py", line 152, in reraise raise value.with_traceback(tb)()
File "/usr/local/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 2276, in _wrap_pool_connect return fn()()
File "/usr/local/lib/python3.8/site-packages/sqlalchemy/pool/base.py", line 303, in unique_connection return _ConnectionFairy._checkout(self)()
File "/usr/local/lib/python3.8/site-packages/sqlalchemy/pool/base.py", line 773, in _checkout fairy = _ConnectionRecord.checkout(pool)()
File "/usr/local/lib/python3.8/site-packages/sqlalchemy/pool/base.py", line 492, in checkout rec = pool._do_get()()
File "/usr/local/lib/python3.8/site-packages/sqlalchemy/pool/impl.py", line 139, in _do_get self._dec_overflow()()
File "/usr/local/lib/python3.8/site-packages/sqlalchemy/util/langhelpers.py", line 68, in __exit__ compat.reraise(exc_type, exc_value, exc_tb)()
File "/usr/local/lib/python3.8/site-packages/sqlalchemy/util/compat.py", line 153, in reraise raise value()
File "/usr/local/lib/python3.8/site-packages/sqlalchemy/pool/impl.py", line 136, in _do_get return self._create_connection()()
File "/usr/local/lib/python3.8/site-packages/sqlalchemy/pool/base.py", line 308, in _create_connection return _ConnectionRecord(self)()
File "/usr/local/lib/python3.8/site-packages/sqlalchemy/pool/base.py", line 437, in __init__ self.__connect(first_connect_check=True)()
File "/usr/local/lib/python3.8/site-packages/sqlalchemy/pool/base.py", line 652, in __connect connection = pool._invoke_creator(self)()
File "/usr/local/lib/python3.8/site-packages/sqlalchemy/engine/strategies.py", line 114, in connect return dialect.connect(*cargs, **cparams)()
File "/usr/local/lib/python3.8/site-packages/sqlalchemy/engine/default.py", line 489, in connect return self.dbapi.connect(*cargs, **cparams)()
File "/usr/local/lib/python3.8/site-packages/pymysql/__init__.py", line 94, in Connect return Connection(*args, **kwargs)()
File "/usr/local/lib/python3.8/site-packages/pymysql/connections.py", line 325, in __init__ self.connect()()
File "/usr/local/lib/python3.8/site-packages/pymysql/connections.py", line 630, in connect raise exc sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (2003, "Can't connect to MySQL server on 'localhost' ([Errno 2] No such()
File or directory)")

Also, I did this via the web console, not the CLI. Here are the settings I passed to the example project provided by Google:

drive.google.com/open?id=17nl_rQVTU2ZirCEu64bjfe90zGweg3a6 drive.google.com/open?id=1_Riy1HNSPvZZUGl4tJ0Z8puYuuMbUMPH

1

1 Answers

0
votes

The question includes some wide-ranging research, nicely done. Addressing a couple points directly:

  • The app.yaml file is specific to App Engine, and is a method to pass Environment Variable configuration to your app. In Cloud Run, you use the --update-env-vars flag on deploy.
  • You may also be missing a flag in your service deploy operation: --add-cloudsql-instances INSTANCE-CONNECTION-NAME

These steps together:

gcloud run deploy SERVICE --image gcr.io/PROJECT/SERVICE \
  --add-cloudsql-instances my-project-270323:us-central1:database
  --update-env-vars CLOUD_SQL_CONNECTION_NAME=my-project-270323:us-central1:database \
  --update-env-vars DB_USER=root \
  --update-env-vars DB_PASS=areallygreatpassword \
  --update-env-vars DB_NAME=database

Note that database in the INSTANCE_CONNECTION_NAME is the Cloud SQL instance, while database as the DB_NAME is a database created within that instance.

The configuration values need to be used as part of creating your database connection.

You can see more of the connection between these environment variables and creating the connection object in the complete sample code on Github.