...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package cloudsqlconn
16
17 import (
18 "context"
19 "crypto/rsa"
20 "net"
21 "net/http"
22 "os"
23 "time"
24
25 "cloud.google.com/go/cloudsqlconn/debug"
26 "cloud.google.com/go/cloudsqlconn/errtype"
27 "cloud.google.com/go/cloudsqlconn/internal/cloudsql"
28 "golang.org/x/oauth2"
29 "golang.org/x/oauth2/google"
30 apiopt "google.golang.org/api/option"
31 sqladmin "google.golang.org/api/sqladmin/v1beta4"
32 )
33
34
35 type Option func(d *dialerConfig)
36
37 type dialerConfig struct {
38 rsaKey *rsa.PrivateKey
39 sqladminOpts []apiopt.ClientOption
40 dialOpts []DialOption
41 dialFunc func(ctx context.Context, network, addr string) (net.Conn, error)
42 refreshTimeout time.Duration
43 useIAMAuthN bool
44 logger debug.ContextLogger
45 lazyRefresh bool
46 iamLoginTokenSource oauth2.TokenSource
47 useragents []string
48 credentialsUniverse string
49 serviceUniverse string
50 setAdminAPIEndpoint bool
51 setUniverseDomain bool
52 setCredentials bool
53 setTokenSource bool
54 setIAMAuthNTokenSource bool
55
56 err error
57 }
58
59
60 func WithOptions(opts ...Option) Option {
61 return func(d *dialerConfig) {
62 for _, opt := range opts {
63 opt(d)
64 }
65 }
66 }
67
68
69
70
71 func WithCredentialsFile(filename string) Option {
72 return func(d *dialerConfig) {
73 b, err := os.ReadFile(filename)
74 if err != nil {
75 d.err = errtype.NewConfigError(err.Error(), "n/a")
76 return
77 }
78 opt := WithCredentialsJSON(b)
79 opt(d)
80 }
81 }
82
83
84
85 func WithCredentialsJSON(b []byte) Option {
86 return func(d *dialerConfig) {
87 c, err := google.CredentialsFromJSON(context.Background(), b, sqladmin.SqlserviceAdminScope)
88 if err != nil {
89 d.err = errtype.NewConfigError(err.Error(), "n/a")
90 return
91 }
92 ud, err := c.GetUniverseDomain()
93 if err != nil {
94 d.err = errtype.NewConfigError(err.Error(), "n/a")
95 return
96 }
97 d.credentialsUniverse = ud
98 d.sqladminOpts = append(d.sqladminOpts, apiopt.WithCredentials(c))
99
100
101 scoped, err := google.CredentialsFromJSON(context.Background(), b, iamLoginScope)
102 if err != nil {
103 d.err = errtype.NewConfigError(err.Error(), "n/a")
104 return
105 }
106 d.iamLoginTokenSource = scoped.TokenSource
107 d.setCredentials = true
108 }
109 }
110
111
112 func WithUserAgent(ua string) Option {
113 return func(d *dialerConfig) {
114 d.useragents = append(d.useragents, ua)
115 }
116 }
117
118
119
120 func WithDefaultDialOptions(opts ...DialOption) Option {
121 return func(d *dialerConfig) {
122 d.dialOpts = append(d.dialOpts, opts...)
123 }
124 }
125
126
127
128
129
130
131
132 func WithTokenSource(s oauth2.TokenSource) Option {
133 return func(d *dialerConfig) {
134 d.setTokenSource = true
135 d.setCredentials = true
136 d.sqladminOpts = append(d.sqladminOpts, apiopt.WithTokenSource(s))
137 }
138 }
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154 func WithIAMAuthNTokenSources(apiTS, iamLoginTS oauth2.TokenSource) Option {
155 return func(d *dialerConfig) {
156 d.setIAMAuthNTokenSource = true
157 d.setCredentials = true
158 d.iamLoginTokenSource = iamLoginTS
159 d.sqladminOpts = append(d.sqladminOpts, apiopt.WithTokenSource(apiTS))
160 }
161 }
162
163
164 func WithRSAKey(k *rsa.PrivateKey) Option {
165 return func(d *dialerConfig) {
166 d.rsaKey = k
167 }
168 }
169
170
171
172 func WithRefreshTimeout(t time.Duration) Option {
173 return func(d *dialerConfig) {
174 d.refreshTimeout = t
175 }
176 }
177
178
179
180
181 func WithHTTPClient(client *http.Client) Option {
182 return func(d *dialerConfig) {
183 d.sqladminOpts = append(d.sqladminOpts, apiopt.WithHTTPClient(client))
184 }
185 }
186
187
188
189 func WithAdminAPIEndpoint(url string) Option {
190 return func(d *dialerConfig) {
191 d.sqladminOpts = append(d.sqladminOpts, apiopt.WithEndpoint(url))
192 d.setAdminAPIEndpoint = true
193 d.serviceUniverse = ""
194 }
195 }
196
197
198
199 func WithUniverseDomain(ud string) Option {
200 return func(d *dialerConfig) {
201 d.sqladminOpts = append(d.sqladminOpts, apiopt.WithUniverseDomain(ud))
202 d.serviceUniverse = ud
203 d.setUniverseDomain = true
204 }
205 }
206
207
208 func WithQuotaProject(p string) Option {
209 return func(cfg *dialerConfig) {
210 cfg.sqladminOpts = append(cfg.sqladminOpts, apiopt.WithQuotaProject(p))
211 }
212 }
213
214
215
216
217
218 func WithDialFunc(dial func(ctx context.Context, network, addr string) (net.Conn, error)) Option {
219 return func(d *dialerConfig) {
220 d.dialFunc = dial
221 }
222 }
223
224
225
226
227
228
229
230
231 func WithIAMAuthN() Option {
232 return func(d *dialerConfig) {
233 d.useIAMAuthN = true
234 }
235 }
236
237 type debugLoggerWithoutContext struct {
238 logger debug.Logger
239 }
240
241
242 func (d *debugLoggerWithoutContext) Debugf(_ context.Context, format string, args ...interface{}) {
243 d.logger.Debugf(format, args...)
244 }
245
246 var _ debug.ContextLogger = new(debugLoggerWithoutContext)
247
248
249
250
251
252 func WithDebugLogger(l debug.Logger) Option {
253 return func(d *dialerConfig) {
254 d.logger = &debugLoggerWithoutContext{l}
255 }
256 }
257
258
259
260 func WithContextDebugLogger(l debug.ContextLogger) Option {
261 return func(d *dialerConfig) {
262 d.logger = l
263 }
264 }
265
266
267
268
269
270
271
272
273 func WithLazyRefresh() Option {
274 return func(d *dialerConfig) {
275 d.lazyRefresh = true
276 }
277 }
278
279
280 type DialOption func(d *dialConfig)
281
282 type dialConfig struct {
283 dialFunc func(ctx context.Context, network, addr string) (net.Conn, error)
284 ipType string
285 tcpKeepAlive time.Duration
286 useIAMAuthN bool
287 }
288
289
290 func DialOptions(opts ...DialOption) DialOption {
291 return func(cfg *dialConfig) {
292 for _, opt := range opts {
293 opt(cfg)
294 }
295 }
296 }
297
298
299
300
301 func WithOneOffDialFunc(dial func(ctx context.Context, network, addr string) (net.Conn, error)) DialOption {
302 return func(c *dialConfig) {
303 c.dialFunc = dial
304 }
305 }
306
307
308 func WithTCPKeepAlive(d time.Duration) DialOption {
309 return func(cfg *dialConfig) {
310 cfg.tcpKeepAlive = d
311 }
312 }
313
314
315 func WithPublicIP() DialOption {
316 return func(cfg *dialConfig) {
317 cfg.ipType = cloudsql.PublicIP
318 }
319 }
320
321
322 func WithPrivateIP() DialOption {
323 return func(cfg *dialConfig) {
324 cfg.ipType = cloudsql.PrivateIP
325 }
326 }
327
328
329 func WithPSC() DialOption {
330 return func(cfg *dialConfig) {
331 cfg.ipType = cloudsql.PSC
332 }
333 }
334
335
336
337
338 func WithAutoIP() DialOption {
339 return func(cfg *dialConfig) {
340 cfg.ipType = cloudsql.AutoIP
341 }
342 }
343
344
345
346
347
348
349
350
351 func WithDialIAMAuthN(b bool) DialOption {
352 return func(cfg *dialConfig) {
353 cfg.useIAMAuthN = b
354 }
355 }
356
View as plain text