Skip to content

Commit 48e391d

Browse files
test: add MCP tests for Postgres and MySQL (GoogleCloudPlatform#966)
1 parent 0da6c9d commit 48e391d

File tree

4 files changed

+103
-0
lines changed

4 files changed

+103
-0
lines changed

.ci/cloudbuild.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ steps:
2525
"MYSQL_USER_IAM",
2626
"MYSQL_PASS",
2727
"MYSQL_DB",
28+
"MYSQL_MCP_CONNECTION_NAME",
29+
"MYSQL_MCP_PASS",
2830
"POSTGRES_CONNECTION_NAME",
2931
"POSTGRES_USER",
3032
"POSTGRES_USER_IAM",
@@ -36,6 +38,8 @@ steps:
3638
"POSTGRES_CUSTOMER_CAS_PASS",
3739
"POSTGRES_CUSTOMER_CAS_DOMAIN_NAME",
3840
"POSTGRES_CUSTOMER_CAS_INVALID_DOMAIN_NAME",
41+
"POSTGRES_MCP_CONNECTION_NAME",
42+
"POSTGRES_MCP_PASS",
3943
"SQLSERVER_CONNECTION_NAME",
4044
"SQLSERVER_USER",
4145
"SQLSERVER_PASS",
@@ -59,6 +63,10 @@ availableSecrets:
5963
env: "MYSQL_PASS"
6064
- versionName: "projects/$PROJECT_ID/secrets/MYSQL_DB/versions/latest"
6165
env: "MYSQL_DB"
66+
- versionName: "projects/$PROJECT_ID/secrets/MYSQL_MCP_CONNECTION_NAME/versions/latest"
67+
env: "MYSQL_MCP_CONNECTION_NAME"
68+
- versionName: "projects/$PROJECT_ID/secrets/MYSQL_MCP_PASS/versions/latest"
69+
env: "MYSQL_MCP_PASS"
6270
- versionName: "projects/$PROJECT_ID/secrets/POSTGRES_CONNECTION_NAME/versions/latest"
6371
env: "POSTGRES_CONNECTION_NAME"
6472
- versionName: "projects/$PROJECT_ID/secrets/POSTGRES_USER/versions/latest"
@@ -81,6 +89,10 @@ availableSecrets:
8189
env: "POSTGRES_CUSTOMER_CAS_DOMAIN_NAME"
8290
- versionName: "projects/$PROJECT_ID/secrets/POSTGRES_CUSTOMER_CAS_INVALID_DOMAIN_NAME/versions/latest"
8391
env: "POSTGRES_CUSTOMER_CAS_INVALID_DOMAIN_NAME"
92+
- versionName: "projects/$PROJECT_ID/secrets/POSTGRES_MCP_CONNECTION_NAME/versions/latest"
93+
env: "POSTGRES_MCP_CONNECTION_NAME"
94+
- versionName: "projects/$PROJECT_ID/secrets/POSTGRES_MCP_PASS/versions/latest"
95+
env: "POSTGRES_MCP_PASS"
8496
- versionName: "projects/$PROJECT_ID/secrets/SQLSERVER_CONNECTION_NAME/versions/latest"
8597
env: "SQLSERVER_CONNECTION_NAME"
8698
- versionName: "projects/$PROJECT_ID/secrets/SQLSERVER_USER/versions/latest"

.github/workflows/tests.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ jobs:
6868
MYSQL_USER_IAM:${{ vars.GOOGLE_CLOUD_PROJECT }}/MYSQL_USER_IAM_GO
6969
MYSQL_PASS:${{ vars.GOOGLE_CLOUD_PROJECT }}/MYSQL_PASS
7070
MYSQL_DB:${{ vars.GOOGLE_CLOUD_PROJECT }}/MYSQL_DB
71+
MYSQL_MCP_CONNECTION_NAME:${{ vars.GOOGLE_CLOUD_PROJECT }}/MYSQL_MCP_CONNECTION_NAME
72+
MYSQL_MCP_PASS:${{ vars.GOOGLE_CLOUD_PROJECT }}/MYSQL_MCP_PASS
7173
POSTGRES_CONNECTION_NAME:${{ vars.GOOGLE_CLOUD_PROJECT }}/POSTGRES_CONNECTION_NAME
7274
POSTGRES_USER:${{ vars.GOOGLE_CLOUD_PROJECT }}/POSTGRES_USER
7375
POSTGRES_USER_IAM:${{ vars.GOOGLE_CLOUD_PROJECT }}/POSTGRES_USER_IAM_GO
@@ -79,6 +81,8 @@ jobs:
7981
POSTGRES_CUSTOMER_CAS_PASS:${{ vars.GOOGLE_CLOUD_PROJECT }}/POSTGRES_CUSTOMER_CAS_PASS
8082
POSTGRES_CUSTOMER_CAS_DOMAIN_NAME:${{ vars.GOOGLE_CLOUD_PROJECT }}/POSTGRES_CUSTOMER_CAS_DOMAIN_NAME
8183
POSTGRES_CUSTOMER_CAS_INVALID_DOMAIN_NAME:${{ vars.GOOGLE_CLOUD_PROJECT }}/POSTGRES_CUSTOMER_CAS_INVALID_DOMAIN_NAME
84+
POSTGRES_MCP_CONNECTION_NAME:${{ vars.GOOGLE_CLOUD_PROJECT }}/POSTGRES_MCP_CONNECTION_NAME
85+
POSTGRES_MCP_PASS:${{ vars.GOOGLE_CLOUD_PROJECT }}/POSTGRES_MCP_PASS
8286
SQLSERVER_CONNECTION_NAME:${{ vars.GOOGLE_CLOUD_PROJECT }}/SQLSERVER_CONNECTION_NAME
8387
SQLSERVER_USER:${{ vars.GOOGLE_CLOUD_PROJECT }}/SQLSERVER_USER
8488
SQLSERVER_PASS:${{ vars.GOOGLE_CLOUD_PROJECT }}/SQLSERVER_PASS
@@ -91,6 +95,8 @@ jobs:
9195
MYSQL_USER_IAM: "${{ steps.secrets.outputs.MYSQL_USER_IAM }}"
9296
MYSQL_PASS: "${{ steps.secrets.outputs.MYSQL_PASS }}"
9397
MYSQL_DB: "${{ steps.secrets.outputs.MYSQL_DB }}"
98+
MYSQL_MCP_CONNECTION_NAME: "${{ steps.secrets.outputs.MYSQL_MCP_CONNECTION_NAME }}"
99+
MYSQL_MCP_PASS: "${{ steps.secrets.outputs.MYSQL_MCP_PASS }}"
94100
POSTGRES_CONNECTION_NAME: "${{ steps.secrets.outputs.POSTGRES_CONNECTION_NAME }}"
95101
POSTGRES_USER: "${{ steps.secrets.outputs.POSTGRES_USER }}"
96102
POSTGRES_USER_IAM: "${{ steps.secrets.outputs.POSTGRES_USER_IAM }}"
@@ -102,6 +108,8 @@ jobs:
102108
POSTGRES_CUSTOMER_CAS_PASS: "${{ steps.secrets.outputs.POSTGRES_CUSTOMER_CAS_PASS }}"
103109
POSTGRES_CUSTOMER_CAS_DOMAIN_NAME: "${{ steps.secrets.outputs.POSTGRES_CUSTOMER_CAS_DOMAIN_NAME }}"
104110
POSTGRES_CUSTOMER_CAS_INVALID_DOMAIN_NAME: "${{ steps.secrets.outputs.POSTGRES_CUSTOMER_CAS_INVALID_DOMAIN_NAME }}"
111+
POSTGRES_MCP_CONNECTION_NAME: "${{ steps.secrets.outputs.POSTGRES_MCP_CONNECTION_NAME }}"
112+
POSTGRES_MCP_PASS: "${{ steps.secrets.outputs.POSTGRES_MCP_PASS }}"
105113
SQLSERVER_CONNECTION_NAME: "${{ steps.secrets.outputs.SQLSERVER_CONNECTION_NAME }}"
106114
SQLSERVER_USER: "${{ steps.secrets.outputs.SQLSERVER_USER }}"
107115
SQLSERVER_PASS: "${{ steps.secrets.outputs.SQLSERVER_PASS }}"

e2e_mysql_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ var (
3737
mysqlPass = os.Getenv("MYSQL_PASS")
3838
// Name of the database to connect to.
3939
mysqlDB = os.Getenv("MYSQL_DB")
40+
// "Cloud SQL MySQL MCP instance connection name, in the form of 'project:region:instance'.
41+
mysqlMCPConnName = os.Getenv("MYSQL_MCP_CONNECTION_NAME")
42+
// Password for the database user of MCP instance; be careful when entering
43+
// a password on the command line (it may go into your terminal's history).
44+
mysqlMCPPass = os.Getenv("MYSQL_MCP_PASS")
4045
// IP Type of the MySQL instance to connect to.
4146
ipType = os.Getenv("IP_TYPE")
4247
)
@@ -51,6 +56,10 @@ func requireMySQLVars(t *testing.T) {
5156
t.Fatal("'MYSQL_PASS' env var not set")
5257
case mysqlDB:
5358
t.Fatal("'MYSQL_DB' env var not set")
59+
case mysqlMCPConnName:
60+
t.Fatal("'MYSQL_MCP_CONNECTION_NAME' env var not set")
61+
case mysqlMCPPass:
62+
t.Fatal("'MYSQL_MCP_PASS' env var not set")
5463
}
5564
}
5665

@@ -88,6 +97,22 @@ func TestMySQLDriver(t *testing.T) {
8897
user: mysqlIAMUser,
8998
password: "password",
9099
},
100+
{
101+
desc: "default options with MCP",
102+
driverName: "cloudsql-mysql-mcp",
103+
opts: opts,
104+
instanceName: mysqlMCPConnName,
105+
user: mysqlUser,
106+
password: mysqlMCPPass,
107+
},
108+
{
109+
desc: "auto IAM authn with MCP",
110+
driverName: "cloudsql-mysql-iam-mcp",
111+
opts: append(opts, cloudsqlconn.WithIAMAuthN()),
112+
instanceName: mysqlMCPConnName,
113+
user: mysqlIAMUser,
114+
password: "password",
115+
},
91116
}
92117

93118
for _, tc := range tcs {

e2e_postgres_test.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,11 @@ var (
4040
postgresConnName = os.Getenv("POSTGRES_CONNECTION_NAME") // "Cloud SQL Postgres instance connection name, in the form of 'project:region:instance'.
4141
postgresCASConnName = os.Getenv("POSTGRES_CAS_CONNECTION_NAME") // "Cloud SQL Postgres CAS instance connection name, in the form of 'project:region:instance'.
4242
postgresCustomerCASConnName = os.Getenv("POSTGRES_CUSTOMER_CAS_CONNECTION_NAME") // "Cloud SQL Postgres Customer CAS instance connection name, in the form of 'project:region:instance'.
43+
postgresMCPConnName = os.Getenv("POSTGRES_MCP_CONNECTION_NAME") // "Cloud SQL Postgres MCP instance connection name, in the form of 'project:region:instance'.
4344
postgresUser = os.Getenv("POSTGRES_USER") // Name of database user.
4445
postgresPass = os.Getenv("POSTGRES_PASS") // Password for the database user; be careful when entering a password on the command line (it may go into your terminal's history).
4546
postgresCASPass = os.Getenv("POSTGRES_CAS_PASS") // Password for the database user for CAS instances; be careful when entering a password on the command line (it may go into your terminal's history).
47+
postgresMCPPass = os.Getenv("POSTGRES_MCP_PASS") // Password for the database user for MCP instances; be careful when entering a password on the command line (it may go into your terminal's history).
4648
postgresCustomerCASPass = os.Getenv("POSTGRES_CUSTOMER_CAS_PASS") // Password for the database user for customer CAS instances; be careful when entering a password on the command line (it may go into your terminal's history).
4749
postgresDB = os.Getenv("POSTGRES_DB") // Name of the database to connect to.
4850
postgresUserIAM = os.Getenv("POSTGRES_USER_IAM") // Name of database IAM user.
@@ -66,12 +68,16 @@ func requirePostgresVars(t *testing.T) {
6668
t.Fatal("'POSTGRES_CAS_CONNECTION_NAME' env var not set")
6769
case postgresCustomerCASConnName:
6870
t.Fatal("'POSTGRES_CUSTOMER_CAS_CONNECTION_NAME' env var not set")
71+
case postgresMCPConnName:
72+
t.Fatal("'POSTGRES_MCP_CONNECTION_NAME' env var not set")
6973
case postgresUser:
7074
t.Fatal("'POSTGRES_USER' env var not set")
7175
case postgresPass:
7276
t.Fatal("'POSTGRES_PASS' env var not set")
7377
case postgresCASPass:
7478
t.Fatal("'POSTGRES_CAS_PASS' env var not set")
79+
case postgresMCPPass:
80+
t.Fatal("'POSTGRES_MCP_PASS' env var not set")
7581
case postgresCustomerCASPass:
7682
t.Fatal("'POSTGRES_CUSTOMER_CAS_PASS' env var not set")
7783
case postgresDB:
@@ -295,6 +301,58 @@ func TestPostgresCustomerCASConnect(t *testing.T) {
295301
t.Log(now)
296302
}
297303

304+
func TestPostgresMCPConnect(t *testing.T) {
305+
if testing.Short() {
306+
t.Skip("skipping Postgres integration tests")
307+
}
308+
requirePostgresVars(t)
309+
310+
ctx := context.Background()
311+
312+
// Configure the driver to connect to the database
313+
dsn := fmt.Sprintf("user=%s password=%s dbname=%s sslmode=disable", postgresUser, postgresMCPPass, postgresDB)
314+
config, err := pgxpool.ParseConfig(dsn)
315+
if err != nil {
316+
t.Fatalf("failed to parse pgx config: %v", err)
317+
}
318+
319+
// Use WithPrivateIP option if the ipType is set to private
320+
var opts []cloudsqlconn.Option
321+
opts = AddIPTypeOptions(opts)
322+
323+
// Create a new dialer with any options
324+
d, err := cloudsqlconn.NewDialer(ctx, opts...)
325+
if err != nil {
326+
t.Fatalf("failed to init Dialer: %v", err)
327+
}
328+
329+
// call cleanup when you're done with the database connection to close dialer
330+
cleanup := func() error { return d.Close() }
331+
332+
// Tell the driver to use the Cloud SQL Go Connector to create connections
333+
// postgresMCPConnName takes the form of 'project:region:instance'.
334+
config.ConnConfig.DialFunc = func(ctx context.Context, _ string, _ string) (net.Conn, error) {
335+
return d.Dial(ctx, postgresMCPConnName)
336+
}
337+
338+
// Interact with the driver directly as you normally would
339+
pool, err := pgxpool.NewWithConfig(ctx, config)
340+
if err != nil {
341+
t.Fatalf("failed to create pool: %s", err)
342+
}
343+
// ... etc
344+
345+
defer cleanup()
346+
defer pool.Close()
347+
348+
var now time.Time
349+
err = pool.QueryRow(context.Background(), "SELECT NOW()").Scan(&now)
350+
if err != nil {
351+
t.Fatalf("QueryRow failed: %s", err)
352+
}
353+
t.Log(now)
354+
}
355+
298356
func TestPostgresSANDomainConnect(t *testing.T) {
299357
if testing.Short() {
300358
t.Skip("skipping Postgres integration tests")

0 commit comments

Comments
 (0)