Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
| ... | ... |
@@ -12,7 +12,6 @@ import ( |
| 12 | 12 |
"github.com/moby/moby/api/types/registry" |
| 13 | 13 |
"github.com/moby/moby/api/types/swarm" |
| 14 | 14 |
"github.com/moby/moby/api/types/system" |
| 15 |
- ocispec "github.com/opencontainers/image-spec/specs-go/v1" |
|
| 16 | 15 |
) |
| 17 | 16 |
|
| 18 | 17 |
// APIClient is an interface that clients that talk with a docker server must implement. |
| ... | ... |
@@ -58,10 +57,10 @@ type HijackDialer interface {
|
| 58 | 58 |
|
| 59 | 59 |
// ContainerAPIClient defines API client methods for the containers |
| 60 | 60 |
type ContainerAPIClient interface {
|
| 61 |
- ContainerAttach(ctx context.Context, container string, options ContainerAttachOptions) (HijackedResponse, error) |
|
| 62 |
- ContainerCommit(ctx context.Context, container string, options ContainerCommitOptions) (container.CommitResponse, error) |
|
| 63 |
- ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, platform *ocispec.Platform, containerName string) (container.CreateResponse, error) |
|
| 64 |
- ContainerDiff(ctx context.Context, container string) ([]container.FilesystemChange, error) |
|
| 61 |
+ ContainerAttach(ctx context.Context, container string, options ContainerAttachOptions) (ContainerAttachResult, error) |
|
| 62 |
+ ContainerCommit(ctx context.Context, container string, options ContainerCommitOptions) (ContainerCommitResult, error) |
|
| 63 |
+ ContainerCreate(ctx context.Context, options ContainerCreateOptions) (ContainerCreateResult, error) |
|
| 64 |
+ ContainerDiff(ctx context.Context, container string, options ContainerDiffOptions) (ContainerDiffResult, error) |
|
| 65 | 65 |
ExecAPIClient |
| 66 | 66 |
ContainerExport(ctx context.Context, container string) (io.ReadCloser, error) |
| 67 | 67 |
ContainerInspect(ctx context.Context, container string) (container.InspectResponse, error) |
| ... | ... |
@@ -16,6 +16,11 @@ type ContainerAttachOptions struct {
|
| 16 | 16 |
Logs bool |
| 17 | 17 |
} |
| 18 | 18 |
|
| 19 |
+// ContainerAttachResult is the result from attaching to a container. |
|
| 20 |
+type ContainerAttachResult struct {
|
|
| 21 |
+ HijackedResponse |
|
| 22 |
+} |
|
| 23 |
+ |
|
| 19 | 24 |
// ContainerAttach attaches a connection to a container in the server. |
| 20 | 25 |
// It returns a [HijackedResponse] with the hijacked connection |
| 21 | 26 |
// and a reader to get output. It's up to the called to close |
| ... | ... |
@@ -44,10 +49,10 @@ type ContainerAttachOptions struct {
|
| 44 | 44 |
// [stdcopy.StdType]: https://pkg.go.dev/github.com/moby/moby/api/pkg/stdcopy#StdType |
| 45 | 45 |
// [Stdout]: https://pkg.go.dev/github.com/moby/moby/api/pkg/stdcopy#Stdout |
| 46 | 46 |
// [Stderr]: https://pkg.go.dev/github.com/moby/moby/api/pkg/stdcopy#Stderr |
| 47 |
-func (cli *Client) ContainerAttach(ctx context.Context, containerID string, options ContainerAttachOptions) (HijackedResponse, error) {
|
|
| 47 |
+func (cli *Client) ContainerAttach(ctx context.Context, containerID string, options ContainerAttachOptions) (ContainerAttachResult, error) {
|
|
| 48 | 48 |
containerID, err := trimID("container", containerID)
|
| 49 | 49 |
if err != nil {
|
| 50 |
- return HijackedResponse{}, err
|
|
| 50 |
+ return ContainerAttachResult{}, err
|
|
| 51 | 51 |
} |
| 52 | 52 |
|
| 53 | 53 |
query := url.Values{}
|
| ... | ... |
@@ -70,7 +75,12 @@ func (cli *Client) ContainerAttach(ctx context.Context, containerID string, opti |
| 70 | 70 |
query.Set("logs", "1")
|
| 71 | 71 |
} |
| 72 | 72 |
|
| 73 |
- return cli.postHijacked(ctx, "/containers/"+containerID+"/attach", query, nil, http.Header{
|
|
| 73 |
+ hijacked, err := cli.postHijacked(ctx, "/containers/"+containerID+"/attach", query, nil, http.Header{
|
|
| 74 | 74 |
"Content-Type": {"text/plain"},
|
| 75 | 75 |
}) |
| 76 |
+ if err != nil {
|
|
| 77 |
+ return ContainerAttachResult{}, err
|
|
| 78 |
+ } |
|
| 79 |
+ |
|
| 80 |
+ return ContainerAttachResult{HijackedResponse: hijacked}, nil
|
|
| 76 | 81 |
} |
| ... | ... |
@@ -20,22 +20,27 @@ type ContainerCommitOptions struct {
|
| 20 | 20 |
Config *container.Config |
| 21 | 21 |
} |
| 22 | 22 |
|
| 23 |
+// ContainerCommitResult is the result from committing a container. |
|
| 24 |
+type ContainerCommitResult struct {
|
|
| 25 |
+ ID string |
|
| 26 |
+} |
|
| 27 |
+ |
|
| 23 | 28 |
// ContainerCommit applies changes to a container and creates a new tagged image. |
| 24 |
-func (cli *Client) ContainerCommit(ctx context.Context, containerID string, options ContainerCommitOptions) (container.CommitResponse, error) {
|
|
| 29 |
+func (cli *Client) ContainerCommit(ctx context.Context, containerID string, options ContainerCommitOptions) (ContainerCommitResult, error) {
|
|
| 25 | 30 |
containerID, err := trimID("container", containerID)
|
| 26 | 31 |
if err != nil {
|
| 27 |
- return container.CommitResponse{}, err
|
|
| 32 |
+ return ContainerCommitResult{}, err
|
|
| 28 | 33 |
} |
| 29 | 34 |
|
| 30 | 35 |
var repository, tag string |
| 31 | 36 |
if options.Reference != "" {
|
| 32 | 37 |
ref, err := reference.ParseNormalizedNamed(options.Reference) |
| 33 | 38 |
if err != nil {
|
| 34 |
- return container.CommitResponse{}, err
|
|
| 39 |
+ return ContainerCommitResult{}, err
|
|
| 35 | 40 |
} |
| 36 | 41 |
|
| 37 | 42 |
if _, ok := ref.(reference.Digested); ok {
|
| 38 |
- return container.CommitResponse{}, errors.New("refusing to create a tag with a digest reference")
|
|
| 43 |
+ return ContainerCommitResult{}, errors.New("refusing to create a tag with a digest reference")
|
|
| 39 | 44 |
} |
| 40 | 45 |
ref = reference.TagNameOnly(ref) |
| 41 | 46 |
|
| ... | ... |
@@ -62,9 +67,9 @@ func (cli *Client) ContainerCommit(ctx context.Context, containerID string, opti |
| 62 | 62 |
resp, err := cli.post(ctx, "/commit", query, options.Config, nil) |
| 63 | 63 |
defer ensureReaderClosed(resp) |
| 64 | 64 |
if err != nil {
|
| 65 |
- return response, err |
|
| 65 |
+ return ContainerCommitResult{}, err
|
|
| 66 | 66 |
} |
| 67 | 67 |
|
| 68 | 68 |
err = json.NewDecoder(resp.Body).Decode(&response) |
| 69 |
- return response, err |
|
| 69 |
+ return ContainerCommitResult{ID: response.ID}, err
|
|
| 70 | 70 |
} |
| ... | ... |
@@ -10,49 +10,48 @@ import ( |
| 10 | 10 |
|
| 11 | 11 |
cerrdefs "github.com/containerd/errdefs" |
| 12 | 12 |
"github.com/moby/moby/api/types/container" |
| 13 |
- "github.com/moby/moby/api/types/network" |
|
| 14 | 13 |
ocispec "github.com/opencontainers/image-spec/specs-go/v1" |
| 15 | 14 |
) |
| 16 | 15 |
|
| 17 | 16 |
// ContainerCreate creates a new container based on the given configuration. |
| 18 | 17 |
// It can be associated with a name, but it's not mandatory. |
| 19 |
-func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, platform *ocispec.Platform, containerName string) (container.CreateResponse, error) {
|
|
| 20 |
- if config == nil {
|
|
| 21 |
- return container.CreateResponse{}, cerrdefs.ErrInvalidArgument.WithMessage("config is nil")
|
|
| 18 |
+func (cli *Client) ContainerCreate(ctx context.Context, options ContainerCreateOptions) (ContainerCreateResult, error) {
|
|
| 19 |
+ if options.Config == nil {
|
|
| 20 |
+ return ContainerCreateResult{}, cerrdefs.ErrInvalidArgument.WithMessage("config is nil")
|
|
| 22 | 21 |
} |
| 23 | 22 |
|
| 24 | 23 |
var response container.CreateResponse |
| 25 | 24 |
|
| 26 |
- if hostConfig != nil {
|
|
| 27 |
- hostConfig.CapAdd = normalizeCapabilities(hostConfig.CapAdd) |
|
| 28 |
- hostConfig.CapDrop = normalizeCapabilities(hostConfig.CapDrop) |
|
| 25 |
+ if options.HostConfig != nil {
|
|
| 26 |
+ options.HostConfig.CapAdd = normalizeCapabilities(options.HostConfig.CapAdd) |
|
| 27 |
+ options.HostConfig.CapDrop = normalizeCapabilities(options.HostConfig.CapDrop) |
|
| 29 | 28 |
} |
| 30 | 29 |
|
| 31 | 30 |
query := url.Values{}
|
| 32 |
- if platform != nil {
|
|
| 33 |
- if p := formatPlatform(*platform); p != "unknown" {
|
|
| 31 |
+ if options.Platform != nil {
|
|
| 32 |
+ if p := formatPlatform(*options.Platform); p != "unknown" {
|
|
| 34 | 33 |
query.Set("platform", p)
|
| 35 | 34 |
} |
| 36 | 35 |
} |
| 37 | 36 |
|
| 38 |
- if containerName != "" {
|
|
| 39 |
- query.Set("name", containerName)
|
|
| 37 |
+ if options.ContainerName != "" {
|
|
| 38 |
+ query.Set("name", options.ContainerName)
|
|
| 40 | 39 |
} |
| 41 | 40 |
|
| 42 | 41 |
body := container.CreateRequest{
|
| 43 |
- Config: config, |
|
| 44 |
- HostConfig: hostConfig, |
|
| 45 |
- NetworkingConfig: networkingConfig, |
|
| 42 |
+ Config: options.Config, |
|
| 43 |
+ HostConfig: options.HostConfig, |
|
| 44 |
+ NetworkingConfig: options.NetworkingConfig, |
|
| 46 | 45 |
} |
| 47 | 46 |
|
| 48 | 47 |
resp, err := cli.post(ctx, "/containers/create", query, body, nil) |
| 49 | 48 |
defer ensureReaderClosed(resp) |
| 50 | 49 |
if err != nil {
|
| 51 |
- return response, err |
|
| 50 |
+ return ContainerCreateResult{}, err
|
|
| 52 | 51 |
} |
| 53 | 52 |
|
| 54 | 53 |
err = json.NewDecoder(resp.Body).Decode(&response) |
| 55 |
- return response, err |
|
| 54 |
+ return ContainerCreateResult{ID: response.ID, Warnings: response.Warnings}, err
|
|
| 56 | 55 |
} |
| 57 | 56 |
|
| 58 | 57 |
// formatPlatform returns a formatted string representing platform (e.g., "linux/arm/v7"). |
| 59 | 58 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,22 @@ |
| 0 |
+package client |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "github.com/moby/moby/api/types/container" |
|
| 4 |
+ "github.com/moby/moby/api/types/network" |
|
| 5 |
+ ocispec "github.com/opencontainers/image-spec/specs-go/v1" |
|
| 6 |
+) |
|
| 7 |
+ |
|
| 8 |
+// ContainerCreateOptions holds parameters to create a container. |
|
| 9 |
+type ContainerCreateOptions struct {
|
|
| 10 |
+ Config *container.Config |
|
| 11 |
+ HostConfig *container.HostConfig |
|
| 12 |
+ NetworkingConfig *network.NetworkingConfig |
|
| 13 |
+ Platform *ocispec.Platform |
|
| 14 |
+ ContainerName string |
|
| 15 |
+} |
|
| 16 |
+ |
|
| 17 |
+// ContainerCreateResult is the result from creating a container. |
|
| 18 |
+type ContainerCreateResult struct {
|
|
| 19 |
+ ID string |
|
| 20 |
+ Warnings []string |
|
| 21 |
+} |
| ... | ... |
@@ -22,11 +22,11 @@ func TestContainerCreateError(t *testing.T) {
|
| 22 | 22 |
) |
| 23 | 23 |
assert.NilError(t, err) |
| 24 | 24 |
|
| 25 |
- _, err = client.ContainerCreate(context.Background(), nil, nil, nil, nil, "nothing") |
|
| 25 |
+ _, err = client.ContainerCreate(context.Background(), ContainerCreateOptions{Config: nil, ContainerName: "nothing"})
|
|
| 26 | 26 |
assert.Error(t, err, "config is nil") |
| 27 | 27 |
assert.Check(t, is.ErrorType(err, cerrdefs.IsInvalidArgument)) |
| 28 | 28 |
|
| 29 |
- _, err = client.ContainerCreate(context.Background(), &container.Config{}, nil, nil, nil, "nothing")
|
|
| 29 |
+ _, err = client.ContainerCreate(context.Background(), ContainerCreateOptions{Config: &container.Config{}, ContainerName: "nothing"})
|
|
| 30 | 30 |
assert.Check(t, is.ErrorType(err, cerrdefs.IsInternal)) |
| 31 | 31 |
|
| 32 | 32 |
// 404 doesn't automatically means an unknown image |
| ... | ... |
@@ -35,7 +35,7 @@ func TestContainerCreateError(t *testing.T) {
|
| 35 | 35 |
) |
| 36 | 36 |
assert.NilError(t, err) |
| 37 | 37 |
|
| 38 |
- _, err = client.ContainerCreate(context.Background(), &container.Config{}, nil, nil, nil, "nothing")
|
|
| 38 |
+ _, err = client.ContainerCreate(context.Background(), ContainerCreateOptions{Config: &container.Config{}, ContainerName: "nothing"})
|
|
| 39 | 39 |
assert.Check(t, is.ErrorType(err, cerrdefs.IsNotFound)) |
| 40 | 40 |
} |
| 41 | 41 |
|
| ... | ... |
@@ -45,7 +45,7 @@ func TestContainerCreateImageNotFound(t *testing.T) {
|
| 45 | 45 |
) |
| 46 | 46 |
assert.NilError(t, err) |
| 47 | 47 |
|
| 48 |
- _, err = client.ContainerCreate(context.Background(), &container.Config{Image: "unknown_image"}, nil, nil, nil, "unknown")
|
|
| 48 |
+ _, err = client.ContainerCreate(context.Background(), ContainerCreateOptions{Config: &container.Config{Image: "unknown_image"}, ContainerName: "unknown"})
|
|
| 49 | 49 |
assert.Check(t, is.ErrorType(err, cerrdefs.IsNotFound)) |
| 50 | 50 |
} |
| 51 | 51 |
|
| ... | ... |
@@ -74,7 +74,7 @@ func TestContainerCreateWithName(t *testing.T) {
|
| 74 | 74 |
) |
| 75 | 75 |
assert.NilError(t, err) |
| 76 | 76 |
|
| 77 |
- r, err := client.ContainerCreate(context.Background(), &container.Config{}, nil, nil, nil, "container_name")
|
|
| 77 |
+ r, err := client.ContainerCreate(context.Background(), ContainerCreateOptions{Config: &container.Config{}, ContainerName: "container_name"})
|
|
| 78 | 78 |
assert.NilError(t, err) |
| 79 | 79 |
assert.Check(t, is.Equal(r.ID, "container_id")) |
| 80 | 80 |
} |
| ... | ... |
@@ -103,7 +103,7 @@ func TestContainerCreateAutoRemove(t *testing.T) {
|
| 103 | 103 |
) |
| 104 | 104 |
assert.NilError(t, err) |
| 105 | 105 |
|
| 106 |
- resp, err := client.ContainerCreate(context.Background(), &container.Config{}, &container.HostConfig{AutoRemove: true}, nil, nil, "")
|
|
| 106 |
+ resp, err := client.ContainerCreate(context.Background(), ContainerCreateOptions{Config: &container.Config{}, HostConfig: &container.HostConfig{AutoRemove: true}})
|
|
| 107 | 107 |
assert.NilError(t, err) |
| 108 | 108 |
assert.Check(t, is.Equal(resp.ID, "container_id")) |
| 109 | 109 |
} |
| ... | ... |
@@ -116,7 +116,7 @@ func TestContainerCreateConnectionError(t *testing.T) {
|
| 116 | 116 |
client, err := NewClientWithOpts(WithAPIVersionNegotiation(), WithHost("tcp://no-such-host.invalid"))
|
| 117 | 117 |
assert.NilError(t, err) |
| 118 | 118 |
|
| 119 |
- _, err = client.ContainerCreate(context.Background(), &container.Config{}, nil, nil, nil, "")
|
|
| 119 |
+ _, err = client.ContainerCreate(context.Background(), ContainerCreateOptions{Config: &container.Config{}})
|
|
| 120 | 120 |
assert.Check(t, is.ErrorType(err, IsErrConnectionFailed)) |
| 121 | 121 |
} |
| 122 | 122 |
|
| ... | ... |
@@ -165,6 +165,6 @@ func TestContainerCreateCapabilities(t *testing.T) {
|
| 165 | 165 |
) |
| 166 | 166 |
assert.NilError(t, err) |
| 167 | 167 |
|
| 168 |
- _, err = client.ContainerCreate(context.Background(), &container.Config{}, &container.HostConfig{CapAdd: inputCaps, CapDrop: inputCaps}, nil, nil, "")
|
|
| 168 |
+ _, err = client.ContainerCreate(context.Background(), ContainerCreateOptions{Config: &container.Config{}, HostConfig: &container.HostConfig{CapAdd: inputCaps, CapDrop: inputCaps}})
|
|
| 169 | 169 |
assert.NilError(t, err) |
| 170 | 170 |
} |
| ... | ... |
@@ -9,22 +9,22 @@ import ( |
| 9 | 9 |
) |
| 10 | 10 |
|
| 11 | 11 |
// ContainerDiff shows differences in a container filesystem since it was started. |
| 12 |
-func (cli *Client) ContainerDiff(ctx context.Context, containerID string) ([]container.FilesystemChange, error) {
|
|
| 12 |
+func (cli *Client) ContainerDiff(ctx context.Context, containerID string, options ContainerDiffOptions) (ContainerDiffResult, error) {
|
|
| 13 | 13 |
containerID, err := trimID("container", containerID)
|
| 14 | 14 |
if err != nil {
|
| 15 |
- return nil, err |
|
| 15 |
+ return ContainerDiffResult{}, err
|
|
| 16 | 16 |
} |
| 17 | 17 |
|
| 18 | 18 |
resp, err := cli.get(ctx, "/containers/"+containerID+"/changes", url.Values{}, nil)
|
| 19 | 19 |
defer ensureReaderClosed(resp) |
| 20 | 20 |
if err != nil {
|
| 21 |
- return nil, err |
|
| 21 |
+ return ContainerDiffResult{}, err
|
|
| 22 | 22 |
} |
| 23 | 23 |
|
| 24 | 24 |
var changes []container.FilesystemChange |
| 25 | 25 |
err = json.NewDecoder(resp.Body).Decode(&changes) |
| 26 | 26 |
if err != nil {
|
| 27 |
- return nil, err |
|
| 27 |
+ return ContainerDiffResult{}, err
|
|
| 28 | 28 |
} |
| 29 |
- return changes, err |
|
| 29 |
+ return ContainerDiffResult{Changes: changes}, err
|
|
| 30 | 30 |
} |
| 31 | 31 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,13 @@ |
| 0 |
+package client |
|
| 1 |
+ |
|
| 2 |
+import "github.com/moby/moby/api/types/container" |
|
| 3 |
+ |
|
| 4 |
+// ContainerDiffOptions holds parameters to show differences in a container filesystem. |
|
| 5 |
+type ContainerDiffOptions struct {
|
|
| 6 |
+ // Currently no options, but this allows for future extensibility |
|
| 7 |
+} |
|
| 8 |
+ |
|
| 9 |
+// ContainerDiffResult is the result from showing differences in a container filesystem. |
|
| 10 |
+type ContainerDiffResult struct {
|
|
| 11 |
+ Changes []container.FilesystemChange |
|
| 12 |
+} |
| ... | ... |
@@ -20,14 +20,14 @@ func TestContainerDiffError(t *testing.T) {
|
| 20 | 20 |
) |
| 21 | 21 |
assert.NilError(t, err) |
| 22 | 22 |
|
| 23 |
- _, err = client.ContainerDiff(context.Background(), "nothing") |
|
| 23 |
+ _, err = client.ContainerDiff(context.Background(), "nothing", ContainerDiffOptions{})
|
|
| 24 | 24 |
assert.Check(t, is.ErrorType(err, cerrdefs.IsInternal)) |
| 25 | 25 |
|
| 26 |
- _, err = client.ContainerDiff(context.Background(), "") |
|
| 26 |
+ _, err = client.ContainerDiff(context.Background(), "", ContainerDiffOptions{})
|
|
| 27 | 27 |
assert.Check(t, is.ErrorType(err, cerrdefs.IsInvalidArgument)) |
| 28 | 28 |
assert.Check(t, is.ErrorContains(err, "value is empty")) |
| 29 | 29 |
|
| 30 |
- _, err = client.ContainerDiff(context.Background(), " ") |
|
| 30 |
+ _, err = client.ContainerDiff(context.Background(), " ", ContainerDiffOptions{})
|
|
| 31 | 31 |
assert.Check(t, is.ErrorType(err, cerrdefs.IsInvalidArgument)) |
| 32 | 32 |
assert.Check(t, is.ErrorContains(err, "value is empty")) |
| 33 | 33 |
} |
| ... | ... |
@@ -67,7 +67,7 @@ func TestContainerDiff(t *testing.T) {
|
| 67 | 67 |
) |
| 68 | 68 |
assert.NilError(t, err) |
| 69 | 69 |
|
| 70 |
- changes, err := client.ContainerDiff(context.Background(), "container_id") |
|
| 70 |
+ result, err := client.ContainerDiff(context.Background(), "container_id", ContainerDiffOptions{})
|
|
| 71 | 71 |
assert.NilError(t, err) |
| 72 |
- assert.Check(t, is.DeepEqual(changes, expected)) |
|
| 72 |
+ assert.Check(t, is.DeepEqual(result.Changes, expected)) |
|
| 73 | 73 |
} |
| ... | ... |
@@ -130,12 +130,12 @@ func (s *DockerAPISuite) TestContainerAPIGetChanges(c *testing.T) {
|
| 130 | 130 |
assert.NilError(c, err) |
| 131 | 131 |
defer apiClient.Close() |
| 132 | 132 |
|
| 133 |
- changes, err := apiClient.ContainerDiff(testutil.GetContext(c), name) |
|
| 133 |
+ result, err := apiClient.ContainerDiff(testutil.GetContext(c), name, client.ContainerDiffOptions{})
|
|
| 134 | 134 |
assert.NilError(c, err) |
| 135 | 135 |
|
| 136 | 136 |
// Check the changelog for removal of /etc/passwd |
| 137 | 137 |
success := false |
| 138 |
- for _, elem := range changes {
|
|
| 138 |
+ for _, elem := range result.Changes {
|
|
| 139 | 139 |
if elem.Path == "/etc/passwd" && elem.Kind == 2 {
|
| 140 | 140 |
success = true |
| 141 | 141 |
} |
| ... | ... |
@@ -517,7 +517,11 @@ func (s *DockerAPISuite) TestContainerAPIBadPort(c *testing.T) {
|
| 517 | 517 |
assert.NilError(c, err) |
| 518 | 518 |
defer apiClient.Close() |
| 519 | 519 |
|
| 520 |
- _, err = apiClient.ContainerCreate(testutil.GetContext(c), &config, &hostConfig, &network.NetworkingConfig{}, nil, "")
|
|
| 520 |
+ _, err = apiClient.ContainerCreate(testutil.GetContext(c), client.ContainerCreateOptions{
|
|
| 521 |
+ Config: &config, |
|
| 522 |
+ HostConfig: &hostConfig, |
|
| 523 |
+ NetworkingConfig: &network.NetworkingConfig{},
|
|
| 524 |
+ }) |
|
| 521 | 525 |
assert.ErrorContains(c, err, `invalid port specification: "aa80"`) |
| 522 | 526 |
} |
| 523 | 527 |
|
| ... | ... |
@@ -531,7 +535,11 @@ func (s *DockerAPISuite) TestContainerAPICreate(c *testing.T) {
|
| 531 | 531 |
assert.NilError(c, err) |
| 532 | 532 |
defer apiClient.Close() |
| 533 | 533 |
|
| 534 |
- ctr, err := apiClient.ContainerCreate(testutil.GetContext(c), &config, &container.HostConfig{}, &network.NetworkingConfig{}, nil, "")
|
|
| 534 |
+ ctr, err := apiClient.ContainerCreate(testutil.GetContext(c), client.ContainerCreateOptions{
|
|
| 535 |
+ Config: &config, |
|
| 536 |
+ HostConfig: &container.HostConfig{},
|
|
| 537 |
+ NetworkingConfig: &network.NetworkingConfig{},
|
|
| 538 |
+ }) |
|
| 535 | 539 |
assert.NilError(c, err) |
| 536 | 540 |
|
| 537 | 541 |
out := cli.DockerCmd(c, "start", "-a", ctr.ID).Stdout() |
| ... | ... |
@@ -543,7 +551,11 @@ func (s *DockerAPISuite) TestContainerAPICreateEmptyConfig(c *testing.T) {
|
| 543 | 543 |
assert.NilError(c, err) |
| 544 | 544 |
defer apiClient.Close() |
| 545 | 545 |
|
| 546 |
- _, err = apiClient.ContainerCreate(testutil.GetContext(c), &container.Config{}, &container.HostConfig{}, &network.NetworkingConfig{}, nil, "")
|
|
| 546 |
+ _, err = apiClient.ContainerCreate(testutil.GetContext(c), client.ContainerCreateOptions{
|
|
| 547 |
+ Config: &container.Config{},
|
|
| 548 |
+ HostConfig: &container.HostConfig{},
|
|
| 549 |
+ NetworkingConfig: &network.NetworkingConfig{},
|
|
| 550 |
+ }) |
|
| 547 | 551 |
|
| 548 | 552 |
assert.ErrorContains(c, err, "no command specified") |
| 549 | 553 |
} |
| ... | ... |
@@ -574,7 +586,11 @@ func UtilCreateNetworkMode(t *testing.T, networkMode container.NetworkMode) {
|
| 574 | 574 |
assert.NilError(t, err) |
| 575 | 575 |
defer apiClient.Close() |
| 576 | 576 |
|
| 577 |
- ctr, err := apiClient.ContainerCreate(testutil.GetContext(t), &config, &hostConfig, &network.NetworkingConfig{}, nil, "")
|
|
| 577 |
+ ctr, err := apiClient.ContainerCreate(testutil.GetContext(t), client.ContainerCreateOptions{
|
|
| 578 |
+ Config: &config, |
|
| 579 |
+ HostConfig: &hostConfig, |
|
| 580 |
+ NetworkingConfig: &network.NetworkingConfig{},
|
|
| 581 |
+ }) |
|
| 578 | 582 |
assert.NilError(t, err) |
| 579 | 583 |
|
| 580 | 584 |
containerJSON, err := apiClient.ContainerInspect(testutil.GetContext(t), ctr.ID) |
| ... | ... |
@@ -601,7 +617,11 @@ func (s *DockerAPISuite) TestContainerAPICreateWithCpuSharesCpuset(c *testing.T) |
| 601 | 601 |
assert.NilError(c, err) |
| 602 | 602 |
defer apiClient.Close() |
| 603 | 603 |
|
| 604 |
- ctr, err := apiClient.ContainerCreate(testutil.GetContext(c), &config, &hostConfig, &network.NetworkingConfig{}, nil, "")
|
|
| 604 |
+ ctr, err := apiClient.ContainerCreate(testutil.GetContext(c), client.ContainerCreateOptions{
|
|
| 605 |
+ Config: &config, |
|
| 606 |
+ HostConfig: &hostConfig, |
|
| 607 |
+ NetworkingConfig: &network.NetworkingConfig{},
|
|
| 608 |
+ }) |
|
| 605 | 609 |
assert.NilError(c, err) |
| 606 | 610 |
|
| 607 | 611 |
containerJSON, err := apiClient.ContainerInspect(testutil.GetContext(c), ctr.ID) |
| ... | ... |
@@ -746,7 +766,12 @@ func (s *DockerAPISuite) TestContainerAPIStart(c *testing.T) {
|
| 746 | 746 |
assert.NilError(c, err) |
| 747 | 747 |
defer apiClient.Close() |
| 748 | 748 |
|
| 749 |
- _, err = apiClient.ContainerCreate(testutil.GetContext(c), &config, &container.HostConfig{}, &network.NetworkingConfig{}, nil, name)
|
|
| 749 |
+ _, err = apiClient.ContainerCreate(testutil.GetContext(c), client.ContainerCreateOptions{
|
|
| 750 |
+ Config: &config, |
|
| 751 |
+ HostConfig: &container.HostConfig{},
|
|
| 752 |
+ NetworkingConfig: &network.NetworkingConfig{},
|
|
| 753 |
+ ContainerName: name, |
|
| 754 |
+ }) |
|
| 750 | 755 |
assert.NilError(c, err) |
| 751 | 756 |
|
| 752 | 757 |
err = apiClient.ContainerStart(testutil.GetContext(c), name, client.ContainerStartOptions{})
|
| ... | ... |
@@ -989,7 +1014,12 @@ func (s *DockerAPISuite) TestPostContainersCreateWithWrongCpusetValues(c *testin |
| 989 | 989 |
} |
| 990 | 990 |
const name = "wrong-cpuset-cpus" |
| 991 | 991 |
|
| 992 |
- _, err = apiClient.ContainerCreate(testutil.GetContext(c), &config, &hostConfig1, &network.NetworkingConfig{}, nil, name)
|
|
| 992 |
+ _, err = apiClient.ContainerCreate(testutil.GetContext(c), client.ContainerCreateOptions{
|
|
| 993 |
+ Config: &config, |
|
| 994 |
+ HostConfig: &hostConfig1, |
|
| 995 |
+ NetworkingConfig: &network.NetworkingConfig{},
|
|
| 996 |
+ ContainerName: name, |
|
| 997 |
+ }) |
|
| 993 | 998 |
expected := "Invalid value 1-42,, for cpuset cpus" |
| 994 | 999 |
assert.ErrorContains(c, err, expected) |
| 995 | 1000 |
|
| ... | ... |
@@ -999,7 +1029,12 @@ func (s *DockerAPISuite) TestPostContainersCreateWithWrongCpusetValues(c *testin |
| 999 | 999 |
}, |
| 1000 | 1000 |
} |
| 1001 | 1001 |
const name2 = "wrong-cpuset-mems" |
| 1002 |
- _, err = apiClient.ContainerCreate(testutil.GetContext(c), &config, &hostConfig2, &network.NetworkingConfig{}, nil, name2)
|
|
| 1002 |
+ _, err = apiClient.ContainerCreate(testutil.GetContext(c), client.ContainerCreateOptions{
|
|
| 1003 |
+ Config: &config, |
|
| 1004 |
+ HostConfig: &hostConfig2, |
|
| 1005 |
+ NetworkingConfig: &network.NetworkingConfig{},
|
|
| 1006 |
+ ContainerName: name2, |
|
| 1007 |
+ }) |
|
| 1003 | 1008 |
expected = "Invalid value 42-3,1-- for cpuset mems" |
| 1004 | 1009 |
assert.ErrorContains(c, err, expected) |
| 1005 | 1010 |
} |
| ... | ... |
@@ -1015,7 +1050,11 @@ func (s *DockerAPISuite) TestPostContainersCreateMemorySwappinessHostConfigOmitt |
| 1015 | 1015 |
assert.NilError(c, err) |
| 1016 | 1016 |
defer apiClient.Close() |
| 1017 | 1017 |
|
| 1018 |
- ctr, err := apiClient.ContainerCreate(testutil.GetContext(c), &config, &container.HostConfig{}, &network.NetworkingConfig{}, nil, "")
|
|
| 1018 |
+ ctr, err := apiClient.ContainerCreate(testutil.GetContext(c), client.ContainerCreateOptions{
|
|
| 1019 |
+ Config: &config, |
|
| 1020 |
+ HostConfig: &container.HostConfig{},
|
|
| 1021 |
+ NetworkingConfig: &network.NetworkingConfig{},
|
|
| 1022 |
+ }) |
|
| 1019 | 1023 |
assert.NilError(c, err) |
| 1020 | 1024 |
|
| 1021 | 1025 |
containerJSON, err := apiClient.ContainerInspect(testutil.GetContext(c), ctr.ID) |
| ... | ... |
@@ -1042,7 +1081,12 @@ func (s *DockerAPISuite) TestPostContainersCreateWithOomScoreAdjInvalidRange(c * |
| 1042 | 1042 |
defer apiClient.Close() |
| 1043 | 1043 |
|
| 1044 | 1044 |
const name = "oomscoreadj-over" |
| 1045 |
- _, err = apiClient.ContainerCreate(testutil.GetContext(c), &config, &hostConfig, &network.NetworkingConfig{}, nil, name)
|
|
| 1045 |
+ _, err = apiClient.ContainerCreate(testutil.GetContext(c), client.ContainerCreateOptions{
|
|
| 1046 |
+ Config: &config, |
|
| 1047 |
+ HostConfig: &hostConfig, |
|
| 1048 |
+ NetworkingConfig: &network.NetworkingConfig{},
|
|
| 1049 |
+ ContainerName: name, |
|
| 1050 |
+ }) |
|
| 1046 | 1051 |
|
| 1047 | 1052 |
expected := "Invalid value 1001, range for oom score adj is [-1000, 1000]" |
| 1048 | 1053 |
assert.ErrorContains(c, err, expected) |
| ... | ... |
@@ -1052,7 +1096,12 @@ func (s *DockerAPISuite) TestPostContainersCreateWithOomScoreAdjInvalidRange(c * |
| 1052 | 1052 |
} |
| 1053 | 1053 |
|
| 1054 | 1054 |
const name2 = "oomscoreadj-low" |
| 1055 |
- _, err = apiClient.ContainerCreate(testutil.GetContext(c), &config, &hostConfig, &network.NetworkingConfig{}, nil, name2)
|
|
| 1055 |
+ _, err = apiClient.ContainerCreate(testutil.GetContext(c), client.ContainerCreateOptions{
|
|
| 1056 |
+ Config: &config, |
|
| 1057 |
+ HostConfig: &hostConfig, |
|
| 1058 |
+ NetworkingConfig: &network.NetworkingConfig{},
|
|
| 1059 |
+ ContainerName: name2, |
|
| 1060 |
+ }) |
|
| 1056 | 1061 |
|
| 1057 | 1062 |
expected = "Invalid value -1001, range for oom score adj is [-1000, 1000]" |
| 1058 | 1063 |
assert.ErrorContains(c, err, expected) |
| ... | ... |
@@ -1085,7 +1134,12 @@ func (s *DockerAPISuite) TestContainerAPIStatsWithNetworkDisabled(c *testing.T) |
| 1085 | 1085 |
assert.NilError(c, err) |
| 1086 | 1086 |
defer apiClient.Close() |
| 1087 | 1087 |
|
| 1088 |
- _, err = apiClient.ContainerCreate(testutil.GetContext(c), &config, &container.HostConfig{}, &network.NetworkingConfig{}, nil, name)
|
|
| 1088 |
+ _, err = apiClient.ContainerCreate(testutil.GetContext(c), client.ContainerCreateOptions{
|
|
| 1089 |
+ Config: &config, |
|
| 1090 |
+ HostConfig: &container.HostConfig{},
|
|
| 1091 |
+ NetworkingConfig: &network.NetworkingConfig{},
|
|
| 1092 |
+ ContainerName: name, |
|
| 1093 |
+ }) |
|
| 1089 | 1094 |
assert.NilError(c, err) |
| 1090 | 1095 |
|
| 1091 | 1096 |
err = apiClient.ContainerStart(testutil.GetContext(c), name, client.ContainerStartOptions{})
|
| ... | ... |
@@ -1421,7 +1475,11 @@ func (s *DockerAPISuite) TestContainersAPICreateMountsValidation(c *testing.T) {
|
| 1421 | 1421 |
// TODO add checks for statuscode returned by API |
| 1422 | 1422 |
for i, tc := range tests {
|
| 1423 | 1423 |
c.Run(fmt.Sprintf("case %d", i), func(c *testing.T) {
|
| 1424 |
- _, err = apiClient.ContainerCreate(testutil.GetContext(c), &tc.config, &tc.hostConfig, &network.NetworkingConfig{}, nil, "")
|
|
| 1424 |
+ _, err = apiClient.ContainerCreate(testutil.GetContext(c), client.ContainerCreateOptions{
|
|
| 1425 |
+ Config: &tc.config, |
|
| 1426 |
+ HostConfig: &tc.hostConfig, |
|
| 1427 |
+ NetworkingConfig: &network.NetworkingConfig{},
|
|
| 1428 |
+ }) |
|
| 1425 | 1429 |
if tc.msg != "" {
|
| 1426 | 1430 |
assert.ErrorContains(c, err, tc.msg, "%v", tests[i].config) |
| 1427 | 1431 |
} else {
|
| ... | ... |
@@ -1454,7 +1512,12 @@ func (s *DockerAPISuite) TestContainerAPICreateMountsBindRead(c *testing.T) {
|
| 1454 | 1454 |
assert.NilError(c, err) |
| 1455 | 1455 |
defer apiClient.Close() |
| 1456 | 1456 |
|
| 1457 |
- _, err = apiClient.ContainerCreate(testutil.GetContext(c), &config, &hostConfig, &network.NetworkingConfig{}, nil, "test")
|
|
| 1457 |
+ _, err = apiClient.ContainerCreate(testutil.GetContext(c), client.ContainerCreateOptions{
|
|
| 1458 |
+ Config: &config, |
|
| 1459 |
+ HostConfig: &hostConfig, |
|
| 1460 |
+ NetworkingConfig: &network.NetworkingConfig{},
|
|
| 1461 |
+ ContainerName: "test", |
|
| 1462 |
+ }) |
|
| 1458 | 1463 |
assert.NilError(c, err) |
| 1459 | 1464 |
|
| 1460 | 1465 |
out := cli.DockerCmd(c, "start", "-a", "test").Combined() |
| ... | ... |
@@ -1590,11 +1653,11 @@ func (s *DockerAPISuite) TestContainersAPICreateMountsCreate(c *testing.T) {
|
| 1590 | 1590 |
c.Run(fmt.Sprintf("%d config: %v", i, tc.spec), func(c *testing.T) {
|
| 1591 | 1591 |
ctr, err := apiclient.ContainerCreate( |
| 1592 | 1592 |
ctx, |
| 1593 |
- &container.Config{Image: testImg},
|
|
| 1594 |
- &container.HostConfig{Mounts: []mount.Mount{tc.spec}},
|
|
| 1595 |
- &network.NetworkingConfig{},
|
|
| 1596 |
- nil, |
|
| 1597 |
- "") |
|
| 1593 |
+ client.ContainerCreateOptions{
|
|
| 1594 |
+ Config: &container.Config{Image: testImg},
|
|
| 1595 |
+ HostConfig: &container.HostConfig{Mounts: []mount.Mount{tc.spec}},
|
|
| 1596 |
+ NetworkingConfig: &network.NetworkingConfig{},
|
|
| 1597 |
+ }) |
|
| 1598 | 1598 |
assert.NilError(c, err) |
| 1599 | 1599 |
|
| 1600 | 1600 |
containerInspect, err := apiclient.ContainerInspect(ctx, ctr.ID) |
| ... | ... |
@@ -1705,7 +1768,12 @@ func (s *DockerAPISuite) TestContainersAPICreateMountsTmpfs(c *testing.T) {
|
| 1705 | 1705 |
Mounts: []mount.Mount{x.cfg},
|
| 1706 | 1706 |
} |
| 1707 | 1707 |
|
| 1708 |
- _, err = apiClient.ContainerCreate(testutil.GetContext(c), &config, &hostConfig, &network.NetworkingConfig{}, nil, cName)
|
|
| 1708 |
+ _, err = apiClient.ContainerCreate(testutil.GetContext(c), client.ContainerCreateOptions{
|
|
| 1709 |
+ Config: &config, |
|
| 1710 |
+ HostConfig: &hostConfig, |
|
| 1711 |
+ NetworkingConfig: &network.NetworkingConfig{},
|
|
| 1712 |
+ ContainerName: cName, |
|
| 1713 |
+ }) |
|
| 1709 | 1714 |
assert.NilError(c, err) |
| 1710 | 1715 |
out := cli.DockerCmd(c, "start", "-a", cName).Combined() |
| 1711 | 1716 |
for _, option := range x.expectedOptions {
|
| ... | ... |
@@ -12,6 +12,7 @@ import ( |
| 12 | 12 |
"github.com/Microsoft/go-winio" |
| 13 | 13 |
"github.com/moby/moby/api/types/container" |
| 14 | 14 |
"github.com/moby/moby/api/types/mount" |
| 15 |
+ "github.com/moby/moby/api/types/network" |
|
| 15 | 16 |
"github.com/moby/moby/client" |
| 16 | 17 |
"github.com/moby/moby/v2/internal/testutil" |
| 17 | 18 |
"github.com/pkg/errors" |
| ... | ... |
@@ -51,19 +52,23 @@ func (s *DockerAPISuite) TestContainersAPICreateMountsBindNamedPipe(c *testing.T |
| 51 | 51 |
ctx := testutil.GetContext(c) |
| 52 | 52 |
apiClient := testEnv.APIClient() |
| 53 | 53 |
_, err = apiClient.ContainerCreate(ctx, |
| 54 |
- &container.Config{
|
|
| 55 |
- Image: testEnv.PlatformDefaults.BaseImage, |
|
| 56 |
- Cmd: []string{"cmd", "/c", cmd},
|
|
| 57 |
- }, &container.HostConfig{
|
|
| 58 |
- Mounts: []mount.Mount{
|
|
| 59 |
- {
|
|
| 60 |
- Type: "npipe", |
|
| 61 |
- Source: hostPipeName, |
|
| 62 |
- Target: containerPipeName, |
|
| 54 |
+ client.ContainerCreateOptions{
|
|
| 55 |
+ Config: &container.Config{
|
|
| 56 |
+ Image: testEnv.PlatformDefaults.BaseImage, |
|
| 57 |
+ Cmd: []string{"cmd", "/c", cmd},
|
|
| 58 |
+ }, |
|
| 59 |
+ HostConfig: &container.HostConfig{
|
|
| 60 |
+ Mounts: []mount.Mount{
|
|
| 61 |
+ {
|
|
| 62 |
+ Type: "npipe", |
|
| 63 |
+ Source: hostPipeName, |
|
| 64 |
+ Target: containerPipeName, |
|
| 65 |
+ }, |
|
| 63 | 66 |
}, |
| 64 | 67 |
}, |
| 65 |
- }, |
|
| 66 |
- nil, nil, name) |
|
| 68 |
+ NetworkingConfig: &network.NetworkingConfig{},
|
|
| 69 |
+ ContainerName: name, |
|
| 70 |
+ }) |
|
| 67 | 71 |
assert.NilError(c, err) |
| 68 | 72 |
|
| 69 | 73 |
err = apiClient.ContainerStart(ctx, name, client.ContainerStartOptions{})
|
| ... | ... |
@@ -596,7 +596,12 @@ func (s *DockerCLIVolumeSuite) TestDuplicateMountpointsForVolumesFromAndMounts(c |
| 596 | 596 |
}, |
| 597 | 597 |
}, |
| 598 | 598 |
} |
| 599 |
- _, err = apiClient.ContainerCreate(testutil.GetContext(c), &config, &hostConfig, &network.NetworkingConfig{}, nil, "app")
|
|
| 599 |
+ _, err = apiClient.ContainerCreate(testutil.GetContext(c), client.ContainerCreateOptions{
|
|
| 600 |
+ Config: &config, |
|
| 601 |
+ HostConfig: &hostConfig, |
|
| 602 |
+ NetworkingConfig: &network.NetworkingConfig{},
|
|
| 603 |
+ ContainerName: "app", |
|
| 604 |
+ }) |
|
| 600 | 605 |
|
| 601 | 606 |
assert.NilError(c, err) |
| 602 | 607 |
|
| ... | ... |
@@ -41,17 +41,15 @@ func TestAttach(t *testing.T) {
|
| 41 | 41 |
t.Parallel() |
| 42 | 42 |
|
| 43 | 43 |
ctx := testutil.StartSpan(ctx, t) |
| 44 |
- resp, err := apiClient.ContainerCreate(ctx, |
|
| 45 |
- &container.Config{
|
|
| 44 |
+ resp, err := apiClient.ContainerCreate(ctx, client.ContainerCreateOptions{
|
|
| 45 |
+ Config: &container.Config{
|
|
| 46 | 46 |
Image: "busybox", |
| 47 | 47 |
Cmd: []string{"echo", "hello"},
|
| 48 | 48 |
Tty: tc.tty, |
| 49 | 49 |
}, |
| 50 |
- &container.HostConfig{},
|
|
| 51 |
- &network.NetworkingConfig{},
|
|
| 52 |
- nil, |
|
| 53 |
- "", |
|
| 54 |
- ) |
|
| 50 |
+ HostConfig: &container.HostConfig{},
|
|
| 51 |
+ NetworkingConfig: &network.NetworkingConfig{},
|
|
| 52 |
+ }) |
|
| 55 | 53 |
assert.NilError(t, err) |
| 56 | 54 |
attach, err := apiClient.ContainerAttach(ctx, resp.ID, client.ContainerAttachOptions{
|
| 57 | 55 |
Stdout: true, |
| ... | ... |
@@ -81,16 +79,14 @@ func TestAttachDisconnectLeak(t *testing.T) {
|
| 81 | 81 |
|
| 82 | 82 |
apiClient := d.NewClientT(t) |
| 83 | 83 |
|
| 84 |
- resp, err := apiClient.ContainerCreate(ctx, |
|
| 85 |
- &container.Config{
|
|
| 84 |
+ resp, err := apiClient.ContainerCreate(ctx, client.ContainerCreateOptions{
|
|
| 85 |
+ Config: &container.Config{
|
|
| 86 | 86 |
Image: "busybox", |
| 87 | 87 |
Cmd: []string{"/bin/sh", "-c", "while true; usleep 100000; done"},
|
| 88 | 88 |
}, |
| 89 |
- &container.HostConfig{},
|
|
| 90 |
- &network.NetworkingConfig{},
|
|
| 91 |
- nil, |
|
| 92 |
- "", |
|
| 93 |
- ) |
|
| 89 |
+ HostConfig: &container.HostConfig{},
|
|
| 90 |
+ NetworkingConfig: &network.NetworkingConfig{},
|
|
| 91 |
+ }) |
|
| 94 | 92 |
assert.NilError(t, err) |
| 95 | 93 |
cID := resp.ID |
| 96 | 94 |
defer apiClient.ContainerRemove(ctx, cID, client.ContainerRemoveOptions{
|
| ... | ... |
@@ -59,13 +59,11 @@ func TestCreateFailsWhenIdentifierDoesNotExist(t *testing.T) {
|
| 59 | 59 |
t.Run(tc.doc, func(t *testing.T) {
|
| 60 | 60 |
t.Parallel() |
| 61 | 61 |
ctx := testutil.StartSpan(ctx, t) |
| 62 |
- _, err := apiClient.ContainerCreate(ctx, |
|
| 63 |
- &container.Config{Image: tc.image},
|
|
| 64 |
- &container.HostConfig{},
|
|
| 65 |
- &network.NetworkingConfig{},
|
|
| 66 |
- nil, |
|
| 67 |
- "", |
|
| 68 |
- ) |
|
| 62 |
+ _, err := apiClient.ContainerCreate(ctx, client.ContainerCreateOptions{
|
|
| 63 |
+ Config: &container.Config{Image: tc.image},
|
|
| 64 |
+ HostConfig: &container.HostConfig{},
|
|
| 65 |
+ NetworkingConfig: &network.NetworkingConfig{},
|
|
| 66 |
+ }) |
|
| 69 | 67 |
assert.Check(t, is.ErrorContains(err, tc.expectedError)) |
| 70 | 68 |
assert.Check(t, is.ErrorType(err, cerrdefs.IsNotFound)) |
| 71 | 69 |
}) |
| ... | ... |
@@ -125,15 +123,11 @@ func TestCreateByImageID(t *testing.T) {
|
| 125 | 125 |
t.Run(tc.doc, func(t *testing.T) {
|
| 126 | 126 |
t.Parallel() |
| 127 | 127 |
ctx := testutil.StartSpan(ctx, t) |
| 128 |
- resp, err := apiClient.ContainerCreate(ctx, |
|
| 129 |
- &container.Config{Image: tc.image},
|
|
| 130 |
- &container.HostConfig{},
|
|
| 131 |
- &network.NetworkingConfig{},
|
|
| 132 |
- nil, |
|
| 133 |
- "", |
|
| 134 |
- ) |
|
| 128 |
+ resp, err := apiClient.ContainerCreate(ctx, client.ContainerCreateOptions{
|
|
| 129 |
+ Config: &container.Config{Image: tc.image},
|
|
| 130 |
+ }) |
|
| 135 | 131 |
if tc.expectedErr != "" {
|
| 136 |
- assert.Check(t, is.DeepEqual(resp, container.CreateResponse{}))
|
|
| 132 |
+ assert.Check(t, is.DeepEqual(resp, client.ContainerCreateResult{}))
|
|
| 137 | 133 |
assert.Check(t, is.Error(err, tc.expectedErr)) |
| 138 | 134 |
assert.Check(t, is.ErrorType(err, tc.expectedErrType)) |
| 139 | 135 |
} else {
|
| ... | ... |
@@ -154,17 +148,14 @@ func TestCreateLinkToNonExistingContainer(t *testing.T) {
|
| 154 | 154 |
ctx := setupTest(t) |
| 155 | 155 |
apiClient := testEnv.APIClient() |
| 156 | 156 |
|
| 157 |
- _, err := apiClient.ContainerCreate(ctx, |
|
| 158 |
- &container.Config{
|
|
| 157 |
+ _, err := apiClient.ContainerCreate(ctx, client.ContainerCreateOptions{
|
|
| 158 |
+ Config: &container.Config{
|
|
| 159 | 159 |
Image: "busybox", |
| 160 | 160 |
}, |
| 161 |
- &container.HostConfig{
|
|
| 161 |
+ HostConfig: &container.HostConfig{
|
|
| 162 | 162 |
Links: []string{"no-such-container"},
|
| 163 | 163 |
}, |
| 164 |
- &network.NetworkingConfig{},
|
|
| 165 |
- nil, |
|
| 166 |
- "", |
|
| 167 |
- ) |
|
| 164 |
+ }) |
|
| 168 | 165 |
assert.Check(t, is.ErrorContains(err, "could not get container for no-such-container")) |
| 169 | 166 |
assert.Check(t, is.ErrorType(err, cerrdefs.IsInvalidArgument)) |
| 170 | 167 |
} |
| ... | ... |
@@ -195,16 +186,12 @@ func TestCreateWithInvalidEnv(t *testing.T) {
|
| 195 | 195 |
t.Run(strconv.Itoa(index), func(t *testing.T) {
|
| 196 | 196 |
t.Parallel() |
| 197 | 197 |
ctx := testutil.StartSpan(ctx, t) |
| 198 |
- _, err := apiClient.ContainerCreate(ctx, |
|
| 199 |
- &container.Config{
|
|
| 198 |
+ _, err := apiClient.ContainerCreate(ctx, client.ContainerCreateOptions{
|
|
| 199 |
+ Config: &container.Config{
|
|
| 200 | 200 |
Image: "busybox", |
| 201 | 201 |
Env: []string{tc.env},
|
| 202 | 202 |
}, |
| 203 |
- &container.HostConfig{},
|
|
| 204 |
- &network.NetworkingConfig{},
|
|
| 205 |
- nil, |
|
| 206 |
- "", |
|
| 207 |
- ) |
|
| 203 |
+ }) |
|
| 208 | 204 |
assert.Check(t, is.ErrorContains(err, tc.expectedError)) |
| 209 | 205 |
assert.Check(t, is.ErrorType(err, cerrdefs.IsInvalidArgument)) |
| 210 | 206 |
}) |
| ... | ... |
@@ -241,17 +228,14 @@ func TestCreateTmpfsMountsTarget(t *testing.T) {
|
| 241 | 241 |
} |
| 242 | 242 |
|
| 243 | 243 |
for _, tc := range testCases {
|
| 244 |
- _, err := apiClient.ContainerCreate(ctx, |
|
| 245 |
- &container.Config{
|
|
| 244 |
+ _, err := apiClient.ContainerCreate(ctx, client.ContainerCreateOptions{
|
|
| 245 |
+ Config: &container.Config{
|
|
| 246 | 246 |
Image: "busybox", |
| 247 | 247 |
}, |
| 248 |
- &container.HostConfig{
|
|
| 248 |
+ HostConfig: &container.HostConfig{
|
|
| 249 | 249 |
Tmpfs: map[string]string{tc.target: ""},
|
| 250 | 250 |
}, |
| 251 |
- &network.NetworkingConfig{},
|
|
| 252 |
- nil, |
|
| 253 |
- "", |
|
| 254 |
- ) |
|
| 251 |
+ }) |
|
| 255 | 252 |
assert.Check(t, is.ErrorContains(err, tc.expectedError)) |
| 256 | 253 |
assert.Check(t, is.ErrorType(err, cerrdefs.IsInvalidArgument)) |
| 257 | 254 |
} |
| ... | ... |
@@ -298,19 +282,17 @@ func TestCreateWithCustomMaskedPaths(t *testing.T) {
|
| 298 | 298 |
t.Parallel() |
| 299 | 299 |
|
| 300 | 300 |
// Create the container. |
| 301 |
- ctr, err := apiClient.ContainerCreate(ctx, |
|
| 302 |
- &container.Config{
|
|
| 301 |
+ ctr, err := apiClient.ContainerCreate(ctx, client.ContainerCreateOptions{
|
|
| 302 |
+ Config: &container.Config{
|
|
| 303 | 303 |
Image: "busybox", |
| 304 | 304 |
Cmd: []string{"true"},
|
| 305 | 305 |
}, |
| 306 |
- &container.HostConfig{
|
|
| 306 |
+ HostConfig: &container.HostConfig{
|
|
| 307 | 307 |
Privileged: tc.privileged, |
| 308 | 308 |
MaskedPaths: tc.maskedPaths, |
| 309 | 309 |
}, |
| 310 |
- nil, |
|
| 311 |
- nil, |
|
| 312 |
- fmt.Sprintf("create-masked-paths-%d", i),
|
|
| 313 |
- ) |
|
| 310 |
+ ContainerName: fmt.Sprintf("create-masked-paths-%d", i),
|
|
| 311 |
+ }) |
|
| 314 | 312 |
assert.NilError(t, err) |
| 315 | 313 |
|
| 316 | 314 |
ctrInspect, err := apiClient.ContainerInspect(ctx, ctr.ID) |
| ... | ... |
@@ -371,19 +353,17 @@ func TestCreateWithCustomReadonlyPaths(t *testing.T) {
|
| 371 | 371 |
for i, tc := range testCases {
|
| 372 | 372 |
t.Run(tc.doc, func(t *testing.T) {
|
| 373 | 373 |
t.Parallel() |
| 374 |
- ctr, err := apiClient.ContainerCreate(ctx, |
|
| 375 |
- &container.Config{
|
|
| 374 |
+ ctr, err := apiClient.ContainerCreate(ctx, client.ContainerCreateOptions{
|
|
| 375 |
+ Config: &container.Config{
|
|
| 376 | 376 |
Image: "busybox", |
| 377 | 377 |
Cmd: []string{"true"},
|
| 378 | 378 |
}, |
| 379 |
- &container.HostConfig{
|
|
| 379 |
+ HostConfig: &container.HostConfig{
|
|
| 380 | 380 |
Privileged: tc.privileged, |
| 381 | 381 |
ReadonlyPaths: tc.readonlyPaths, |
| 382 | 382 |
}, |
| 383 |
- nil, |
|
| 384 |
- nil, |
|
| 385 |
- fmt.Sprintf("create-readonly-paths-%d", i),
|
|
| 386 |
- ) |
|
| 383 |
+ ContainerName: fmt.Sprintf("create-readonly-paths-%d", i),
|
|
| 384 |
+ }) |
|
| 387 | 385 |
assert.NilError(t, err) |
| 388 | 386 |
|
| 389 | 387 |
ctrInspect, err := apiClient.ContainerInspect(ctx, ctr.ID) |
| ... | ... |
@@ -482,7 +462,9 @@ func TestCreateWithInvalidHealthcheckParams(t *testing.T) {
|
| 482 | 482 |
cfg.Healthcheck.StartPeriod = tc.startPeriod |
| 483 | 483 |
} |
| 484 | 484 |
|
| 485 |
- resp, err := apiClient.ContainerCreate(ctx, &cfg, &container.HostConfig{}, nil, nil, "")
|
|
| 485 |
+ resp, err := apiClient.ContainerCreate(ctx, client.ContainerCreateOptions{
|
|
| 486 |
+ Config: &cfg, |
|
| 487 |
+ }) |
|
| 486 | 488 |
assert.Check(t, is.Equal(len(resp.Warnings), 0)) |
| 487 | 489 |
assert.Check(t, is.ErrorType(err, cerrdefs.IsInvalidArgument)) |
| 488 | 490 |
assert.ErrorContains(t, err, tc.expectedErr) |
| ... | ... |
@@ -553,7 +535,10 @@ func TestCreateDifferentPlatform(t *testing.T) {
|
| 553 | 553 |
Architecture: img.Architecture, |
| 554 | 554 |
Variant: img.Variant, |
| 555 | 555 |
} |
| 556 |
- _, err := apiClient.ContainerCreate(ctx, &container.Config{Image: "busybox:latest"}, &container.HostConfig{}, nil, &p, "")
|
|
| 556 |
+ _, err := apiClient.ContainerCreate(ctx, client.ContainerCreateOptions{
|
|
| 557 |
+ Config: &container.Config{Image: "busybox:latest"},
|
|
| 558 |
+ Platform: &p, |
|
| 559 |
+ }) |
|
| 557 | 560 |
assert.Check(t, is.ErrorType(err, cerrdefs.IsNotFound)) |
| 558 | 561 |
}) |
| 559 | 562 |
t.Run("different cpu arch", func(t *testing.T) {
|
| ... | ... |
@@ -563,7 +548,10 @@ func TestCreateDifferentPlatform(t *testing.T) {
|
| 563 | 563 |
Architecture: img.Architecture + "DifferentArch", |
| 564 | 564 |
Variant: img.Variant, |
| 565 | 565 |
} |
| 566 |
- _, err := apiClient.ContainerCreate(ctx, &container.Config{Image: "busybox:latest"}, &container.HostConfig{}, nil, &p, "")
|
|
| 566 |
+ _, err := apiClient.ContainerCreate(ctx, client.ContainerCreateOptions{
|
|
| 567 |
+ Config: &container.Config{Image: "busybox:latest"},
|
|
| 568 |
+ Platform: &p, |
|
| 569 |
+ }) |
|
| 567 | 570 |
assert.Check(t, is.ErrorType(err, cerrdefs.IsNotFound)) |
| 568 | 571 |
}) |
| 569 | 572 |
} |
| ... | ... |
@@ -574,12 +562,10 @@ func TestCreateVolumesFromNonExistingContainer(t *testing.T) {
|
| 574 | 574 |
|
| 575 | 575 |
_, err := apiClient.ContainerCreate( |
| 576 | 576 |
ctx, |
| 577 |
- &container.Config{Image: "busybox"},
|
|
| 578 |
- &container.HostConfig{VolumesFrom: []string{"nosuchcontainer"}},
|
|
| 579 |
- nil, |
|
| 580 |
- nil, |
|
| 581 |
- "", |
|
| 582 |
- ) |
|
| 577 |
+ client.ContainerCreateOptions{
|
|
| 578 |
+ Config: &container.Config{Image: "busybox"},
|
|
| 579 |
+ HostConfig: &container.HostConfig{VolumesFrom: []string{"nosuchcontainer"}},
|
|
| 580 |
+ }) |
|
| 583 | 581 |
assert.Check(t, is.ErrorType(err, cerrdefs.IsInvalidArgument)) |
| 584 | 582 |
} |
| 585 | 583 |
|
| ... | ... |
@@ -594,12 +580,9 @@ func TestCreatePlatformSpecificImageNoPlatform(t *testing.T) {
|
| 594 | 594 |
|
| 595 | 595 |
_, err := apiClient.ContainerCreate( |
| 596 | 596 |
ctx, |
| 597 |
- &container.Config{Image: "arm32v7/hello-world"},
|
|
| 598 |
- &container.HostConfig{},
|
|
| 599 |
- nil, |
|
| 600 |
- nil, |
|
| 601 |
- "", |
|
| 602 |
- ) |
|
| 597 |
+ client.ContainerCreateOptions{
|
|
| 598 |
+ Config: &container.Config{Image: "arm32v7/hello-world"},
|
|
| 599 |
+ }) |
|
| 603 | 600 |
assert.NilError(t, err) |
| 604 | 601 |
} |
| 605 | 602 |
|
| ... | ... |
@@ -653,7 +636,10 @@ func TestCreateInvalidHostConfig(t *testing.T) {
|
| 653 | 653 |
cfg := container.Config{
|
| 654 | 654 |
Image: "busybox", |
| 655 | 655 |
} |
| 656 |
- resp, err := apiClient.ContainerCreate(ctx, &cfg, &tc.hc, nil, nil, "") |
|
| 656 |
+ resp, err := apiClient.ContainerCreate(ctx, client.ContainerCreateOptions{
|
|
| 657 |
+ Config: &cfg, |
|
| 658 |
+ HostConfig: &tc.hc, |
|
| 659 |
+ }) |
|
| 657 | 660 |
assert.Check(t, is.Equal(len(resp.Warnings), 0)) |
| 658 | 661 |
assert.Check(t, cerrdefs.IsInvalidArgument(err), "got: %T", err) |
| 659 | 662 |
assert.Error(t, err, tc.expectedErr) |
| ... | ... |
@@ -760,7 +746,10 @@ func TestCreateWithMultipleEndpointSettings(t *testing.T) {
|
| 760 | 760 |
"net3": {},
|
| 761 | 761 |
}, |
| 762 | 762 |
} |
| 763 |
- _, err = apiClient.ContainerCreate(ctx, &config, &container.HostConfig{}, &networkingConfig, nil, "")
|
|
| 763 |
+ _, err = apiClient.ContainerCreate(ctx, client.ContainerCreateOptions{
|
|
| 764 |
+ Config: &config, |
|
| 765 |
+ NetworkingConfig: &networkingConfig, |
|
| 766 |
+ }) |
|
| 764 | 767 |
if tc.expectedErr == "" {
|
| 765 | 768 |
assert.NilError(t, err) |
| 766 | 769 |
} else {
|
| ... | ... |
@@ -5,6 +5,7 @@ import ( |
| 5 | 5 |
"time" |
| 6 | 6 |
|
| 7 | 7 |
containertypes "github.com/moby/moby/api/types/container" |
| 8 |
+ "github.com/moby/moby/client" |
|
| 8 | 9 |
"github.com/moby/moby/v2/integration/internal/container" |
| 9 | 10 |
"gotest.tools/v3/assert" |
| 10 | 11 |
"gotest.tools/v3/poll" |
| ... | ... |
@@ -24,9 +25,9 @@ func TestDiff(t *testing.T) {
|
| 24 | 24 |
} |
| 25 | 25 |
|
| 26 | 26 |
poll.WaitOn(t, container.IsStopped(ctx, apiClient, cID)) |
| 27 |
- items, err := apiClient.ContainerDiff(ctx, cID) |
|
| 27 |
+ result, err := apiClient.ContainerDiff(ctx, cID, client.ContainerDiffOptions{})
|
|
| 28 | 28 |
assert.NilError(t, err) |
| 29 |
- assert.DeepEqual(t, expected, items) |
|
| 29 |
+ assert.DeepEqual(t, expected, result.Changes) |
|
| 30 | 30 |
} |
| 31 | 31 |
|
| 32 | 32 |
func TestDiffStoppedContainer(t *testing.T) {
|
| ... | ... |
@@ -51,7 +52,7 @@ func TestDiffStoppedContainer(t *testing.T) {
|
| 51 | 51 |
} |
| 52 | 52 |
} |
| 53 | 53 |
|
| 54 |
- items, err := apiClient.ContainerDiff(ctx, cID) |
|
| 54 |
+ result, err := apiClient.ContainerDiff(ctx, cID, client.ContainerDiffOptions{})
|
|
| 55 | 55 |
assert.NilError(t, err) |
| 56 |
- assert.DeepEqual(t, expected, items) |
|
| 56 |
+ assert.DeepEqual(t, expected, result.Changes) |
|
| 57 | 57 |
} |
| ... | ... |
@@ -64,7 +64,10 @@ func testIpcNonePrivateShareable(t *testing.T, mode string, mustBeMounted bool, |
| 64 | 64 |
} |
| 65 | 65 |
apiClient := testEnv.APIClient() |
| 66 | 66 |
|
| 67 |
- resp, err := apiClient.ContainerCreate(ctx, &cfg, &hostCfg, nil, nil, "") |
|
| 67 |
+ resp, err := apiClient.ContainerCreate(ctx, client.ContainerCreateOptions{
|
|
| 68 |
+ Config: &cfg, |
|
| 69 |
+ HostConfig: &hostCfg, |
|
| 70 |
+ }) |
|
| 68 | 71 |
assert.NilError(t, err) |
| 69 | 72 |
assert.Check(t, is.Equal(len(resp.Warnings), 0)) |
| 70 | 73 |
|
| ... | ... |
@@ -135,7 +138,10 @@ func testIpcContainer(t *testing.T, donorMode string, mustWork bool) {
|
| 135 | 135 |
apiClient := testEnv.APIClient() |
| 136 | 136 |
|
| 137 | 137 |
// create and start the "donor" container |
| 138 |
- resp, err := apiClient.ContainerCreate(ctx, &cfg, &hostCfg, nil, nil, "") |
|
| 138 |
+ resp, err := apiClient.ContainerCreate(ctx, client.ContainerCreateOptions{
|
|
| 139 |
+ Config: &cfg, |
|
| 140 |
+ HostConfig: &hostCfg, |
|
| 141 |
+ }) |
|
| 139 | 142 |
assert.NilError(t, err) |
| 140 | 143 |
assert.Check(t, is.Equal(len(resp.Warnings), 0)) |
| 141 | 144 |
name1 := resp.ID |
| ... | ... |
@@ -145,7 +151,10 @@ func testIpcContainer(t *testing.T, donorMode string, mustWork bool) {
|
| 145 | 145 |
|
| 146 | 146 |
// create and start the second container |
| 147 | 147 |
hostCfg.IpcMode = containertypes.IpcMode("container:" + name1)
|
| 148 |
- resp, err = apiClient.ContainerCreate(ctx, &cfg, &hostCfg, nil, nil, "") |
|
| 148 |
+ resp, err = apiClient.ContainerCreate(ctx, client.ContainerCreateOptions{
|
|
| 149 |
+ Config: &cfg, |
|
| 150 |
+ HostConfig: &hostCfg, |
|
| 151 |
+ }) |
|
| 149 | 152 |
assert.NilError(t, err) |
| 150 | 153 |
assert.Check(t, is.Equal(len(resp.Warnings), 0)) |
| 151 | 154 |
name2 := resp.ID |
| ... | ... |
@@ -201,7 +210,10 @@ func TestAPIIpcModeHost(t *testing.T) {
|
| 201 | 201 |
ctx := testutil.StartSpan(baseContext, t) |
| 202 | 202 |
|
| 203 | 203 |
apiClient := testEnv.APIClient() |
| 204 |
- resp, err := apiClient.ContainerCreate(ctx, &cfg, &hostCfg, nil, nil, "") |
|
| 204 |
+ resp, err := apiClient.ContainerCreate(ctx, client.ContainerCreateOptions{
|
|
| 205 |
+ Config: &cfg, |
|
| 206 |
+ HostConfig: &hostCfg, |
|
| 207 |
+ }) |
|
| 205 | 208 |
assert.NilError(t, err) |
| 206 | 209 |
assert.Check(t, is.Equal(len(resp.Warnings), 0)) |
| 207 | 210 |
name := resp.ID |
| ... | ... |
@@ -237,7 +249,10 @@ func testDaemonIpcPrivateShareable(t *testing.T, mustBeShared bool, arg ...strin |
| 237 | 237 |
Cmd: []string{"top"},
|
| 238 | 238 |
} |
| 239 | 239 |
|
| 240 |
- resp, err := c.ContainerCreate(ctx, &cfg, &containertypes.HostConfig{}, nil, nil, "")
|
|
| 240 |
+ resp, err := c.ContainerCreate(ctx, client.ContainerCreateOptions{
|
|
| 241 |
+ Config: &cfg, |
|
| 242 |
+ HostConfig: &containertypes.HostConfig{},
|
|
| 243 |
+ }) |
|
| 241 | 244 |
assert.NilError(t, err) |
| 242 | 245 |
assert.Check(t, is.Equal(len(resp.Warnings), 0)) |
| 243 | 246 |
|
| ... | ... |
@@ -67,7 +67,11 @@ func TestContainerNetworkMountsNoChown(t *testing.T) {
|
| 67 | 67 |
assert.NilError(t, err) |
| 68 | 68 |
defer cli.Close() |
| 69 | 69 |
|
| 70 |
- ctrCreate, err := cli.ContainerCreate(ctx, &config, &hostConfig, &network.NetworkingConfig{}, nil, "")
|
|
| 70 |
+ ctrCreate, err := cli.ContainerCreate(ctx, client.ContainerCreateOptions{
|
|
| 71 |
+ Config: &config, |
|
| 72 |
+ HostConfig: &hostConfig, |
|
| 73 |
+ NetworkingConfig: &network.NetworkingConfig{},
|
|
| 74 |
+ }) |
|
| 71 | 75 |
assert.NilError(t, err) |
| 72 | 76 |
// container will exit immediately because of no tty, but we only need the start sequence to test the condition |
| 73 | 77 |
err = cli.ContainerStart(ctx, ctrCreate.ID, client.ContainerStartOptions{})
|
| ... | ... |
@@ -179,10 +183,13 @@ func TestMountDaemonRoot(t *testing.T) {
|
| 179 | 179 |
|
| 180 | 180 |
ctx := testutil.StartSpan(ctx, t) |
| 181 | 181 |
|
| 182 |
- c, err := apiClient.ContainerCreate(ctx, &containertypes.Config{
|
|
| 183 |
- Image: "busybox", |
|
| 184 |
- Cmd: []string{"true"},
|
|
| 185 |
- }, hc, nil, nil, "") |
|
| 182 |
+ c, err := apiClient.ContainerCreate(ctx, client.ContainerCreateOptions{
|
|
| 183 |
+ Config: &containertypes.Config{
|
|
| 184 |
+ Image: "busybox", |
|
| 185 |
+ Cmd: []string{"true"},
|
|
| 186 |
+ }, |
|
| 187 |
+ HostConfig: hc, |
|
| 188 |
+ }) |
|
| 186 | 189 |
if err != nil {
|
| 187 | 190 |
if test.expected != "" {
|
| 188 | 191 |
t.Fatal(err) |
| ... | ... |
@@ -430,7 +437,13 @@ func TestContainerVolumeAnonymous(t *testing.T) {
|
| 430 | 430 |
}, |
| 431 | 431 |
}, |
| 432 | 432 |
})) |
| 433 |
- _, err := apiClient.ContainerCreate(ctx, config.Config, config.HostConfig, config.NetworkingConfig, config.Platform, config.Name) |
|
| 433 |
+ _, err := apiClient.ContainerCreate(ctx, client.ContainerCreateOptions{
|
|
| 434 |
+ Config: config.Config, |
|
| 435 |
+ HostConfig: config.HostConfig, |
|
| 436 |
+ NetworkingConfig: config.NetworkingConfig, |
|
| 437 |
+ Platform: config.Platform, |
|
| 438 |
+ ContainerName: config.Name, |
|
| 439 |
+ }) |
|
| 434 | 440 |
// We use [testNonExistingPlugin] for this, which produces an error |
| 435 | 441 |
// when used, which we use as indicator that the driver was passed |
| 436 | 442 |
// through. We should have a cleaner way for this, but that would |
| ... | ... |
@@ -28,7 +28,7 @@ func TestNoOverlayfsWarningsAboutUndefinedBehaviors(t *testing.T) {
|
| 28 | 28 |
operation func(t *testing.T) error |
| 29 | 29 |
}{
|
| 30 | 30 |
{name: "diff", operation: func(*testing.T) error {
|
| 31 |
- _, err := apiClient.ContainerDiff(ctx, cID) |
|
| 31 |
+ _, err := apiClient.ContainerDiff(ctx, cID, client.ContainerDiffOptions{})
|
|
| 32 | 32 |
return err |
| 33 | 33 |
}}, |
| 34 | 34 |
{name: "export", operation: func(*testing.T) error {
|
| ... | ... |
@@ -100,7 +100,10 @@ func TestDaemonRestartKillContainers(t *testing.T) {
|
| 100 | 100 |
Interval: 60 * time.Second, |
| 101 | 101 |
} |
| 102 | 102 |
} |
| 103 |
- resp, err := apiClient.ContainerCreate(ctx, &config, &hostConfig, nil, nil, "") |
|
| 103 |
+ resp, err := apiClient.ContainerCreate(ctx, client.ContainerCreateOptions{
|
|
| 104 |
+ Config: &config, |
|
| 105 |
+ HostConfig: &hostConfig, |
|
| 106 |
+ }) |
|
| 104 | 107 |
assert.NilError(t, err) |
| 105 | 108 |
defer apiClient.ContainerRemove(ctx, resp.ID, client.ContainerRemoveOptions{Force: true})
|
| 106 | 109 |
|
| ... | ... |
@@ -55,10 +55,13 @@ func TestGraphDriverPersistence(t *testing.T) {
|
| 55 | 55 |
assert.Check(t, info.DriverStatus[0][1] != "io.containerd.snapshotter.v1") |
| 56 | 56 |
prevDriver := info.Driver |
| 57 | 57 |
|
| 58 |
- containerResp, err := c.ContainerCreate(ctx, &containertypes.Config{
|
|
| 59 |
- Image: testImage, |
|
| 60 |
- Cmd: []string{"echo", "test"},
|
|
| 61 |
- }, nil, nil, nil, "test-container") |
|
| 58 |
+ containerResp, err := c.ContainerCreate(ctx, client.ContainerCreateOptions{
|
|
| 59 |
+ Config: &containertypes.Config{
|
|
| 60 |
+ Image: testImage, |
|
| 61 |
+ Cmd: []string{"echo", "test"},
|
|
| 62 |
+ }, |
|
| 63 |
+ ContainerName: "test-container", |
|
| 64 |
+ }) |
|
| 62 | 65 |
assert.NilError(t, err, "Failed to create container") |
| 63 | 66 |
|
| 64 | 67 |
containerID := containerResp.ID |
| ... | ... |
@@ -141,7 +144,7 @@ func TestInspectGraphDriverAPIBC(t *testing.T) {
|
| 141 | 141 |
} |
| 142 | 142 |
|
| 143 | 143 |
const testImage = "busybox:latest" |
| 144 |
- ctr, err := c.ContainerCreate(ctx, &containertypes.Config{Image: testImage}, nil, nil, nil, "test-container")
|
|
| 144 |
+ ctr, err := c.ContainerCreate(ctx, client.ContainerCreateOptions{Image: testImage, Name: "test-container"})
|
|
| 145 | 145 |
assert.NilError(t, err) |
| 146 | 146 |
defer func() { _ = c.ContainerRemove(ctx, ctr.ID, client.ContainerRemoveOptions{Force: true}) }()
|
| 147 | 147 |
|
| ... | ... |
@@ -55,7 +55,13 @@ func NewTestConfig(ops ...func(*TestContainerConfig)) *TestContainerConfig {
|
| 55 | 55 |
func Create(ctx context.Context, t *testing.T, apiClient client.APIClient, ops ...func(*TestContainerConfig)) string {
|
| 56 | 56 |
t.Helper() |
| 57 | 57 |
config := NewTestConfig(ops...) |
| 58 |
- c, err := apiClient.ContainerCreate(ctx, config.Config, config.HostConfig, config.NetworkingConfig, config.Platform, config.Name) |
|
| 58 |
+ c, err := apiClient.ContainerCreate(ctx, client.ContainerCreateOptions{
|
|
| 59 |
+ Config: config.Config, |
|
| 60 |
+ HostConfig: config.HostConfig, |
|
| 61 |
+ NetworkingConfig: config.NetworkingConfig, |
|
| 62 |
+ Platform: config.Platform, |
|
| 63 |
+ ContainerName: config.Name, |
|
| 64 |
+ }) |
|
| 59 | 65 |
assert.NilError(t, err) |
| 60 | 66 |
|
| 61 | 67 |
return c.ID |
| ... | ... |
@@ -67,8 +73,14 @@ func Create(ctx context.Context, t *testing.T, apiClient client.APIClient, ops . |
| 67 | 67 |
// |
| 68 | 68 |
// ctr, err := container.CreateFromConfig(ctx, apiClient, container.NewTestConfig(container.WithAutoRemove)) |
| 69 | 69 |
// assert.Check(t, err) |
| 70 |
-func CreateFromConfig(ctx context.Context, apiClient client.APIClient, config *TestContainerConfig) (container.CreateResponse, error) {
|
|
| 71 |
- return apiClient.ContainerCreate(ctx, config.Config, config.HostConfig, config.NetworkingConfig, config.Platform, config.Name) |
|
| 70 |
+func CreateFromConfig(ctx context.Context, apiClient client.APIClient, config *TestContainerConfig) (client.ContainerCreateResult, error) {
|
|
| 71 |
+ return apiClient.ContainerCreate(ctx, client.ContainerCreateOptions{
|
|
| 72 |
+ Config: config.Config, |
|
| 73 |
+ HostConfig: config.HostConfig, |
|
| 74 |
+ NetworkingConfig: config.NetworkingConfig, |
|
| 75 |
+ Platform: config.Platform, |
|
| 76 |
+ ContainerName: config.Name, |
|
| 77 |
+ }) |
|
| 72 | 78 |
} |
| 73 | 79 |
|
| 74 | 80 |
// Run creates and start a container with the specified options |
| ... | ... |
@@ -108,7 +120,7 @@ func RunAttach(ctx context.Context, t *testing.T, apiClient client.APIClient, op |
| 108 | 108 |
err = apiClient.ContainerStart(ctx, id, client.ContainerStartOptions{})
|
| 109 | 109 |
assert.NilError(t, err) |
| 110 | 110 |
|
| 111 |
- s, err := demultiplexStreams(ctx, aresp) |
|
| 111 |
+ s, err := demultiplexStreams(ctx, aresp.HijackedResponse) |
|
| 112 | 112 |
if !errors.Is(err, context.DeadlineExceeded) && !errors.Is(err, context.Canceled) {
|
| 113 | 113 |
assert.NilError(t, err) |
| 114 | 114 |
} |
| ... | ... |
@@ -963,7 +963,13 @@ func TestEmptyPortBindingsBC(t *testing.T) {
|
| 963 | 963 |
config := ctr.NewTestConfig(ctr.WithCmd("top"),
|
| 964 | 964 |
ctr.WithExposedPorts("80/tcp"),
|
| 965 | 965 |
ctr.WithPortMap(networktypes.PortMap{networktypes.MustParsePort("80/tcp"): pbs}))
|
| 966 |
- c, err := apiClient.ContainerCreate(ctx, config.Config, config.HostConfig, config.NetworkingConfig, config.Platform, config.Name) |
|
| 966 |
+ c, err := apiClient.ContainerCreate(ctx, client.ContainerCreateOptions{
|
|
| 967 |
+ Config: config.Config, |
|
| 968 |
+ HostConfig: config.HostConfig, |
|
| 969 |
+ NetworkingConfig: config.NetworkingConfig, |
|
| 970 |
+ Platform: config.Platform, |
|
| 971 |
+ ContainerName: config.Name, |
|
| 972 |
+ }) |
|
| 967 | 973 |
assert.NilError(t, err) |
| 968 | 974 |
defer apiClient.ContainerRemove(ctx, c.ID, client.ContainerRemoveOptions{Force: true})
|
| 969 | 975 |
|
| ... | ... |
@@ -54,13 +54,12 @@ func TestReadPluginNoRead(t *testing.T) {
|
| 54 | 54 |
ctx := testutil.StartSpan(ctx, t) |
| 55 | 55 |
d.Start(t, append([]string{"--iptables=false", "--ip6tables=false"}, test.dOpts...)...)
|
| 56 | 56 |
defer d.Stop(t) |
| 57 |
- c, err := apiclient.ContainerCreate(ctx, |
|
| 58 |
- cfg, |
|
| 59 |
- &container.HostConfig{LogConfig: container.LogConfig{Type: "test"}},
|
|
| 60 |
- nil, |
|
| 61 |
- nil, |
|
| 62 |
- "", |
|
| 63 |
- ) |
|
| 57 |
+ c, err := apiclient.ContainerCreate(ctx, client.ContainerCreateOptions{
|
|
| 58 |
+ Config: cfg, |
|
| 59 |
+ HostConfig: &container.HostConfig{
|
|
| 60 |
+ LogConfig: container.LogConfig{Type: "test"},
|
|
| 61 |
+ }, |
|
| 62 |
+ }) |
|
| 64 | 63 |
assert.Assert(t, err) |
| 65 | 64 |
defer apiclient.ContainerRemove(ctx, c.ID, client.ContainerRemoveOptions{Force: true})
|
| 66 | 65 |
|
| ... | ... |
@@ -80,7 +80,12 @@ func TestRunMountVolumeSubdir(t *testing.T) {
|
| 80 | 80 |
} |
| 81 | 81 |
|
| 82 | 82 |
ctrName := strings.ReplaceAll(t.Name(), "/", "_") |
| 83 |
- create, creatErr := apiClient.ContainerCreate(ctx, &cfg, &hostCfg, &network.NetworkingConfig{}, nil, ctrName)
|
|
| 83 |
+ create, creatErr := apiClient.ContainerCreate(ctx, client.ContainerCreateOptions{
|
|
| 84 |
+ Config: &cfg, |
|
| 85 |
+ HostConfig: &hostCfg, |
|
| 86 |
+ NetworkingConfig: &network.NetworkingConfig{},
|
|
| 87 |
+ ContainerName: ctrName, |
|
| 88 |
+ }) |
|
| 84 | 89 |
id := create.ID |
| 85 | 90 |
if id != "" {
|
| 86 | 91 |
defer apiClient.ContainerRemove(ctx, id, client.ContainerRemoveOptions{Force: true})
|
| ... | ... |
@@ -175,7 +180,12 @@ func TestRunMountImage(t *testing.T) {
|
| 175 | 175 |
} |
| 176 | 176 |
|
| 177 | 177 |
ctrName := strings.ReplaceAll(t.Name(), "/", "_") |
| 178 |
- create, creatErr := apiClient.ContainerCreate(ctx, &cfg, &hostCfg, &network.NetworkingConfig{}, nil, ctrName)
|
|
| 178 |
+ create, creatErr := apiClient.ContainerCreate(ctx, client.ContainerCreateOptions{
|
|
| 179 |
+ Config: &cfg, |
|
| 180 |
+ HostConfig: &hostCfg, |
|
| 181 |
+ NetworkingConfig: &network.NetworkingConfig{},
|
|
| 182 |
+ ContainerName: ctrName, |
|
| 183 |
+ }) |
|
| 179 | 184 |
id := create.ID |
| 180 | 185 |
if id != "" {
|
| 181 | 186 |
defer container.Remove(ctx, t, apiClient, id, client.ContainerRemoveOptions{Force: true})
|
| ... | ... |
@@ -154,10 +154,11 @@ COPY . /static`); err != nil {
|
| 154 | 154 |
assert.NilError(t, err) |
| 155 | 155 |
|
| 156 | 156 |
// Start the container |
| 157 |
- b, err := c.ContainerCreate(context.Background(), |
|
| 158 |
- &containertypes.Config{Image: imgName},
|
|
| 159 |
- &containertypes.HostConfig{PublishAllPorts: true},
|
|
| 160 |
- nil, nil, ctrName) |
|
| 157 |
+ b, err := c.ContainerCreate(context.Background(), client.ContainerCreateOptions{
|
|
| 158 |
+ Config: &containertypes.Config{Image: imgName},
|
|
| 159 |
+ HostConfig: &containertypes.HostConfig{PublishAllPorts: true},
|
|
| 160 |
+ ContainerName: ctrName, |
|
| 161 |
+ }) |
|
| 161 | 162 |
assert.NilError(t, err) |
| 162 | 163 |
err = c.ContainerStart(context.Background(), b.ID, client.ContainerStartOptions{})
|
| 163 | 164 |
assert.NilError(t, err) |
| ... | ... |
@@ -12,7 +12,6 @@ import ( |
| 12 | 12 |
"github.com/moby/moby/api/types/registry" |
| 13 | 13 |
"github.com/moby/moby/api/types/swarm" |
| 14 | 14 |
"github.com/moby/moby/api/types/system" |
| 15 |
- ocispec "github.com/opencontainers/image-spec/specs-go/v1" |
|
| 16 | 15 |
) |
| 17 | 16 |
|
| 18 | 17 |
// APIClient is an interface that clients that talk with a docker server must implement. |
| ... | ... |
@@ -58,10 +57,10 @@ type HijackDialer interface {
|
| 58 | 58 |
|
| 59 | 59 |
// ContainerAPIClient defines API client methods for the containers |
| 60 | 60 |
type ContainerAPIClient interface {
|
| 61 |
- ContainerAttach(ctx context.Context, container string, options ContainerAttachOptions) (HijackedResponse, error) |
|
| 62 |
- ContainerCommit(ctx context.Context, container string, options ContainerCommitOptions) (container.CommitResponse, error) |
|
| 63 |
- ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, platform *ocispec.Platform, containerName string) (container.CreateResponse, error) |
|
| 64 |
- ContainerDiff(ctx context.Context, container string) ([]container.FilesystemChange, error) |
|
| 61 |
+ ContainerAttach(ctx context.Context, container string, options ContainerAttachOptions) (ContainerAttachResult, error) |
|
| 62 |
+ ContainerCommit(ctx context.Context, container string, options ContainerCommitOptions) (ContainerCommitResult, error) |
|
| 63 |
+ ContainerCreate(ctx context.Context, options ContainerCreateOptions) (ContainerCreateResult, error) |
|
| 64 |
+ ContainerDiff(ctx context.Context, container string, options ContainerDiffOptions) (ContainerDiffResult, error) |
|
| 65 | 65 |
ExecAPIClient |
| 66 | 66 |
ContainerExport(ctx context.Context, container string) (io.ReadCloser, error) |
| 67 | 67 |
ContainerInspect(ctx context.Context, container string) (container.InspectResponse, error) |
| ... | ... |
@@ -16,6 +16,11 @@ type ContainerAttachOptions struct {
|
| 16 | 16 |
Logs bool |
| 17 | 17 |
} |
| 18 | 18 |
|
| 19 |
+// ContainerAttachResult is the result from attaching to a container. |
|
| 20 |
+type ContainerAttachResult struct {
|
|
| 21 |
+ HijackedResponse |
|
| 22 |
+} |
|
| 23 |
+ |
|
| 19 | 24 |
// ContainerAttach attaches a connection to a container in the server. |
| 20 | 25 |
// It returns a [HijackedResponse] with the hijacked connection |
| 21 | 26 |
// and a reader to get output. It's up to the called to close |
| ... | ... |
@@ -44,10 +49,10 @@ type ContainerAttachOptions struct {
|
| 44 | 44 |
// [stdcopy.StdType]: https://pkg.go.dev/github.com/moby/moby/api/pkg/stdcopy#StdType |
| 45 | 45 |
// [Stdout]: https://pkg.go.dev/github.com/moby/moby/api/pkg/stdcopy#Stdout |
| 46 | 46 |
// [Stderr]: https://pkg.go.dev/github.com/moby/moby/api/pkg/stdcopy#Stderr |
| 47 |
-func (cli *Client) ContainerAttach(ctx context.Context, containerID string, options ContainerAttachOptions) (HijackedResponse, error) {
|
|
| 47 |
+func (cli *Client) ContainerAttach(ctx context.Context, containerID string, options ContainerAttachOptions) (ContainerAttachResult, error) {
|
|
| 48 | 48 |
containerID, err := trimID("container", containerID)
|
| 49 | 49 |
if err != nil {
|
| 50 |
- return HijackedResponse{}, err
|
|
| 50 |
+ return ContainerAttachResult{}, err
|
|
| 51 | 51 |
} |
| 52 | 52 |
|
| 53 | 53 |
query := url.Values{}
|
| ... | ... |
@@ -70,7 +75,12 @@ func (cli *Client) ContainerAttach(ctx context.Context, containerID string, opti |
| 70 | 70 |
query.Set("logs", "1")
|
| 71 | 71 |
} |
| 72 | 72 |
|
| 73 |
- return cli.postHijacked(ctx, "/containers/"+containerID+"/attach", query, nil, http.Header{
|
|
| 73 |
+ hijacked, err := cli.postHijacked(ctx, "/containers/"+containerID+"/attach", query, nil, http.Header{
|
|
| 74 | 74 |
"Content-Type": {"text/plain"},
|
| 75 | 75 |
}) |
| 76 |
+ if err != nil {
|
|
| 77 |
+ return ContainerAttachResult{}, err
|
|
| 78 |
+ } |
|
| 79 |
+ |
|
| 80 |
+ return ContainerAttachResult{HijackedResponse: hijacked}, nil
|
|
| 76 | 81 |
} |
| ... | ... |
@@ -20,22 +20,27 @@ type ContainerCommitOptions struct {
|
| 20 | 20 |
Config *container.Config |
| 21 | 21 |
} |
| 22 | 22 |
|
| 23 |
+// ContainerCommitResult is the result from committing a container. |
|
| 24 |
+type ContainerCommitResult struct {
|
|
| 25 |
+ ID string |
|
| 26 |
+} |
|
| 27 |
+ |
|
| 23 | 28 |
// ContainerCommit applies changes to a container and creates a new tagged image. |
| 24 |
-func (cli *Client) ContainerCommit(ctx context.Context, containerID string, options ContainerCommitOptions) (container.CommitResponse, error) {
|
|
| 29 |
+func (cli *Client) ContainerCommit(ctx context.Context, containerID string, options ContainerCommitOptions) (ContainerCommitResult, error) {
|
|
| 25 | 30 |
containerID, err := trimID("container", containerID)
|
| 26 | 31 |
if err != nil {
|
| 27 |
- return container.CommitResponse{}, err
|
|
| 32 |
+ return ContainerCommitResult{}, err
|
|
| 28 | 33 |
} |
| 29 | 34 |
|
| 30 | 35 |
var repository, tag string |
| 31 | 36 |
if options.Reference != "" {
|
| 32 | 37 |
ref, err := reference.ParseNormalizedNamed(options.Reference) |
| 33 | 38 |
if err != nil {
|
| 34 |
- return container.CommitResponse{}, err
|
|
| 39 |
+ return ContainerCommitResult{}, err
|
|
| 35 | 40 |
} |
| 36 | 41 |
|
| 37 | 42 |
if _, ok := ref.(reference.Digested); ok {
|
| 38 |
- return container.CommitResponse{}, errors.New("refusing to create a tag with a digest reference")
|
|
| 43 |
+ return ContainerCommitResult{}, errors.New("refusing to create a tag with a digest reference")
|
|
| 39 | 44 |
} |
| 40 | 45 |
ref = reference.TagNameOnly(ref) |
| 41 | 46 |
|
| ... | ... |
@@ -62,9 +67,9 @@ func (cli *Client) ContainerCommit(ctx context.Context, containerID string, opti |
| 62 | 62 |
resp, err := cli.post(ctx, "/commit", query, options.Config, nil) |
| 63 | 63 |
defer ensureReaderClosed(resp) |
| 64 | 64 |
if err != nil {
|
| 65 |
- return response, err |
|
| 65 |
+ return ContainerCommitResult{}, err
|
|
| 66 | 66 |
} |
| 67 | 67 |
|
| 68 | 68 |
err = json.NewDecoder(resp.Body).Decode(&response) |
| 69 |
- return response, err |
|
| 69 |
+ return ContainerCommitResult{ID: response.ID}, err
|
|
| 70 | 70 |
} |
| ... | ... |
@@ -10,49 +10,48 @@ import ( |
| 10 | 10 |
|
| 11 | 11 |
cerrdefs "github.com/containerd/errdefs" |
| 12 | 12 |
"github.com/moby/moby/api/types/container" |
| 13 |
- "github.com/moby/moby/api/types/network" |
|
| 14 | 13 |
ocispec "github.com/opencontainers/image-spec/specs-go/v1" |
| 15 | 14 |
) |
| 16 | 15 |
|
| 17 | 16 |
// ContainerCreate creates a new container based on the given configuration. |
| 18 | 17 |
// It can be associated with a name, but it's not mandatory. |
| 19 |
-func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, platform *ocispec.Platform, containerName string) (container.CreateResponse, error) {
|
|
| 20 |
- if config == nil {
|
|
| 21 |
- return container.CreateResponse{}, cerrdefs.ErrInvalidArgument.WithMessage("config is nil")
|
|
| 18 |
+func (cli *Client) ContainerCreate(ctx context.Context, options ContainerCreateOptions) (ContainerCreateResult, error) {
|
|
| 19 |
+ if options.Config == nil {
|
|
| 20 |
+ return ContainerCreateResult{}, cerrdefs.ErrInvalidArgument.WithMessage("config is nil")
|
|
| 22 | 21 |
} |
| 23 | 22 |
|
| 24 | 23 |
var response container.CreateResponse |
| 25 | 24 |
|
| 26 |
- if hostConfig != nil {
|
|
| 27 |
- hostConfig.CapAdd = normalizeCapabilities(hostConfig.CapAdd) |
|
| 28 |
- hostConfig.CapDrop = normalizeCapabilities(hostConfig.CapDrop) |
|
| 25 |
+ if options.HostConfig != nil {
|
|
| 26 |
+ options.HostConfig.CapAdd = normalizeCapabilities(options.HostConfig.CapAdd) |
|
| 27 |
+ options.HostConfig.CapDrop = normalizeCapabilities(options.HostConfig.CapDrop) |
|
| 29 | 28 |
} |
| 30 | 29 |
|
| 31 | 30 |
query := url.Values{}
|
| 32 |
- if platform != nil {
|
|
| 33 |
- if p := formatPlatform(*platform); p != "unknown" {
|
|
| 31 |
+ if options.Platform != nil {
|
|
| 32 |
+ if p := formatPlatform(*options.Platform); p != "unknown" {
|
|
| 34 | 33 |
query.Set("platform", p)
|
| 35 | 34 |
} |
| 36 | 35 |
} |
| 37 | 36 |
|
| 38 |
- if containerName != "" {
|
|
| 39 |
- query.Set("name", containerName)
|
|
| 37 |
+ if options.ContainerName != "" {
|
|
| 38 |
+ query.Set("name", options.ContainerName)
|
|
| 40 | 39 |
} |
| 41 | 40 |
|
| 42 | 41 |
body := container.CreateRequest{
|
| 43 |
- Config: config, |
|
| 44 |
- HostConfig: hostConfig, |
|
| 45 |
- NetworkingConfig: networkingConfig, |
|
| 42 |
+ Config: options.Config, |
|
| 43 |
+ HostConfig: options.HostConfig, |
|
| 44 |
+ NetworkingConfig: options.NetworkingConfig, |
|
| 46 | 45 |
} |
| 47 | 46 |
|
| 48 | 47 |
resp, err := cli.post(ctx, "/containers/create", query, body, nil) |
| 49 | 48 |
defer ensureReaderClosed(resp) |
| 50 | 49 |
if err != nil {
|
| 51 |
- return response, err |
|
| 50 |
+ return ContainerCreateResult{}, err
|
|
| 52 | 51 |
} |
| 53 | 52 |
|
| 54 | 53 |
err = json.NewDecoder(resp.Body).Decode(&response) |
| 55 |
- return response, err |
|
| 54 |
+ return ContainerCreateResult{ID: response.ID, Warnings: response.Warnings}, err
|
|
| 56 | 55 |
} |
| 57 | 56 |
|
| 58 | 57 |
// formatPlatform returns a formatted string representing platform (e.g., "linux/arm/v7"). |
| 59 | 58 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,22 @@ |
| 0 |
+package client |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "github.com/moby/moby/api/types/container" |
|
| 4 |
+ "github.com/moby/moby/api/types/network" |
|
| 5 |
+ ocispec "github.com/opencontainers/image-spec/specs-go/v1" |
|
| 6 |
+) |
|
| 7 |
+ |
|
| 8 |
+// ContainerCreateOptions holds parameters to create a container. |
|
| 9 |
+type ContainerCreateOptions struct {
|
|
| 10 |
+ Config *container.Config |
|
| 11 |
+ HostConfig *container.HostConfig |
|
| 12 |
+ NetworkingConfig *network.NetworkingConfig |
|
| 13 |
+ Platform *ocispec.Platform |
|
| 14 |
+ ContainerName string |
|
| 15 |
+} |
|
| 16 |
+ |
|
| 17 |
+// ContainerCreateResult is the result from creating a container. |
|
| 18 |
+type ContainerCreateResult struct {
|
|
| 19 |
+ ID string |
|
| 20 |
+ Warnings []string |
|
| 21 |
+} |
| ... | ... |
@@ -9,22 +9,22 @@ import ( |
| 9 | 9 |
) |
| 10 | 10 |
|
| 11 | 11 |
// ContainerDiff shows differences in a container filesystem since it was started. |
| 12 |
-func (cli *Client) ContainerDiff(ctx context.Context, containerID string) ([]container.FilesystemChange, error) {
|
|
| 12 |
+func (cli *Client) ContainerDiff(ctx context.Context, containerID string, options ContainerDiffOptions) (ContainerDiffResult, error) {
|
|
| 13 | 13 |
containerID, err := trimID("container", containerID)
|
| 14 | 14 |
if err != nil {
|
| 15 |
- return nil, err |
|
| 15 |
+ return ContainerDiffResult{}, err
|
|
| 16 | 16 |
} |
| 17 | 17 |
|
| 18 | 18 |
resp, err := cli.get(ctx, "/containers/"+containerID+"/changes", url.Values{}, nil)
|
| 19 | 19 |
defer ensureReaderClosed(resp) |
| 20 | 20 |
if err != nil {
|
| 21 |
- return nil, err |
|
| 21 |
+ return ContainerDiffResult{}, err
|
|
| 22 | 22 |
} |
| 23 | 23 |
|
| 24 | 24 |
var changes []container.FilesystemChange |
| 25 | 25 |
err = json.NewDecoder(resp.Body).Decode(&changes) |
| 26 | 26 |
if err != nil {
|
| 27 |
- return nil, err |
|
| 27 |
+ return ContainerDiffResult{}, err
|
|
| 28 | 28 |
} |
| 29 |
- return changes, err |
|
| 29 |
+ return ContainerDiffResult{Changes: changes}, err
|
|
| 30 | 30 |
} |
| 31 | 31 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,13 @@ |
| 0 |
+package client |
|
| 1 |
+ |
|
| 2 |
+import "github.com/moby/moby/api/types/container" |
|
| 3 |
+ |
|
| 4 |
+// ContainerDiffOptions holds parameters to show differences in a container filesystem. |
|
| 5 |
+type ContainerDiffOptions struct {
|
|
| 6 |
+ // Currently no options, but this allows for future extensibility |
|
| 7 |
+} |
|
| 8 |
+ |
|
| 9 |
+// ContainerDiffResult is the result from showing differences in a container filesystem. |
|
| 10 |
+type ContainerDiffResult struct {
|
|
| 11 |
+ Changes []container.FilesystemChange |
|
| 12 |
+} |