Skip to content

Commit

Permalink
chore: Move dialer options out of cmd/main.go and into internal/proxy…
Browse files Browse the repository at this point in the history
….go (#1247)

Move dialer options out of cmd/main.go and into internal/proxy.go. This consolidates all code relating to cloud.google.com/go/cloudsqlconn into the internal/proxy package.
  • Loading branch information
hessjcg authored and enocom committed Aug 29, 2022
1 parent 97445cd commit 8ea6191
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 53 deletions.
46 changes: 3 additions & 43 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,12 @@ import (
"syscall"
"time"

"cloud.google.com/go/cloudsqlconn"
"contrib.go.opencensus.io/exporter/prometheus"
"contrib.go.opencensus.io/exporter/stackdriver"
"github.com/GoogleCloudPlatform/cloudsql-proxy/v2/cloudsql"
"github.com/GoogleCloudPlatform/cloudsql-proxy/v2/internal/gcloud"
"github.com/GoogleCloudPlatform/cloudsql-proxy/v2/internal/proxy"
"github.com/spf13/cobra"
"go.opencensus.io/trace"
"golang.org/x/oauth2"
)

var (
Expand Down Expand Up @@ -162,6 +159,8 @@ func parseConfig(cmd *cobra.Command, conf *proxy.Config, args []string) error {
return newBadCommandError("missing instance_connection_name (e.g., project:region:instance)")
}

conf.UserAgent = userAgent

userHasSet := func(f string) bool {
return cmd.PersistentFlags().Lookup(f).Changed
}
Expand All @@ -185,34 +184,6 @@ func parseConfig(cmd *cobra.Command, conf *proxy.Config, args []string) error {
if conf.CredentialsFile != "" && conf.GcloudAuth {
return newBadCommandError("cannot specify --credentials-file and --gcloud-auth flags at the same time")
}
conf.DialerOpts = []cloudsqlconn.Option{
cloudsqlconn.WithUserAgent(userAgent),
}
switch {
case conf.Token != "":
cmd.Printf("Authorizing with the -token flag\n")
conf.DialerOpts = append(conf.DialerOpts, cloudsqlconn.WithTokenSource(
oauth2.StaticTokenSource(&oauth2.Token{AccessToken: conf.Token}),
))
case conf.CredentialsFile != "":
cmd.Printf("Authorizing with the credentials file at %q\n", conf.CredentialsFile)
conf.DialerOpts = append(conf.DialerOpts, cloudsqlconn.WithCredentialsFile(
conf.CredentialsFile,
))
case conf.GcloudAuth:
cmd.Println("Authorizing with gcloud user credentials")
ts, err := gcloud.TokenSource()
if err != nil {
return err
}
conf.DialerOpts = append(conf.DialerOpts, cloudsqlconn.WithTokenSource(ts))
default:
cmd.Println("Authorizing with Application Default Credentials")
}

if conf.IAMAuthN {
conf.DialerOpts = append(conf.DialerOpts, cloudsqlconn.WithIAMAuthN())
}

if userHasSet("http-port") && !userHasSet("prometheus-namespace") {
return newBadCommandError("cannot specify --http-port without --prometheus-namespace")
Expand Down Expand Up @@ -406,18 +377,7 @@ func runSignalWrapper(cmd *Command) error {
startCh := make(chan *proxy.Client)
go func() {
defer close(startCh)
// Check if the caller has configured a dialer.
// Otherwise, initialize a new one.
d := cmd.conf.Dialer
if d == nil {
var err error
d, err = cloudsqlconn.NewDialer(ctx, cmd.conf.DialerOpts...)
if err != nil {
shutdownCh <- fmt.Errorf("error initializing dialer: %v", err)
return
}
}
p, err := proxy.NewClient(ctx, d, cmd.Command, cmd.conf)
p, err := proxy.NewClient(ctx, cmd.Command, cmd.conf)
if err != nil {
shutdownCh <- fmt.Errorf("unable to start: %v", err)
return
Expand Down
7 changes: 4 additions & 3 deletions cmd/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import (
"cloud.google.com/go/cloudsqlconn"
"github.com/GoogleCloudPlatform/cloudsql-proxy/v2/internal/proxy"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/spf13/cobra"
)

Expand All @@ -36,6 +35,9 @@ func TestNewCommandArguments(t *testing.T) {
trueValue := true

withDefaults := func(c *proxy.Config) *proxy.Config {
if c.UserAgent == "" {
c.UserAgent = userAgent
}
if c.Addr == "" {
c.Addr = "127.0.0.1"
}
Expand Down Expand Up @@ -218,8 +220,7 @@ func TestNewCommandArguments(t *testing.T) {
t.Fatalf("want error = nil, got = %v", err)
}

opts := cmpopts.IgnoreFields(proxy.Config{}, "DialerOpts")
if got := c.conf; !cmp.Equal(tc.want, got, opts) {
if got := c.conf; !cmp.Equal(tc.want, got) {
t.Fatalf("want = %#v\ngot = %#v\ndiff = %v", tc.want, got, cmp.Diff(tc.want, got))
}
})
Expand Down
55 changes: 51 additions & 4 deletions internal/proxy/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ import (

"cloud.google.com/go/cloudsqlconn"
"github.com/GoogleCloudPlatform/cloudsql-proxy/v2/cloudsql"
"github.com/GoogleCloudPlatform/cloudsql-proxy/v2/internal/gcloud"
"github.com/spf13/cobra"
"golang.org/x/oauth2"
)

// InstanceConnConfig holds the configuration for an individual instance
Expand All @@ -49,6 +51,9 @@ type InstanceConnConfig struct {

// Config contains all the configuration provided by the caller.
type Config struct {
// UserAgent is the user agent to use when connecting to the cloudsql instance
UserAgent string

// Token is the Bearer token used for authorization.
Token string

Expand Down Expand Up @@ -81,10 +86,37 @@ type Config struct {
// Dialer specifies the dialer to use when connecting to Cloud SQL
// instances.
Dialer cloudsql.Dialer
}

// DialerOptions builds appropriate list of options from the Config
// values for use by cloudsqlconn.NewClient()
func (c *Config) DialerOptions() ([]cloudsqlconn.Option, error) {
opts := []cloudsqlconn.Option{
cloudsqlconn.WithUserAgent(c.UserAgent),
}
switch {
case c.Token != "":
opts = append(opts, cloudsqlconn.WithTokenSource(
oauth2.StaticTokenSource(&oauth2.Token{AccessToken: c.Token}),
))
case c.CredentialsFile != "":
opts = append(opts, cloudsqlconn.WithCredentialsFile(
c.CredentialsFile,
))
case c.GcloudAuth:
ts, err := gcloud.TokenSource()
if err != nil {
return nil, err
}
opts = append(opts, cloudsqlconn.WithTokenSource(ts))
default:
}

if c.IAMAuthN {
opts = append(opts, cloudsqlconn.WithIAMAuthN())
}

// DialerOpts specifies the opts to use when creating a new dialer. This
// value is ignored when a Dialer has been set.
DialerOpts []cloudsqlconn.Option
return opts, nil
}

type portConfig struct {
Expand Down Expand Up @@ -140,7 +172,22 @@ type Client struct {
}

// NewClient completes the initial setup required to get the proxy to a "steady" state.
func NewClient(ctx context.Context, d cloudsql.Dialer, cmd *cobra.Command, conf *Config) (*Client, error) {
func NewClient(ctx context.Context, cmd *cobra.Command, conf *Config) (*Client, error) {
// Check if the caller has configured a dialer.
// Otherwise, initialize a new one.
d := conf.Dialer
if d == nil {
var err error
dialerOpts, err := conf.DialerOptions()
if err != nil {
return nil, fmt.Errorf("error initializing dialer: %v", err)
}
d, err = cloudsqlconn.NewDialer(ctx, dialerOpts...)
if err != nil {
return nil, fmt.Errorf("error initializing dialer: %v", err)
}
}

var mnts []*socketMount
for _, inst := range conf.Instances {
go func(name string) {
Expand Down
9 changes: 6 additions & 3 deletions internal/proxy/proxy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,8 @@ func TestClientInitialization(t *testing.T) {

for _, tc := range tcs {
t.Run(tc.desc, func(t *testing.T) {
c, err := proxy.NewClient(ctx, fakeDialer{}, &cobra.Command{}, tc.in)
tc.in.Dialer = fakeDialer{}
c, err := proxy.NewClient(ctx, &cobra.Command{}, tc.in)
if err != nil {
t.Fatalf("want error = nil, got = %v", err)
}
Expand Down Expand Up @@ -254,14 +255,16 @@ func TestClientInitializationWorksRepeatedly(t *testing.T) {
Instances: []proxy.InstanceConnConfig{
{Name: "proj:region:pg"},
},
Dialer: fakeDialer{},
}
c, err := proxy.NewClient(ctx, fakeDialer{}, &cobra.Command{}, in)

c, err := proxy.NewClient(ctx, &cobra.Command{}, in)
if err != nil {
t.Fatalf("want error = nil, got = %v", err)
}
c.Close()

c, err = proxy.NewClient(ctx, fakeDialer{}, &cobra.Command{}, in)
c, err = proxy.NewClient(ctx, &cobra.Command{}, in)
if err != nil {
t.Fatalf("want error = nil, got = %v", err)
}
Expand Down

0 comments on commit 8ea6191

Please sign in to comment.