From bedbd1856e4c57ea284956b37bef297721a8cf91 Mon Sep 17 00:00:00 2001 From: Eno Compton Date: Thu, 9 Dec 2021 13:38:40 -0700 Subject: [PATCH 1/6] feat: add support for specifying a quota project This commit adds a CLI flag quota_project such that users may provide a project against which the SQL Admin API quota is calculated. Typically, this flag will be used for internal development purposes. Note: there is an API option WithQuotaProject that does the same thing. However, that option is not compatible with WithHTTPClient and so we manually add the quota project instead. --- cmd/cloud_sql_proxy/cloud_sql_proxy.go | 45 +++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/cmd/cloud_sql_proxy/cloud_sql_proxy.go b/cmd/cloud_sql_proxy/cloud_sql_proxy.go index e7ce73766..042694787 100644 --- a/cmd/cloud_sql_proxy/cloud_sql_proxy.go +++ b/cmd/cloud_sql_proxy/cloud_sql_proxy.go @@ -130,8 +130,10 @@ unavailable.`, // Setting to choose what API to connect to host = flag.String("host", "", `When set, the proxy uses this host as the base API path. Example: - https://sqladmin.googleapis.com`, +https://sqladmin.googleapis.com`, ) + quotaProject = flag.String("quota_project", "", + `Specifies the project to use for Cloud SQL Admin API quota tracking.`) // Settings for healthcheck useHTTPHealthCheck = flag.Bool("use_http_health_check", false, "When set, creates an HTTP server that checks and communicates the health of the proxy client.") @@ -374,6 +376,42 @@ func authenticatedClient(ctx context.Context) (*http.Client, oauth2.TokenSource, return oauth2.NewClient(ctx, src), src, nil } +// quotaProjectTransport is an http.RoundTripper that adds an X-Goog-User-Project +// header to all requests for quota and billing purposes. +// +// For details, see: +// https://cloud.google.com/apis/docs/system-parameters#definitions +type quotaProjectTransport struct { + base http.RoundTripper + project string +} + +var _ http.RoundTripper = quotaProjectTransport{} + +// RoundTrip adds a X-Goog-User-Project header each request. +func (t quotaProjectTransport) RoundTrip(req *http.Request) (*http.Response, error) { + if req.Header == nil { + req.Header = make(http.Header) + } + req.Header.Add("X-Goog-User-Project", t.project) + return t.base.RoundTrip(req) +} + +// configureQuotaProject returns a HTTP client that adds a given user project for all +// requests. +func configureQuotaProject(cl *http.Client, project string) { + // Copy the given client's tripper. Note that tripper can be nil, which is equivalent to + // http.DefaultTransport. (See https://golang.org/pkg/net/http/#Client) + baseTripper := cl.Transport + if baseTripper == nil { + baseTripper = http.DefaultTransport + } + cl.Transport = quotaProjectTransport{ + base: baseTripper, + project: project, + } +} + func stringList(s string) []string { spl := strings.Split(s, ",") if len(spl) == 1 && spl[0] == "" { @@ -523,6 +561,11 @@ func runProxy() int { return 1 } + if *quotaProject != "" { + logging.Infof("Using the project %q for SQL Admin API quota", *quotaProject) + configureQuotaProject(client, *quotaProject) + } + ins, err := listInstances(ctx, client, projList) if err != nil { logging.Errorf(err.Error()) From da1f99c933b7bfd1d3deb05810b5097b9dfb8515 Mon Sep 17 00:00:00 2001 From: Eno Compton Date: Thu, 9 Dec 2021 13:50:58 -0700 Subject: [PATCH 2/6] fix wording --- cmd/cloud_sql_proxy/cloud_sql_proxy.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/cloud_sql_proxy/cloud_sql_proxy.go b/cmd/cloud_sql_proxy/cloud_sql_proxy.go index 042694787..4d58a1f1c 100644 --- a/cmd/cloud_sql_proxy/cloud_sql_proxy.go +++ b/cmd/cloud_sql_proxy/cloud_sql_proxy.go @@ -397,8 +397,8 @@ func (t quotaProjectTransport) RoundTrip(req *http.Request) (*http.Response, err return t.base.RoundTrip(req) } -// configureQuotaProject returns a HTTP client that adds a given user project for all -// requests. +// configureQuotaProject returns an HTTP client that uses the provided project +// for quota calculations for all requests. func configureQuotaProject(cl *http.Client, project string) { // Copy the given client's tripper. Note that tripper can be nil, which is equivalent to // http.DefaultTransport. (See https://golang.org/pkg/net/http/#Client) From 303329fc1e31c720b2442fb1a008b28e0ca8ccc2 Mon Sep 17 00:00:00 2001 From: Eno Compton Date: Thu, 9 Dec 2021 13:56:58 -0700 Subject: [PATCH 3/6] style nits --- cmd/cloud_sql_proxy/cloud_sql_proxy.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cmd/cloud_sql_proxy/cloud_sql_proxy.go b/cmd/cloud_sql_proxy/cloud_sql_proxy.go index 4d58a1f1c..9cad9ab73 100644 --- a/cmd/cloud_sql_proxy/cloud_sql_proxy.go +++ b/cmd/cloud_sql_proxy/cloud_sql_proxy.go @@ -399,15 +399,15 @@ func (t quotaProjectTransport) RoundTrip(req *http.Request) (*http.Response, err // configureQuotaProject returns an HTTP client that uses the provided project // for quota calculations for all requests. -func configureQuotaProject(cl *http.Client, project string) { +func configureQuotaProject(c *http.Client, project string) { // Copy the given client's tripper. Note that tripper can be nil, which is equivalent to // http.DefaultTransport. (See https://golang.org/pkg/net/http/#Client) - baseTripper := cl.Transport - if baseTripper == nil { + base := c.Transport + if base == nil { baseTripper = http.DefaultTransport } - cl.Transport = quotaProjectTransport{ - base: baseTripper, + c.Transport = quotaProjectTransport{ + base: base, project: project, } } From b2e1b3a033b8b8069fe4bfff57db56fcc2c98e5c Mon Sep 17 00:00:00 2001 From: Eno Compton Date: Thu, 9 Dec 2021 14:31:32 -0700 Subject: [PATCH 4/6] Address comment --- cmd/cloud_sql_proxy/cloud_sql_proxy.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/cloud_sql_proxy/cloud_sql_proxy.go b/cmd/cloud_sql_proxy/cloud_sql_proxy.go index 9cad9ab73..5a3c08d64 100644 --- a/cmd/cloud_sql_proxy/cloud_sql_proxy.go +++ b/cmd/cloud_sql_proxy/cloud_sql_proxy.go @@ -397,7 +397,7 @@ func (t quotaProjectTransport) RoundTrip(req *http.Request) (*http.Response, err return t.base.RoundTrip(req) } -// configureQuotaProject returns an HTTP client that uses the provided project +// configureQuotaProject configures an HTTP client to use the provided project // for quota calculations for all requests. func configureQuotaProject(c *http.Client, project string) { // Copy the given client's tripper. Note that tripper can be nil, which is equivalent to From 85c00578dd5c295e171bc9d876c18400d355ebd8 Mon Sep 17 00:00:00 2001 From: Eno Compton Date: Thu, 9 Dec 2021 14:35:31 -0700 Subject: [PATCH 5/6] woops --- cmd/cloud_sql_proxy/cloud_sql_proxy.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/cloud_sql_proxy/cloud_sql_proxy.go b/cmd/cloud_sql_proxy/cloud_sql_proxy.go index 5a3c08d64..bae738f87 100644 --- a/cmd/cloud_sql_proxy/cloud_sql_proxy.go +++ b/cmd/cloud_sql_proxy/cloud_sql_proxy.go @@ -404,7 +404,7 @@ func configureQuotaProject(c *http.Client, project string) { // http.DefaultTransport. (See https://golang.org/pkg/net/http/#Client) base := c.Transport if base == nil { - baseTripper = http.DefaultTransport + base = http.DefaultTransport } c.Transport = quotaProjectTransport{ base: base, From 39e9b8a37e43bb2df3fac6e28bcaccc9d90d84af Mon Sep 17 00:00:00 2001 From: Eno Compton Date: Thu, 9 Dec 2021 14:47:19 -0700 Subject: [PATCH 6/6] typo --- cmd/cloud_sql_proxy/cloud_sql_proxy.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/cloud_sql_proxy/cloud_sql_proxy.go b/cmd/cloud_sql_proxy/cloud_sql_proxy.go index bae738f87..9d95b4a52 100644 --- a/cmd/cloud_sql_proxy/cloud_sql_proxy.go +++ b/cmd/cloud_sql_proxy/cloud_sql_proxy.go @@ -388,7 +388,7 @@ type quotaProjectTransport struct { var _ http.RoundTripper = quotaProjectTransport{} -// RoundTrip adds a X-Goog-User-Project header each request. +// RoundTrip adds a X-Goog-User-Project header to each request. func (t quotaProjectTransport) RoundTrip(req *http.Request) (*http.Response, error) { if req.Header == nil { req.Header = make(http.Header)