mirror of
https://github.com/moby/moby.git
synced 2026-01-11 18:51:37 +00:00
client/container_create: Add Image outside of Config
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
This commit is contained in:
@@ -16,8 +16,23 @@ import (
|
||||
// ContainerCreate creates a new container based on the given configuration.
|
||||
// It can be associated with a name, but it's not mandatory.
|
||||
func (cli *Client) ContainerCreate(ctx context.Context, options ContainerCreateOptions) (ContainerCreateResult, error) {
|
||||
if options.Config == nil {
|
||||
return ContainerCreateResult{}, cerrdefs.ErrInvalidArgument.WithMessage("config is nil")
|
||||
cfg := options.Config
|
||||
|
||||
if cfg == nil {
|
||||
cfg = &container.Config{}
|
||||
}
|
||||
|
||||
if options.Image != "" {
|
||||
if cfg.Image != "" {
|
||||
return ContainerCreateResult{}, cerrdefs.ErrInvalidArgument.WithMessage("either Image or config.Image should be set")
|
||||
}
|
||||
newCfg := *cfg
|
||||
newCfg.Image = options.Image
|
||||
cfg = &newCfg
|
||||
}
|
||||
|
||||
if cfg.Image == "" {
|
||||
return ContainerCreateResult{}, cerrdefs.ErrInvalidArgument.WithMessage("config.Image or Image is required")
|
||||
}
|
||||
|
||||
var response container.CreateResponse
|
||||
@@ -39,7 +54,7 @@ func (cli *Client) ContainerCreate(ctx context.Context, options ContainerCreateO
|
||||
}
|
||||
|
||||
body := container.CreateRequest{
|
||||
Config: options.Config,
|
||||
Config: cfg,
|
||||
HostConfig: options.HostConfig,
|
||||
NetworkingConfig: options.NetworkingConfig,
|
||||
}
|
||||
|
||||
@@ -13,6 +13,9 @@ type ContainerCreateOptions struct {
|
||||
NetworkingConfig *network.NetworkingConfig
|
||||
Platform *ocispec.Platform
|
||||
Name string
|
||||
|
||||
// Image is a shortcut for Config.Image - only one of Image or Config.Image should be set.
|
||||
Image string
|
||||
}
|
||||
|
||||
// ContainerCreateResult is the result from creating a container.
|
||||
|
||||
@@ -23,20 +23,11 @@ func TestContainerCreateError(t *testing.T) {
|
||||
assert.NilError(t, err)
|
||||
|
||||
_, err = client.ContainerCreate(context.Background(), ContainerCreateOptions{Config: nil, Name: "nothing"})
|
||||
assert.Error(t, err, "config is nil")
|
||||
assert.Error(t, err, "config.Image or Image is required")
|
||||
assert.Check(t, is.ErrorType(err, cerrdefs.IsInvalidArgument))
|
||||
|
||||
_, err = client.ContainerCreate(context.Background(), ContainerCreateOptions{Config: &container.Config{}, Name: "nothing"})
|
||||
assert.Check(t, is.ErrorType(err, cerrdefs.IsInternal))
|
||||
|
||||
// 404 doesn't automatically means an unknown image
|
||||
client, err = NewClientWithOpts(
|
||||
WithMockClient(errorMock(http.StatusNotFound, "Server error")),
|
||||
)
|
||||
assert.NilError(t, err)
|
||||
|
||||
_, err = client.ContainerCreate(context.Background(), ContainerCreateOptions{Config: &container.Config{}, Name: "nothing"})
|
||||
assert.Check(t, is.ErrorType(err, cerrdefs.IsNotFound))
|
||||
assert.Check(t, is.ErrorType(err, cerrdefs.IsInvalidArgument))
|
||||
}
|
||||
|
||||
func TestContainerCreateImageNotFound(t *testing.T) {
|
||||
@@ -74,7 +65,7 @@ func TestContainerCreateWithName(t *testing.T) {
|
||||
)
|
||||
assert.NilError(t, err)
|
||||
|
||||
r, err := client.ContainerCreate(context.Background(), ContainerCreateOptions{Config: &container.Config{}, Name: "container_name"})
|
||||
r, err := client.ContainerCreate(context.Background(), ContainerCreateOptions{Config: &container.Config{Image: "test"}, Name: "container_name"})
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(r.ID, "container_id"))
|
||||
}
|
||||
@@ -103,7 +94,7 @@ func TestContainerCreateAutoRemove(t *testing.T) {
|
||||
)
|
||||
assert.NilError(t, err)
|
||||
|
||||
resp, err := client.ContainerCreate(context.Background(), ContainerCreateOptions{Config: &container.Config{}, HostConfig: &container.HostConfig{AutoRemove: true}})
|
||||
resp, err := client.ContainerCreate(context.Background(), ContainerCreateOptions{Config: &container.Config{Image: "test"}, HostConfig: &container.HostConfig{AutoRemove: true}})
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(resp.ID, "container_id"))
|
||||
}
|
||||
@@ -116,7 +107,7 @@ func TestContainerCreateConnectionError(t *testing.T) {
|
||||
client, err := NewClientWithOpts(WithAPIVersionNegotiation(), WithHost("tcp://no-such-host.invalid"))
|
||||
assert.NilError(t, err)
|
||||
|
||||
_, err = client.ContainerCreate(context.Background(), ContainerCreateOptions{Config: &container.Config{}})
|
||||
_, err = client.ContainerCreate(context.Background(), ContainerCreateOptions{Config: &container.Config{Image: "test"}})
|
||||
assert.Check(t, is.ErrorType(err, IsErrConnectionFailed))
|
||||
}
|
||||
|
||||
@@ -165,6 +156,6 @@ func TestContainerCreateCapabilities(t *testing.T) {
|
||||
)
|
||||
assert.NilError(t, err)
|
||||
|
||||
_, err = client.ContainerCreate(context.Background(), ContainerCreateOptions{Config: &container.Config{}, HostConfig: &container.HostConfig{CapAdd: inputCaps, CapDrop: inputCaps}})
|
||||
_, err = client.ContainerCreate(context.Background(), ContainerCreateOptions{Config: &container.Config{Image: "test"}, HostConfig: &container.HostConfig{CapAdd: inputCaps, CapDrop: inputCaps}})
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
@@ -557,7 +557,7 @@ func (s *DockerAPISuite) TestContainerAPICreateEmptyConfig(c *testing.T) {
|
||||
NetworkingConfig: &network.NetworkingConfig{},
|
||||
})
|
||||
|
||||
assert.ErrorContains(c, err, "no command specified")
|
||||
assert.ErrorContains(c, err, "config.Image or Image is required")
|
||||
}
|
||||
|
||||
func (s *DockerAPISuite) TestContainerAPICreateBridgeNetworkMode(c *testing.T) {
|
||||
|
||||
21
vendor/github.com/moby/moby/client/container_create.go
generated
vendored
21
vendor/github.com/moby/moby/client/container_create.go
generated
vendored
@@ -16,8 +16,23 @@ import (
|
||||
// ContainerCreate creates a new container based on the given configuration.
|
||||
// It can be associated with a name, but it's not mandatory.
|
||||
func (cli *Client) ContainerCreate(ctx context.Context, options ContainerCreateOptions) (ContainerCreateResult, error) {
|
||||
if options.Config == nil {
|
||||
return ContainerCreateResult{}, cerrdefs.ErrInvalidArgument.WithMessage("config is nil")
|
||||
cfg := options.Config
|
||||
|
||||
if cfg == nil {
|
||||
cfg = &container.Config{}
|
||||
}
|
||||
|
||||
if options.Image != "" {
|
||||
if cfg.Image != "" {
|
||||
return ContainerCreateResult{}, cerrdefs.ErrInvalidArgument.WithMessage("either Image or config.Image should be set")
|
||||
}
|
||||
newCfg := *cfg
|
||||
newCfg.Image = options.Image
|
||||
cfg = &newCfg
|
||||
}
|
||||
|
||||
if cfg.Image == "" {
|
||||
return ContainerCreateResult{}, cerrdefs.ErrInvalidArgument.WithMessage("config.Image or Image is required")
|
||||
}
|
||||
|
||||
var response container.CreateResponse
|
||||
@@ -39,7 +54,7 @@ func (cli *Client) ContainerCreate(ctx context.Context, options ContainerCreateO
|
||||
}
|
||||
|
||||
body := container.CreateRequest{
|
||||
Config: options.Config,
|
||||
Config: cfg,
|
||||
HostConfig: options.HostConfig,
|
||||
NetworkingConfig: options.NetworkingConfig,
|
||||
}
|
||||
|
||||
3
vendor/github.com/moby/moby/client/container_create_opts.go
generated
vendored
3
vendor/github.com/moby/moby/client/container_create_opts.go
generated
vendored
@@ -13,6 +13,9 @@ type ContainerCreateOptions struct {
|
||||
NetworkingConfig *network.NetworkingConfig
|
||||
Platform *ocispec.Platform
|
||||
Name string
|
||||
|
||||
// Image is a shortcut for Config.Image - only one of Image or Config.Image should be set.
|
||||
Image string
|
||||
}
|
||||
|
||||
// ContainerCreateResult is the result from creating a container.
|
||||
|
||||
Reference in New Issue
Block a user