Sails on Google App Engine with Cloud SQL - mysql

I have followed this guide https://cloud.google.com/community/tutorials/run-sailsjs-on-google-app-engine
on how to deployed Sails to Google App Engine.
However, my app used MySQL as the database and I have set it up like this in "connection.js".
mysql: {
adapter: 'sails-mysql',
host: '104.199.196.99', // Internal IP Address of the Cloud SQL Instance
user: 'root',
password: 'xxxxxx',
database: 'xxxxxxxx'
}
The error I got when trying to connect with Cloud SQL (when I make a requrest to log-in which involved connection to database) was:
Sending 500 ("Server Error") response:
Error (E_UNKNOWN) :: Encountered an unexpected error
Could not connect to MySQL:
Error: connect ETIMEDOUT
Did I set it up correctly?

For those who seek the solution for connecting to Google Cloud SQL using Google App Engine with Sails.js, I have figured it out.
Connecting to the Google Cloud SQL using host address doest not work here, because the Firewall Rules and the Access Control of the Cloud SQL will prevent this kind of connection to the whitelisted addresses. Unfortunately, Google App Engine could not be assigned with Static IP Address. Therefore, the App Engine could not be whitelisted by the Cloud SQL or you would need to whitelist 0.0.0.0/0 which is everything and that is not secure.
The solution is to use this configuration in your connection.js.
googleCloudSQL: {
adapter: 'sails-mysql',
socketPath: '/cloudsql/' + process.env.INSTANCE_CONNECTION_NAME,
user: 'XXXXX',
password: 'XXXXXXX',
database: 'XXXXXXXX'
}
By connecting to the Cloud SQL via socket path using the Instance Connection Name of the Cloud SQL, this is the native way of doing it. If your App Engine is already in the same project with your Cloud SQL then it will already be authorized to connect. However, if they are in different projects, you would need to set up service account and IAM.

Related

Cloud Run:<Cloud SQL instance IP adress> :3306: connect: connection timed out

I want to connect Cloud SQL in Cloud Run Application. I used golang. this is the code around sql connect setting.
func getEnv(key, def string) string {
v := os.Getenv(key)
if v == "" {
return def
}
return v
}
DB: DB{
User: getEnv("DB_USER", "<user name>"),
Pass: getEnv("DB_PASS", "<password>"),
Host: getEnv("DB_HOST", "0.0.0.0"),
Port: getEnv("DB_PORT", "3306"),
Database: getEnv("DB_DATABASE", "<database name>"),
},
dsn := fmt.Sprintf("%s:%s#tcp(%s:%s)/%s?charset=utf8&parseTime=true",
config.DB.User, config.DB.Pass, config.DB.Host, config.DB.Port, config.DB.Database)
db, err := gorm.Open("mysql", dsn)
I set environment variable at Cloud Run setting console. After delpoy Application, Cloud Run console display Cloud Run error: Container failed to start. Failed to start and then listen on the port defined by the PORT environment variable. Logs for this revision might contain more information. and dial tcp <Cloud SQL Private IP> :3306: connect: connection timed out I wonder SQL connection is wrong...
You have not mentioned the word "VPC" in your question so I'm assuming you don't use it.
Cloud Run cannot directly connect to a private IP of a Cloud SQL instance. You need to configure a Serverless VPC Access Connector and specify it while deploying your Cloud Run app.
Cloud Run containers are not part of a VPC by default, so unless you do this, they will not have access to the private networks.
There is several way to connect your Cloud SQL database to Cloud Run. If it's MySQL, the easiest way is to follow the official documentation
If you want to use the IP with TCP connection, firstly, you can't use 0.0.0.0 as IP.
Use the Cloud SQL public IP (for this you have to authorize 0.0.0.0/0 network range on your Cloud SQL instance, and it's absolutely not recommended)
Plug your Cloud SQL to your VPC. And, as described by Ahmet, use serverless VPC connector to link Cloud Run with your VPC. Then add the private IP of your Cloud SQL in your code.

Unable to connect to cloud sql on GCP

I am trying to connect to cloud sql hosted in gcp from eclipse, not able to do so. I have whitelisted my ip using the connection settings on cloud sql instance. I have added the driver also in eclipse for mysql.
I think I am making mistake in constructing the connection string. Please refer below details.
connectionName: abc-dev:europe-west1:abc-instance
So in connection section
database: abc-dev:europe-west1:abc-instance
url: jdbc:mysql://35.233.100.100:3306/abcInsoles
user: root
password: xyz123
It throws exception:
com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure
I am running it from local.
Can you throw some insights?
Many thanks.
The "database" value is incorrect - this is the name of the database on the instance itself (not the instance's connection string).
Since you are using Java, you may be interested in the Cloud SQL JDBC Socket Factory - it allows you to connect to the Cloud SQL instance without whitelisting an IP.

Google App engine and Cloud sql connection refused

I am using Google App Engine and Cloud SQL (My SQL 2nd Gen Instance) in my Node JS application and I am having troubles.
I am connecting fine in local using cloud proxy, but as soon as I deploy it fails.
I am using Sequelize to connect to cloud SQL.
I do have correct password/username/instance connection name.
I have enabled API, otherwise I would not be able to connect from proxy.
In my "app.yaml" I do have correct "beta_settings" tag with correct "cloud_sql_instances" value.
Message from Cloud SQL:
`{insertId: "s=7560d77466cb46cebc3933acc1c41082;i=1a5ff5;b=30867f100f0d483ea84a5718c3948aed;m=886b8bfcbb;t=578fd8d7ad54f;x=a821eba2c35efe29-0#a1"
logName: "projects/[CORRECT PROJECT]/logs/cloudsql.googleapis.com%2Fmysql.err"
receiveTimestamp: "2018-10-24T18:21:25.190291090Z"
resource: {
labels: {
database_id: "[CORRECT DB ID]"
project_id: "[CORRECT PROJECT ID]"
region: "us-central"
}
type: "cloudsql_database"
}
severity: "ERROR"
textPayload: "2018-10-24T18:21:19.249532Z 53509 [Note] Access denied for user 'root'#'cloudsqlproxy~66.85.23.1' (using password: NO)"
timestamp: "2018-10-24T18:21:19.249743Z" }`
Message fron APP Engine (Express, Sequelize):
`Error: connect ECONNREFUSED 127.0.0.1:3306 at TCPConnectWrap.afterConnect [as oncomplete]`
It seems like similar question has been asked numerous times, and I have read more than 10 stackoverflow questions and answers and I still do not have right answer for it.
Can I get some help?
Thank you.
I know this is old - but I've been having the same problem with my NodeJS app connecting to CloudSQL Postgres. A little digging on the AppEngine instance eventually showed that while the docs show 127.0.0.1 as the host, it's actually running the CloudSQL proxy docker image - so while it's 127.0.0.1 from the instance itself, my database hostname actually needed to be "cloudsql" from the app container.
Try connecting to cloudsql:3306 and see if it works!

Containerized server application failing to connect to MySQL databases

I'm trying to connect my server code running as a Docker container in our Kubernetes cluster (hosted on Google Container Engine) to a Google Cloud SQL managed MySQL 5.7 instance. The issue I'm running into is that every connection is being rejected by the database server with Access denied for user 'USER'#'IP' (using password: YES). The database credentials (username, password, database name, and SSL certificates) are all correct and work when connecting via other MySQL clients or the same application running as a container on a local instance.
I've verified that all credentials are the same on the local and the server-hosted versions of the app and that the user I'm connecting with has the wildcard % host specified. Not really sure what to check next here, to be honest...
An edited version of the connection code is below:
let connectionCreds = {
host: Config.SQL.HOST,
user: Config.SQL.USER,
password: Config.SQL.PASSWORD,
database: Config.SQL.DATABASE,
charset: 'utf8mb4',
};
if (Config.SQL.SSL_ENABLE) {
connectionCreds['ssl'] = {
key: fs.readFileSync(Config.SQL.SSL_CLIENT_KEY_PATH),
cert: fs.readFileSync(Config.SQL.SSL_CLIENT_CERT_PATH),
ca: fs.readFileSync(Config.SQL.SSL_SERVER_CA_PATH)
}
}
this.connection = MySQL.createConnection(connectionCreds);
Additional information: the server application is built in Node using the mysql2 library to connect to the database. There are no special firewall rules in place that are causing network issues, and that's confirmed by the fact that the library IS connecting, but failing to authenticate.
After setting up Cloud SQL Proxy I managed to figure out what the actual error was: somewhere between the secret and the pod configuration an extra newline was being added to the database name, causing any connection attempt to fail. With the proxy set up this was made clear because there was an actual error message to that effect displayed.
(notably all of my logging around the credentials that I was using to validate that the credentials were accurate didn't explicitly display the newline and was disguised by the fact that the console display added line breaks to wrap the display, and it happened to line up exactly with where the database name ended)
Have you read the documentation on https://cloud.google.com/sql/docs/mysql/connect-container-engine ?
In Container Engine, you need to set up a Cloud SQL Proxy container alongside your application pod and talk to it. The Cloud SQL Proxy will then make the actual call to Cloud SQL service.
If the container worked locally, I assume you have Application Default Credentials set on your development machine. It could be failing because those credentials are not on your container as a Service Account file. Try configuring a Service Account file, or create your GKE cluster with --scopes argument that gives your instances access to Cloud SQL.

NodeJS + MySql hosting

I want to host my application based on node.js and MySql database. I try heroku hosting. I've create an application and add ClearDB add-on with Punch DB plan. The main restriction of this add-on that I cannot create any user-defined functions and events in this plan. It is sopported for expensive database plans.
Then I host my db on Google Cloud SQL. It allows to create user-defined functions and events. However I cannot access to the database from my heroku app because I don't know how to authorize external heroku network for my google cloud database. How can I do this?
Or may be there are any other hostings for NodeJS + MySql application where there are no the restrictions mentioned above?
You should be able to:
a) Use Cloud SQL by authorizing the external IP of your Heroku dyno via a proxy service like QuotaGuard Static or Proximo;
b) Do the same using Amazon RDS.
Additional details that may help:
1. SO question related to QuotaGuard
To clarify: you have to use a third-party add-on like this because Heroku won't guarantee a single IP or even a range of IPs for your dyno.
I add QuotaGuard Static add-on and it holds two ip adresses. Than I add this addresses to the Authorized Networks of my Google Cloud Sql. After then I try to connect to tha database using a guide. Here is my code:
exports.getConnection = () ->
dbConnParams =
host: 'google cloud sql ip'
port: 3306
proxy = url.parse process.env.QUOTAGUARDSTATIC_URL
auth = proxy.auth;
username = auth.split(":")[0]
pass = auth.split(":")[1]
sock_options =
host: proxy.hostname
port: proxy.port
user: username
pass: pass
sockConn = new SocksConnection dbConnParams, sock_options
dbConnection = mysql.createConnection({
user: 'root',
password: 'pwd',
stream: sockConn
});
return dbConnection
However I obtain an error: "connect ECONNREFUSED". Whats wrong with this approach?