Skip to content

Commit 26dcf57

Browse files
authored
test: add Customer CAS and Custom SAN e2e tests (#958)
Adds e2e tests to ensure instances with a domain name and custom SAN can connect.
1 parent 6873ba9 commit 26dcf57

File tree

2 files changed

+122
-22
lines changed

2 files changed

+122
-22
lines changed

.github/workflows/tests.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ jobs:
7777
POSTGRES_CAS_PASS:${{ vars.GOOGLE_CLOUD_PROJECT }}/POSTGRES_CAS_PASS
7878
POSTGRES_CUSTOMER_CAS_CONNECTION_NAME:${{ vars.GOOGLE_CLOUD_PROJECT }}/POSTGRES_CUSTOMER_CAS_CONNECTION_NAME
7979
POSTGRES_CUSTOMER_CAS_PASS:${{ vars.GOOGLE_CLOUD_PROJECT }}/POSTGRES_CUSTOMER_CAS_PASS
80+
POSTGRES_CUSTOMER_CAS_DOMAIN_NAME:${{ vars.GOOGLE_CLOUD_PROJECT }}/POSTGRES_CUSTOMER_CAS_DOMAIN_NAME
81+
POSTGRES_CUSTOMER_CAS_INVALID_DOMAIN_NAME:${{ vars.GOOGLE_CLOUD_PROJECT }}/POSTGRES_CUSTOMER_CAS_INVALID_DOMAIN_NAME
8082
SQLSERVER_CONNECTION_NAME:${{ vars.GOOGLE_CLOUD_PROJECT }}/SQLSERVER_CONNECTION_NAME
8183
SQLSERVER_USER:${{ vars.GOOGLE_CLOUD_PROJECT }}/SQLSERVER_USER
8284
SQLSERVER_PASS:${{ vars.GOOGLE_CLOUD_PROJECT }}/SQLSERVER_PASS
@@ -98,6 +100,8 @@ jobs:
98100
POSTGRES_CAS_PASS: "${{ steps.secrets.outputs.POSTGRES_CAS_PASS }}"
99101
POSTGRES_CUSTOMER_CAS_CONNECTION_NAME: "${{ steps.secrets.outputs.POSTGRES_CUSTOMER_CAS_CONNECTION_NAME }}"
100102
POSTGRES_CUSTOMER_CAS_PASS: "${{ steps.secrets.outputs.POSTGRES_CUSTOMER_CAS_PASS }}"
103+
POSTGRES_CUSTOMER_CAS_DOMAIN_NAME: "${{ steps.secrets.outputs.POSTGRES_CUSTOMER_CAS_DOMAIN_NAME }}"
104+
POSTGRES_CUSTOMER_CAS_INVALID_DOMAIN_NAME: "${{ steps.secrets.outputs.POSTGRES_CUSTOMER_CAS_INVALID_DOMAIN_NAME }}"
101105
SQLSERVER_CONNECTION_NAME: "${{ steps.secrets.outputs.SQLSERVER_CONNECTION_NAME }}"
102106
SQLSERVER_USER: "${{ steps.secrets.outputs.SQLSERVER_USER }}"
103107
SQLSERVER_PASS: "${{ steps.secrets.outputs.SQLSERVER_PASS }}"

e2e_postgres_test.go

Lines changed: 118 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ import (
2828
"time"
2929

3030
"cloud.google.com/go/cloudsqlconn"
31-
"cloud.google.com/go/cloudsqlconn/instance"
3231
"github.com/jackc/pgx/v5/pgxpool"
3332
"golang.org/x/oauth2"
3433
"golang.org/x/oauth2/google"
@@ -38,16 +37,18 @@ import (
3837
)
3938

4039
var (
41-
postgresConnName = os.Getenv("POSTGRES_CONNECTION_NAME") // "Cloud SQL Postgres instance connection name, in the form of 'project:region:instance'.
42-
postgresCASConnName = os.Getenv("POSTGRES_CAS_CONNECTION_NAME") // "Cloud SQL Postgres CAS instance connection name, in the form of 'project:region:instance'.
43-
postgresCustomerCASConnName = os.Getenv("POSTGRES_CUSTOMER_CAS_CONNECTION_NAME") // "Cloud SQL Postgres Customer CAS instance connection name, in the form of 'project:region:instance'.
44-
postgresUser = os.Getenv("POSTGRES_USER") // Name of database user.
45-
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).
46-
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-
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).
48-
postgresDB = os.Getenv("POSTGRES_DB") // Name of the database to connect to.
49-
postgresUserIAM = os.Getenv("POSTGRES_USER_IAM") // Name of database IAM user.
50-
project = os.Getenv("QUOTA_PROJECT") // Name of the Google Cloud Platform project to use for quota and billing.
40+
postgresConnName = os.Getenv("POSTGRES_CONNECTION_NAME") // "Cloud SQL Postgres instance connection name, in the form of 'project:region:instance'.
41+
postgresCASConnName = os.Getenv("POSTGRES_CAS_CONNECTION_NAME") // "Cloud SQL Postgres CAS instance connection name, in the form of 'project:region:instance'.
42+
postgresCustomerCASConnName = os.Getenv("POSTGRES_CUSTOMER_CAS_CONNECTION_NAME") // "Cloud SQL Postgres Customer CAS instance connection name, in the form of 'project:region:instance'.
43+
postgresUser = os.Getenv("POSTGRES_USER") // Name of database user.
44+
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).
45+
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).
46+
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).
47+
postgresDB = os.Getenv("POSTGRES_DB") // Name of the database to connect to.
48+
postgresUserIAM = os.Getenv("POSTGRES_USER_IAM") // Name of database IAM user.
49+
project = os.Getenv("QUOTA_PROJECT") // Name of the Google Cloud Platform project to use for quota and billing.
50+
postgresSANDomainName = os.Getenv("POSTGRES_CUSTOMER_CAS_DOMAIN_NAME") // Cloud SQL Postgres CAS domain name that is an instance Custom SAN of the postgresSANConnName instance.
51+
postgresSANInvalidDomainName = os.Getenv("POSTGRES_CUSTOMER_CAS_INVALID_DOMAIN_NAME") // Cloud SQL Postgres CAS domain name that IS NOT an instance Custom SAN of the postgresSANConnName instance.
5152
)
5253

5354
func requirePostgresVars(t *testing.T) {
@@ -72,6 +73,10 @@ func requirePostgresVars(t *testing.T) {
7273
t.Fatal("'POSTGRES_USER_IAM' env var not set")
7374
case project:
7475
t.Fatal("'QUOTA_PROJECT' env var not set")
76+
case postgresSANDomainName:
77+
t.Fatal("'POSTGRES_SAN_DOMAIN_NAME' env var not set")
78+
case postgresSANInvalidDomainName:
79+
t.Fatal("'POSTGRES_SAN_INVALID_DOMAIN_NAME' env var not set")
7580
}
7681
}
7782

@@ -267,34 +272,125 @@ func TestPostgresCustomerCASConnect(t *testing.T) {
267272
t.Log(now)
268273
}
269274

270-
type pgMockResolver struct {
275+
func TestPostgresSANDomainConnect(t *testing.T) {
276+
if testing.Short() {
277+
t.Skip("skipping Postgres integration tests")
278+
}
279+
requirePostgresVars(t)
280+
281+
ctx := context.Background()
282+
283+
// Configure the driver to connect to the database
284+
dsn := fmt.Sprintf("user=%s password=%s dbname=%s sslmode=disable", postgresUser, postgresCustomerCASPass, "postgres")
285+
config, err := pgxpool.ParseConfig(dsn)
286+
if err != nil {
287+
t.Fatalf("failed to parse pgx config: %v", err)
288+
}
289+
290+
// Create a new dialer with any options
291+
d, err := cloudsqlconn.NewDialer(ctx, cloudsqlconn.WithDNSResolver())
292+
293+
if err != nil {
294+
t.Fatalf("failed to init Dialer: %v", err)
295+
}
296+
297+
// call cleanup when you're done with the database connection to close dialer
298+
cleanup := func() error { return d.Close() }
299+
300+
// Tell the driver to use the Cloud SQL Go Connector to create connections
301+
// postgresConnName takes the form of 'project:region:instance'.
302+
config.ConnConfig.DialFunc = func(ctx context.Context, _ string, _ string) (net.Conn, error) {
303+
return d.Dial(ctx, postgresSANDomainName)
304+
}
305+
306+
// Interact with the driver directly as you normally would
307+
pool, err := pgxpool.NewWithConfig(ctx, config)
308+
if err != nil {
309+
t.Fatalf("failed to create pool: %s", err)
310+
}
311+
// ... etc
312+
313+
defer cleanup()
314+
defer pool.Close()
315+
316+
var now time.Time
317+
err = pool.QueryRow(context.Background(), "SELECT NOW()").Scan(&now)
318+
if err != nil {
319+
t.Fatalf("QueryRow failed: %s", err)
320+
}
321+
t.Log(now)
271322
}
272323

273-
func (r *pgMockResolver) Resolve(_ context.Context, name string) (instanceName instance.ConnName, err error) {
274-
if name == "pg.example.com" {
275-
return instance.ParseConnNameWithDomainName(postgresConnName, "pg.example.com")
324+
func TestPostgresSANBadDomainCausesConnectError(t *testing.T) {
325+
if testing.Short() {
326+
t.Skip("skipping Postgres integration tests")
327+
}
328+
requirePostgresVars(t)
329+
330+
ctx := context.Background()
331+
332+
// Configure the driver to connect to the database
333+
dsn := fmt.Sprintf("user=%s password=%s dbname=%s sslmode=disable", postgresUser, postgresCustomerCASPass, "postgres")
334+
config, err := pgxpool.ParseConfig(dsn)
335+
if err != nil {
336+
t.Fatalf("failed to parse pgx config: %v", err)
276337
}
277-
return instance.ConnName{}, fmt.Errorf("no resolution for %v", name)
338+
339+
// Create a new dialer with any options
340+
d, err := cloudsqlconn.NewDialer(ctx, cloudsqlconn.WithDNSResolver())
341+
342+
if err != nil {
343+
t.Fatalf("failed to init Dialer: %v", err)
344+
}
345+
346+
// call cleanup when you're done with the database connection to close dialer
347+
cleanup := func() error { return d.Close() }
348+
349+
// Tell the driver to use the Cloud SQL Go Connector to create connections
350+
// postgresConnName takes the form of 'project:region:instance'.
351+
config.ConnConfig.DialFunc = func(ctx context.Context, _ string, _ string) (net.Conn, error) {
352+
return d.Dial(ctx, postgresSANInvalidDomainName)
353+
}
354+
355+
// Interact with the driver directly as you normally would
356+
pool, err := pgxpool.NewWithConfig(ctx, config)
357+
if err != nil {
358+
t.Fatalf("failed to create pool: %s", err)
359+
}
360+
// ... etc
361+
362+
defer cleanup()
363+
defer pool.Close()
364+
365+
var now time.Time
366+
err = pool.QueryRow(context.Background(), "SELECT NOW()").Scan(&now)
367+
if err == nil {
368+
t.Fatal("Want error, got invalid error")
369+
}
370+
if !strings.Contains(fmt.Sprint(err), "Dial error: handshake failed") {
371+
t.Fatal("Want error 'Dial error: handshake failed'. got: ", err)
372+
}
373+
t.Log(now)
278374
}
279375

280376
func TestPostgresPgxPoolConnectDomainName(t *testing.T) {
281377
if testing.Short() {
282378
t.Skip("skipping Postgres integration tests")
283379
}
284380
requirePostgresVars(t)
285-
pgxv5.RegisterDriver("pgxpool-connect")
381+
pgxv5.RegisterDriver("pgxpool-connect", cloudsqlconn.WithDNSResolver())
286382

287383
ctx := context.Background()
288384

289385
// Configure the driver to connect to the database
290-
dsn := fmt.Sprintf("user=%s password=%s dbname=%s sslmode=disable", postgresUser, postgresPass, postgresDB)
386+
dsn := fmt.Sprintf("user=%s password=%s dbname=%s sslmode=disable", postgresUser, postgresCustomerCASPass, postgresDB)
291387
config, err := pgxpool.ParseConfig(dsn)
292388
if err != nil {
293389
t.Fatalf("failed to parse pgx config: %v", err)
294390
}
295391

296392
// Create a new dialer with any options
297-
d, err := cloudsqlconn.NewDialer(ctx, cloudsqlconn.WithResolver(&pgMockResolver{}))
393+
d, err := cloudsqlconn.NewDialer(ctx, cloudsqlconn.WithDNSResolver())
298394
if err != nil {
299395
t.Fatalf("failed to init Dialer: %v", err)
300396
}
@@ -306,7 +402,7 @@ func TestPostgresPgxPoolConnectDomainName(t *testing.T) {
306402
// Tell the driver to use the Cloud SQL Go Connector to create connections
307403
// postgresConnName takes the form of 'project:region:instance'.
308404
config.ConnConfig.DialFunc = func(ctx context.Context, _ string, _ string) (net.Conn, error) {
309-
return d.Dial(ctx, "pg.example.com")
405+
return d.Dial(ctx, postgresSANDomainName)
310406
}
311407

312408
pool, err := pgxpool.NewWithConfig(ctx, config)
@@ -443,7 +539,7 @@ func TestPostgresV5Hook(t *testing.T) {
443539
{
444540
driver: "cloudsql-postgres-v5-dns",
445541
source: fmt.Sprintf("host=%s user=%s password=%s dbname=%s sslmode=disable",
446-
"pg.example.com", postgresUser, postgresPass, postgresDB),
542+
postgresSANDomainName, postgresUser, postgresCustomerCASPass, postgresDB),
447543
IAMAuthN: false,
448544
resolver: true,
449545
},
@@ -464,7 +560,7 @@ func TestPostgresV5Hook(t *testing.T) {
464560
if tc.IAMAuthN {
465561
pgxv5.RegisterDriver(tc.driver, cloudsqlconn.WithIAMAuthN())
466562
} else if tc.resolver {
467-
pgxv5.RegisterDriver(tc.driver, cloudsqlconn.WithResolver(&pgMockResolver{}))
563+
pgxv5.RegisterDriver(tc.driver, cloudsqlconn.WithDNSResolver())
468564
} else {
469565
pgxv5.RegisterDriver(tc.driver)
470566
}

0 commit comments

Comments
 (0)