diff --git a/client/checkpoint_create_test.go b/client/checkpoint_create_test.go index e2ae36e1e0..96e5187618 100644 --- a/client/checkpoint_create_test.go +++ b/client/checkpoint_create_test.go @@ -15,7 +15,7 @@ import ( func TestCheckpointCreateError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } err := client.CheckpointCreate(context.Background(), "nothing", types.CheckpointCreateOptions{ CheckpointID: "noting", @@ -33,7 +33,7 @@ func TestCheckpointCreate(t *testing.T) { expectedURL := "/containers/container_id/checkpoints" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/checkpoint_delete_test.go b/client/checkpoint_delete_test.go index 097ab37693..23931c6523 100644 --- a/client/checkpoint_delete_test.go +++ b/client/checkpoint_delete_test.go @@ -13,7 +13,7 @@ import ( func TestCheckpointDeleteError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } err := client.CheckpointDelete(context.Background(), "container_id", "checkpoint_id") @@ -26,7 +26,7 @@ func TestCheckpointDelete(t *testing.T) { expectedURL := "/containers/container_id/checkpoints/checkpoint_id" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/checkpoint_list_test.go b/client/checkpoint_list_test.go index 5960436eb1..e636995bc1 100644 --- a/client/checkpoint_list_test.go +++ b/client/checkpoint_list_test.go @@ -15,7 +15,7 @@ import ( func TestCheckpointListError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.CheckpointList(context.Background(), "container_id") @@ -28,7 +28,7 @@ func TestCheckpointList(t *testing.T) { expectedURL := "/containers/container_id/checkpoints" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/client.go b/client/client.go index 6a85121c6d..deccb4ab74 100644 --- a/client/client.go +++ b/client/client.go @@ -8,7 +8,7 @@ import ( "path/filepath" "strings" - "github.com/docker/docker/client/transport" + "github.com/docker/go-connections/sockets" "github.com/docker/go-connections/tlsconfig" ) @@ -26,8 +26,8 @@ type Client struct { addr string // basePath holds the path to prepend to the requests. basePath string - // transport is the interface to send request with, it implements transport.Client. - transport transport.Client + // client used to send and receive http requests. + client *http.Client // version of the server to talk to. version string // custom http headers configured by users. @@ -86,9 +86,15 @@ func NewClient(host string, version string, client *http.Client, httpHeaders map return nil, err } - transport, err := transport.NewTransportWithHTTP(proto, addr, client) - if err != nil { - return nil, err + if client == nil { + client = &http.Client{} + } + + if client.Transport == nil { + // setup the transport, if not already present + transport := new(http.Transport) + sockets.ConfigureTransport(transport, proto, addr) + client.Transport = transport } return &Client{ @@ -96,7 +102,7 @@ func NewClient(host string, version string, client *http.Client, httpHeaders map proto: proto, addr: addr, basePath: basePath, - transport: transport, + client: client, version: version, customHTTPHeaders: httpHeaders, }, nil diff --git a/client/client_mock_test.go b/client/client_mock_test.go index 33c247266c..0ab935d536 100644 --- a/client/client_mock_test.go +++ b/client/client_mock_test.go @@ -2,48 +2,17 @@ package client import ( "bytes" - "crypto/tls" "encoding/json" "io/ioutil" "net/http" "github.com/docker/docker/api/types" - "github.com/docker/docker/client/transport" ) -type mockClient struct { - do func(*http.Request) (*http.Response, error) -} - -// TLSConfig returns the TLS configuration. -func (m *mockClient) TLSConfig() *tls.Config { - return &tls.Config{} -} - -// Scheme returns protocol scheme to use. -func (m *mockClient) Scheme() string { - return "http" -} - -// Secure returns true if there is a TLS configuration. -func (m *mockClient) Secure() bool { - return false -} - -// NewMockClient returns a mocked client that runs the function supplied as `client.Do` call -func newMockClient(tlsConfig *tls.Config, doer func(*http.Request) (*http.Response, error)) transport.Client { - if tlsConfig != nil { - panic("this actually gets set!") +func newMockClient(doer func(*http.Request) (*http.Response, error)) *http.Client { + return &http.Client{ + Transport: transportFunc(doer), } - - return &mockClient{ - do: doer, - } -} - -// Do executes the supplied function for the mock. -func (m mockClient) Do(req *http.Request) (*http.Response, error) { - return m.do(req) } func errorMock(statusCode int, message string) func(req *http.Request) (*http.Response, error) { diff --git a/client/client_test.go b/client/client_test.go index 60af3db029..60e44dc299 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -173,7 +173,7 @@ func TestParseHost(t *testing.T) { func TestUpdateClientVersion(t *testing.T) { client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { splitQuery := strings.Split(req.URL.Path, "/") queryVersion := splitQuery[1] b, err := json.Marshal(types.Version{ diff --git a/client/container_commit_test.go b/client/container_commit_test.go index 3fc3e5cfd0..8f1b58be81 100644 --- a/client/container_commit_test.go +++ b/client/container_commit_test.go @@ -15,7 +15,7 @@ import ( func TestContainerCommitError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.ContainerCommit(context.Background(), "nothing", types.ContainerCommitOptions{}) if err == nil || err.Error() != "Error response from daemon: Server error" { @@ -34,7 +34,7 @@ func TestContainerCommit(t *testing.T) { expectedChanges := []string{"change1", "change2"} client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/container_copy_test.go b/client/container_copy_test.go index 39cd05ac2d..7eded611fd 100644 --- a/client/container_copy_test.go +++ b/client/container_copy_test.go @@ -17,7 +17,7 @@ import ( func TestContainerStatPathError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.ContainerStatPath(context.Background(), "container_id", "path") if err == nil || err.Error() != "Error response from daemon: Server error" { @@ -27,7 +27,7 @@ func TestContainerStatPathError(t *testing.T) { func TestContainerStatPathNoHeaderError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { return &http.Response{ StatusCode: http.StatusOK, Body: ioutil.NopCloser(bytes.NewReader([]byte(""))), @@ -44,7 +44,7 @@ func TestContainerStatPath(t *testing.T) { expectedURL := "/containers/container_id/archive" expectedPath := "path/to/file" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } @@ -87,7 +87,7 @@ func TestContainerStatPath(t *testing.T) { func TestCopyToContainerError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } err := client.CopyToContainer(context.Background(), "container_id", "path/to/file", bytes.NewReader([]byte("")), types.CopyToContainerOptions{}) if err == nil || err.Error() != "Error response from daemon: Server error" { @@ -97,7 +97,7 @@ func TestCopyToContainerError(t *testing.T) { func TestCopyToContainerNotStatusOKError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusNoContent, "No content")), + client: newMockClient(errorMock(http.StatusNoContent, "No content")), } err := client.CopyToContainer(context.Background(), "container_id", "path/to/file", bytes.NewReader([]byte("")), types.CopyToContainerOptions{}) if err == nil || err.Error() != "unexpected status code from daemon: 204" { @@ -109,7 +109,7 @@ func TestCopyToContainer(t *testing.T) { expectedURL := "/containers/container_id/archive" expectedPath := "path/to/file" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } @@ -153,7 +153,7 @@ func TestCopyToContainer(t *testing.T) { func TestCopyFromContainerError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, _, err := client.CopyFromContainer(context.Background(), "container_id", "path/to/file") if err == nil || err.Error() != "Error response from daemon: Server error" { @@ -163,7 +163,7 @@ func TestCopyFromContainerError(t *testing.T) { func TestCopyFromContainerNotStatusOKError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusNoContent, "No content")), + client: newMockClient(errorMock(http.StatusNoContent, "No content")), } _, _, err := client.CopyFromContainer(context.Background(), "container_id", "path/to/file") if err == nil || err.Error() != "unexpected status code from daemon: 204" { @@ -173,7 +173,7 @@ func TestCopyFromContainerNotStatusOKError(t *testing.T) { func TestCopyFromContainerNoHeaderError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { return &http.Response{ StatusCode: http.StatusOK, Body: ioutil.NopCloser(bytes.NewReader([]byte(""))), @@ -190,7 +190,7 @@ func TestCopyFromContainer(t *testing.T) { expectedURL := "/containers/container_id/archive" expectedPath := "path/to/file" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/container_create_test.go b/client/container_create_test.go index 4c14cdc5d1..5325156beb 100644 --- a/client/container_create_test.go +++ b/client/container_create_test.go @@ -16,7 +16,7 @@ import ( func TestContainerCreateError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.ContainerCreate(context.Background(), nil, nil, nil, "nothing") if err == nil || err.Error() != "Error response from daemon: Server error" { @@ -25,7 +25,7 @@ func TestContainerCreateError(t *testing.T) { // 404 doesn't automagitally means an unknown image client = &Client{ - transport: newMockClient(nil, errorMock(http.StatusNotFound, "Server error")), + client: newMockClient(errorMock(http.StatusNotFound, "Server error")), } _, err = client.ContainerCreate(context.Background(), nil, nil, nil, "nothing") if err == nil || err.Error() != "Error response from daemon: Server error" { @@ -35,7 +35,7 @@ func TestContainerCreateError(t *testing.T) { func TestContainerCreateImageNotFound(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusNotFound, "No such image")), + client: newMockClient(errorMock(http.StatusNotFound, "No such image")), } _, err := client.ContainerCreate(context.Background(), &container.Config{Image: "unknown_image"}, nil, nil, "unknown") if err == nil || !IsErrImageNotFound(err) { @@ -46,7 +46,7 @@ func TestContainerCreateImageNotFound(t *testing.T) { func TestContainerCreateWithName(t *testing.T) { expectedURL := "/containers/create" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/container_diff_test.go b/client/container_diff_test.go index 03ea3354d2..1ce1117684 100644 --- a/client/container_diff_test.go +++ b/client/container_diff_test.go @@ -15,7 +15,7 @@ import ( func TestContainerDiffError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.ContainerDiff(context.Background(), "nothing") if err == nil || err.Error() != "Error response from daemon: Server error" { @@ -27,7 +27,7 @@ func TestContainerDiffError(t *testing.T) { func TestContainerDiff(t *testing.T) { expectedURL := "/containers/container_id/changes" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/container_exec_test.go b/client/container_exec_test.go index abe824e47b..42146ae8a5 100644 --- a/client/container_exec_test.go +++ b/client/container_exec_test.go @@ -16,7 +16,7 @@ import ( func TestContainerExecCreateError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.ContainerExecCreate(context.Background(), "container_id", types.ExecConfig{}) if err == nil || err.Error() != "Error response from daemon: Server error" { @@ -27,7 +27,7 @@ func TestContainerExecCreateError(t *testing.T) { func TestContainerExecCreate(t *testing.T) { expectedURL := "/containers/container_id/exec" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("expected URL '%s', got '%s'", expectedURL, req.URL) } @@ -71,7 +71,7 @@ func TestContainerExecCreate(t *testing.T) { func TestContainerExecStartError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } err := client.ContainerExecStart(context.Background(), "nothing", types.ExecStartCheck{}) if err == nil || err.Error() != "Error response from daemon: Server error" { @@ -82,7 +82,7 @@ func TestContainerExecStartError(t *testing.T) { func TestContainerExecStart(t *testing.T) { expectedURL := "/exec/exec_id/start" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } @@ -115,7 +115,7 @@ func TestContainerExecStart(t *testing.T) { func TestContainerExecInspectError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.ContainerExecInspect(context.Background(), "nothing") if err == nil || err.Error() != "Error response from daemon: Server error" { @@ -126,7 +126,7 @@ func TestContainerExecInspectError(t *testing.T) { func TestContainerExecInspect(t *testing.T) { expectedURL := "/exec/exec_id/json" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/container_export_test.go b/client/container_export_test.go index 10eba33d2f..5849fe9252 100644 --- a/client/container_export_test.go +++ b/client/container_export_test.go @@ -13,7 +13,7 @@ import ( func TestContainerExportError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.ContainerExport(context.Background(), "nothing") if err == nil || err.Error() != "Error response from daemon: Server error" { @@ -24,7 +24,7 @@ func TestContainerExportError(t *testing.T) { func TestContainerExport(t *testing.T) { expectedURL := "/containers/container_id/export" client := &Client{ - transport: newMockClient(nil, func(r *http.Request) (*http.Response, error) { + client: newMockClient(func(r *http.Request) (*http.Response, error) { if !strings.HasPrefix(r.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, r.URL) } diff --git a/client/container_inspect_test.go b/client/container_inspect_test.go index 0dc8ac3753..f1a6f4ac7d 100644 --- a/client/container_inspect_test.go +++ b/client/container_inspect_test.go @@ -15,7 +15,7 @@ import ( func TestContainerInspectError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.ContainerInspect(context.Background(), "nothing") @@ -26,7 +26,7 @@ func TestContainerInspectError(t *testing.T) { func TestContainerInspectContainerNotFound(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusNotFound, "Server error")), + client: newMockClient(errorMock(http.StatusNotFound, "Server error")), } _, err := client.ContainerInspect(context.Background(), "unknown") @@ -38,7 +38,7 @@ func TestContainerInspectContainerNotFound(t *testing.T) { func TestContainerInspect(t *testing.T) { expectedURL := "/containers/container_id/json" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } @@ -76,7 +76,7 @@ func TestContainerInspect(t *testing.T) { func TestContainerInspectNode(t *testing.T) { client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { content, err := json.Marshal(types.ContainerJSON{ ContainerJSONBase: &types.ContainerJSONBase{ ID: "container_id", diff --git a/client/container_kill_test.go b/client/container_kill_test.go index a34a7b5b11..9477b0abd2 100644 --- a/client/container_kill_test.go +++ b/client/container_kill_test.go @@ -13,7 +13,7 @@ import ( func TestContainerKillError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } err := client.ContainerKill(context.Background(), "nothing", "SIGKILL") if err == nil || err.Error() != "Error response from daemon: Server error" { @@ -24,7 +24,7 @@ func TestContainerKillError(t *testing.T) { func TestContainerKill(t *testing.T) { expectedURL := "/containers/container_id/kill" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/container_list_test.go b/client/container_list_test.go index 3aa2101f27..5068b7573e 100644 --- a/client/container_list_test.go +++ b/client/container_list_test.go @@ -16,7 +16,7 @@ import ( func TestContainerListError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.ContainerList(context.Background(), types.ContainerListOptions{}) if err == nil || err.Error() != "Error response from daemon: Server error" { @@ -28,7 +28,7 @@ func TestContainerList(t *testing.T) { expectedURL := "/containers/json" expectedFilters := `{"before":{"container":true},"label":{"label1":true,"label2":true}}` client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/container_logs_test.go b/client/container_logs_test.go index d7f0adc9c0..99e31842c9 100644 --- a/client/container_logs_test.go +++ b/client/container_logs_test.go @@ -19,7 +19,7 @@ import ( func TestContainerLogsError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.ContainerLogs(context.Background(), "container_id", types.ContainerLogsOptions{}) if err == nil || err.Error() != "Error response from daemon: Server error" { @@ -83,7 +83,7 @@ func TestContainerLogs(t *testing.T) { } for _, logCase := range cases { client := &Client{ - transport: newMockClient(nil, func(r *http.Request) (*http.Response, error) { + client: newMockClient(func(r *http.Request) (*http.Response, error) { if !strings.HasPrefix(r.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, r.URL) } diff --git a/client/container_pause_test.go b/client/container_pause_test.go index ebd12a6ac7..0ee2f05d7e 100644 --- a/client/container_pause_test.go +++ b/client/container_pause_test.go @@ -13,7 +13,7 @@ import ( func TestContainerPauseError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } err := client.ContainerPause(context.Background(), "nothing") if err == nil || err.Error() != "Error response from daemon: Server error" { @@ -24,7 +24,7 @@ func TestContainerPauseError(t *testing.T) { func TestContainerPause(t *testing.T) { expectedURL := "/containers/container_id/pause" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/container_remove_test.go b/client/container_remove_test.go index 6e135d6ef2..798c08b333 100644 --- a/client/container_remove_test.go +++ b/client/container_remove_test.go @@ -14,7 +14,7 @@ import ( func TestContainerRemoveError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } err := client.ContainerRemove(context.Background(), "container_id", types.ContainerRemoveOptions{}) if err == nil || err.Error() != "Error response from daemon: Server error" { @@ -25,7 +25,7 @@ func TestContainerRemoveError(t *testing.T) { func TestContainerRemove(t *testing.T) { expectedURL := "/containers/container_id" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/container_rename_test.go b/client/container_rename_test.go index 9344bab7db..732ebff5f7 100644 --- a/client/container_rename_test.go +++ b/client/container_rename_test.go @@ -13,7 +13,7 @@ import ( func TestContainerRenameError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } err := client.ContainerRename(context.Background(), "nothing", "newNothing") if err == nil || err.Error() != "Error response from daemon: Server error" { @@ -24,7 +24,7 @@ func TestContainerRenameError(t *testing.T) { func TestContainerRename(t *testing.T) { expectedURL := "/containers/container_id/rename" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/container_resize_test.go b/client/container_resize_test.go index e0056c88d1..5b2efecdce 100644 --- a/client/container_resize_test.go +++ b/client/container_resize_test.go @@ -14,7 +14,7 @@ import ( func TestContainerResizeError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } err := client.ContainerResize(context.Background(), "container_id", types.ResizeOptions{}) if err == nil || err.Error() != "Error response from daemon: Server error" { @@ -24,7 +24,7 @@ func TestContainerResizeError(t *testing.T) { func TestContainerExecResizeError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } err := client.ContainerExecResize(context.Background(), "exec_id", types.ResizeOptions{}) if err == nil || err.Error() != "Error response from daemon: Server error" { @@ -34,7 +34,7 @@ func TestContainerExecResizeError(t *testing.T) { func TestContainerResize(t *testing.T) { client := &Client{ - transport: newMockClient(nil, resizeTransport("/containers/container_id/resize")), + client: newMockClient(resizeTransport("/containers/container_id/resize")), } err := client.ContainerResize(context.Background(), "container_id", types.ResizeOptions{ @@ -48,7 +48,7 @@ func TestContainerResize(t *testing.T) { func TestContainerExecResize(t *testing.T) { client := &Client{ - transport: newMockClient(nil, resizeTransport("/exec/exec_id/resize")), + client: newMockClient(resizeTransport("/exec/exec_id/resize")), } err := client.ContainerExecResize(context.Background(), "exec_id", types.ResizeOptions{ diff --git a/client/container_restart_test.go b/client/container_restart_test.go index 080656d368..8c3cfd6a6f 100644 --- a/client/container_restart_test.go +++ b/client/container_restart_test.go @@ -14,7 +14,7 @@ import ( func TestContainerRestartError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } timeout := 0 * time.Second err := client.ContainerRestart(context.Background(), "nothing", &timeout) @@ -26,7 +26,7 @@ func TestContainerRestartError(t *testing.T) { func TestContainerRestart(t *testing.T) { expectedURL := "/containers/container_id/restart" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/container_start_test.go b/client/container_start_test.go index 79f85b332a..5826fa8bc7 100644 --- a/client/container_start_test.go +++ b/client/container_start_test.go @@ -16,7 +16,7 @@ import ( func TestContainerStartError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } err := client.ContainerStart(context.Background(), "nothing", types.ContainerStartOptions{}) if err == nil || err.Error() != "Error response from daemon: Server error" { @@ -27,7 +27,7 @@ func TestContainerStartError(t *testing.T) { func TestContainerStart(t *testing.T) { expectedURL := "/containers/container_id/start" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/container_stats_test.go b/client/container_stats_test.go index dc7c56492b..7414f135c3 100644 --- a/client/container_stats_test.go +++ b/client/container_stats_test.go @@ -13,7 +13,7 @@ import ( func TestContainerStatsError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.ContainerStats(context.Background(), "nothing", false) if err == nil || err.Error() != "Error response from daemon: Server error" { @@ -37,7 +37,7 @@ func TestContainerStats(t *testing.T) { } for _, c := range cases { client := &Client{ - transport: newMockClient(nil, func(r *http.Request) (*http.Response, error) { + client: newMockClient(func(r *http.Request) (*http.Response, error) { if !strings.HasPrefix(r.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, r.URL) } diff --git a/client/container_stop_test.go b/client/container_stop_test.go index 4b052f9908..c32cd691c4 100644 --- a/client/container_stop_test.go +++ b/client/container_stop_test.go @@ -14,7 +14,7 @@ import ( func TestContainerStopError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } timeout := 0 * time.Second err := client.ContainerStop(context.Background(), "nothing", &timeout) @@ -26,7 +26,7 @@ func TestContainerStopError(t *testing.T) { func TestContainerStop(t *testing.T) { expectedURL := "/containers/container_id/stop" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/container_top_test.go b/client/container_top_test.go index 4df7d82d84..7802be063e 100644 --- a/client/container_top_test.go +++ b/client/container_top_test.go @@ -16,7 +16,7 @@ import ( func TestContainerTopError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.ContainerTop(context.Background(), "nothing", []string{}) if err == nil || err.Error() != "Error response from daemon: Server error" { @@ -33,7 +33,7 @@ func TestContainerTop(t *testing.T) { expectedTitles := []string{"title1", "title2"} client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/container_unpause_test.go b/client/container_unpause_test.go index a5b21bf56c..2c42727191 100644 --- a/client/container_unpause_test.go +++ b/client/container_unpause_test.go @@ -13,7 +13,7 @@ import ( func TestContainerUnpauseError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } err := client.ContainerUnpause(context.Background(), "nothing") if err == nil || err.Error() != "Error response from daemon: Server error" { @@ -24,7 +24,7 @@ func TestContainerUnpauseError(t *testing.T) { func TestContainerUnpause(t *testing.T) { expectedURL := "/containers/container_id/unpause" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/container_update_test.go b/client/container_update_test.go index 46e34d6936..e151637a2b 100644 --- a/client/container_update_test.go +++ b/client/container_update_test.go @@ -16,7 +16,7 @@ import ( func TestContainerUpdateError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.ContainerUpdate(context.Background(), "nothing", container.UpdateConfig{}) if err == nil || err.Error() != "Error response from daemon: Server error" { @@ -28,7 +28,7 @@ func TestContainerUpdate(t *testing.T) { expectedURL := "/containers/container_id/update" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/container_wait_test.go b/client/container_wait_test.go index bf2ba6b925..dab5acbdd3 100644 --- a/client/container_wait_test.go +++ b/client/container_wait_test.go @@ -18,7 +18,7 @@ import ( func TestContainerWaitError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } code, err := client.ContainerWait(context.Background(), "nothing") if err == nil || err.Error() != "Error response from daemon: Server error" { @@ -32,7 +32,7 @@ func TestContainerWaitError(t *testing.T) { func TestContainerWait(t *testing.T) { expectedURL := "/containers/container_id/wait" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/events_test.go b/client/events_test.go index 57689322c3..6328983609 100644 --- a/client/events_test.go +++ b/client/events_test.go @@ -34,7 +34,7 @@ func TestEventsErrorInOptions(t *testing.T) { } for _, e := range errorCases { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.Events(context.Background(), e.options) if err == nil || !strings.Contains(err.Error(), e.expectedError) { @@ -45,7 +45,7 @@ func TestEventsErrorInOptions(t *testing.T) { func TestEventsErrorFromServer(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.Events(context.Background(), types.EventsOptions{}) if err == nil || err.Error() != "Error response from daemon: Server error" { @@ -93,7 +93,7 @@ func TestEvents(t *testing.T) { for _, eventsCase := range eventsCases { client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/hijack.go b/client/hijack.go index 9376d21b97..f3461ecf78 100644 --- a/client/hijack.go +++ b/client/hijack.go @@ -11,7 +11,7 @@ import ( "time" "github.com/docker/docker/api/types" - "github.com/docker/docker/client/transport" + "github.com/docker/docker/pkg/tlsconfig" "github.com/docker/go-connections/sockets" "golang.org/x/net/context" ) @@ -47,7 +47,12 @@ func (cli *Client) postHijacked(ctx context.Context, path string, query url.Valu req.Header.Set("Connection", "Upgrade") req.Header.Set("Upgrade", "tcp") - conn, err := dial(cli.proto, cli.addr, cli.transport.TLSConfig()) + tlsConfig, err := resolveTLSConfig(cli.client.Transport) + if err != nil { + return types.HijackedResponse{}, err + } + + conn, err := dial(cli.proto, cli.addr, tlsConfig) if err != nil { if strings.Contains(err.Error(), "connection refused") { return types.HijackedResponse{}, fmt.Errorf("Cannot connect to the Docker daemon. Is 'docker daemon' running on this host?") @@ -136,7 +141,7 @@ func tlsDialWithDialer(dialer *net.Dialer, network, addr string, config *tls.Con // from the hostname we're connecting to. if config.ServerName == "" { // Make a copy to avoid polluting argument or default. - config = transport.TLSConfigClone(config) + config = tlsconfig.Clone(config) config.ServerName = hostname } diff --git a/client/image_build_test.go b/client/image_build_test.go index def88c3cb6..53dd93376a 100644 --- a/client/image_build_test.go +++ b/client/image_build_test.go @@ -18,7 +18,7 @@ import ( func TestImageBuildError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.ImageBuild(context.Background(), nil, types.ImageBuildOptions{}) if err == nil || err.Error() != "Error response from daemon: Server error" { @@ -157,7 +157,7 @@ func TestImageBuild(t *testing.T) { for _, buildCase := range buildCases { expectedURL := "/build" client := &Client{ - transport: newMockClient(nil, func(r *http.Request) (*http.Response, error) { + client: newMockClient(func(r *http.Request) (*http.Response, error) { if !strings.HasPrefix(r.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, r.URL) } diff --git a/client/image_create_test.go b/client/image_create_test.go index a2e001be5d..5c2edd2ad5 100644 --- a/client/image_create_test.go +++ b/client/image_create_test.go @@ -15,7 +15,7 @@ import ( func TestImageCreateError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.ImageCreate(context.Background(), "reference", types.ImageCreateOptions{}) if err == nil || err.Error() != "Error response from daemon: Server error" { @@ -30,7 +30,7 @@ func TestImageCreate(t *testing.T) { expectedReference := fmt.Sprintf("%s@%s", expectedImage, expectedTag) expectedRegistryAuth := "eyJodHRwczovL2luZGV4LmRvY2tlci5pby92MS8iOnsiYXV0aCI6ImRHOTBid289IiwiZW1haWwiOiJqb2huQGRvZS5jb20ifX0=" client := &Client{ - transport: newMockClient(nil, func(r *http.Request) (*http.Response, error) { + client: newMockClient(func(r *http.Request) (*http.Response, error) { if !strings.HasPrefix(r.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, r.URL) } diff --git a/client/image_history_test.go b/client/image_history_test.go index c9516151b7..729edb1ad5 100644 --- a/client/image_history_test.go +++ b/client/image_history_test.go @@ -15,7 +15,7 @@ import ( func TestImageHistoryError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.ImageHistory(context.Background(), "nothing") if err == nil || err.Error() != "Error response from daemon: Server error" { @@ -26,7 +26,7 @@ func TestImageHistoryError(t *testing.T) { func TestImageHistory(t *testing.T) { expectedURL := "/images/image_id/history" client := &Client{ - transport: newMockClient(nil, func(r *http.Request) (*http.Response, error) { + client: newMockClient(func(r *http.Request) (*http.Response, error) { if !strings.HasPrefix(r.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, r.URL) } diff --git a/client/image_import_test.go b/client/image_import_test.go index b64ca74d7b..e309be74e6 100644 --- a/client/image_import_test.go +++ b/client/image_import_test.go @@ -15,7 +15,7 @@ import ( func TestImageImportError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.ImageImport(context.Background(), types.ImageImportSource{}, "image:tag", types.ImageImportOptions{}) if err == nil || err.Error() != "Error response from daemon: Server error" { @@ -26,7 +26,7 @@ func TestImageImportError(t *testing.T) { func TestImageImport(t *testing.T) { expectedURL := "/images/create" client := &Client{ - transport: newMockClient(nil, func(r *http.Request) (*http.Response, error) { + client: newMockClient(func(r *http.Request) (*http.Response, error) { if !strings.HasPrefix(r.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, r.URL) } diff --git a/client/image_inspect_test.go b/client/image_inspect_test.go index 5c7ca2721f..74a4e49805 100644 --- a/client/image_inspect_test.go +++ b/client/image_inspect_test.go @@ -16,7 +16,7 @@ import ( func TestImageInspectError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, _, err := client.ImageInspectWithRaw(context.Background(), "nothing") @@ -27,7 +27,7 @@ func TestImageInspectError(t *testing.T) { func TestImageInspectImageNotFound(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusNotFound, "Server error")), + client: newMockClient(errorMock(http.StatusNotFound, "Server error")), } _, _, err := client.ImageInspectWithRaw(context.Background(), "unknown") @@ -40,7 +40,7 @@ func TestImageInspect(t *testing.T) { expectedURL := "/images/image_id/json" expectedTags := []string{"tag1", "tag2"} client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/image_list_test.go b/client/image_list_test.go index 99ed1964a2..2a52279081 100644 --- a/client/image_list_test.go +++ b/client/image_list_test.go @@ -16,7 +16,7 @@ import ( func TestImageListError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.ImageList(context.Background(), types.ImageListOptions{}) @@ -82,7 +82,7 @@ func TestImageList(t *testing.T) { } for _, listCase := range listCases { client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/image_load_test.go b/client/image_load_test.go index 0ee7cf35a6..68dc14ff22 100644 --- a/client/image_load_test.go +++ b/client/image_load_test.go @@ -13,7 +13,7 @@ import ( func TestImageLoadError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.ImageLoad(context.Background(), nil, true) @@ -51,7 +51,7 @@ func TestImageLoad(t *testing.T) { } for _, loadCase := range loadCases { client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/image_pull_test.go b/client/image_pull_test.go index c33a6dcc8a..fe6bafed97 100644 --- a/client/image_pull_test.go +++ b/client/image_pull_test.go @@ -15,7 +15,7 @@ import ( func TestImagePullReferenceParseError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { return nil, nil }), } @@ -28,7 +28,7 @@ func TestImagePullReferenceParseError(t *testing.T) { func TestImagePullAnyError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.ImagePull(context.Background(), "myimage", types.ImagePullOptions{}) if err == nil || err.Error() != "Error response from daemon: Server error" { @@ -38,7 +38,7 @@ func TestImagePullAnyError(t *testing.T) { func TestImagePullStatusUnauthorizedError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusUnauthorized, "Unauthorized error")), + client: newMockClient(errorMock(http.StatusUnauthorized, "Unauthorized error")), } _, err := client.ImagePull(context.Background(), "myimage", types.ImagePullOptions{}) if err == nil || err.Error() != "Error response from daemon: Unauthorized error" { @@ -48,7 +48,7 @@ func TestImagePullStatusUnauthorizedError(t *testing.T) { func TestImagePullWithUnauthorizedErrorAndPrivilegeFuncError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusUnauthorized, "Unauthorized error")), + client: newMockClient(errorMock(http.StatusUnauthorized, "Unauthorized error")), } privilegeFunc := func() (string, error) { return "", fmt.Errorf("Error requesting privilege") @@ -63,7 +63,7 @@ func TestImagePullWithUnauthorizedErrorAndPrivilegeFuncError(t *testing.T) { func TestImagePullWithUnauthorizedErrorAndAnotherUnauthorizedError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusUnauthorized, "Unauthorized error")), + client: newMockClient(errorMock(http.StatusUnauthorized, "Unauthorized error")), } privilegeFunc := func() (string, error) { return "a-auth-header", nil @@ -79,7 +79,7 @@ func TestImagePullWithUnauthorizedErrorAndAnotherUnauthorizedError(t *testing.T) func TestImagePullWithPrivilegedFuncNoError(t *testing.T) { expectedURL := "/images/create" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } @@ -163,7 +163,7 @@ func TestImagePullWithoutErrors(t *testing.T) { } for _, pullCase := range pullCases { client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/image_push_test.go b/client/image_push_test.go index d32f3ef3c7..b52da8b8dc 100644 --- a/client/image_push_test.go +++ b/client/image_push_test.go @@ -15,7 +15,7 @@ import ( func TestImagePushReferenceError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { return nil, nil }), } @@ -33,7 +33,7 @@ func TestImagePushReferenceError(t *testing.T) { func TestImagePushAnyError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.ImagePush(context.Background(), "myimage", types.ImagePushOptions{}) if err == nil || err.Error() != "Error response from daemon: Server error" { @@ -43,7 +43,7 @@ func TestImagePushAnyError(t *testing.T) { func TestImagePushStatusUnauthorizedError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusUnauthorized, "Unauthorized error")), + client: newMockClient(errorMock(http.StatusUnauthorized, "Unauthorized error")), } _, err := client.ImagePush(context.Background(), "myimage", types.ImagePushOptions{}) if err == nil || err.Error() != "Error response from daemon: Unauthorized error" { @@ -53,7 +53,7 @@ func TestImagePushStatusUnauthorizedError(t *testing.T) { func TestImagePushWithUnauthorizedErrorAndPrivilegeFuncError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusUnauthorized, "Unauthorized error")), + client: newMockClient(errorMock(http.StatusUnauthorized, "Unauthorized error")), } privilegeFunc := func() (string, error) { return "", fmt.Errorf("Error requesting privilege") @@ -68,7 +68,7 @@ func TestImagePushWithUnauthorizedErrorAndPrivilegeFuncError(t *testing.T) { func TestImagePushWithUnauthorizedErrorAndAnotherUnauthorizedError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusUnauthorized, "Unauthorized error")), + client: newMockClient(errorMock(http.StatusUnauthorized, "Unauthorized error")), } privilegeFunc := func() (string, error) { return "a-auth-header", nil @@ -84,7 +84,7 @@ func TestImagePushWithUnauthorizedErrorAndAnotherUnauthorizedError(t *testing.T) func TestImagePushWithPrivilegedFuncNoError(t *testing.T) { expectedURL := "/images/myimage/push" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } @@ -149,7 +149,7 @@ func TestImagePushWithoutErrors(t *testing.T) { } for _, pullCase := range pullCases { client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { expectedURL := fmt.Sprintf(expectedURLFormat, pullCase.expectedImage) if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) diff --git a/client/image_remove_test.go b/client/image_remove_test.go index 696d06729d..7b004f70e6 100644 --- a/client/image_remove_test.go +++ b/client/image_remove_test.go @@ -15,7 +15,7 @@ import ( func TestImageRemoveError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.ImageRemove(context.Background(), "image_id", types.ImageRemoveOptions{}) @@ -49,7 +49,7 @@ func TestImageRemove(t *testing.T) { } for _, removeCase := range removeCases { client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/image_save_test.go b/client/image_save_test.go index 8ee40c43ae..8f0cf88640 100644 --- a/client/image_save_test.go +++ b/client/image_save_test.go @@ -15,7 +15,7 @@ import ( func TestImageSaveError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.ImageSave(context.Background(), []string{"nothing"}) if err == nil || err.Error() != "Error response from daemon: Server error" { @@ -26,7 +26,7 @@ func TestImageSaveError(t *testing.T) { func TestImageSave(t *testing.T) { expectedURL := "/images/get" client := &Client{ - transport: newMockClient(nil, func(r *http.Request) (*http.Response, error) { + client: newMockClient(func(r *http.Request) (*http.Response, error) { if !strings.HasPrefix(r.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, r.URL) } diff --git a/client/image_search_test.go b/client/image_search_test.go index 2f21b2cc14..e46d86437f 100644 --- a/client/image_search_test.go +++ b/client/image_search_test.go @@ -18,7 +18,7 @@ import ( func TestImageSearchAnyError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.ImageSearch(context.Background(), "some-image", types.ImageSearchOptions{}) if err == nil || err.Error() != "Error response from daemon: Server error" { @@ -28,7 +28,7 @@ func TestImageSearchAnyError(t *testing.T) { func TestImageSearchStatusUnauthorizedError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusUnauthorized, "Unauthorized error")), + client: newMockClient(errorMock(http.StatusUnauthorized, "Unauthorized error")), } _, err := client.ImageSearch(context.Background(), "some-image", types.ImageSearchOptions{}) if err == nil || err.Error() != "Error response from daemon: Unauthorized error" { @@ -38,7 +38,7 @@ func TestImageSearchStatusUnauthorizedError(t *testing.T) { func TestImageSearchWithUnauthorizedErrorAndPrivilegeFuncError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusUnauthorized, "Unauthorized error")), + client: newMockClient(errorMock(http.StatusUnauthorized, "Unauthorized error")), } privilegeFunc := func() (string, error) { return "", fmt.Errorf("Error requesting privilege") @@ -53,7 +53,7 @@ func TestImageSearchWithUnauthorizedErrorAndPrivilegeFuncError(t *testing.T) { func TestImageSearchWithUnauthorizedErrorAndAnotherUnauthorizedError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusUnauthorized, "Unauthorized error")), + client: newMockClient(errorMock(http.StatusUnauthorized, "Unauthorized error")), } privilegeFunc := func() (string, error) { return "a-auth-header", nil @@ -69,7 +69,7 @@ func TestImageSearchWithUnauthorizedErrorAndAnotherUnauthorizedError(t *testing. func TestImageSearchWithPrivilegedFuncNoError(t *testing.T) { expectedURL := "/images/search" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } @@ -126,7 +126,7 @@ func TestImageSearchWithoutErrors(t *testing.T) { expectedFilters := `{"is-automated":{"true":true},"stars":{"3":true}}` client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/image_tag_test.go b/client/image_tag_test.go index f3571dfdd3..7925db9f1b 100644 --- a/client/image_tag_test.go +++ b/client/image_tag_test.go @@ -13,7 +13,7 @@ import ( func TestImageTagError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } err := client.ImageTag(context.Background(), "image_id", "repo:tag") @@ -26,7 +26,7 @@ func TestImageTagError(t *testing.T) { // of distribution/reference package. func TestImageTagInvalidReference(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } err := client.ImageTag(context.Background(), "image_id", "aa/asdf$$^/aa") @@ -93,7 +93,7 @@ func TestImageTag(t *testing.T) { } for _, tagCase := range tagCases { client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/info_test.go b/client/info_test.go index 9d51b1a78b..79f23c8af2 100644 --- a/client/info_test.go +++ b/client/info_test.go @@ -15,7 +15,7 @@ import ( func TestInfoServerError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.Info(context.Background()) if err == nil || err.Error() != "Error response from daemon: Server error" { @@ -25,7 +25,7 @@ func TestInfoServerError(t *testing.T) { func TestInfoInvalidResponseJSONError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { return &http.Response{ StatusCode: http.StatusOK, Body: ioutil.NopCloser(bytes.NewReader([]byte("invalid json"))), @@ -41,7 +41,7 @@ func TestInfoInvalidResponseJSONError(t *testing.T) { func TestInfo(t *testing.T) { expectedURL := "/info" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/network_connect_test.go b/client/network_connect_test.go index 95b149e685..d472f4520c 100644 --- a/client/network_connect_test.go +++ b/client/network_connect_test.go @@ -17,7 +17,7 @@ import ( func TestNetworkConnectError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } err := client.NetworkConnect(context.Background(), "network_id", "container_id", nil) @@ -30,7 +30,7 @@ func TestNetworkConnectEmptyNilEndpointSettings(t *testing.T) { expectedURL := "/networks/network_id/connect" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } @@ -69,7 +69,7 @@ func TestNetworkConnect(t *testing.T) { expectedURL := "/networks/network_id/connect" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/network_create_test.go b/client/network_create_test.go index 611ed8173e..0e2457f89c 100644 --- a/client/network_create_test.go +++ b/client/network_create_test.go @@ -15,7 +15,7 @@ import ( func TestNetworkCreateError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.NetworkCreate(context.Background(), "mynetwork", types.NetworkCreate{}) @@ -28,7 +28,7 @@ func TestNetworkCreate(t *testing.T) { expectedURL := "/networks/create" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/network_disconnect_test.go b/client/network_disconnect_test.go index d9dbb67159..b54a2b1ccf 100644 --- a/client/network_disconnect_test.go +++ b/client/network_disconnect_test.go @@ -15,7 +15,7 @@ import ( func TestNetworkDisconnectError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } err := client.NetworkDisconnect(context.Background(), "network_id", "container_id", false) @@ -28,7 +28,7 @@ func TestNetworkDisconnect(t *testing.T) { expectedURL := "/networks/network_id/disconnect" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/network_inspect_test.go b/client/network_inspect_test.go index a6eb626c67..1f926d66ba 100644 --- a/client/network_inspect_test.go +++ b/client/network_inspect_test.go @@ -15,7 +15,7 @@ import ( func TestNetworkInspectError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.NetworkInspect(context.Background(), "nothing") @@ -26,7 +26,7 @@ func TestNetworkInspectError(t *testing.T) { func TestNetworkInspectContainerNotFound(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusNotFound, "Server error")), + client: newMockClient(errorMock(http.StatusNotFound, "Server error")), } _, err := client.NetworkInspect(context.Background(), "unknown") @@ -38,7 +38,7 @@ func TestNetworkInspectContainerNotFound(t *testing.T) { func TestNetworkInspect(t *testing.T) { expectedURL := "/networks/network_id" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/network_list_test.go b/client/network_list_test.go index cb66139271..4d443496ac 100644 --- a/client/network_list_test.go +++ b/client/network_list_test.go @@ -16,7 +16,7 @@ import ( func TestNetworkListError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.NetworkList(context.Background(), types.NetworkListOptions{ @@ -69,7 +69,7 @@ func TestNetworkList(t *testing.T) { for _, listCase := range listCases { client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/network_remove_test.go b/client/network_remove_test.go index d8cfa0ed6e..2a7b9640c1 100644 --- a/client/network_remove_test.go +++ b/client/network_remove_test.go @@ -13,7 +13,7 @@ import ( func TestNetworkRemoveError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } err := client.NetworkRemove(context.Background(), "network_id") @@ -26,7 +26,7 @@ func TestNetworkRemove(t *testing.T) { expectedURL := "/networks/network_id" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/node_inspect_test.go b/client/node_inspect_test.go index bf67728311..fc13283084 100644 --- a/client/node_inspect_test.go +++ b/client/node_inspect_test.go @@ -15,7 +15,7 @@ import ( func TestNodeInspectError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, _, err := client.NodeInspectWithRaw(context.Background(), "nothing") @@ -26,7 +26,7 @@ func TestNodeInspectError(t *testing.T) { func TestNodeInspectNodeNotFound(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusNotFound, "Server error")), + client: newMockClient(errorMock(http.StatusNotFound, "Server error")), } _, _, err := client.NodeInspectWithRaw(context.Background(), "unknown") @@ -38,7 +38,7 @@ func TestNodeInspectNodeNotFound(t *testing.T) { func TestNodeInspect(t *testing.T) { expectedURL := "/nodes/node_id" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/node_list_test.go b/client/node_list_test.go index 899ac7f455..1b3b35f357 100644 --- a/client/node_list_test.go +++ b/client/node_list_test.go @@ -17,7 +17,7 @@ import ( func TestNodeListError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.NodeList(context.Background(), types.NodeListOptions{}) @@ -54,7 +54,7 @@ func TestNodeList(t *testing.T) { } for _, listCase := range listCases { client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/node_remove_test.go b/client/node_remove_test.go index 9fdf2d7eb3..f2f8adc4a3 100644 --- a/client/node_remove_test.go +++ b/client/node_remove_test.go @@ -15,7 +15,7 @@ import ( func TestNodeRemoveError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } err := client.NodeRemove(context.Background(), "node_id", types.NodeRemoveOptions{Force: false}) @@ -42,7 +42,7 @@ func TestNodeRemove(t *testing.T) { for _, removeCase := range removeCases { client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/node_update_test.go b/client/node_update_test.go index 1acf65854a..613ff104eb 100644 --- a/client/node_update_test.go +++ b/client/node_update_test.go @@ -15,7 +15,7 @@ import ( func TestNodeUpdateError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } err := client.NodeUpdate(context.Background(), "node_id", swarm.Version{}, swarm.NodeSpec{}) @@ -28,7 +28,7 @@ func TestNodeUpdate(t *testing.T) { expectedURL := "/nodes/node_id/update" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/plugin_disable_test.go b/client/plugin_disable_test.go index f37c157866..7b50b25730 100644 --- a/client/plugin_disable_test.go +++ b/client/plugin_disable_test.go @@ -15,7 +15,7 @@ import ( func TestPluginDisableError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } err := client.PluginDisable(context.Background(), "plugin_name") @@ -28,7 +28,7 @@ func TestPluginDisable(t *testing.T) { expectedURL := "/plugins/plugin_name/disable" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/plugin_enable_test.go b/client/plugin_enable_test.go index fc0fe226a9..a2b57be4c2 100644 --- a/client/plugin_enable_test.go +++ b/client/plugin_enable_test.go @@ -15,7 +15,7 @@ import ( func TestPluginEnableError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } err := client.PluginEnable(context.Background(), "plugin_name") @@ -28,7 +28,7 @@ func TestPluginEnable(t *testing.T) { expectedURL := "/plugins/plugin_name/enable" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/plugin_inspect_test.go b/client/plugin_inspect_test.go index 19f829b2de..df4ca9c841 100644 --- a/client/plugin_inspect_test.go +++ b/client/plugin_inspect_test.go @@ -17,7 +17,7 @@ import ( func TestPluginInspectError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, _, err := client.PluginInspectWithRaw(context.Background(), "nothing") @@ -29,7 +29,7 @@ func TestPluginInspectError(t *testing.T) { func TestPluginInspect(t *testing.T) { expectedURL := "/plugins/plugin_name" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/plugin_list_test.go b/client/plugin_list_test.go index 92aee61187..95c51595ca 100644 --- a/client/plugin_list_test.go +++ b/client/plugin_list_test.go @@ -17,7 +17,7 @@ import ( func TestPluginListError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.PluginList(context.Background()) @@ -29,7 +29,7 @@ func TestPluginListError(t *testing.T) { func TestPluginList(t *testing.T) { expectedURL := "/plugins" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/plugin_push_test.go b/client/plugin_push_test.go index b77ea00273..ed685694ec 100644 --- a/client/plugin_push_test.go +++ b/client/plugin_push_test.go @@ -15,7 +15,7 @@ import ( func TestPluginPushError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } err := client.PluginPush(context.Background(), "plugin_name", "") @@ -28,7 +28,7 @@ func TestPluginPush(t *testing.T) { expectedURL := "/plugins/plugin_name" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/plugin_remove_test.go b/client/plugin_remove_test.go index de565f441b..fc789fd04d 100644 --- a/client/plugin_remove_test.go +++ b/client/plugin_remove_test.go @@ -17,7 +17,7 @@ import ( func TestPluginRemoveError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } err := client.PluginRemove(context.Background(), "plugin_name", types.PluginRemoveOptions{}) @@ -30,7 +30,7 @@ func TestPluginRemove(t *testing.T) { expectedURL := "/plugins/plugin_name" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/plugin_set_test.go b/client/plugin_set_test.go index 128dee04be..fa1cde044e 100644 --- a/client/plugin_set_test.go +++ b/client/plugin_set_test.go @@ -15,7 +15,7 @@ import ( func TestPluginSetError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } err := client.PluginSet(context.Background(), "plugin_name", []string{}) @@ -28,7 +28,7 @@ func TestPluginSet(t *testing.T) { expectedURL := "/plugins/plugin_name/set" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/request.go b/client/request.go index 7b4f5406b8..f5c239bf25 100644 --- a/client/request.go +++ b/client/request.go @@ -13,9 +13,9 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/versions" - "github.com/docker/docker/client/transport/cancellable" "github.com/pkg/errors" "golang.org/x/net/context" + "golang.org/x/net/context/ctxhttp" ) // serverResponse is a wrapper for http API responses. @@ -98,20 +98,27 @@ func (cli *Client) sendClientRequest(ctx context.Context, method, path string, q // need a valid and meaningful host name. (See #189) req.Host = "docker" } + + scheme, err := resolveScheme(cli.client.Transport) + if err != nil { + return serverResp, err + } + req.URL.Host = cli.addr - req.URL.Scheme = cli.transport.Scheme() + req.URL.Scheme = scheme if expectedPayload && req.Header.Get("Content-Type") == "" { req.Header.Set("Content-Type", "text/plain") } - resp, err := cancellable.Do(ctx, cli.transport, req) + resp, err := ctxhttp.Do(ctx, cli.client, req) if err != nil { - if !cli.transport.Secure() && strings.Contains(err.Error(), "malformed HTTP response") { + + if scheme == "https" && strings.Contains(err.Error(), "malformed HTTP response") { return serverResp, fmt.Errorf("%v.\n* Are you trying to connect to a TLS-enabled daemon without TLS?", err) } - if cli.transport.Secure() && strings.Contains(err.Error(), "bad certificate") { + if scheme == "https" && strings.Contains(err.Error(), "bad certificate") { return serverResp, fmt.Errorf("The server probably has client authentication (--tlsverify) enabled. Please check your TLS client certification settings: %v", err) } diff --git a/client/request_test.go b/client/request_test.go index 446adf9c66..63908aec4b 100644 --- a/client/request_test.go +++ b/client/request_test.go @@ -50,7 +50,7 @@ func TestSetHostHeader(t *testing.T) { } client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, testURL) { return nil, fmt.Errorf("Test Case #%d: Expected URL %q, got %q", c, testURL, req.URL) } @@ -65,6 +65,7 @@ func TestSetHostHeader(t *testing.T) { Body: ioutil.NopCloser(bytes.NewReader(([]byte("")))), }, nil }), + proto: proto, addr: addr, basePath: basePath, @@ -82,7 +83,7 @@ func TestSetHostHeader(t *testing.T) { // errors returned as JSON func TestPlainTextError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, plainTextErrorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(plainTextErrorMock(http.StatusInternalServerError, "Server error")), } _, err := client.ContainerList(context.Background(), types.ContainerListOptions{}) if err == nil || err.Error() != "Error response from daemon: Server error" { diff --git a/client/service_create_test.go b/client/service_create_test.go index a79f040c0a..1e07382870 100644 --- a/client/service_create_test.go +++ b/client/service_create_test.go @@ -16,7 +16,7 @@ import ( func TestServiceCreateError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.ServiceCreate(context.Background(), swarm.ServiceSpec{}, types.ServiceCreateOptions{}) if err == nil || err.Error() != "Error response from daemon: Server error" { @@ -27,7 +27,7 @@ func TestServiceCreateError(t *testing.T) { func TestServiceCreate(t *testing.T) { expectedURL := "/services/create" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/service_inspect_test.go b/client/service_inspect_test.go index e4eafff5d7..e235cf0fef 100644 --- a/client/service_inspect_test.go +++ b/client/service_inspect_test.go @@ -15,7 +15,7 @@ import ( func TestServiceInspectError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, _, err := client.ServiceInspectWithRaw(context.Background(), "nothing") @@ -26,7 +26,7 @@ func TestServiceInspectError(t *testing.T) { func TestServiceInspectServiceNotFound(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusNotFound, "Server error")), + client: newMockClient(errorMock(http.StatusNotFound, "Server error")), } _, _, err := client.ServiceInspectWithRaw(context.Background(), "unknown") @@ -38,7 +38,7 @@ func TestServiceInspectServiceNotFound(t *testing.T) { func TestServiceInspect(t *testing.T) { expectedURL := "/services/service_id" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/service_list_test.go b/client/service_list_test.go index 6e6851a3a5..728187919f 100644 --- a/client/service_list_test.go +++ b/client/service_list_test.go @@ -17,7 +17,7 @@ import ( func TestServiceListError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.ServiceList(context.Background(), types.ServiceListOptions{}) @@ -54,7 +54,7 @@ func TestServiceList(t *testing.T) { } for _, listCase := range listCases { client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/service_remove_test.go b/client/service_remove_test.go index e1316f959b..8e2ac259c1 100644 --- a/client/service_remove_test.go +++ b/client/service_remove_test.go @@ -13,7 +13,7 @@ import ( func TestServiceRemoveError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } err := client.ServiceRemove(context.Background(), "service_id") @@ -26,7 +26,7 @@ func TestServiceRemove(t *testing.T) { expectedURL := "/services/service_id" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/service_update_test.go b/client/service_update_test.go index bd616c09bf..081649f492 100644 --- a/client/service_update_test.go +++ b/client/service_update_test.go @@ -16,7 +16,7 @@ import ( func TestServiceUpdateError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } err := client.ServiceUpdate(context.Background(), "service_id", swarm.Version{}, swarm.ServiceSpec{}, types.ServiceUpdateOptions{}) @@ -51,7 +51,7 @@ func TestServiceUpdate(t *testing.T) { for _, updateCase := range updateCases { client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/swarm_init_test.go b/client/swarm_init_test.go index 077c8c4efb..811155aff4 100644 --- a/client/swarm_init_test.go +++ b/client/swarm_init_test.go @@ -15,7 +15,7 @@ import ( func TestSwarmInitError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.SwarmInit(context.Background(), swarm.InitRequest{}) @@ -28,7 +28,7 @@ func TestSwarmInit(t *testing.T) { expectedURL := "/swarm/init" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/swarm_inspect_test.go b/client/swarm_inspect_test.go index 7143e77181..6432d172b4 100644 --- a/client/swarm_inspect_test.go +++ b/client/swarm_inspect_test.go @@ -15,7 +15,7 @@ import ( func TestSwarmInspectError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.SwarmInspect(context.Background()) @@ -27,7 +27,7 @@ func TestSwarmInspectError(t *testing.T) { func TestSwarmInspect(t *testing.T) { expectedURL := "/swarm" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/swarm_join_test.go b/client/swarm_join_test.go index 922716d85f..31ef2a76ee 100644 --- a/client/swarm_join_test.go +++ b/client/swarm_join_test.go @@ -15,7 +15,7 @@ import ( func TestSwarmJoinError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } err := client.SwarmJoin(context.Background(), swarm.JoinRequest{}) @@ -28,7 +28,7 @@ func TestSwarmJoin(t *testing.T) { expectedURL := "/swarm/join" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/swarm_leave_test.go b/client/swarm_leave_test.go index d0bef2b257..c96dac8120 100644 --- a/client/swarm_leave_test.go +++ b/client/swarm_leave_test.go @@ -13,7 +13,7 @@ import ( func TestSwarmLeaveError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } err := client.SwarmLeave(context.Background(), false) @@ -40,7 +40,7 @@ func TestSwarmLeave(t *testing.T) { for _, leaveCase := range leaveCases { client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/swarm_update_test.go b/client/swarm_update_test.go index ecf1731e5b..3b23db078f 100644 --- a/client/swarm_update_test.go +++ b/client/swarm_update_test.go @@ -15,7 +15,7 @@ import ( func TestSwarmUpdateError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } err := client.SwarmUpdate(context.Background(), swarm.Version{}, swarm.Spec{}, swarm.UpdateFlags{}) @@ -28,7 +28,7 @@ func TestSwarmUpdate(t *testing.T) { expectedURL := "/swarm/update" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/task_inspect_test.go b/client/task_inspect_test.go index 2c73b37642..148cdad3a7 100644 --- a/client/task_inspect_test.go +++ b/client/task_inspect_test.go @@ -15,7 +15,7 @@ import ( func TestTaskInspectError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, _, err := client.TaskInspectWithRaw(context.Background(), "nothing") @@ -27,7 +27,7 @@ func TestTaskInspectError(t *testing.T) { func TestTaskInspect(t *testing.T) { expectedURL := "/tasks/task_id" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/task_list_test.go b/client/task_list_test.go index b520ab589f..2d9b812bc2 100644 --- a/client/task_list_test.go +++ b/client/task_list_test.go @@ -17,7 +17,7 @@ import ( func TestTaskListError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.TaskList(context.Background(), types.TaskListOptions{}) @@ -54,7 +54,7 @@ func TestTaskList(t *testing.T) { } for _, listCase := range listCases { client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/transport.go b/client/transport.go new file mode 100644 index 0000000000..43a667272d --- /dev/null +++ b/client/transport.go @@ -0,0 +1,51 @@ +package client + +import ( + "crypto/tls" + "errors" + "net/http" +) + +var errTLSConfigUnavailable = errors.New("TLSConfig unavailable") + +// transportFunc allows us to inject a mock transport for testing. We define it +// here so we can detect the tlsconfig and return nil for only this type. +type transportFunc func(*http.Request) (*http.Response, error) + +func (tf transportFunc) RoundTrip(req *http.Request) (*http.Response, error) { + return tf(req) +} + +// resolveTLSConfig attempts to resolve the tls configuration from the +// RoundTripper. +func resolveTLSConfig(transport http.RoundTripper) (*tls.Config, error) { + switch tr := transport.(type) { + case *http.Transport: + return tr.TLSClientConfig, nil + case transportFunc: + return nil, nil // detect this type for testing. + default: + return nil, errTLSConfigUnavailable + } +} + +// resolveScheme detects a tls config on the transport and returns the +// appropriate http scheme. +// +// TODO(stevvooe): This isn't really the right way to write clients in Go. +// `NewClient` should probably only take an `*http.Client` and work from there. +// Unfortunately, the model of having a host-ish/url-thingy as the connection +// string has us confusing protocol and transport layers. We continue doing +// this to avoid breaking existing clients but this should be addressed. +func resolveScheme(transport http.RoundTripper) (string, error) { + c, err := resolveTLSConfig(transport) + if err != nil { + return "", err + } + + if c != nil { + return "https", nil + } + + return "http", nil +} diff --git a/client/transport/cancellable/LICENSE b/client/transport/cancellable/LICENSE deleted file mode 100644 index 6a66aea5ea..0000000000 --- a/client/transport/cancellable/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/client/transport/cancellable/canceler.go b/client/transport/cancellable/canceler.go deleted file mode 100644 index 62770b777b..0000000000 --- a/client/transport/cancellable/canceler.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build go1.5 - -package cancellable - -import ( - "net/http" - - "github.com/docker/docker/client/transport" -) - -func canceler(client transport.Sender, req *http.Request) func() { - // TODO(djd): Respect any existing value of req.Cancel. - ch := make(chan struct{}) - req.Cancel = ch - - return func() { - close(ch) - } -} diff --git a/client/transport/cancellable/canceler_go14.go b/client/transport/cancellable/canceler_go14.go deleted file mode 100644 index dd2723d94f..0000000000 --- a/client/transport/cancellable/canceler_go14.go +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !go1.5 - -package cancellable - -import ( - "net/http" - - "github.com/docker/docker/client/transport" -) - -type requestCanceler interface { - CancelRequest(*http.Request) -} - -func canceler(client transport.Sender, req *http.Request) func() { - rc, ok := client.(requestCanceler) - if !ok { - return func() {} - } - return func() { - rc.CancelRequest(req) - } -} diff --git a/client/transport/cancellable/cancellable.go b/client/transport/cancellable/cancellable.go deleted file mode 100644 index 1f8eac5c1c..0000000000 --- a/client/transport/cancellable/cancellable.go +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package cancellable provides helper function to cancel http requests. -package cancellable - -import ( - "io" - "net/http" - "sync" - - "github.com/docker/docker/client/transport" - - "golang.org/x/net/context" -) - -func nop() {} - -var ( - testHookContextDoneBeforeHeaders = nop - testHookDoReturned = nop - testHookDidBodyClose = nop -) - -// Do sends an HTTP request with the provided transport.Sender and returns an HTTP response. -// If the client is nil, http.DefaultClient is used. -// If the context is canceled or times out, ctx.Err() will be returned. -// -// FORK INFORMATION: -// -// This function deviates from the upstream version in golang.org/x/net/context/ctxhttp by -// taking a Sender interface rather than a *http.Client directly. That allow us to use -// this function with mocked clients and hijacked connections. -func Do(ctx context.Context, client transport.Sender, req *http.Request) (*http.Response, error) { - if client == nil { - client = http.DefaultClient - } - - // Request cancelation changed in Go 1.5, see canceler.go and canceler_go14.go. - cancel := canceler(client, req) - - type responseAndError struct { - resp *http.Response - err error - } - result := make(chan responseAndError, 1) - - go func() { - resp, err := client.Do(req) - testHookDoReturned() - result <- responseAndError{resp, err} - }() - - var resp *http.Response - - select { - case <-ctx.Done(): - testHookContextDoneBeforeHeaders() - cancel() - // Clean up after the goroutine calling client.Do: - go func() { - if r := <-result; r.resp != nil && r.resp.Body != nil { - testHookDidBodyClose() - r.resp.Body.Close() - } - }() - return nil, ctx.Err() - case r := <-result: - var err error - resp, err = r.resp, r.err - if err != nil { - return resp, err - } - } - - c := make(chan struct{}) - go func() { - select { - case <-ctx.Done(): - cancel() - case <-c: - // The response's Body is closed. - } - }() - resp.Body = ¬ifyingReader{ReadCloser: resp.Body, notify: c} - - return resp, nil -} - -// notifyingReader is an io.ReadCloser that closes the notify channel after -// Close is called or a Read fails on the underlying ReadCloser. -type notifyingReader struct { - io.ReadCloser - notify chan<- struct{} - notifyOnce sync.Once -} - -func (r *notifyingReader) Read(p []byte) (int, error) { - n, err := r.ReadCloser.Read(p) - if err != nil { - r.notifyOnce.Do(func() { - close(r.notify) - }) - } - return n, err -} - -func (r *notifyingReader) Close() error { - err := r.ReadCloser.Close() - r.notifyOnce.Do(func() { - close(r.notify) - }) - return err -} diff --git a/client/transport/client.go b/client/transport/client.go deleted file mode 100644 index 13d4b3ab3d..0000000000 --- a/client/transport/client.go +++ /dev/null @@ -1,47 +0,0 @@ -package transport - -import ( - "crypto/tls" - "net/http" -) - -// Sender is an interface that clients must implement -// to be able to send requests to a remote connection. -type Sender interface { - // Do sends request to a remote endpoint. - Do(*http.Request) (*http.Response, error) -} - -// Client is an interface that abstracts all remote connections. -type Client interface { - Sender - // Secure tells whether the connection is secure or not. - Secure() bool - // Scheme returns the connection protocol the client uses. - Scheme() string - // TLSConfig returns any TLS configuration the client uses. - TLSConfig() *tls.Config -} - -// tlsInfo returns information about the TLS configuration. -type tlsInfo struct { - tlsConfig *tls.Config -} - -// TLSConfig returns the TLS configuration. -func (t *tlsInfo) TLSConfig() *tls.Config { - return t.tlsConfig -} - -// Scheme returns protocol scheme to use. -func (t *tlsInfo) Scheme() string { - if t.tlsConfig != nil { - return "https" - } - return "http" -} - -// Secure returns true if there is a TLS configuration. -func (t *tlsInfo) Secure() bool { - return t.tlsConfig != nil -} diff --git a/client/transport/tlsconfig_clone.go b/client/transport/tlsconfig_clone.go deleted file mode 100644 index 034bc01d33..0000000000 --- a/client/transport/tlsconfig_clone.go +++ /dev/null @@ -1,11 +0,0 @@ -// +build go1.8 - -package transport - -import "crypto/tls" - -// TLSConfigClone returns a clone of tls.Config. This function is provided for -// compatibility for go1.7 that doesn't include this method in stdlib. -func TLSConfigClone(c *tls.Config) *tls.Config { - return c.Clone() -} diff --git a/client/transport/transport.go b/client/transport/transport.go deleted file mode 100644 index ff28af1855..0000000000 --- a/client/transport/transport.go +++ /dev/null @@ -1,57 +0,0 @@ -// Package transport provides function to send request to remote endpoints. -package transport - -import ( - "fmt" - "net/http" - - "github.com/docker/go-connections/sockets" -) - -// apiTransport holds information about the http transport to connect with the API. -type apiTransport struct { - *http.Client - *tlsInfo - transport *http.Transport -} - -// NewTransportWithHTTP creates a new transport based on the provided proto, address and http client. -// It uses Docker's default http transport configuration if the client is nil. -// It does not modify the client's transport if it's not nil. -func NewTransportWithHTTP(proto, addr string, client *http.Client) (Client, error) { - var transport *http.Transport - - if client != nil { - tr, ok := client.Transport.(*http.Transport) - if !ok { - return nil, fmt.Errorf("unable to verify TLS configuration, invalid transport %v", client.Transport) - } - transport = tr - } else { - transport = defaultTransport(proto, addr) - client = &http.Client{ - Transport: transport, - } - } - - return &apiTransport{ - Client: client, - tlsInfo: &tlsInfo{transport.TLSClientConfig}, - transport: transport, - }, nil -} - -// CancelRequest stops a request execution. -func (a *apiTransport) CancelRequest(req *http.Request) { - a.transport.CancelRequest(req) -} - -// defaultTransport creates a new http.Transport with Docker's -// default transport configuration. -func defaultTransport(proto, addr string) *http.Transport { - tr := new(http.Transport) - sockets.ConfigureTransport(tr, proto, addr) - return tr -} - -var _ Client = &apiTransport{} diff --git a/client/volume_create_test.go b/client/volume_create_test.go index d3cfa7132f..75085296cc 100644 --- a/client/volume_create_test.go +++ b/client/volume_create_test.go @@ -15,7 +15,7 @@ import ( func TestVolumeCreateError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.VolumeCreate(context.Background(), types.VolumeCreateRequest{}) @@ -28,7 +28,7 @@ func TestVolumeCreate(t *testing.T) { expectedURL := "/volumes/create" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/volume_inspect_test.go b/client/volume_inspect_test.go index 4b9f47358d..0d1d118828 100644 --- a/client/volume_inspect_test.go +++ b/client/volume_inspect_test.go @@ -15,7 +15,7 @@ import ( func TestVolumeInspectError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.VolumeInspect(context.Background(), "nothing") @@ -26,7 +26,7 @@ func TestVolumeInspectError(t *testing.T) { func TestVolumeInspectNotFound(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusNotFound, "Server error")), + client: newMockClient(errorMock(http.StatusNotFound, "Server error")), } _, err := client.VolumeInspect(context.Background(), "unknown") @@ -38,7 +38,7 @@ func TestVolumeInspectNotFound(t *testing.T) { func TestVolumeInspect(t *testing.T) { expectedURL := "/volumes/volume_id" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/volume_list_test.go b/client/volume_list_test.go index d30d9fcd52..0af420eaff 100644 --- a/client/volume_list_test.go +++ b/client/volume_list_test.go @@ -16,7 +16,7 @@ import ( func TestVolumeListError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } _, err := client.VolumeList(context.Background(), filters.NewArgs()) @@ -59,7 +59,7 @@ func TestVolumeList(t *testing.T) { for _, listCase := range listCases { client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/client/volume_remove_test.go b/client/volume_remove_test.go index 0675bfd458..1fe657349a 100644 --- a/client/volume_remove_test.go +++ b/client/volume_remove_test.go @@ -13,7 +13,7 @@ import ( func TestVolumeRemoveError(t *testing.T) { client := &Client{ - transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")), + client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } err := client.VolumeRemove(context.Background(), "volume_id", false) @@ -26,7 +26,7 @@ func TestVolumeRemove(t *testing.T) { expectedURL := "/volumes/volume_id" client := &Client{ - transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) { + client: newMockClient(func(req *http.Request) (*http.Response, error) { if !strings.HasPrefix(req.URL.Path, expectedURL) { return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) } diff --git a/pkg/tlsconfig/tlsconfig_clone.go b/pkg/tlsconfig/tlsconfig_clone.go new file mode 100644 index 0000000000..e4dec3a5d1 --- /dev/null +++ b/pkg/tlsconfig/tlsconfig_clone.go @@ -0,0 +1,11 @@ +// +build go1.8 + +package tlsconfig + +import "crypto/tls" + +// Clone returns a clone of tls.Config. This function is provided for +// compatibility for go1.7 that doesn't include this method in stdlib. +func Clone(c *tls.Config) *tls.Config { + return c.Clone() +} diff --git a/client/transport/tlsconfig_clone_go16.go b/pkg/tlsconfig/tlsconfig_clone_go16.go similarity index 87% rename from client/transport/tlsconfig_clone_go16.go rename to pkg/tlsconfig/tlsconfig_clone_go16.go index 12f13e4694..0b816650ec 100644 --- a/client/transport/tlsconfig_clone_go16.go +++ b/pkg/tlsconfig/tlsconfig_clone_go16.go @@ -1,12 +1,12 @@ // +build go1.6,!go1.7 -package transport +package tlsconfig import "crypto/tls" -// TLSConfigClone returns a clone of tls.Config. This function is provided for +// Clone returns a clone of tls.Config. This function is provided for // compatibility for go1.6 that doesn't include this method in stdlib. -func TLSConfigClone(c *tls.Config) *tls.Config { +func Clone(c *tls.Config) *tls.Config { return &tls.Config{ Rand: c.Rand, Time: c.Time, diff --git a/client/transport/tlsconfig_clone_go17.go b/pkg/tlsconfig/tlsconfig_clone_go17.go similarity index 88% rename from client/transport/tlsconfig_clone_go17.go rename to pkg/tlsconfig/tlsconfig_clone_go17.go index 50bf389e43..0d5b448fec 100644 --- a/client/transport/tlsconfig_clone_go17.go +++ b/pkg/tlsconfig/tlsconfig_clone_go17.go @@ -1,12 +1,12 @@ // +build go1.7,!go1.8 -package transport +package tlsconfig import "crypto/tls" -// TLSConfigClone returns a clone of tls.Config. This function is provided for +// Clone returns a clone of tls.Config. This function is provided for // compatibility for go1.7 that doesn't include this method in stdlib. -func TLSConfigClone(c *tls.Config) *tls.Config { +func Clone(c *tls.Config) *tls.Config { return &tls.Config{ Rand: c.Rand, Time: c.Time,