Skip to content

Commit

Permalink
feat: add support for PSC connections (#565)
Browse files Browse the repository at this point in the history
  • Loading branch information
jackwotherspoon committed Jul 6, 2023
1 parent a156b3b commit 10a46b0
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 2 deletions.
8 changes: 8 additions & 0 deletions internal/cloudsql/refresh.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ const (
PublicIP = "PUBLIC"
// PrivateIP is the value for private IP Cloud SQL instances.
PrivateIP = "PRIVATE"
// PSC is the value for private service connect Cloud SQL instances.
PSC = "PSC"
// AutoIP selects public IP if available and otherwise selects private
// IP.
AutoIP = "AutoIP"
Expand Down Expand Up @@ -81,6 +83,12 @@ func fetchMetadata(ctx context.Context, client *sqladmin.Service, inst ConnName)
ipAddrs[PrivateIP] = ip.IpAddress
}
}

// resolve DnsName into IP address for PSC
if db.DnsName != "" {
ipAddrs[PSC] = db.DnsName
}

if len(ipAddrs) == 0 {
return metadata{}, errtype.NewConfigError(
"cannot connect to instance - it has no supported IP addresses",
Expand Down
13 changes: 11 additions & 2 deletions internal/cloudsql/refresh_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const testDialerID = "some-dialer-id"
func TestRefresh(t *testing.T) {
wantPublicIP := "127.0.0.1"
wantPrivateIP := "10.0.0.1"
wantPSC := "abcde.12345.us-central1.sql.goog"
wantExpiry := time.Now().Add(time.Hour).UTC().Round(time.Second)
wantConnName := "my-project:my-region:my-instance"
cn, err := ParseConnName(wantConnName)
Expand All @@ -45,6 +46,7 @@ func TestRefresh(t *testing.T) {
"my-project", "my-region", "my-instance",
mock.WithPublicIP(wantPublicIP),
mock.WithPrivateIP(wantPrivateIP),
mock.WithPSC(wantPSC),
mock.WithCertExpiry(wantExpiry),
)
client, cleanup, err := mock.NewSQLAdminService(
Expand All @@ -69,18 +71,25 @@ func TestRefresh(t *testing.T) {

gotIP, ok := rr.ipAddrs[PublicIP]
if !ok {
t.Fatalf("metadata IP addresses did not include public address")
t.Fatal("metadata IP addresses did not include public address")
}
if wantPublicIP != gotIP {
t.Fatalf("metadata IP mismatch, want = %v, got = %v", wantPublicIP, gotIP)
}
gotIP, ok = rr.ipAddrs[PrivateIP]
if !ok {
t.Fatalf("metadata IP addresses did not include private address")
t.Fatal("metadata IP addresses did not include private address")
}
if wantPrivateIP != gotIP {
t.Fatalf("metadata IP mismatch, want = %v, got = %v", wantPrivateIP, gotIP)
}
gotPSC, ok := rr.ipAddrs[PSC]
if !ok {
t.Fatal("metadata IP addresses did not include PSC endpoint")
}
if wantPSC != gotPSC {
t.Fatalf("metadata IP mismatch, want = %v. got = %v", wantPSC, gotPSC)
}
if wantExpiry != rr.expiry {
t.Fatalf("expiry mismatch, want = %v, got = %v", wantExpiry, rr.expiry)
}
Expand Down
9 changes: 9 additions & 0 deletions internal/mock/cloudsql.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ type FakeCSQLInstance struct {
// ipAddrs is a map of IP type (PUBLIC or PRIVATE) to IP address.
ipAddrs map[string]string
backendType string
DNSName string
signer SignFunc
clientSigner ClientSignFunc
Key *rsa.PrivateKey
Expand Down Expand Up @@ -81,6 +82,13 @@ func WithPrivateIP(addr string) FakeCSQLInstanceOption {
}
}

// WithPSC sets the PSC DnsName to addr.
func WithPSC(dns string) FakeCSQLInstanceOption {
return func(f *FakeCSQLInstance) {
f.DNSName = dns
}
}

// WithCertExpiry sets the server certificate's expiration to t.
func WithCertExpiry(t time.Time) FakeCSQLInstanceOption {
return func(f *FakeCSQLInstance) {
Expand Down Expand Up @@ -155,6 +163,7 @@ func NewFakeCSQLInstance(project, region, name string, opts ...FakeCSQLInstanceO
region: region,
name: name,
ipAddrs: map[string]string{"PUBLIC": "0.0.0.0"},
DNSName: "",
dbVersion: "POSTGRES_12", // default of no particular importance
backendType: "SECOND_GEN",
signer: SelfSign,
Expand Down
1 change: 1 addition & 0 deletions internal/mock/sqladmin.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ func InstanceGetSuccess(i FakeCSQLInstance, ct int) *Request {
db := &sqladmin.ConnectSettings{
BackendType: i.backendType,
DatabaseVersion: i.dbVersion,
DnsName: i.DNSName,
IpAddresses: ips,
Region: i.region,
ServerCaCert: &sqladmin.SslCert{Cert: string(certBytes)},
Expand Down
7 changes: 7 additions & 0 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,13 @@ func WithPrivateIP() DialOption {
}
}

// WithPSC returns a DialOption that specifies a PSC endpoint will be used to connect.
func WithPSC() DialOption {
return func(cfg *dialCfg) {
cfg.ipType = cloudsql.PSC
}
}

// WithAutoIP returns a DialOption that selects the public IP if available and
// otherwise falls back to private IP. This option is present for backwards
// compatibility only and is not recommended for use in production.
Expand Down

0 comments on commit 10a46b0

Please sign in to comment.