...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package tests
16
17 import (
18 "context"
19 "database/sql"
20 "fmt"
21 "net"
22 "net/http"
23 "testing"
24 "time"
25
26 "github.com/GoogleCloudPlatform/cloudsql-proxy/proxy/certs"
27 "github.com/GoogleCloudPlatform/cloudsql-proxy/proxy/proxy"
28 "github.com/jackc/pgx/v4"
29 "github.com/jackc/pgx/v4/stdlib"
30 "golang.org/x/oauth2"
31 "golang.org/x/oauth2/google"
32 "google.golang.org/api/option"
33 "google.golang.org/api/sqladmin/v1"
34 )
35
36 func TestClientHandlesSSLReset(t *testing.T) {
37 if testing.Short() {
38 t.Skip("skipping dialer integration tests")
39 }
40 newClient := func(c *http.Client) *proxy.Client {
41 return &proxy.Client{
42 Port: 3307,
43 Certs: certs.NewCertSourceOpts(c, certs.RemoteOpts{
44 UserAgent: "cloud_sql_proxy/test_build",
45 IPAddrTypeOpts: []string{"PUBLIC", "PRIVATE"},
46 }),
47 Conns: proxy.NewConnSet(),
48 }
49 }
50 connectToDB := func(c *proxy.Client) (*sql.DB, error) {
51 var (
52 dbUser = *postgresUser
53 dbPwd = *postgresPass
54 dbName = *postgresDb
55 )
56 dsn := fmt.Sprintf("user=%s password=%s database=%s", dbUser, dbPwd, dbName)
57 config, err := pgx.ParseConfig(dsn)
58 if err != nil {
59 return nil, err
60 }
61 config.DialFunc = func(ctx context.Context, network, instance string) (net.Conn, error) {
62 return c.DialContext(ctx, *postgresConnName)
63 }
64 dbURI := stdlib.RegisterConnConfig(config)
65 return sql.Open("pgx", dbURI)
66 }
67 resetSSL := func(c *http.Client) error {
68 svc, err := sqladmin.NewService(context.Background(), option.WithHTTPClient(c))
69 if err != nil {
70 return err
71 }
72 project, _, instance, _, _ := proxy.ParseInstanceConnectionName(*postgresConnName)
73 t.Log("Resetting SSL config.")
74 op, err := svc.Instances.ResetSslConfig(project, instance).Do()
75 if err != nil {
76 return err
77 }
78 for {
79 t.Log("Waiting for operation to complete.")
80 op, err = svc.Operations.Get(project, op.Name).Do()
81 if err != nil {
82 return err
83 }
84 if op.Status == "DONE" {
85 t.Log("reset SSL config operation complete")
86 break
87 }
88 time.Sleep(time.Second)
89 }
90 return nil
91 }
92
93
94 src, err := google.DefaultTokenSource(context.Background(), proxy.SQLScope)
95 if err != nil {
96 t.Fatal(err)
97 }
98 client := oauth2.NewClient(context.Background(), src)
99 proxyClient := newClient(client)
100
101 db, err := connectToDB(proxyClient)
102 if err != nil {
103 t.Fatalf("failed to connect to DB: %v", err)
104 }
105
106
107 tx, err := db.Begin()
108 if err != nil {
109 t.Fatal(err)
110 }
111 defer tx.Rollback()
112
113 resetSSL(client)
114
115
116 var attempts int
117 for {
118 t.Log("Re-dialing instance")
119 _, err = proxyClient.DialContext(context.Background(), *postgresConnName)
120 if err != nil {
121 t.Logf("Dial error: %v", err)
122 }
123 if err == nil {
124 break
125 }
126 attempts++
127 if attempts > 1 {
128 t.Fatalf("could not dial: %v", err)
129 }
130 time.Sleep(time.Second)
131 }
132
133 for i := 0; i < 5; i++ {
134 row, err := tx.Query("SELECT 1")
135 if err != nil {
136 t.Logf("Query after Reset SSL failed as expected after %v retries (error was %v)", i, err)
137 break
138 }
139 row.Close()
140 time.Sleep(time.Second)
141 }
142
143 if err = db.Ping(); err != nil {
144 t.Fatalf("could not re-stablish a DB connection: %v", err)
145 }
146 }
147
View as plain text