Skip to content

Commit

Permalink
Made base transport layer force ipv4 usage if ipv6 is not supported
Browse files Browse the repository at this point in the history
  • Loading branch information
melinath committed Apr 18, 2024
1 parent 3b4b2e0 commit 82d8a8f
Showing 1 changed file with 47 additions and 5 deletions.
52 changes: 47 additions & 5 deletions mmv1/third_party/terraform/transport/config.go.erb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"encoding/json"
"fmt"
"log"
"net"
"net/http"
"regexp"
"strconv"
Expand All @@ -28,6 +29,8 @@ import (

"github.com/hashicorp/terraform-provider-google/google/verify"

"golang.org/x/net/http2"
"golang.org/x/net/nettest"
"golang.org/x/oauth2"
"google.golang.org/grpc"
googleoauth "golang.org/x/oauth2/google"
Expand Down Expand Up @@ -82,6 +85,7 @@ import (
"google.golang.org/api/storage/v1"
"google.golang.org/api/storagetransfer/v1"
"google.golang.org/api/transport"
apihttp "google.golang.org/api/transport/http"
)

type ProviderMeta struct {
Expand Down Expand Up @@ -429,6 +433,39 @@ func SetEndpointDefaults(d *schema.ResourceData) error {
return nil
}

// baseTransport returns the base HTTP transport. It starts with the
// default transport and makes some tweaks to match best practices
// from google-api-go-client, as well as ensuring that IPv6 does
// not get used in environments that don't support it.
func baseTransport() (http.RoundTripper, error) {
trans := http.DefaultTransport.(*http.Transport).Clone()
// Increase MaxIdleConnsPerHost due to reported performance issues under load in the
// GCS client.
trans.MaxIdleConnsPerHost = 100

// Configure the ReadIdleTimeout HTTP/2 option for the
// transport. This allows broken idle connections to be pruned more quickly,
// preventing the client from attempting to re-use connections that will no
// longer work. http2Trans is discarded after configuration.
http2Trans, err := http2.ConfigureTransports(trans)
if err != nil {
return trans, err
}
http2Trans.ReadIdleTimeout = time.Second * 31

// Override dialer so that we don't try IPv6 if it's not supported.
// https://github.com/golang/go/issues/25321
trans.DialContext = func(ctx context.Context, network string, addr string) (net.Conn, error) {
d := &net.Dialer{}
if !nettest.SupportsIPv6() {
return d.DialContext(ctx, "tcp4", addr)
}
return d.DialContext(ctx, network, addr)
}

return trans, nil
}

func (c *Config) LoadAndValidate(ctx context.Context) error {
if len(c.Scopes) == 0 {
c.Scopes = DefaultClientScopes
Expand All @@ -445,8 +482,13 @@ func (c *Config) LoadAndValidate(ctx context.Context) error {

cleanCtx := context.WithValue(ctx, oauth2.HTTPClient, cleanhttp.DefaultClient())

// 1. MTLS TRANSPORT/CLIENT - sets up proper auth headers
client, _, err := transport.NewHTTPClient(cleanCtx, option.WithTokenSource(tokenSource))
// 1. Set up base HTTP transport and configure token auth / API communication
base, err := baseTransport()
if err != nil {
return err
}

transport, err := apihttp.NewTransport(cleanCtx, base, option.WithTokenSource(tokenSource))
if err != nil {
return err
}
Expand All @@ -458,7 +500,7 @@ func (c *Config) LoadAndValidate(ctx context.Context) error {
}

// 2. Logging Transport - ensure we log HTTP requests to GCP APIs.
loggingTransport := logging.NewTransport("Google", client.Transport)
loggingTransport := logging.NewTransport("Google", transport)

// 3. Retry Transport - retries common temporary errors
// Keep order for wrapping logging so we log each retried request as well.
Expand All @@ -479,8 +521,8 @@ func (c *Config) LoadAndValidate(ctx context.Context) error {
headerTransport.Set("X-Goog-User-Project", c.BillingProject)
}

// Set final transport value.
client.Transport = headerTransport
// Create http client
client := &http.Client{Transport: headerTransport}

// This timeout is a timeout per HTTP request, not per logical operation.
client.Timeout = c.synchronousTimeout()
Expand Down

0 comments on commit 82d8a8f

Please sign in to comment.