1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
16
17 package mysql
18
19 import (
20 "context"
21 "encoding/json"
22 "errors"
23 "fmt"
24 "log"
25 "strings"
26
27 "cloud.google.com/go/compute/metadata"
28 "golang.org/x/oauth2"
29 "golang.org/x/oauth2/google"
30 sqladmin "google.golang.org/api/sqladmin/v1beta4"
31 )
32
33 const cloudSQLSuffix = ".cloudsql.google.internal"
34
35 func maybeRemapCloudSQL(host string) (out string, err error) {
36 if !strings.HasSuffix(host, cloudSQLSuffix) {
37 return host, nil
38 }
39 inst := strings.TrimSuffix(host, cloudSQLSuffix)
40 if !metadata.OnGCE() {
41 return "", errors.New("CloudSQL support only available when running on Google Compute Engine.")
42 }
43 proj, err := metadata.ProjectID()
44 if err != nil {
45 return "", fmt.Errorf("Failed to lookup GCE project ID: %v", err)
46 }
47
48 admin, _ := sqladmin.New(oauth2.NewClient(context.Background(), google.ComputeTokenSource("")))
49 listRes, err := admin.Instances.List(proj).Do()
50 if err != nil {
51 return "", fmt.Errorf("error enumerating Cloud SQL instances: %v", err)
52 }
53 for _, it := range listRes.Items {
54 if !strings.EqualFold(it.Name, inst) {
55 continue
56 }
57 js, _ := json.Marshal(it)
58 log.Printf("Found Cloud SQL instance %s: %s", inst, js)
59 for _, ipm := range it.IpAddresses {
60 return ipm.IpAddress, nil
61 }
62 return "", fmt.Errorf("No external IP address for Cloud SQL instances %s", inst)
63 }
64 var found []string
65 for _, it := range listRes.Items {
66 found = append(found, it.Name)
67 }
68 return "", fmt.Errorf("Cloud SQL instance %q not found. Found: %q", inst, found)
69 }