diff --git a/components/engine/client/client.go b/components/engine/client/client.go index ab208c319b..240e32ae05 100644 --- a/components/engine/client/client.go +++ b/components/engine/client/client.go @@ -107,8 +107,14 @@ func CheckRedirect(req *http.Request, via []*http.Request) error { // Use DOCKER_API_VERSION to set the version of the API to reach, leave empty for latest. // Use DOCKER_CERT_PATH to load the TLS certificates from. // Use DOCKER_TLS_VERIFY to enable or disable TLS verification, off by default. +// deprecated: use NewClientWithOpts(FromEnv) func NewEnvClient() (*Client, error) { - var client *http.Client + return NewClientWithOpts(FromEnv) +} + +// FromEnv enhance the default client with values from environment variables +func FromEnv(c *Client) error { + var httpClient *http.Client if dockerCertPath := os.Getenv("DOCKER_CERT_PATH"); dockerCertPath != "" { options := tlsconfig.Options{ CAFile: filepath.Join(dockerCertPath, "ca.pem"), @@ -118,10 +124,10 @@ func NewEnvClient() (*Client, error) { } tlsc, err := tlsconfig.Client(options) if err != nil { - return nil, err + return err } - client = &http.Client{ + httpClient = &http.Client{ Transport: &http.Transport{ TLSClientConfig: tlsc, }, @@ -130,22 +136,128 @@ func NewEnvClient() (*Client, error) { } host := os.Getenv("DOCKER_HOST") - if host == "" { - host = DefaultDockerHost + if host != "" { + var err error + if err := WithHost(host)(c); err != nil { + return err + } + httpClient, err = defaultHTTPClient(host) + if err != nil { + return err + } + } + if httpClient != nil { + if err := WithHTTPClient(httpClient)(c); err != nil { + return err + } } version := os.Getenv("DOCKER_API_VERSION") - if version == "" { - version = api.DefaultVersion + if version != "" { + c.version = version + c.manualOverride = true + } + return nil +} + +// WithVersion overrides the client version with the specified one +func WithVersion(version string) func(*Client) error { + return func(c *Client) error { + c.version = version + return nil + } +} + +// WithHost overrides the client host with the specified one +func WithHost(host string) func(*Client) error { + return func(c *Client) error { + hostURL, err := ParseHostURL(host) + if err != nil { + return err + } + c.host = host + c.proto = hostURL.Scheme + c.addr = hostURL.Host + c.basePath = hostURL.Path + client, err := defaultHTTPClient(host) + if err != nil { + return err + } + return WithHTTPClient(client)(c) + } +} + +// WithHTTPClient overrides the client http client with the specified one +func WithHTTPClient(client *http.Client) func(*Client) error { + return func(c *Client) error { + if client != nil { + c.client = client + } + return nil + } +} + +// WithHTTPHeaders overrides the client default http headers +func WithHTTPHeaders(headers map[string]string) func(*Client) error { + return func(c *Client) error { + c.customHTTPHeaders = headers + return nil + } +} + +// NewClientWithOpts initializes a new API client with default values. It takes functors +// to modify values when creating it, like `NewClientWithOpts(WithVersion(…))` +// It also initializes the custom http headers to add to each request. +// +// It won't send any version information if the version number is empty. It is +// highly recommended that you set a version or your client may break if the +// server is upgraded. +func NewClientWithOpts(ops ...func(*Client) error) (*Client, error) { + client, err := defaultHTTPClient(DefaultDockerHost) + if err != nil { + return nil, err + } + c := &Client{ + host: DefaultDockerHost, + version: api.DefaultVersion, + scheme: "http", + client: client, + proto: defaultProto, + addr: defaultAddr, } - cli, err := NewClient(host, version, client, nil) + for _, op := range ops { + if err := op(c); err != nil { + return nil, err + } + } + + if _, ok := c.client.Transport.(http.RoundTripper); !ok { + return nil, fmt.Errorf("unable to verify TLS configuration, invalid transport %v", c.client.Transport) + } + tlsConfig := resolveTLSConfig(c.client.Transport) + if tlsConfig != nil { + // 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. + c.scheme = "https" + } + + return c, nil +} + +func defaultHTTPClient(host string) (*http.Client, error) { + url, err := ParseHostURL(host) if err != nil { - return cli, err + return nil, err } - if os.Getenv("DOCKER_API_VERSION") != "" { - cli.manualOverride = true - } - return cli, nil + transport := new(http.Transport) + sockets.ConfigureTransport(transport, url.Scheme, url.Host) + return &http.Client{ + Transport: transport, + CheckRedirect: CheckRedirect, + }, nil } // NewClient initializes a new API client for the given host and API version. @@ -155,47 +267,9 @@ func NewEnvClient() (*Client, error) { // It won't send any version information if the version number is empty. It is // highly recommended that you set a version or your client may break if the // server is upgraded. +// deprecated: use NewClientWithOpts func NewClient(host string, version string, client *http.Client, httpHeaders map[string]string) (*Client, error) { - hostURL, err := ParseHostURL(host) - if err != nil { - return nil, err - } - - if client != nil { - if _, ok := client.Transport.(http.RoundTripper); !ok { - return nil, fmt.Errorf("unable to verify TLS configuration, invalid transport %v", client.Transport) - } - } else { - transport := new(http.Transport) - sockets.ConfigureTransport(transport, hostURL.Scheme, hostURL.Host) - client = &http.Client{ - Transport: transport, - CheckRedirect: CheckRedirect, - } - } - - scheme := "http" - tlsConfig := resolveTLSConfig(client.Transport) - if tlsConfig != nil { - // 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. - scheme = "https" - } - - // TODO: store URL instead of proto/addr/basePath - return &Client{ - scheme: scheme, - host: host, - proto: hostURL.Scheme, - addr: hostURL.Host, - basePath: hostURL.Path, - client: client, - version: version, - customHTTPHeaders: httpHeaders, - }, nil + return NewClientWithOpts(WithHost(host), WithVersion(version), WithHTTPClient(client), WithHTTPHeaders(httpHeaders)) } // Close the transport used by the client diff --git a/components/engine/client/client_unix.go b/components/engine/client/client_unix.go index c5e887e277..3d24470ba3 100644 --- a/components/engine/client/client_unix.go +++ b/components/engine/client/client_unix.go @@ -4,3 +4,6 @@ package client // import "github.com/docker/docker/client" // DefaultDockerHost defines os specific default if DOCKER_HOST is unset const DefaultDockerHost = "unix:///var/run/docker.sock" + +const defaultProto = "unix" +const defaultAddr = "/var/run/docker.sock" diff --git a/components/engine/client/client_windows.go b/components/engine/client/client_windows.go index 45d8c7c9e6..c649e54412 100644 --- a/components/engine/client/client_windows.go +++ b/components/engine/client/client_windows.go @@ -2,3 +2,6 @@ package client // import "github.com/docker/docker/client" // DefaultDockerHost defines os specific default if DOCKER_HOST is unset const DefaultDockerHost = "npipe:////./pipe/docker_engine" + +const defaultProto = "npipe" +const defaultAddr = "//./pipe/docker_engine" diff --git a/components/engine/integration-cli/daemon/daemon.go b/components/engine/integration-cli/daemon/daemon.go index 149d775fea..69a87d9d9c 100644 --- a/components/engine/integration-cli/daemon/daemon.go +++ b/components/engine/integration-cli/daemon/daemon.go @@ -566,7 +566,7 @@ func (d *Daemon) WaitRun(contID string) error { // Info returns the info struct for this daemon func (d *Daemon) Info(t require.TestingT) types.Info { - apiclient, err := request.NewClientForHost(d.Sock()) + apiclient, err := client.NewClientWithOpts(client.WithHost((d.Sock()))) require.NoError(t, err) info, err := apiclient.Info(context.Background()) require.NoError(t, err) diff --git a/components/engine/integration-cli/docker_api_containers_test.go b/components/engine/integration-cli/docker_api_containers_test.go index 02e8e9f7d2..a91c91abe5 100644 --- a/components/engine/integration-cli/docker_api_containers_test.go +++ b/components/engine/integration-cli/docker_api_containers_test.go @@ -1372,7 +1372,8 @@ func (s *DockerSuite) TestContainerAPICreateNoHostConfig118(c *check.C) { Image: "busybox", } - cli, err := request.NewEnvClientWithVersion("v1.18") + cli, err := client.NewClientWithOpts(client.FromEnv, client.WithVersion("v1.18")) + c.Assert(err, checker.IsNil) _, err = cli.ContainerCreate(context.Background(), &config, &containertypes.HostConfig{}, &networktypes.NetworkingConfig{}, "") c.Assert(err, checker.IsNil) diff --git a/components/engine/integration-cli/docker_api_images_test.go b/components/engine/integration-cli/docker_api_images_test.go index 10cb52eeb0..a5628e41b9 100644 --- a/components/engine/integration-cli/docker_api_images_test.go +++ b/components/engine/integration-cli/docker_api_images_test.go @@ -179,7 +179,7 @@ func (s *DockerSuite) TestAPIImagesSizeCompatibility(c *check.C) { Labels map[string]string } - cli, err = request.NewEnvClientWithVersion("v1.24") + cli, err = client.NewClientWithOpts(client.FromEnv, client.WithVersion("v1.24")) c.Assert(err, checker.IsNil) defer cli.Close() diff --git a/components/engine/integration-cli/docker_api_inspect_unix_test.go b/components/engine/integration-cli/docker_api_inspect_unix_test.go index dae64be2a7..17844e0bfc 100644 --- a/components/engine/integration-cli/docker_api_inspect_unix_test.go +++ b/components/engine/integration-cli/docker_api_inspect_unix_test.go @@ -5,8 +5,8 @@ package main import ( "encoding/json" + "github.com/docker/docker/client" "github.com/docker/docker/integration-cli/checker" - "github.com/docker/docker/integration-cli/request" "github.com/go-check/check" "golang.org/x/net/context" ) @@ -18,7 +18,7 @@ func (s *DockerSuite) TestInspectAPICpusetInConfigPre120(c *check.C) { name := "cpusetinconfig-pre120" dockerCmd(c, "run", "--name", name, "--cpuset-cpus", "0", "busybox", "true") - cli, err := request.NewEnvClientWithVersion("v1.19") + cli, err := client.NewClientWithOpts(client.FromEnv, client.WithVersion("v1.19")) c.Assert(err, checker.IsNil) defer cli.Close() _, body, err := cli.ContainerInspectWithRaw(context.Background(), name, false) diff --git a/components/engine/integration-cli/docker_cli_kill_test.go b/components/engine/integration-cli/docker_cli_kill_test.go index 0a5aac5f8c..e2e510fcaa 100644 --- a/components/engine/integration-cli/docker_cli_kill_test.go +++ b/components/engine/integration-cli/docker_cli_kill_test.go @@ -6,37 +6,9 @@ import ( "github.com/docker/docker/integration-cli/checker" "github.com/docker/docker/integration-cli/cli" - "github.com/docker/docker/integration-cli/request" "github.com/go-check/check" - "github.com/gotestyourself/gotestyourself/icmd" - "golang.org/x/net/context" ) -func (s *DockerSuite) TestKillContainer(c *check.C) { - out := runSleepingContainer(c, "-d") - cleanedContainerID := strings.TrimSpace(out) - cli.WaitRun(c, cleanedContainerID) - - cli.DockerCmd(c, "kill", cleanedContainerID) - cli.WaitExited(c, cleanedContainerID, 10*time.Second) - - out = cli.DockerCmd(c, "ps", "-q").Combined() - c.Assert(out, checker.Not(checker.Contains), cleanedContainerID, check.Commentf("killed container is still running")) - -} - -func (s *DockerSuite) TestKillOffStoppedContainer(c *check.C) { - out := runSleepingContainer(c, "-d") - cleanedContainerID := strings.TrimSpace(out) - - cli.DockerCmd(c, "stop", cleanedContainerID) - cli.WaitExited(c, cleanedContainerID, 10*time.Second) - - cli.Docker(cli.Args("kill", "-s", "30", cleanedContainerID)).Assert(c, icmd.Expected{ - ExitCode: 1, - }) -} - func (s *DockerSuite) TestKillDifferentUserContainer(c *check.C) { // TODO Windows: Windows does not yet support -u (Feb 2016). testRequires(c, DaemonIsLinux) @@ -51,88 +23,3 @@ func (s *DockerSuite) TestKillDifferentUserContainer(c *check.C) { c.Assert(out, checker.Not(checker.Contains), cleanedContainerID, check.Commentf("killed container is still running")) } - -// regression test about correct signal parsing see #13665 -func (s *DockerSuite) TestKillWithSignal(c *check.C) { - // Cannot port to Windows - does not support signals in the same way Linux does - testRequires(c, DaemonIsLinux) - out, _ := dockerCmd(c, "run", "-d", "busybox", "top") - cid := strings.TrimSpace(out) - c.Assert(waitRun(cid), check.IsNil) - - dockerCmd(c, "kill", "-s", "SIGWINCH", cid) - time.Sleep(250 * time.Millisecond) - - running := inspectField(c, cid, "State.Running") - - c.Assert(running, checker.Equals, "true", check.Commentf("Container should be in running state after SIGWINCH")) -} - -func (s *DockerSuite) TestKillWithStopSignalWithSameSignalShouldDisableRestartPolicy(c *check.C) { - // Cannot port to Windows - does not support signals int the same way as Linux does - testRequires(c, DaemonIsLinux) - out := cli.DockerCmd(c, "run", "-d", "--stop-signal=TERM", "--restart=always", "busybox", "top").Combined() - cid := strings.TrimSpace(out) - cli.WaitRun(c, cid) - - // Let docker send a TERM signal to the container - // It will kill the process and disable the restart policy - cli.DockerCmd(c, "kill", "-s", "TERM", cid) - cli.WaitExited(c, cid, 10*time.Second) - - out = cli.DockerCmd(c, "ps", "-q").Combined() - c.Assert(out, checker.Not(checker.Contains), cid, check.Commentf("killed container is still running")) -} - -func (s *DockerSuite) TestKillWithStopSignalWithDifferentSignalShouldKeepRestartPolicy(c *check.C) { - // Cannot port to Windows - does not support signals int the same way as Linux does - testRequires(c, DaemonIsLinux) - out := cli.DockerCmd(c, "run", "-d", "--stop-signal=CONT", "--restart=always", "busybox", "top").Combined() - cid := strings.TrimSpace(out) - cli.WaitRun(c, cid) - - // Let docker send a TERM signal to the container - // It will kill the process, but not disable the restart policy - cli.DockerCmd(c, "kill", "-s", "TERM", cid) - cli.WaitRestart(c, cid, 10*time.Second) - - // Restart policy should still be in place, so it should be still running - cli.WaitRun(c, cid) -} - -// FIXME(vdemeester) should be a unit test -func (s *DockerSuite) TestKillWithInvalidSignal(c *check.C) { - out := runSleepingContainer(c, "-d") - cid := strings.TrimSpace(out) - c.Assert(waitRun(cid), check.IsNil) - - out, _, err := dockerCmdWithError("kill", "-s", "0", cid) - c.Assert(err, check.NotNil) - c.Assert(out, checker.Contains, "Invalid signal: 0", check.Commentf("Kill with an invalid signal didn't error out correctly")) - - running := inspectField(c, cid, "State.Running") - c.Assert(running, checker.Equals, "true", check.Commentf("Container should be in running state after an invalid signal")) - - out = runSleepingContainer(c, "-d") - cid = strings.TrimSpace(out) - c.Assert(waitRun(cid), check.IsNil) - - out, _, err = dockerCmdWithError("kill", "-s", "SIG42", cid) - c.Assert(err, check.NotNil) - c.Assert(out, checker.Contains, "Invalid signal: SIG42", check.Commentf("Kill with an invalid signal error out correctly")) - - running = inspectField(c, cid, "State.Running") - c.Assert(running, checker.Equals, "true", check.Commentf("Container should be in running state after an invalid signal")) - -} - -func (s *DockerSuite) TestKillStoppedContainerAPIPre120(c *check.C) { - testRequires(c, DaemonIsLinux) // Windows only supports 1.25 or later - runSleepingContainer(c, "--name", "docker-kill-test-api", "-d") - dockerCmd(c, "stop", "docker-kill-test-api") - cli, err := request.NewEnvClientWithVersion("v1.19") - c.Assert(err, check.IsNil) - defer cli.Close() - err = cli.ContainerKill(context.Background(), "docker-kill-test-api", "SIGKILL") - c.Assert(err, check.IsNil) -} diff --git a/components/engine/integration-cli/docker_utils_test.go b/components/engine/integration-cli/docker_utils_test.go index 6eda88c684..ea780cc6e8 100644 --- a/components/engine/integration-cli/docker_utils_test.go +++ b/components/engine/integration-cli/docker_utils_test.go @@ -372,7 +372,7 @@ func waitInspectWithArgs(name, expr, expected string, timeout time.Duration, arg } func getInspectBody(c *check.C, version, id string) []byte { - cli, err := request.NewEnvClientWithVersion(version) + cli, err := client.NewClientWithOpts(client.FromEnv, client.WithVersion(version)) c.Assert(err, check.IsNil) defer cli.Close() _, body, err := cli.ContainerInspectWithRaw(context.Background(), id, false) diff --git a/components/engine/integration-cli/request/request.go b/components/engine/integration-cli/request/request.go index a937708665..e4a1e3e892 100644 --- a/components/engine/integration-cli/request/request.go +++ b/components/engine/integration-cli/request/request.go @@ -17,7 +17,6 @@ import ( "strings" "time" - "github.com/docker/docker/api" dclient "github.com/docker/docker/client" "github.com/docker/docker/opts" "github.com/docker/docker/pkg/ioutils" @@ -169,16 +168,7 @@ func NewHTTPClient(host string) (*http.Client, error) { // NewClient returns a new Docker API client func NewClient() (dclient.APIClient, error) { - return NewClientForHost(DaemonHost()) -} - -// NewClientForHost returns a Docker API client for the host -func NewClientForHost(host string) (dclient.APIClient, error) { - httpClient, err := NewHTTPClient(host) - if err != nil { - return nil, err - } - return dclient.NewClient(host, api.DefaultVersion, httpClient, nil) + return dclient.NewClientWithOpts(dclient.WithHost(DaemonHost())) } // FIXME(vdemeester) httputil.ClientConn is deprecated, use http.Client instead (closer to actual client) @@ -323,35 +313,3 @@ func DaemonHost() string { } return daemonURLStr } - -// NewEnvClientWithVersion returns a docker client with a specified version. -// See: github.com/docker/docker/client `NewEnvClient()` -func NewEnvClientWithVersion(version string) (*dclient.Client, error) { - if version == "" { - return nil, errors.New("version not specified") - } - - var httpClient *http.Client - if os.Getenv("DOCKER_CERT_PATH") != "" { - tlsConfig, err := getTLSConfig() - if err != nil { - return nil, err - } - httpClient = &http.Client{ - Transport: &http.Transport{ - TLSClientConfig: tlsConfig, - }, - } - } - - host := os.Getenv("DOCKER_HOST") - if host == "" { - host = dclient.DefaultDockerHost - } - - cli, err := dclient.NewClient(host, version, httpClient, nil) - if err != nil { - return cli, err - } - return cli, nil -} diff --git a/components/engine/integration/container/kill_test.go b/components/engine/integration/container/kill_test.go new file mode 100644 index 0000000000..57343942da --- /dev/null +++ b/components/engine/integration/container/kill_test.go @@ -0,0 +1,177 @@ +package container + +import ( + "context" + "testing" + "time" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" + "github.com/docker/docker/api/types/network" + "github.com/docker/docker/api/types/strslice" + "github.com/docker/docker/client" + "github.com/docker/docker/integration/util/request" + "github.com/gotestyourself/gotestyourself/poll" + "github.com/gotestyourself/gotestyourself/skip" + "github.com/stretchr/testify/require" +) + +func TestKillContainerInvalidSignal(t *testing.T) { + defer setupTest(t)() + client := request.NewAPIClient(t) + ctx := context.Background() + c, err := client.ContainerCreate(ctx, + &container.Config{ + Image: "busybox", + Cmd: strslice.StrSlice([]string{"top"}), + }, + &container.HostConfig{}, + &network.NetworkingConfig{}, + "") + require.NoError(t, err) + err = client.ContainerStart(ctx, c.ID, types.ContainerStartOptions{}) + require.NoError(t, err) + + err = client.ContainerKill(ctx, c.ID, "0") + require.EqualError(t, err, "Error response from daemon: Invalid signal: 0") + poll.WaitOn(t, containerIsInState(ctx, client, c.ID, "running"), poll.WithDelay(100*time.Millisecond)) + + err = client.ContainerKill(ctx, c.ID, "SIG42") + require.EqualError(t, err, "Error response from daemon: Invalid signal: SIG42") + poll.WaitOn(t, containerIsInState(ctx, client, c.ID, "running"), poll.WithDelay(100*time.Millisecond)) +} + +func TestKillContainer(t *testing.T) { + defer setupTest(t)() + client := request.NewAPIClient(t) + + testCases := []struct { + doc string + signal string + status string + }{ + { + doc: "no signal", + signal: "", + status: "exited", + }, + { + doc: "non killing signal", + signal: "SIGWINCH", + status: "running", + }, + { + doc: "killing signal", + signal: "SIGTERM", + status: "exited", + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.doc, func(t *testing.T) { + ctx := context.Background() + c, err := client.ContainerCreate(ctx, + &container.Config{ + Image: "busybox", + Cmd: strslice.StrSlice([]string{"top"}), + }, + &container.HostConfig{}, + &network.NetworkingConfig{}, + "") + require.NoError(t, err) + err = client.ContainerStart(ctx, c.ID, types.ContainerStartOptions{}) + require.NoError(t, err) + err = client.ContainerKill(ctx, c.ID, tc.signal) + require.NoError(t, err) + + poll.WaitOn(t, containerIsInState(ctx, client, c.ID, tc.status), poll.WithDelay(100*time.Millisecond)) + }) + } +} + +func TestKillWithStopSignalAndRestartPolicies(t *testing.T) { + skip.If(t, testEnv.OSType != "linux", "Windows only supports 1.25 or later") + defer setupTest(t)() + client := request.NewAPIClient(t) + + testCases := []struct { + doc string + stopsignal string + status string + }{ + { + doc: "same-signal-disables-restart-policy", + stopsignal: "TERM", + status: "exited", + }, + { + doc: "different-signal-keep-restart-policy", + stopsignal: "CONT", + status: "running", + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.doc, func(t *testing.T) { + ctx := context.Background() + c, err := client.ContainerCreate(ctx, + &container.Config{ + Image: "busybox", + Cmd: strslice.StrSlice([]string{"top"}), + StopSignal: tc.stopsignal, + }, + &container.HostConfig{ + RestartPolicy: container.RestartPolicy{ + Name: "always", + }}, + &network.NetworkingConfig{}, + "") + require.NoError(t, err) + err = client.ContainerStart(ctx, c.ID, types.ContainerStartOptions{}) + require.NoError(t, err) + err = client.ContainerKill(ctx, c.ID, "TERM") + require.NoError(t, err) + + poll.WaitOn(t, containerIsInState(ctx, client, c.ID, tc.status), poll.WithDelay(100*time.Millisecond)) + }) + } +} + +func TestKillStoppedContainer(t *testing.T) { + skip.If(t, testEnv.OSType != "linux") // Windows only supports 1.25 or later + defer setupTest(t)() + ctx := context.Background() + client := request.NewAPIClient(t) + c, err := client.ContainerCreate(ctx, + &container.Config{ + Image: "busybox", + Cmd: strslice.StrSlice([]string{"top"}), + }, + &container.HostConfig{}, + &network.NetworkingConfig{}, + "") + require.NoError(t, err) + err = client.ContainerKill(ctx, c.ID, "SIGKILL") + require.Error(t, err) + require.Contains(t, err.Error(), "is not running") +} + +func TestKillStoppedContainerAPIPre120(t *testing.T) { + skip.If(t, testEnv.OSType != "linux") // Windows only supports 1.25 or later + defer setupTest(t)() + ctx := context.Background() + client := request.NewAPIClient(t, client.WithVersion("1.19")) + c, err := client.ContainerCreate(ctx, + &container.Config{ + Image: "busybox", + Cmd: strslice.StrSlice([]string{"top"}), + }, + &container.HostConfig{}, + &network.NetworkingConfig{}, + "") + require.NoError(t, err) + err = client.ContainerKill(ctx, c.ID, "SIGKILL") + require.NoError(t, err) +} diff --git a/components/engine/integration/network/inspect_test.go b/components/engine/integration/network/inspect_test.go index 36b65d1d11..94218af084 100644 --- a/components/engine/integration/network/inspect_test.go +++ b/components/engine/integration/network/inspect_test.go @@ -11,7 +11,6 @@ import ( "github.com/docker/docker/api/types/swarm" "github.com/docker/docker/client" "github.com/docker/docker/integration-cli/daemon" - "github.com/docker/docker/integration-cli/request" "github.com/gotestyourself/gotestyourself/poll" "github.com/stretchr/testify/require" "golang.org/x/net/context" @@ -24,7 +23,7 @@ func TestInspectNetwork(t *testing.T) { defer setupTest(t)() d := newSwarm(t) defer d.Stop(t) - client, err := request.NewClientForHost(d.Sock()) + client, err := client.NewClientWithOpts(client.WithHost((d.Sock()))) require.NoError(t, err) overlayName := "overlay1" diff --git a/components/engine/integration/secret/secret_test.go b/components/engine/integration/secret/secret_test.go index 7637304ad8..922fd33028 100644 --- a/components/engine/integration/secret/secret_test.go +++ b/components/engine/integration/secret/secret_test.go @@ -4,7 +4,7 @@ import ( "testing" swarmtypes "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/integration-cli/request" + "github.com/docker/docker/client" "github.com/docker/docker/integration/util/swarm" "github.com/gotestyourself/gotestyourself/skip" "github.com/stretchr/testify/assert" @@ -18,7 +18,7 @@ func TestSecretInspect(t *testing.T) { defer setupTest(t)() d := swarm.NewSwarm(t, testEnv) defer d.Stop(t) - client, err := request.NewClientForHost(d.Sock()) + client, err := client.NewClientWithOpts(client.WithHost((d.Sock()))) require.NoError(t, err) ctx := context.Background() diff --git a/components/engine/integration/service/create_test.go b/components/engine/integration/service/create_test.go index 19b9eee949..c74c8fb52e 100644 --- a/components/engine/integration/service/create_test.go +++ b/components/engine/integration/service/create_test.go @@ -10,7 +10,6 @@ import ( "github.com/docker/docker/api/types/filters" swarmtypes "github.com/docker/docker/api/types/swarm" "github.com/docker/docker/client" - "github.com/docker/docker/integration-cli/request" "github.com/docker/docker/integration/util/swarm" "github.com/gotestyourself/gotestyourself/poll" "github.com/stretchr/testify/assert" @@ -22,7 +21,7 @@ func TestCreateServiceMultipleTimes(t *testing.T) { defer setupTest(t)() d := swarm.NewSwarm(t, testEnv) defer d.Stop(t) - client, err := request.NewClientForHost(d.Sock()) + client, err := client.NewClientWithOpts(client.WithHost((d.Sock()))) require.NoError(t, err) overlayName := "overlay1" @@ -88,7 +87,7 @@ func TestCreateWithDuplicateNetworkNames(t *testing.T) { defer setupTest(t)() d := swarm.NewSwarm(t, testEnv) defer d.Stop(t) - client, err := request.NewClientForHost(d.Sock()) + client, err := client.NewClientWithOpts(client.WithHost((d.Sock()))) require.NoError(t, err) name := "foo" @@ -150,7 +149,7 @@ func TestCreateServiceSecretFileMode(t *testing.T) { defer setupTest(t)() d := swarm.NewSwarm(t, testEnv) defer d.Stop(t) - client, err := request.NewClientForHost(d.Sock()) + client, err := client.NewClientWithOpts(client.WithHost((d.Sock()))) require.NoError(t, err) ctx := context.Background() @@ -231,7 +230,7 @@ func TestCreateServiceConfigFileMode(t *testing.T) { defer setupTest(t)() d := swarm.NewSwarm(t, testEnv) defer d.Stop(t) - client, err := request.NewClientForHost(d.Sock()) + client, err := client.NewClientWithOpts(client.WithHost((d.Sock()))) require.NoError(t, err) ctx := context.Background() diff --git a/components/engine/integration/service/inspect_test.go b/components/engine/integration/service/inspect_test.go index 2ca0ec6b06..8fe97d98ad 100644 --- a/components/engine/integration/service/inspect_test.go +++ b/components/engine/integration/service/inspect_test.go @@ -9,7 +9,6 @@ import ( "github.com/docker/docker/api/types/filters" swarmtypes "github.com/docker/docker/api/types/swarm" "github.com/docker/docker/client" - "github.com/docker/docker/integration-cli/request" "github.com/docker/docker/integration/util/swarm" "github.com/gotestyourself/gotestyourself/poll" "github.com/gotestyourself/gotestyourself/skip" @@ -23,7 +22,7 @@ func TestInspect(t *testing.T) { defer setupTest(t)() d := swarm.NewSwarm(t, testEnv) defer d.Stop(t) - client, err := request.NewClientForHost(d.Sock()) + client, err := client.NewClientWithOpts(client.WithHost((d.Sock()))) require.NoError(t, err) var before = time.Now() diff --git a/components/engine/integration/service/network_test.go b/components/engine/integration/service/network_test.go index 089c7ae19c..1a9297c6b3 100644 --- a/components/engine/integration/service/network_test.go +++ b/components/engine/integration/service/network_test.go @@ -7,7 +7,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/network" - "github.com/docker/docker/integration-cli/request" + "github.com/docker/docker/client" "github.com/docker/docker/integration/util/swarm" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -17,7 +17,7 @@ func TestDockerNetworkConnectAlias(t *testing.T) { defer setupTest(t)() d := swarm.NewSwarm(t, testEnv) defer d.Stop(t) - client, err := request.NewClientForHost(d.Sock()) + client, err := client.NewClientWithOpts(client.WithHost((d.Sock()))) require.NoError(t, err) ctx := context.Background() diff --git a/components/engine/integration/util/request/client.go b/components/engine/integration/util/request/client.go index b4a15a8c99..5c1ec08607 100644 --- a/components/engine/integration/util/request/client.go +++ b/components/engine/integration/util/request/client.go @@ -6,7 +6,6 @@ import ( "testing" "time" - "github.com/docker/docker/api" "github.com/docker/docker/client" "github.com/docker/go-connections/sockets" "github.com/docker/go-connections/tlsconfig" @@ -14,8 +13,9 @@ import ( ) // NewAPIClient returns a docker API client configured from environment variables -func NewAPIClient(t *testing.T) client.APIClient { - clt, err := client.NewEnvClient() +func NewAPIClient(t *testing.T, ops ...func(*client.Client) error) client.APIClient { + ops = append([]func(*client.Client) error{client.FromEnv}, ops...) + clt, err := client.NewClientWithOpts(ops...) require.NoError(t, err) return clt } @@ -47,7 +47,5 @@ func NewTLSAPIClient(t *testing.T, host, cacertPath, certPath, keyPath string) ( Transport: tr, CheckRedirect: client.CheckRedirect, } - verStr := api.DefaultVersion - customHeaders := map[string]string{} - return client.NewClient(host, verStr, httpClient, customHeaders) + return client.NewClientWithOpts(client.WithHost(host), client.WithHTTPClient(httpClient)) } diff --git a/components/engine/internal/test/environment/environment.go b/components/engine/internal/test/environment/environment.go index 5ff4139e5d..bde4c0a1bc 100644 --- a/components/engine/internal/test/environment/environment.go +++ b/components/engine/internal/test/environment/environment.go @@ -32,7 +32,7 @@ type PlatformDefaults struct { // New creates a new Execution struct func New() (*Execution, error) { - client, err := client.NewEnvClient() + client, err := client.NewClientWithOpts(client.FromEnv) if err != nil { return nil, errors.Wrapf(err, "failed to create client") }