...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package util
16
17 import (
18 "bytes"
19 "context"
20 "encoding/json"
21 "fmt"
22 "runtime"
23 "time"
24
25 "github.com/GoogleCloudPlatform/cloudsql-proxy/logging"
26 "golang.org/x/oauth2"
27 exec "golang.org/x/sys/execabs"
28 )
29
30
31 type GcloudConfigData struct {
32 Configuration struct {
33 Properties struct {
34 Core struct {
35 Project string
36 Account string
37 }
38 }
39 }
40 Credential struct {
41 AccessToken string `json:"access_token"`
42 TokenExpiry time.Time `json:"token_expiry"`
43 }
44 }
45
46 func (cfg *GcloudConfigData) oauthToken() *oauth2.Token {
47 return &oauth2.Token{
48 AccessToken: cfg.Credential.AccessToken,
49 Expiry: cfg.Credential.TokenExpiry,
50 }
51 }
52
53 type GcloudStatusCode int
54
55 const (
56 GcloudOk GcloudStatusCode = iota
57 GcloudNotFound
58
59 GcloudExecErr
60 )
61
62 type GcloudError struct {
63 GcloudError error
64 Status GcloudStatusCode
65 }
66
67 func (e *GcloudError) Error() string {
68 return e.GcloudError.Error()
69 }
70
71
72 func GcloudConfig() (*GcloudConfigData, error) {
73 gcloudCmd := "gcloud"
74 if runtime.GOOS == "windows" {
75 gcloudCmd = gcloudCmd + ".cmd"
76 }
77
78 if _, err := exec.LookPath(gcloudCmd); err != nil {
79 return nil, &GcloudError{err, GcloudNotFound}
80 }
81
82 buf, errbuf := new(bytes.Buffer), new(bytes.Buffer)
83 cmd := exec.Command(gcloudCmd, "--format", "json", "config", "config-helper", "--min-expiry", "1h")
84 cmd.Stdout = buf
85 cmd.Stderr = errbuf
86
87 if err := cmd.Run(); err != nil {
88 err = fmt.Errorf("error reading config: %v; stderr was:\n%v", err, errbuf)
89 logging.Errorf("GcloudConfig: %v", err)
90 return nil, &GcloudError{err, GcloudExecErr}
91 }
92
93 data := &GcloudConfigData{}
94 if err := json.Unmarshal(buf.Bytes(), data); err != nil {
95 logging.Errorf("Failed to unmarshal bytes from gcloud: %v", err)
96 logging.Errorf(" gcloud returned:\n%s", buf)
97 return nil, &GcloudError{err, GcloudExecErr}
98 }
99
100 return data, nil
101 }
102
103
104 type gcloudTokenSource struct {
105 }
106
107
108 func (src *gcloudTokenSource) Token() (*oauth2.Token, error) {
109 cfg, err := GcloudConfig()
110 if err != nil {
111 return nil, err
112 }
113 return cfg.oauthToken(), nil
114 }
115
116 func GcloudTokenSource(ctx context.Context) (oauth2.TokenSource, error) {
117 src := &gcloudTokenSource{}
118 tok, err := src.Token()
119 if err != nil {
120 return nil, err
121 }
122 return oauth2.ReuseTokenSource(tok, src), nil
123 }
124
View as plain text