From cd76e3e7f8d07f8a2d102948500fd17e9a45208b Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Sat, 8 Jun 2024 18:56:54 +0200 Subject: [PATCH] api/types: move ExecConfig to api/types/container Signed-off-by: Sebastiaan van Stijn --- api/server/router/container/backend.go | 2 +- api/server/router/container/exec.go | 2 +- api/types/{configs.go => container/exec.go} | 6 ++--- api/types/types_deprecated.go | 7 +++++ client/container_exec.go | 9 ++++--- client/container_exec_test.go | 9 ++++--- client/interface.go | 2 +- daemon/exec.go | 29 ++++++++++----------- integration-cli/docker_api_exec_test.go | 17 +++++------- integration/config/config_test.go | 5 ++-- integration/container/exec_linux_test.go | 4 +-- integration/container/exec_test.go | 5 ++-- integration/internal/container/exec.go | 11 ++++---- integration/internal/swarm/service.go | 5 ++-- integration/secret/secret_test.go | 5 ++-- integration/system/event_test.go | 9 +++---- 16 files changed, 68 insertions(+), 59 deletions(-) rename api/types/{configs.go => container/exec.go} (81%) diff --git a/api/server/router/container/backend.go b/api/server/router/container/backend.go index cc7e8f6767..64dc754083 100644 --- a/api/server/router/container/backend.go +++ b/api/server/router/container/backend.go @@ -14,7 +14,7 @@ import ( // execBackend includes functions to implement to provide exec functionality. type execBackend interface { - ContainerExecCreate(name string, config *types.ExecConfig) (string, error) + ContainerExecCreate(name string, options *container.ExecOptions) (string, error) ContainerExecInspect(id string) (*backend.ExecInspect, error) ContainerExecResize(name string, height, width int) error ContainerExecStart(ctx context.Context, name string, options container.ExecStartOptions) error diff --git a/api/server/router/container/exec.go b/api/server/router/container/exec.go index e13170f009..a815814d10 100644 --- a/api/server/router/container/exec.go +++ b/api/server/router/container/exec.go @@ -38,7 +38,7 @@ func (s *containerRouter) postContainerExecCreate(ctx context.Context, w http.Re return err } - execConfig := &types.ExecConfig{} + execConfig := &container.ExecOptions{} if err := httputils.ReadJSON(r, execConfig); err != nil { return err } diff --git a/api/types/configs.go b/api/types/container/exec.go similarity index 81% rename from api/types/configs.go rename to api/types/container/exec.go index 945b6efadd..c36e3c5cde 100644 --- a/api/types/configs.go +++ b/api/types/container/exec.go @@ -1,8 +1,8 @@ -package types // import "github.com/docker/docker/api/types" +package container -// ExecConfig is a small subset of the Config struct that holds the configuration +// ExecOptions is a small subset of the Config struct that holds the configuration // for the exec feature of docker. -type ExecConfig struct { +type ExecOptions struct { User string // User that will run the command Privileged bool // Is the container in privileged mode Tty bool // Attach standard streams to a tty. diff --git a/api/types/types_deprecated.go b/api/types/types_deprecated.go index c0e146ca7d..da1c193043 100644 --- a/api/types/types_deprecated.go +++ b/api/types/types_deprecated.go @@ -1,6 +1,7 @@ package types import ( + "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/network" ) @@ -54,3 +55,9 @@ type NetworkResource = network.Inspect // // Deprecated: use [network.PruneReport]. type NetworksPruneReport = network.PruneReport + +// ExecConfig is a small subset of the Config struct that holds the configuration +// for the exec feature of docker. +// +// Deprecated: use [container.ExecOptions]. +type ExecConfig = container.ExecOptions diff --git a/client/container_exec.go b/client/container_exec.go index 526a3876a4..d153458077 100644 --- a/client/container_exec.go +++ b/client/container_exec.go @@ -6,11 +6,12 @@ import ( "net/http" "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/versions" ) // ContainerExecCreate creates a new exec configuration to run an exec process. -func (cli *Client) ContainerExecCreate(ctx context.Context, container string, config types.ExecConfig) (types.IDResponse, error) { +func (cli *Client) ContainerExecCreate(ctx context.Context, container string, options container.ExecOptions) (types.IDResponse, error) { var response types.IDResponse // Make sure we negotiated (if the client is configured to do so), @@ -22,14 +23,14 @@ func (cli *Client) ContainerExecCreate(ctx context.Context, container string, co return response, err } - if err := cli.NewVersionError(ctx, "1.25", "env"); len(config.Env) != 0 && err != nil { + if err := cli.NewVersionError(ctx, "1.25", "env"); len(options.Env) != 0 && err != nil { return response, err } if versions.LessThan(cli.ClientVersion(), "1.42") { - config.ConsoleSize = nil + options.ConsoleSize = nil } - resp, err := cli.post(ctx, "/containers/"+container+"/exec", nil, config, nil) + resp, err := cli.post(ctx, "/containers/"+container+"/exec", nil, options, nil) defer ensureReaderClosed(resp) if err != nil { return response, err diff --git a/client/container_exec_test.go b/client/container_exec_test.go index cceba81eac..26a1924f29 100644 --- a/client/container_exec_test.go +++ b/client/container_exec_test.go @@ -11,6 +11,7 @@ import ( "testing" "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" "github.com/docker/docker/errdefs" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" @@ -20,7 +21,7 @@ func TestContainerExecCreateError(t *testing.T) { client := &Client{ client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } - _, err := client.ContainerExecCreate(context.Background(), "container_id", types.ExecConfig{}) + _, err := client.ContainerExecCreate(context.Background(), "container_id", container.ExecOptions{}) assert.Check(t, is.ErrorType(err, errdefs.IsSystem)) } @@ -32,7 +33,7 @@ func TestContainerExecCreateConnectionError(t *testing.T) { client, err := NewClientWithOpts(WithAPIVersionNegotiation(), WithHost("tcp://no-such-host.invalid")) assert.NilError(t, err) - _, err = client.ContainerExecCreate(context.Background(), "", types.ExecConfig{}) + _, err = client.ContainerExecCreate(context.Background(), "", container.ExecOptions{}) assert.Check(t, is.ErrorType(err, IsErrConnectionFailed)) } @@ -50,7 +51,7 @@ func TestContainerExecCreate(t *testing.T) { if err := req.ParseForm(); err != nil { return nil, err } - execConfig := &types.ExecConfig{} + execConfig := &container.ExecOptions{} if err := json.NewDecoder(req.Body).Decode(execConfig); err != nil { return nil, err } @@ -70,7 +71,7 @@ func TestContainerExecCreate(t *testing.T) { }), } - r, err := client.ContainerExecCreate(context.Background(), "container_id", types.ExecConfig{ + r, err := client.ContainerExecCreate(context.Background(), "container_id", container.ExecOptions{ User: "user", }) if err != nil { diff --git a/client/interface.go b/client/interface.go index 29fd76ab81..7cef020330 100644 --- a/client/interface.go +++ b/client/interface.go @@ -51,7 +51,7 @@ type ContainerAPIClient interface { ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, platform *ocispec.Platform, containerName string) (container.CreateResponse, error) ContainerDiff(ctx context.Context, container string) ([]container.FilesystemChange, error) ContainerExecAttach(ctx context.Context, execID string, config types.ExecStartCheck) (types.HijackedResponse, error) - ContainerExecCreate(ctx context.Context, container string, config types.ExecConfig) (types.IDResponse, error) + ContainerExecCreate(ctx context.Context, container string, options container.ExecOptions) (types.IDResponse, error) ContainerExecInspect(ctx context.Context, execID string) (types.ContainerExecInspect, error) ContainerExecResize(ctx context.Context, execID string, options container.ResizeOptions) error ContainerExecStart(ctx context.Context, execID string, config types.ExecStartCheck) error diff --git a/daemon/exec.go b/daemon/exec.go index 2ab0b6b409..4725105609 100644 --- a/daemon/exec.go +++ b/daemon/exec.go @@ -11,7 +11,6 @@ import ( "github.com/containerd/containerd" "github.com/containerd/log" - "github.com/docker/docker/api/types" containertypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/events" "github.com/docker/docker/api/types/strslice" @@ -94,42 +93,42 @@ func (daemon *Daemon) getActiveContainer(name string) (*container.Container, err } // ContainerExecCreate sets up an exec in a running container. -func (daemon *Daemon) ContainerExecCreate(name string, config *types.ExecConfig) (string, error) { +func (daemon *Daemon) ContainerExecCreate(name string, options *containertypes.ExecOptions) (string, error) { cntr, err := daemon.getActiveContainer(name) if err != nil { return "", err } - cmd := strslice.StrSlice(config.Cmd) + cmd := strslice.StrSlice(options.Cmd) entrypoint, args := daemon.getEntrypointAndArgs(strslice.StrSlice{}, cmd) keys := []byte{} - if config.DetachKeys != "" { - keys, err = term.ToBytes(config.DetachKeys) + if options.DetachKeys != "" { + keys, err = term.ToBytes(options.DetachKeys) if err != nil { - err = fmt.Errorf("Invalid escape keys (%s) provided", config.DetachKeys) + err = fmt.Errorf("Invalid escape keys (%s) provided", options.DetachKeys) return "", err } } execConfig := container.NewExecConfig(cntr) - execConfig.OpenStdin = config.AttachStdin - execConfig.OpenStdout = config.AttachStdout - execConfig.OpenStderr = config.AttachStderr + execConfig.OpenStdin = options.AttachStdin + execConfig.OpenStdout = options.AttachStdout + execConfig.OpenStderr = options.AttachStderr execConfig.DetachKeys = keys execConfig.Entrypoint = entrypoint execConfig.Args = args - execConfig.Tty = config.Tty - execConfig.ConsoleSize = config.ConsoleSize - execConfig.Privileged = config.Privileged - execConfig.User = config.User - execConfig.WorkingDir = config.WorkingDir + execConfig.Tty = options.Tty + execConfig.ConsoleSize = options.ConsoleSize + execConfig.Privileged = options.Privileged + execConfig.User = options.User + execConfig.WorkingDir = options.WorkingDir linkedEnv, err := daemon.setupLinkedContainers(cntr) if err != nil { return "", err } - execConfig.Env = container.ReplaceOrAppendEnvValues(cntr.CreateDaemonEnvironment(config.Tty, linkedEnv), config.Env) + execConfig.Env = container.ReplaceOrAppendEnvValues(cntr.CreateDaemonEnvironment(options.Tty, linkedEnv), options.Env) if len(execConfig.User) == 0 { execConfig.User = cntr.Config.User } diff --git a/integration-cli/docker_api_exec_test.go b/integration-cli/docker_api_exec_test.go index 612ef292b1..64fada3de9 100644 --- a/integration-cli/docker_api_exec_test.go +++ b/integration-cli/docker_api_exec_test.go @@ -12,7 +12,7 @@ import ( "testing" "time" - "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" "github.com/docker/docker/client" "github.com/docker/docker/integration-cli/checker" "github.com/docker/docker/integration-cli/cli" @@ -65,10 +65,9 @@ func (s *DockerAPISuite) TestExecAPICreateContainerPaused(c *testing.T) { assert.NilError(c, err) defer apiClient.Close() - config := types.ExecConfig{ + _, err = apiClient.ContainerExecCreate(testutil.GetContext(c), name, container.ExecOptions{ Cmd: []string{"true"}, - } - _, err = apiClient.ContainerExecCreate(testutil.GetContext(c), name, config) + }) assert.ErrorContains(c, err, "Container "+name+" is paused, unpause the container before exec", "Expected message when creating exec command with Container %s is paused", name) } @@ -126,16 +125,14 @@ func (s *DockerAPISuite) TestExecAPIStartWithDetach(c *testing.T) { ctx := testutil.GetContext(c) - config := types.ExecConfig{ - Cmd: []string{"true"}, - AttachStderr: true, - } - apiClient, err := client.NewClientWithOpts(client.FromEnv) assert.NilError(c, err) defer apiClient.Close() - createResp, err := apiClient.ContainerExecCreate(ctx, name, config) + createResp, err := apiClient.ContainerExecCreate(ctx, name, container.ExecOptions{ + Cmd: []string{"true"}, + AttachStderr: true, + }) assert.NilError(c, err) _, body, err := request.Post(ctx, fmt.Sprintf("/exec/%s/start", createResp.ID), request.RawString(`{"Detach": true}`), request.JSON) diff --git a/integration/config/config_test.go b/integration/config/config_test.go index 6d83698e9e..261423295e 100644 --- a/integration/config/config_test.go +++ b/integration/config/config_test.go @@ -9,6 +9,7 @@ import ( "time" "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/filters" swarmtypes "github.com/docker/docker/api/types/swarm" "github.com/docker/docker/client" @@ -313,7 +314,7 @@ func TestTemplatedConfig(t *testing.T) { tasks := swarm.GetRunningTasks(ctx, t, c, serviceID) assert.Assert(t, len(tasks) > 0, "no running tasks found for service %s", serviceID) - attach := swarm.ExecTask(ctx, t, d, tasks[0], types.ExecConfig{ + attach := swarm.ExecTask(ctx, t, d, tasks[0], container.ExecOptions{ Cmd: []string{"/bin/cat", "/templated_config"}, AttachStdout: true, AttachStderr: true, @@ -324,7 +325,7 @@ func TestTemplatedConfig(t *testing.T) { "this is a config\n" assertAttachedStream(t, attach, expect) - attach = swarm.ExecTask(ctx, t, d, tasks[0], types.ExecConfig{ + attach = swarm.ExecTask(ctx, t, d, tasks[0], container.ExecOptions{ Cmd: []string{"mount"}, AttachStdout: true, AttachStderr: true, diff --git a/integration/container/exec_linux_test.go b/integration/container/exec_linux_test.go index 06f5856f18..a91d065b25 100644 --- a/integration/container/exec_linux_test.go +++ b/integration/container/exec_linux_test.go @@ -4,7 +4,7 @@ import ( "strings" "testing" - "github.com/docker/docker/api/types" + containertypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/versions" "github.com/docker/docker/integration/internal/container" "gotest.tools/v3/assert" @@ -21,7 +21,7 @@ func TestExecConsoleSize(t *testing.T) { cID := container.Run(ctx, t, apiClient, container.WithImage("busybox")) result, err := container.Exec(ctx, apiClient, cID, []string{"stty", "size"}, - func(ec *types.ExecConfig) { + func(ec *containertypes.ExecOptions) { ec.Tty = true ec.ConsoleSize = &[2]uint{57, 123} }, diff --git a/integration/container/exec_test.go b/integration/container/exec_test.go index 33c23bc92c..b8dfadac7b 100644 --- a/integration/container/exec_test.go +++ b/integration/container/exec_test.go @@ -7,6 +7,7 @@ import ( "time" "github.com/docker/docker/api/types" + containertypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/integration/internal/container" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" @@ -24,7 +25,7 @@ func TestExecWithCloseStdin(t *testing.T) { cID := container.Run(ctx, t, apiClient) const expected = "closeIO" - execResp, err := apiClient.ContainerExecCreate(ctx, cID, types.ExecConfig{ + execResp, err := apiClient.ContainerExecCreate(ctx, cID, containertypes.ExecOptions{ AttachStdin: true, AttachStdout: true, Cmd: []string{"sh", "-c", "cat && echo " + expected}, @@ -79,7 +80,7 @@ func TestExec(t *testing.T) { cID := container.Run(ctx, t, apiClient, container.WithTty(true), container.WithWorkingDir("/root")) - id, err := apiClient.ContainerExecCreate(ctx, cID, types.ExecConfig{ + id, err := apiClient.ContainerExecCreate(ctx, cID, containertypes.ExecOptions{ WorkingDir: "/tmp", Env: []string{"FOO=BAR"}, AttachStdout: true, diff --git a/integration/internal/container/exec.go b/integration/internal/container/exec.go index 74b5109072..1f69d90ab8 100644 --- a/integration/internal/container/exec.go +++ b/integration/internal/container/exec.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" "github.com/docker/docker/client" ) @@ -47,19 +48,19 @@ func (res ExecResult) AssertSuccess(t testing.TB) { // containing stdout, stderr, and exit code. Note: // - this is a synchronous operation; // - cmd stdin is closed. -func Exec(ctx context.Context, apiClient client.APIClient, id string, cmd []string, ops ...func(*types.ExecConfig)) (ExecResult, error) { +func Exec(ctx context.Context, apiClient client.APIClient, id string, cmd []string, ops ...func(*container.ExecOptions)) (ExecResult, error) { // prepare exec - execConfig := types.ExecConfig{ + execOptions := container.ExecOptions{ AttachStdout: true, AttachStderr: true, Cmd: cmd, } for _, op := range ops { - op(&execConfig) + op(&execOptions) } - cresp, err := apiClient.ContainerExecCreate(ctx, id, execConfig) + cresp, err := apiClient.ContainerExecCreate(ctx, id, execOptions) if err != nil { return ExecResult{}, err } @@ -87,7 +88,7 @@ func Exec(ctx context.Context, apiClient client.APIClient, id string, cmd []stri } // ExecT calls Exec() and aborts the test if an error occurs. -func ExecT(ctx context.Context, t testing.TB, apiClient client.APIClient, id string, cmd []string, ops ...func(*types.ExecConfig)) ExecResult { +func ExecT(ctx context.Context, t testing.TB, apiClient client.APIClient, id string, cmd []string, ops ...func(*container.ExecOptions)) ExecResult { t.Helper() res, err := Exec(ctx, apiClient, id, cmd, ops...) if err != nil { diff --git a/integration/internal/swarm/service.go b/integration/internal/swarm/service.go index 5abe4c39e0..01d388725e 100644 --- a/integration/internal/swarm/service.go +++ b/integration/internal/swarm/service.go @@ -7,6 +7,7 @@ import ( "time" "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/filters" swarmtypes "github.com/docker/docker/api/types/swarm" "github.com/docker/docker/client" @@ -211,12 +212,12 @@ func GetRunningTasks(ctx context.Context, t *testing.T, c client.ServiceAPIClien } // ExecTask runs the passed in exec config on the given task -func ExecTask(ctx context.Context, t *testing.T, d *daemon.Daemon, task swarmtypes.Task, config types.ExecConfig) types.HijackedResponse { +func ExecTask(ctx context.Context, t *testing.T, d *daemon.Daemon, task swarmtypes.Task, options container.ExecOptions) types.HijackedResponse { t.Helper() apiClient := d.NewClientT(t) defer apiClient.Close() - resp, err := apiClient.ContainerExecCreate(ctx, task.Status.ContainerStatus.ContainerID, config) + resp, err := apiClient.ContainerExecCreate(ctx, task.Status.ContainerStatus.ContainerID, options) assert.NilError(t, err, "error creating exec") attach, err := apiClient.ContainerExecAttach(ctx, resp.ID, types.ExecStartCheck{}) diff --git a/integration/secret/secret_test.go b/integration/secret/secret_test.go index ffb0718196..aaec4368ae 100644 --- a/integration/secret/secret_test.go +++ b/integration/secret/secret_test.go @@ -9,6 +9,7 @@ import ( "time" "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/filters" swarmtypes "github.com/docker/docker/api/types/swarm" "github.com/docker/docker/client" @@ -313,7 +314,7 @@ func TestTemplatedSecret(t *testing.T) { tasks := swarm.GetRunningTasks(ctx, t, c, serviceID) assert.Assert(t, len(tasks) > 0, "no running tasks found for service %s", serviceID) - attach := swarm.ExecTask(ctx, t, d, tasks[0], types.ExecConfig{ + attach := swarm.ExecTask(ctx, t, d, tasks[0], container.ExecOptions{ Cmd: []string{"/bin/cat", "/run/secrets/templated_secret"}, AttachStdout: true, AttachStderr: true, @@ -324,7 +325,7 @@ func TestTemplatedSecret(t *testing.T) { "this is a config\n" assertAttachedStream(t, attach, expect) - attach = swarm.ExecTask(ctx, t, d, tasks[0], types.ExecConfig{ + attach = swarm.ExecTask(ctx, t, d, tasks[0], container.ExecOptions{ Cmd: []string{"mount"}, AttachStdout: true, AttachStderr: true, diff --git a/integration/system/event_test.go b/integration/system/event_test.go index e4566c1d0d..9137dc6d16 100644 --- a/integration/system/event_test.go +++ b/integration/system/event_test.go @@ -12,6 +12,7 @@ import ( "time" "github.com/docker/docker/api/types" + containertypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/events" "github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/mount" @@ -32,11 +33,9 @@ func TestEventsExecDie(t *testing.T) { cID := container.Run(ctx, t, client) - id, err := client.ContainerExecCreate(ctx, cID, - types.ExecConfig{ - Cmd: []string{"echo", "hello"}, - }, - ) + id, err := client.ContainerExecCreate(ctx, cID, containertypes.ExecOptions{ + Cmd: []string{"echo", "hello"}, + }) assert.NilError(t, err) msg, errs := client.Events(ctx, types.EventsOptions{