How to connect MySQL with AWS? - mysql

I am trying to connect the MySQL database with AWS RDS but don't have any idea what should be included.
I created the RDS database, got the DB HOST value, and got the region but I don't know how to apply it and make it work.
func Connect() (db *sql.DB) {
db_user := middleware.LoadEnvVariable("DB_USER")
db_password := middleware.LoadEnvVariable("DB_PASSWORD")
db_address := middleware.LoadEnvVariable("DB_ADDRESS")
db_db := middleware.LoadEnvVariable("DB_DB")
s := fmt.Sprintf("%s:%s#tcp(%s:3306)/%s", db_user, db_password, db_address, db_db)
db, err := sql.Open("mysql", s)
if err != nil {
log.Fatal(err)
}
return db
}

Related

How to connect to AWS RDS using Golang?

I am trying to connect to the AWS RDS using the following code. I got help from this website but when I executed this code, it gave me the following error.
Error
panic: failed to create authentication token: failed to refresh cached credentials, no EC2 IMDS role found, operation error ec2imds: GetMetadata, request canceled, context deadline exceeded
Code
func Connect() (db *sql.DB) {
db_user := middleware.LoadEnvVariable("DB_USER")
// db_password := middleware.LoadEnvVariable("DB_PASSWORD")
db_host := "database endpoint string"
db_db := middleware.LoadEnvVariable("DB_DB")
dbEndpoint := fmt.Sprintf("%s:%d", db_address, 3306)
region := "ap-south-1a"
cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
panic("configuration error: " + err.Error())
}
authenticationToken, err := auth.BuildAuthToken(context.TODO(), dbEndpoint, region, db_user, cfg.Credentials)
if err != nil {
panic("failed to create authentication token: " + err.Error())
}
s := fmt.Sprintf("%s:%s#tcp(%s)/%s?tls=true&allowCleartextPasswords=true", db_user, authenticationToken, dbEndpoint, db_db)
dbbase, err := sql.Open("mysql", s)
if err != nil {
log.Fatal(err)
}
return dbbase
}

Error while creating connection with phpmyadmin using golang "commands out of sync. Did you run multiple statements at once?"

I'm facing some issue while fetching the data from the MySQL database using golang below is my code and the error that I'm facing
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
func ConnectMsqlDb() (db *sql.DB, err error) {
db, err = sql.Open("mysql", fmt.Sprintf("%s:%s#tcp(%s:"+sqlDbPort+")/"+sqlDB, sqlUserName, sqlPassword, dbServerIP))
if err != nil {
return nil, err
}
//defer db.Close()
err = db.Ping()
if err != nil {
return nil, err
}
return db, nil
}
func GetSqlData() (err error, data interface{}) {
db, err := ConnectMsqlDb()
if err != nil {
// here it will returning me the error
return err, nil
}
rows, err := db.Query("SELECT * FROM users")
if err != nil {
return err, nil
}
for rows.Next() {
}
defer db.Close()
fmt.Println(rows)
return err, rows
}
func main() {
err, data := GetSqlData()
fmt.Println("data", data, "err", err)
}
error
data commands out of sync. Did you run multiple statements at once?
Can anyone tell me why I'm facing this issue
If the error is comming while opening a connection to mysqld , it could be possible that MySQL server (mysqld) is blocking the host from connecting to it. It means that mysqld has received many connection requests from the given host that were interrupted in the middle.
Read why? To confirm you could see the DB's logs as well. So, a way to unblock it is to flush the cached hosts using the MySQL CLI:
mysql> FLUSH HOSTS;
And then try again to connect.
Plus, give this answer a read as well. Might help.
You can check the state of the socket used by mysqld using (For Linux):
netstat -nt
Check if there's any previously hanging connection from the host to mysqld. If yes, then kill it and try again.

How to use the go-mysql-driver with ssl on aws with a mysql rds instance

I have a RDS instance running on AWS and I want to know how to connect to that instance over ssl.
From this link Using SSL with mysql database. AWS sets up our database registered with a certificate and provides the root certificate for download.
AWS rds root ca
Now the go-mysql-driver provides this information in there documentation to setup an ssl connection.
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,
})
db, err := sql.Open("mysql", "user#tcp(localhost:3306)/test?tls=custom")
The example indicates that I need a client certificate and client key.
But amazon only provides the root certificate. How can I use that with go-mysql-driver to connect to my mysql instance?
I'd add a comment to the previous answer, but my reputation isn't high enough. This is working for me:
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.")
}
mysql.RegisterTLSConfig("custom", &tls.Config{
ServerName: "qcaurora.cb556lynvxio.us-east-1.rds.amazonaws.com",
RootCAs: rootCertPool,
})
db, err := sql.Open("mysql", "user:pass#tcp(qcrds.example.com:3306)/databasename?tls=custom")
The only change from the above is the addition of the ServerName field. I've also clarified the address field for use with a CNAME dns entry and using a password. If you don't use a CNAME to RDS, you could leave out the ServerName field.
I'm using go 1.11 with go-sql-driver/mysql version v1.4.1.
From looking at the docs here and here and here, it looks like you simply need to set the RootCAs value to the root certificate you obtained from AWS. You don't need to set the Certificates value since you aren't using a client cert. So the code would look something like:
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.")
}
mysql.RegisterTLSConfig("custom", &tls.Config{
RootCAs: rootCertPool,
})
db, err := sql.Open("mysql", "user#tcp(localhost:3306)/test?tls=custom")

Cant' connect to a MySQL database

I have a MySQL server on CentOS 7 and I want to try connecting a program written in Go to that database server. For the database server (MySQL) is work correctly and I tried to make one database and table.
+-----+------------+
| no | nama |
+-----+------------+
| 001 | Example |
+-----+------------+
MySQL username: golang
MySQL password: cobadatabase
CentOS 7 (MySQL Server) Machine's IP: 192.168.102.175:3306 (Default Port)
and My laptop's IP: 192.168.102.170
**. So, Database server exist on different machine (remotely).
Here is my Go code:
func main() {
/* Ini konekin database-nya dulu */
app_database, err := sql.Open("mysql", "golang:cobadatabase#tcp(192.168.102.175:3360)/example")
/* Nah klo ini Error Handling */
if err != nil {
log.Fatal(err) // informasi log jika koneksi database gagal
}
defer app_database.Close() // Close koneksi jika benar-benar gagal
/* End of Error Handling Connection */
var (
no string
nama string
)
baris, err := app_database.Query("SELECT * FROM example_table")
if err != nil {
log.Fatal(err)
}
defer baris.Close()
for baris.Next() {
err := baris.Scan(&no, &nama)
if err != nil {
log.Fatal(err)
}
log.Println(no, nama)
}
err = baris.Err()
if err != nil {
log.Fatal(err)
}
}
When I run my program, it fails with this error:
dial tcp 192.168.102.175:3360 connectex: A connection attempt failed because the connected party did not properly respond.

How to create a new MySQL database with go-sql-driver

I'm working on Golang script that automatically clone a database.
I'm using go-sql-driver but i can't find in the documentation a way to create a new database.
Connection to MySQL require an URL scheme like:
user:password#tcp(localhost:3306)/database_name
But the database not exists yet, I just want to connect to the server and then create a new one.
How can I do that? I have to use another driver?
You can perfectly use the go-sql-driver. However, you need to use a mysql user which has the proper access rights to create new databases.
Here is an example:
func create(name string) {
db, err := sql.Open("mysql", "admin:admin#tcp(127.0.0.1:3306)/")
if err != nil {
panic(err)
}
defer db.Close()
_,err = db.Exec("CREATE DATABASE "+name)
if err != nil {
panic(err)
}
_,err = db.Exec("USE "+name)
if err != nil {
panic(err)
}
_,err = db.Exec("CREATE TABLE example ( id integer, data varchar(32) )")
if err != nil {
panic(err)
}
}
Note that the database name is not provided in the connection string. We just create the database after the connection (CREATE DATABASE command), and switch the connection to use it (USE command).
Note: the VividCortex guys maintain a nice database/sql tutorial and documentation at http://go-database-sql.org/index.html
If you want to create a new database if it does not exist, and use it directly in your program, be aware that database/sql maintains a connection pool.
Therefore the opened database connection, should preferably contain the database name. I've seen "Error 1046: No database selected" when database/sql opens a new connection after using db.Exec("USE "+name) manually.
func createAndOpen(name string) *sql.DB {
db, err := sql.Open("mysql", "admin:admin#tcp(127.0.0.1:3306)/")
if err != nil {
panic(err)
}
defer db.Close()
_,err = db.Exec("CREATE DATABASE IF NOT EXISTS "+name)
if err != nil {
panic(err)
}
db.Close()
db, err = sql.Open("mysql", "admin:admin#tcp(127.0.0.1:3306)/" + name)
if err != nil {
panic(err)
}
defer db.Close()
return db
}
My db_config.go file looks like for GO ORM 2.0:
package infrastructure
import (
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm2.0/utils"
)
//Setup Models: initializaing the mysql database
func GetDatabaseInstance() *gorm.DB {
get := utils.GetEnvWithKey
USER := get("DB_USER")
PASS := get("DB_PASS")
HOST := get("DB_HOST")
PORT := get("DB_PORT")
DBNAME := get("DB_NAME")
dsn := fmt.Sprintf("%s:%s#tcp(%s:%s)/%s?charset=utf8&parseTime=True&loc=Local", USER, PASS, HOST, PORT, DBNAME)
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
_ = db.Exec("CREATE DATABASE IF NOT EXISTS " + DBNAME + ";")
if err != nil {
panic(err.Error())
}
return db
}