Merge pull request #60012 from atlassian/dial-with-context

Automatic merge from submit-queue (batch tested with PRs 60012, 63692, 63977, 63960, 64008). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

Use Dial with context

**What this PR does / why we need it**:
`net/http/Transport.Dial` field is deprecated:
```go
// DialContext specifies the dial function for creating unencrypted TCP connections.
// If DialContext is nil (and the deprecated Dial below is also nil),
// then the transport dials using package net.
DialContext func(ctx context.Context, network, addr string) (net.Conn, error)

// Dial specifies the dial function for creating unencrypted TCP connections.
//
// Deprecated: Use DialContext instead, which allows the transport
// to cancel dials as soon as they are no longer needed.
// If both are set, DialContext takes priority.
Dial func(network, addr string) (net.Conn, error)
```
This PR switches all `Dial` usages to `DialContext`. Fixes #63455.

**Special notes for your reviewer**:
Also related: https://github.com/kubernetes/kubernetes/pull/59287 https://github.com/kubernetes/kubernetes/pull/58532 https://github.com/kubernetes/kubernetes/issues/815 https://github.com/kubernetes/community/pull/1166 https://github.com/kubernetes/kubernetes/pull/58677 https://github.com/kubernetes/kubernetes/pull/57932

**Release note**:
```release-note
HTTP transport now uses `context.Context` to cancel dial operations. k8s.io/client-go/transport/Config struct has been updated to accept a function with a `context.Context` parameter. This is a breaking change if you use this field in your code.
```
/sig api-machinery
/kind enhancement
/cc @sttts

Kubernetes-commit: ddf551c24b7d88454f8332ce6855e53281440958
This commit is contained in:
Kubernetes Publisher 2018-05-18 23:35:13 -07:00
commit d9cf977510
8 changed files with 78 additions and 100 deletions

100
Godeps/Godeps.json generated
View File

@ -388,203 +388,203 @@
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/api/equality", "ImportPath": "k8s.io/apimachinery/pkg/api/equality",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/api/errors", "ImportPath": "k8s.io/apimachinery/pkg/api/errors",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/api/meta", "ImportPath": "k8s.io/apimachinery/pkg/api/meta",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/api/resource", "ImportPath": "k8s.io/apimachinery/pkg/api/resource",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/api/testing", "ImportPath": "k8s.io/apimachinery/pkg/api/testing",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/api/testing/fuzzer", "ImportPath": "k8s.io/apimachinery/pkg/api/testing/fuzzer",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/api/testing/roundtrip", "ImportPath": "k8s.io/apimachinery/pkg/api/testing/roundtrip",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/fuzzer", "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/fuzzer",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/internalversion", "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/internalversion",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1", "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured", "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1beta1", "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1beta1",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/conversion", "ImportPath": "k8s.io/apimachinery/pkg/conversion",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/conversion/queryparams", "ImportPath": "k8s.io/apimachinery/pkg/conversion/queryparams",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/fields", "ImportPath": "k8s.io/apimachinery/pkg/fields",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/labels", "ImportPath": "k8s.io/apimachinery/pkg/labels",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/runtime", "ImportPath": "k8s.io/apimachinery/pkg/runtime",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/runtime/schema", "ImportPath": "k8s.io/apimachinery/pkg/runtime/schema",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer", "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/json", "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/json",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/protobuf", "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/protobuf",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/recognizer", "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/recognizer",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/streaming", "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/streaming",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/versioning", "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/versioning",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/selection", "ImportPath": "k8s.io/apimachinery/pkg/selection",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/types", "ImportPath": "k8s.io/apimachinery/pkg/types",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/cache", "ImportPath": "k8s.io/apimachinery/pkg/util/cache",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/clock", "ImportPath": "k8s.io/apimachinery/pkg/util/clock",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/diff", "ImportPath": "k8s.io/apimachinery/pkg/util/diff",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/errors", "ImportPath": "k8s.io/apimachinery/pkg/util/errors",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/framer", "ImportPath": "k8s.io/apimachinery/pkg/util/framer",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/httpstream", "ImportPath": "k8s.io/apimachinery/pkg/util/httpstream",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/httpstream/spdy", "ImportPath": "k8s.io/apimachinery/pkg/util/httpstream/spdy",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/intstr", "ImportPath": "k8s.io/apimachinery/pkg/util/intstr",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/json", "ImportPath": "k8s.io/apimachinery/pkg/util/json",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/mergepatch", "ImportPath": "k8s.io/apimachinery/pkg/util/mergepatch",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/net", "ImportPath": "k8s.io/apimachinery/pkg/util/net",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/remotecommand", "ImportPath": "k8s.io/apimachinery/pkg/util/remotecommand",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/runtime", "ImportPath": "k8s.io/apimachinery/pkg/util/runtime",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/sets", "ImportPath": "k8s.io/apimachinery/pkg/util/sets",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/strategicpatch", "ImportPath": "k8s.io/apimachinery/pkg/util/strategicpatch",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/validation", "ImportPath": "k8s.io/apimachinery/pkg/util/validation",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/validation/field", "ImportPath": "k8s.io/apimachinery/pkg/util/validation/field",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/wait", "ImportPath": "k8s.io/apimachinery/pkg/util/wait",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/yaml", "ImportPath": "k8s.io/apimachinery/pkg/util/yaml",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/version", "ImportPath": "k8s.io/apimachinery/pkg/version",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/watch", "ImportPath": "k8s.io/apimachinery/pkg/watch",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/json", "ImportPath": "k8s.io/apimachinery/third_party/forked/golang/json",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/netutil", "ImportPath": "k8s.io/apimachinery/third_party/forked/golang/netutil",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/reflect", "ImportPath": "k8s.io/apimachinery/third_party/forked/golang/reflect",
"Rev": "3492ef8dace114d765f20d9c1a03f306449e5252" "Rev": "e226be1f5ed46b19fedc971f410f84de5b3dab8a"
}, },
{ {
"ImportPath": "k8s.io/kube-openapi/pkg/util/proto", "ImportPath": "k8s.io/kube-openapi/pkg/util/proto",

View File

@ -44,12 +44,8 @@ const (
defaultRetries = 2 defaultRetries = 2
// protobuf mime type // protobuf mime type
mimePb = "application/com.github.proto-openapi.spec.v2@v1.0+protobuf" mimePb = "application/com.github.proto-openapi.spec.v2@v1.0+protobuf"
)
var (
// defaultTimeout is the maximum amount of time per request when no timeout has been set on a RESTClient. // defaultTimeout is the maximum amount of time per request when no timeout has been set on a RESTClient.
// Defaults to 32s in order to have a distinguishable length of time, relative to other timeouts that exist. // Defaults to 32s in order to have a distinguishable length of time, relative to other timeouts that exist.
// It's a variable to be able to change it in tests.
defaultTimeout = 32 * time.Second defaultTimeout = 32 * time.Second
) )

View File

@ -23,12 +23,11 @@ import (
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"reflect" "reflect"
"strings"
"testing" "testing"
"time"
"github.com/gogo/protobuf/proto" "github.com/gogo/protobuf/proto"
"github.com/googleapis/gnostic/OpenAPIv2" "github.com/googleapis/gnostic/OpenAPIv2"
"github.com/stretchr/testify/assert"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
@ -131,31 +130,11 @@ func TestGetServerGroupsWithBrokenServer(t *testing.T) {
} }
} }
} }
func TestGetServerGroupsWithTimeout(t *testing.T) {
done := make(chan bool) func TestTimeoutIsSet(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { cfg := &restclient.Config{}
// first we need to write headers, otherwise http client will complain about setDiscoveryDefaults(cfg)
// exceeding timeout awaiting headers, only after we can block the call assert.Equal(t, defaultTimeout, cfg.Timeout)
w.Header().Set("Connection", "keep-alive")
if wf, ok := w.(http.Flusher); ok {
wf.Flush()
}
<-done
}))
defer server.Close()
defer close(done)
client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL, Timeout: 2 * time.Second})
_, err := client.ServerGroups()
// the error we're getting here is wrapped in errors.errorString which makes
// it impossible to unwrap and check it's attributes, so instead we're checking
// the textual output which is presenting http.httpError with timeout set to true
if err == nil {
t.Fatal("missing error")
}
if !strings.Contains(err.Error(), "timeout:true") &&
!strings.Contains(err.Error(), "context.deadlineExceededError") {
t.Fatalf("unexpected error: %v", err)
}
} }
func TestGetServerResourcesWithV1Server(t *testing.T) { func TestGetServerResourcesWithV1Server(t *testing.T) {

View File

@ -17,6 +17,7 @@ limitations under the License.
package rest package rest
import ( import (
"context"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"net" "net"
@ -110,7 +111,7 @@ type Config struct {
Timeout time.Duration Timeout time.Duration
// Dial specifies the dial function for creating unencrypted TCP connections. // Dial specifies the dial function for creating unencrypted TCP connections.
Dial func(network, addr string) (net.Conn, error) Dial func(ctx context.Context, network, address string) (net.Conn, error)
// Version forces a specific version to be used (if registered) // Version forces a specific version to be used (if registered)
// Do we need this? // Do we need this?

View File

@ -17,6 +17,8 @@ limitations under the License.
package rest package rest
import ( import (
"context"
"errors"
"io" "io"
"net" "net"
"net/http" "net/http"
@ -25,8 +27,6 @@ import (
"strings" "strings"
"testing" "testing"
fuzz "github.com/google/gofuzz"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
@ -35,8 +35,7 @@ import (
clientcmdapi "k8s.io/client-go/tools/clientcmd/api" clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
"k8s.io/client-go/util/flowcontrol" "k8s.io/client-go/util/flowcontrol"
"errors" fuzz "github.com/google/gofuzz"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -208,7 +207,7 @@ func (n *fakeNegotiatedSerializer) DecoderToVersion(serializer runtime.Decoder,
return &fakeCodec{} return &fakeCodec{}
} }
var fakeDialFunc = func(network, addr string) (net.Conn, error) { var fakeDialFunc = func(ctx context.Context, network, addr string) (net.Conn, error) {
return nil, fakeDialerError return nil, fakeDialerError
} }
var fakeDialerError = errors.New("fakedialer") var fakeDialerError = errors.New("fakedialer")
@ -253,7 +252,7 @@ func TestAnonymousConfig(t *testing.T) {
r.Config = map[string]string{} r.Config = map[string]string{}
}, },
// Dial does not require fuzzer // Dial does not require fuzzer
func(r *func(network, addr string) (net.Conn, error), f fuzz.Continue) {}, func(r *func(ctx context.Context, network, addr string) (net.Conn, error), f fuzz.Continue) {},
) )
for i := 0; i < 20; i++ { for i := 0; i < 20; i++ {
original := &Config{} original := &Config{}
@ -284,10 +283,10 @@ func TestAnonymousConfig(t *testing.T) {
expected.WrapTransport = nil expected.WrapTransport = nil
} }
if actual.Dial != nil { if actual.Dial != nil {
_, actualError := actual.Dial("", "") _, actualError := actual.Dial(context.Background(), "", "")
_, expectedError := actual.Dial("", "") _, expectedError := expected.Dial(context.Background(), "", "")
if !reflect.DeepEqual(expectedError, actualError) { if !reflect.DeepEqual(expectedError, actualError) {
t.Fatalf("CopyConfig dropped the Dial field") t.Fatalf("CopyConfig dropped the Dial field")
} }
} else { } else {
actual.Dial = nil actual.Dial = nil
@ -329,7 +328,7 @@ func TestCopyConfig(t *testing.T) {
func(r *AuthProviderConfigPersister, f fuzz.Continue) { func(r *AuthProviderConfigPersister, f fuzz.Continue) {
*r = fakeAuthProviderConfigPersister{} *r = fakeAuthProviderConfigPersister{}
}, },
func(r *func(network, addr string) (net.Conn, error), f fuzz.Continue) { func(r *func(ctx context.Context, network, addr string) (net.Conn, error), f fuzz.Continue) {
*r = fakeDialFunc *r = fakeDialFunc
}, },
) )
@ -351,8 +350,8 @@ func TestCopyConfig(t *testing.T) {
expected.WrapTransport = nil expected.WrapTransport = nil
} }
if actual.Dial != nil { if actual.Dial != nil {
_, actualError := actual.Dial("", "") _, actualError := actual.Dial(context.Background(), "", "")
_, expectedError := actual.Dial("", "") _, expectedError := expected.Dial(context.Background(), "", "")
if !reflect.DeepEqual(expectedError, actualError) { if !reflect.DeepEqual(expectedError, actualError) {
t.Fatalf("CopyConfig dropped the Dial field") t.Fatalf("CopyConfig dropped the Dial field")
} }
@ -361,7 +360,7 @@ func TestCopyConfig(t *testing.T) {
expected.Dial = nil expected.Dial = nil
if actual.AuthConfigPersister != nil { if actual.AuthConfigPersister != nil {
actualError := actual.AuthConfigPersister.Persist(nil) actualError := actual.AuthConfigPersister.Persist(nil)
expectedError := actual.AuthConfigPersister.Persist(nil) expectedError := expected.AuthConfigPersister.Persist(nil)
if !reflect.DeepEqual(expectedError, actualError) { if !reflect.DeepEqual(expectedError, actualError) {
t.Fatalf("CopyConfig dropped the Dial field") t.Fatalf("CopyConfig dropped the Dial field")
} }

View File

@ -85,7 +85,7 @@ func (c *tlsTransportCache) get(config *Config) (http.RoundTripper, error) {
dial = (&net.Dialer{ dial = (&net.Dialer{
Timeout: 30 * time.Second, Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second, KeepAlive: 30 * time.Second,
}).Dial }).DialContext
} }
// Cache a single transport for these options // Cache a single transport for these options
c.transports[key] = utilnet.SetTransportDefaults(&http.Transport{ c.transports[key] = utilnet.SetTransportDefaults(&http.Transport{
@ -93,7 +93,7 @@ func (c *tlsTransportCache) get(config *Config) (http.RoundTripper, error) {
TLSHandshakeTimeout: 10 * time.Second, TLSHandshakeTimeout: 10 * time.Second,
TLSClientConfig: tlsConfig, TLSClientConfig: tlsConfig,
MaxIdleConnsPerHost: idleConnsPerHost, MaxIdleConnsPerHost: idleConnsPerHost,
Dial: dial, DialContext: dial,
}) })
return c.transports[key], nil return c.transports[key], nil
} }

View File

@ -17,6 +17,7 @@ limitations under the License.
package transport package transport
import ( import (
"context"
"net" "net"
"net/http" "net/http"
"testing" "testing"
@ -52,10 +53,11 @@ func TestTLSConfigKey(t *testing.T) {
} }
// Make sure config fields that affect the tls config affect the cache key // Make sure config fields that affect the tls config affect the cache key
dialer := net.Dialer{}
uniqueConfigurations := map[string]*Config{ uniqueConfigurations := map[string]*Config{
"no tls": {}, "no tls": {},
"dialer": {Dial: net.Dial}, "dialer": {Dial: dialer.DialContext},
"dialer2": {Dial: func(network, address string) (net.Conn, error) { return nil, nil }}, "dialer2": {Dial: func(ctx context.Context, network, address string) (net.Conn, error) { return nil, nil }},
"insecure": {TLS: TLSConfig{Insecure: true}}, "insecure": {TLS: TLSConfig{Insecure: true}},
"cadata 1": {TLS: TLSConfig{CAData: []byte{1}}}, "cadata 1": {TLS: TLSConfig{CAData: []byte{1}}},
"cadata 2": {TLS: TLSConfig{CAData: []byte{2}}}, "cadata 2": {TLS: TLSConfig{CAData: []byte{2}}},

View File

@ -17,6 +17,7 @@ limitations under the License.
package transport package transport
import ( import (
"context"
"net" "net"
"net/http" "net/http"
) )
@ -53,7 +54,7 @@ type Config struct {
WrapTransport func(rt http.RoundTripper) http.RoundTripper WrapTransport func(rt http.RoundTripper) http.RoundTripper
// Dial specifies the dial function for creating unencrypted TCP connections. // Dial specifies the dial function for creating unencrypted TCP connections.
Dial func(network, addr string) (net.Conn, error) Dial func(ctx context.Context, network, address string) (net.Conn, error)
} }
// ImpersonationConfig has all the available impersonation options // ImpersonationConfig has all the available impersonation options