I've seen other posts with the same issue here however none of the answers could help in my case. I have a Google SQLCloud 2nd generation database which I'm trying to make my Go Appengine app establish a connection to. I'm using go-sql-driver/mysql
At first I tried to connect the same way I used with the 1st generation just passing the project and instance names as parameters:
sql.Open("mysql", "root@cloudsql(project:instance)/database"
Then I've noticed from the Cloud Console and also from this post that the region is also required so my connection parameters now look like:
sql.Open("mysql", "root@cloudsql(project:uscentral1:instance)/database"
and also with password
sql.Open("mysql", "root:password@cloudsql(project:uscentral1:instance)/database"
Still not working
My last attempt was to connect using SSL as described on this post using the code provided from the drivers documentation:
rootCertPool := x509.NewCertPool()
pem, err := ioutil.ReadFile("/path/ca-cert.pem")
if err != nil {
log.Fatal(err)
}
if ok := rootCertPool.AppendCertsFromPEM(pem); !ok {
log.Fatal("Failed to append PEM.")
}
clientCert := make([]tls.Certificate, 0, 1)
certs, err := tls.LoadX509KeyPair("/path/client-cert.pem", "/path/client-key.pem")
if err != nil {
log.Fatal(err)
}
clientCert = append(clientCert, certs)
mysql.RegisterTLSConfig("custom", &tls.Config{
RootCAs: rootCertPool,
Certificates: clientCert,
})
sql.Open("mysql","root:password@cloudsql(project:uscentral1:instance)/database?tls=custom")
Also no luck.
At this point I'm just running out of ideas in what the issue could be. Has anyone done anything different than what most people did in order to get it working? At this point I'm not sure if the issue is with my code, with the driver or some configuration in the CloudSQL database.
Turns out my project did not have the default credentials for AppEngine. The documentation in the console says that at project creation the default Credentials for AppEngine and Compute Engine would be created by default, however this project in particular has been created a while ago through the Old App Engine console and my assumptions is that when Google migrated AppEngine projects onto the new architecture it hasn't created the default credentials as it does when we create a new project nowadays. I've deleted the old project and created a new one and everything works fine. I suppose creating the right credentials for the old project would also work. I'm leaving this answer here because I was just relying at the documentation and actually spent a lot of time with this before checking the obvious. It might be a good suggestion to the Google Cloud Doc guys to document this somewhere.
Please take the following working example and compare it to what you have in your application. Replace INSTANCE_CONNECTION_NAME with the "Instance connection name" shown in Cloud Console or in gcloud sql describe
. If you don't notice anything different in your app, try running this example and see what error you get.
package hello
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
"net/http"
)
func init() {
http.HandleFunc("/", handler)
}
func handler(w http.ResponseWriter, r *http.Request) {
db, err := sql.Open("mysql", "root@cloudsql(INSTANCE_CONNECTION_NAME)/mysql")
if err != nil {
fmt.Fprintf(w, "Error constructing DB: %v", err)
return
}
rows, err := db.Query("SELECT 1")
if err != nil {
fmt.Fprintf(w, "Error performing query: %v", err)
return
}
fmt.Fprintf(w, "Success!")
rows.Close()
}