Accept platform spec on container create
This enables image lookup when creating a container to fail when the reference exists but it is for the wrong platform. This prevents trying to run an image for the wrong platform, as can be the case with, for example binfmt_misc+qemu. Signed-off-by: Brian Goff <cpuguy83@gmail.com>
This commit is contained in:
parent
30d54e64f6
commit
7a9cb29fb9
28 changed files with 188 additions and 62 deletions
|
@ -9,6 +9,7 @@ import (
|
|||
"strconv"
|
||||
"syscall"
|
||||
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/docker/docker/api/server/httputils"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/backend"
|
||||
|
@ -19,6 +20,7 @@ import (
|
|||
"github.com/docker/docker/errdefs"
|
||||
"github.com/docker/docker/pkg/ioutils"
|
||||
"github.com/docker/docker/pkg/signal"
|
||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/net/websocket"
|
||||
|
@ -497,6 +499,28 @@ func (s *containerRouter) postContainersCreate(ctx context.Context, w http.Respo
|
|||
}
|
||||
}
|
||||
|
||||
var platform *specs.Platform
|
||||
if versions.GreaterThanOrEqualTo(version, "1.41") {
|
||||
if v := r.Form.Get("platform"); v != "" {
|
||||
p, err := platforms.Parse(v)
|
||||
if err != nil {
|
||||
return errdefs.InvalidParameter(err)
|
||||
}
|
||||
platform = &p
|
||||
}
|
||||
defaultPlatform := platforms.DefaultSpec()
|
||||
if platform == nil {
|
||||
platform = &defaultPlatform
|
||||
}
|
||||
if platform.OS == "" {
|
||||
platform.OS = defaultPlatform.OS
|
||||
}
|
||||
if platform.Architecture == "" {
|
||||
platform.Architecture = defaultPlatform.Architecture
|
||||
platform.Variant = defaultPlatform.Variant
|
||||
}
|
||||
}
|
||||
|
||||
if hostConfig != nil && hostConfig.PidsLimit != nil && *hostConfig.PidsLimit <= 0 {
|
||||
// Don't set a limit if either no limit was specified, or "unlimited" was
|
||||
// explicitly set.
|
||||
|
@ -511,6 +535,7 @@ func (s *containerRouter) postContainersCreate(ctx context.Context, w http.Respo
|
|||
HostConfig: hostConfig,
|
||||
NetworkingConfig: networkingConfig,
|
||||
AdjustCPUShares: adjustCPUShares,
|
||||
Platform: platform,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -3,6 +3,7 @@ package types // import "github.com/docker/docker/api/types"
|
|||
import (
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/network"
|
||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// configs holds structs used for internal communication between the
|
||||
|
@ -15,6 +16,7 @@ type ContainerCreateConfig struct {
|
|||
Config *container.Config
|
||||
HostConfig *container.HostConfig
|
||||
NetworkingConfig *network.NetworkingConfig
|
||||
Platform *specs.Platform
|
||||
AdjustCPUShares bool
|
||||
}
|
||||
|
||||
|
|
|
@ -5,20 +5,23 @@ import (
|
|||
"encoding/json"
|
||||
"net/url"
|
||||
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/network"
|
||||
"github.com/docker/docker/api/types/versions"
|
||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
type configWrapper struct {
|
||||
*container.Config
|
||||
HostConfig *container.HostConfig
|
||||
NetworkingConfig *network.NetworkingConfig
|
||||
Platform *specs.Platform
|
||||
}
|
||||
|
||||
// ContainerCreate creates a new container based in the given configuration.
|
||||
// It can be associated with a name, but it's not mandatory.
|
||||
func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, containerName string) (container.ContainerCreateCreatedBody, error) {
|
||||
func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, platform *specs.Platform, containerName string) (container.ContainerCreateCreatedBody, error) {
|
||||
var response container.ContainerCreateCreatedBody
|
||||
|
||||
if err := cli.NewVersionError("1.25", "stop timeout"); config != nil && config.StopTimeout != nil && err != nil {
|
||||
|
@ -30,7 +33,15 @@ func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config
|
|||
hostConfig.AutoRemove = false
|
||||
}
|
||||
|
||||
if err := cli.NewVersionError("1.41", "specify container image platform"); platform != nil && err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
query := url.Values{}
|
||||
if platform != nil {
|
||||
query.Set("platform", platforms.Format(*platform))
|
||||
}
|
||||
|
||||
if containerName != "" {
|
||||
query.Set("name", containerName)
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ func TestContainerCreateError(t *testing.T) {
|
|||
client := &Client{
|
||||
client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
|
||||
}
|
||||
_, err := client.ContainerCreate(context.Background(), nil, nil, nil, "nothing")
|
||||
_, err := client.ContainerCreate(context.Background(), nil, nil, nil, nil, "nothing")
|
||||
if !errdefs.IsSystem(err) {
|
||||
t.Fatalf("expected a Server Error while testing StatusInternalServerError, got %T", err)
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ func TestContainerCreateError(t *testing.T) {
|
|||
client = &Client{
|
||||
client: newMockClient(errorMock(http.StatusNotFound, "Server error")),
|
||||
}
|
||||
_, err = client.ContainerCreate(context.Background(), nil, nil, nil, "nothing")
|
||||
_, err = client.ContainerCreate(context.Background(), nil, nil, nil, nil, "nothing")
|
||||
if err == nil || !IsErrNotFound(err) {
|
||||
t.Fatalf("expected a Server Error while testing StatusNotFound, got %T", err)
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ func TestContainerCreateImageNotFound(t *testing.T) {
|
|||
client := &Client{
|
||||
client: newMockClient(errorMock(http.StatusNotFound, "No such image")),
|
||||
}
|
||||
_, err := client.ContainerCreate(context.Background(), &container.Config{Image: "unknown_image"}, nil, nil, "unknown")
|
||||
_, err := client.ContainerCreate(context.Background(), &container.Config{Image: "unknown_image"}, nil, nil, nil, "unknown")
|
||||
if err == nil || !IsErrNotFound(err) {
|
||||
t.Fatalf("expected an imageNotFound error, got %v, %T", err, err)
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ func TestContainerCreateWithName(t *testing.T) {
|
|||
}),
|
||||
}
|
||||
|
||||
r, err := client.ContainerCreate(context.Background(), nil, nil, nil, "container_name")
|
||||
r, err := client.ContainerCreate(context.Background(), nil, nil, nil, nil, "container_name")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -106,14 +106,14 @@ func TestContainerCreateAutoRemove(t *testing.T) {
|
|||
client: newMockClient(autoRemoveValidator(false)),
|
||||
version: "1.24",
|
||||
}
|
||||
if _, err := client.ContainerCreate(context.Background(), nil, &container.HostConfig{AutoRemove: true}, nil, ""); err != nil {
|
||||
if _, err := client.ContainerCreate(context.Background(), nil, &container.HostConfig{AutoRemove: true}, nil, nil, ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
client = &Client{
|
||||
client: newMockClient(autoRemoveValidator(true)),
|
||||
version: "1.25",
|
||||
}
|
||||
if _, err := client.ContainerCreate(context.Background(), nil, &container.HostConfig{AutoRemove: true}, nil, ""); err != nil {
|
||||
if _, err := client.ContainerCreate(context.Background(), nil, &container.HostConfig{AutoRemove: true}, nil, nil, ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import (
|
|||
"github.com/docker/docker/api/types/registry"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
volumetypes "github.com/docker/docker/api/types/volume"
|
||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// CommonAPIClient is the common methods between stable and experimental versions of APIClient.
|
||||
|
@ -47,7 +48,7 @@ type CommonAPIClient interface {
|
|||
type ContainerAPIClient interface {
|
||||
ContainerAttach(ctx context.Context, container string, options types.ContainerAttachOptions) (types.HijackedResponse, error)
|
||||
ContainerCommit(ctx context.Context, container string, options types.ContainerCommitOptions) (types.IDResponse, error)
|
||||
ContainerCreate(ctx context.Context, config *containertypes.Config, hostConfig *containertypes.HostConfig, networkingConfig *networktypes.NetworkingConfig, containerName string) (containertypes.ContainerCreateCreatedBody, error)
|
||||
ContainerCreate(ctx context.Context, config *containertypes.Config, hostConfig *containertypes.HostConfig, networkingConfig *networktypes.NetworkingConfig, platform *specs.Platform, containerName string) (containertypes.ContainerCreateCreatedBody, error)
|
||||
ContainerDiff(ctx context.Context, container string) ([]containertypes.ContainerChangeResponseItem, 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)
|
||||
|
|
|
@ -60,7 +60,7 @@ func (daemon *Daemon) containerCreate(opts createOpts) (containertypes.Container
|
|||
|
||||
os := runtime.GOOS
|
||||
if opts.params.Config.Image != "" {
|
||||
img, err := daemon.imageService.GetImage(opts.params.Config.Image)
|
||||
img, err := daemon.imageService.GetImage(opts.params.Config.Image, opts.params.Platform)
|
||||
if err == nil {
|
||||
os = img.OS
|
||||
}
|
||||
|
@ -114,7 +114,7 @@ func (daemon *Daemon) create(opts createOpts) (retC *container.Container, retErr
|
|||
|
||||
os := runtime.GOOS
|
||||
if opts.params.Config.Image != "" {
|
||||
img, err = daemon.imageService.GetImage(opts.params.Config.Image)
|
||||
img, err = daemon.imageService.GetImage(opts.params.Config.Image, opts.params.Platform)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ func (i *ImageService) MakeImageCache(sourceRefs []string) builder.ImageCache {
|
|||
cache := cache.New(i.imageStore)
|
||||
|
||||
for _, ref := range sourceRefs {
|
||||
img, err := i.GetImage(ref)
|
||||
img, err := i.GetImage(ref, nil)
|
||||
if err != nil {
|
||||
logrus.Warnf("Could not look up %s for cache resolution, skipping: %+v", ref, err)
|
||||
continue
|
||||
|
|
|
@ -3,9 +3,12 @@ package images // import "github.com/docker/docker/daemon/images"
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/docker/docker/errdefs"
|
||||
"github.com/docker/docker/image"
|
||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// ErrImageDoesNotExist is error returned when no image can be found for a reference.
|
||||
|
@ -25,7 +28,39 @@ func (e ErrImageDoesNotExist) Error() string {
|
|||
func (e ErrImageDoesNotExist) NotFound() {}
|
||||
|
||||
// GetImage returns an image corresponding to the image referred to by refOrID.
|
||||
func (i *ImageService) GetImage(refOrID string) (*image.Image, error) {
|
||||
func (i *ImageService) GetImage(refOrID string, platform *specs.Platform) (retImg *image.Image, retErr error) {
|
||||
defer func() {
|
||||
if retErr != nil || retImg == nil || platform == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// This allows us to tell clients that we don't have the image they asked for
|
||||
// Where this gets hairy is the image store does not currently support multi-arch images, e.g.:
|
||||
// An image `foo` may have a multi-arch manifest, but the image store only fetches the image for a specific platform
|
||||
// The image store does not store the manifest list and image tags are assigned to architecture specific images.
|
||||
// So we can have a `foo` image that is amd64 but the user requested armv7. If the user looks at the list of images.
|
||||
// This may be confusing.
|
||||
// The alternative to this is to return a errdefs.Conflict error with a helpful message, but clients will not be
|
||||
// able to automatically tell what causes the conflict.
|
||||
if retImg.OS != platform.OS {
|
||||
retErr = errdefs.NotFound(errors.Errorf("image with reference %s was found but does not match the specified OS platform: wanted: %s, actual: %s", refOrID, platform.OS, retImg.OS))
|
||||
retImg = nil
|
||||
return
|
||||
}
|
||||
if retImg.Architecture != platform.Architecture {
|
||||
retErr = errdefs.NotFound(errors.Errorf("image with reference %s was found but does not match the specified platform cpu architecture: wanted: %s, actual: %s", refOrID, platform.Architecture, retImg.Architecture))
|
||||
retImg = nil
|
||||
return
|
||||
}
|
||||
|
||||
// Only validate variant if retImg has a variant set.
|
||||
// The image variant may not be set since it's a newer field.
|
||||
if platform.Variant != "" && retImg.Variant != "" && retImg.Variant != platform.Variant {
|
||||
retErr = errdefs.NotFound(errors.Errorf("image with reference %s was found but does not match the specified platform cpu architecture variant: wanted: %s, actual: %s", refOrID, platform.Variant, retImg.Variant))
|
||||
retImg = nil
|
||||
return
|
||||
}
|
||||
}()
|
||||
ref, err := reference.ParseAnyReference(refOrID)
|
||||
if err != nil {
|
||||
return nil, errdefs.InvalidParameter(err)
|
||||
|
|
|
@ -161,7 +161,7 @@ func (i *ImageService) pullForBuilder(ctx context.Context, name string, authConf
|
|||
if err := i.pullImageWithReference(ctx, ref, platform, nil, pullRegistryAuth, output); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return i.GetImage(name)
|
||||
return i.GetImage(name, platform)
|
||||
}
|
||||
|
||||
// GetImageAndReleasableLayer returns an image and releaseable layer for a reference or ID.
|
||||
|
@ -184,7 +184,7 @@ func (i *ImageService) GetImageAndReleasableLayer(ctx context.Context, refOrID s
|
|||
}
|
||||
|
||||
if opts.PullOption != backend.PullOptionForcePull {
|
||||
image, err := i.GetImage(refOrID)
|
||||
image, err := i.GetImage(refOrID, opts.Platform)
|
||||
if err != nil && opts.PullOption == backend.PullOptionNoPull {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ func (i *ImageService) ImageDelete(imageRef string, force, prune bool) ([]types.
|
|||
start := time.Now()
|
||||
records := []types.ImageDeleteResponseItem{}
|
||||
|
||||
img, err := i.GetImage(imageRef)
|
||||
img, err := i.GetImage(imageRef, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ func (i *ImageService) LogImageEvent(imageID, refName, action string) {
|
|||
|
||||
// LogImageEventWithAttributes generates an event related to an image with specific given attributes.
|
||||
func (i *ImageService) LogImageEventWithAttributes(imageID, refName, action string, attributes map[string]string) {
|
||||
img, err := i.GetImage(imageID)
|
||||
img, err := i.GetImage(imageID, nil)
|
||||
if err == nil && img.Config != nil {
|
||||
// image has not been removed yet.
|
||||
// it could be missing if the event is `delete`.
|
||||
|
|
|
@ -14,7 +14,7 @@ import (
|
|||
// name by walking the image lineage.
|
||||
func (i *ImageService) ImageHistory(name string) ([]*image.HistoryResponseItem, error) {
|
||||
start := time.Now()
|
||||
img, err := i.GetImage(name)
|
||||
img, err := i.GetImage(name, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ func (i *ImageService) ImageHistory(name string) ([]*image.HistoryResponseItem,
|
|||
if id == "" {
|
||||
break
|
||||
}
|
||||
histImg, err = i.GetImage(id.String())
|
||||
histImg, err = i.GetImage(id.String(), nil)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ import (
|
|||
// LookupImage looks up an image by name and returns it as an ImageInspect
|
||||
// structure.
|
||||
func (i *ImageService) LookupImage(name string) (*types.ImageInspect, error) {
|
||||
img, err := i.GetImage(name)
|
||||
img, err := i.GetImage(name, nil)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "no such image: %s", name)
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
// TagImage creates the tag specified by newTag, pointing to the image named
|
||||
// imageName (alternatively, imageName can also be an image ID).
|
||||
func (i *ImageService) TagImage(imageName, repository, tag string) (string, error) {
|
||||
img, err := i.GetImage(imageName)
|
||||
img, err := i.GetImage(imageName, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ func (i *ImageService) Images(imageFilters filters.Args, all bool, withExtraAttr
|
|||
|
||||
var beforeFilter, sinceFilter *image.Image
|
||||
err = imageFilters.WalkValues("before", func(value string) error {
|
||||
beforeFilter, err = i.GetImage(value)
|
||||
beforeFilter, err = i.GetImage(value, nil)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
|
@ -77,7 +77,7 @@ func (i *ImageService) Images(imageFilters filters.Args, all bool, withExtraAttr
|
|||
}
|
||||
|
||||
err = imageFilters.WalkValues("since", func(value string) error {
|
||||
sinceFilter, err = i.GetImage(value)
|
||||
sinceFilter, err = i.GetImage(value, nil)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
|
|
|
@ -317,7 +317,7 @@ func (daemon *Daemon) foldFilter(view container.View, config *types.ContainerLis
|
|||
if psFilters.Contains("ancestor") {
|
||||
ancestorFilter = true
|
||||
psFilters.WalkValues("ancestor", func(ancestor string) error {
|
||||
img, err := daemon.imageService.GetImage(ancestor)
|
||||
img, err := daemon.imageService.GetImage(ancestor, nil)
|
||||
if err != nil {
|
||||
logrus.Warnf("Error while looking up for image %v", ancestor)
|
||||
return nil
|
||||
|
@ -585,7 +585,7 @@ func (daemon *Daemon) refreshImage(s *container.Snapshot, ctx *listContext) (*ty
|
|||
c := s.Container
|
||||
image := s.Image // keep the original ref if still valid (hasn't changed)
|
||||
if image != s.ImageID {
|
||||
img, err := daemon.imageService.GetImage(image)
|
||||
img, err := daemon.imageService.GetImage(image, nil)
|
||||
if _, isDNE := err.(images.ErrImageDoesNotExist); err != nil && !isDNE {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ const (
|
|||
|
||||
func (daemon *Daemon) createSpec(c *container.Container) (*specs.Spec, error) {
|
||||
|
||||
img, err := daemon.imageService.GetImage(string(c.ImageID))
|
||||
img, err := daemon.imageService.GetImage(string(c.ImageID), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -523,7 +523,7 @@ func (s *DockerSuite) TestContainerAPIBadPort(c *testing.T) {
|
|||
assert.NilError(c, err)
|
||||
defer cli.Close()
|
||||
|
||||
_, err = cli.ContainerCreate(context.Background(), &config, &hostConfig, &networktypes.NetworkingConfig{}, "")
|
||||
_, err = cli.ContainerCreate(context.Background(), &config, &hostConfig, &networktypes.NetworkingConfig{}, nil, "")
|
||||
assert.ErrorContains(c, err, `invalid port specification: "aa80"`)
|
||||
}
|
||||
|
||||
|
@ -537,7 +537,7 @@ func (s *DockerSuite) TestContainerAPICreate(c *testing.T) {
|
|||
assert.NilError(c, err)
|
||||
defer cli.Close()
|
||||
|
||||
container, err := cli.ContainerCreate(context.Background(), &config, &containertypes.HostConfig{}, &networktypes.NetworkingConfig{}, "")
|
||||
container, err := cli.ContainerCreate(context.Background(), &config, &containertypes.HostConfig{}, &networktypes.NetworkingConfig{}, nil, "")
|
||||
assert.NilError(c, err)
|
||||
|
||||
out, _ := dockerCmd(c, "start", "-a", container.ID)
|
||||
|
@ -550,7 +550,7 @@ func (s *DockerSuite) TestContainerAPICreateEmptyConfig(c *testing.T) {
|
|||
assert.NilError(c, err)
|
||||
defer cli.Close()
|
||||
|
||||
_, err = cli.ContainerCreate(context.Background(), &containertypes.Config{}, &containertypes.HostConfig{}, &networktypes.NetworkingConfig{}, "")
|
||||
_, err = cli.ContainerCreate(context.Background(), &containertypes.Config{}, &containertypes.HostConfig{}, &networktypes.NetworkingConfig{}, nil, "")
|
||||
|
||||
expected := "No command specified"
|
||||
assert.ErrorContains(c, err, expected)
|
||||
|
@ -574,7 +574,7 @@ func (s *DockerSuite) TestContainerAPICreateMultipleNetworksConfig(c *testing.T)
|
|||
assert.NilError(c, err)
|
||||
defer cli.Close()
|
||||
|
||||
_, err = cli.ContainerCreate(context.Background(), &config, &containertypes.HostConfig{}, &networkingConfig, "")
|
||||
_, err = cli.ContainerCreate(context.Background(), &config, &containertypes.HostConfig{}, &networkingConfig, nil, "")
|
||||
msg := err.Error()
|
||||
// network name order in error message is not deterministic
|
||||
assert.Assert(c, strings.Contains(msg, "Container cannot be connected to network endpoints"))
|
||||
|
@ -609,7 +609,7 @@ func UtilCreateNetworkMode(c *testing.T, networkMode containertypes.NetworkMode)
|
|||
assert.NilError(c, err)
|
||||
defer cli.Close()
|
||||
|
||||
container, err := cli.ContainerCreate(context.Background(), &config, &hostConfig, &networktypes.NetworkingConfig{}, "")
|
||||
container, err := cli.ContainerCreate(context.Background(), &config, &hostConfig, &networktypes.NetworkingConfig{}, nil, "")
|
||||
assert.NilError(c, err)
|
||||
|
||||
containerJSON, err := cli.ContainerInspect(context.Background(), container.ID)
|
||||
|
@ -636,7 +636,7 @@ func (s *DockerSuite) TestContainerAPICreateWithCpuSharesCpuset(c *testing.T) {
|
|||
assert.NilError(c, err)
|
||||
defer cli.Close()
|
||||
|
||||
container, err := cli.ContainerCreate(context.Background(), &config, &hostConfig, &networktypes.NetworkingConfig{}, "")
|
||||
container, err := cli.ContainerCreate(context.Background(), &config, &hostConfig, &networktypes.NetworkingConfig{}, nil, "")
|
||||
assert.NilError(c, err)
|
||||
|
||||
containerJSON, err := cli.ContainerInspect(context.Background(), container.ID)
|
||||
|
@ -948,7 +948,7 @@ func (s *DockerSuite) TestContainerAPIStart(c *testing.T) {
|
|||
assert.NilError(c, err)
|
||||
defer cli.Close()
|
||||
|
||||
_, err = cli.ContainerCreate(context.Background(), &config, &containertypes.HostConfig{}, &networktypes.NetworkingConfig{}, name)
|
||||
_, err = cli.ContainerCreate(context.Background(), &config, &containertypes.HostConfig{}, &networktypes.NetworkingConfig{}, nil, name)
|
||||
assert.NilError(c, err)
|
||||
|
||||
err = cli.ContainerStart(context.Background(), name, types.ContainerStartOptions{})
|
||||
|
@ -1272,7 +1272,7 @@ func (s *DockerSuite) TestPostContainerAPICreateWithStringOrSliceEntrypoint(c *t
|
|||
assert.NilError(c, err)
|
||||
defer cli.Close()
|
||||
|
||||
_, err = cli.ContainerCreate(context.Background(), &config, &containertypes.HostConfig{}, &networktypes.NetworkingConfig{}, "echotest")
|
||||
_, err = cli.ContainerCreate(context.Background(), &config, &containertypes.HostConfig{}, &networktypes.NetworkingConfig{}, nil, "echotest")
|
||||
assert.NilError(c, err)
|
||||
out, _ := dockerCmd(c, "start", "-a", "echotest")
|
||||
assert.Equal(c, strings.TrimSpace(out), "hello world")
|
||||
|
@ -1299,7 +1299,7 @@ func (s *DockerSuite) TestPostContainersCreateWithStringOrSliceCmd(c *testing.T)
|
|||
assert.NilError(c, err)
|
||||
defer cli.Close()
|
||||
|
||||
_, err = cli.ContainerCreate(context.Background(), &config, &containertypes.HostConfig{}, &networktypes.NetworkingConfig{}, "echotest")
|
||||
_, err = cli.ContainerCreate(context.Background(), &config, &containertypes.HostConfig{}, &networktypes.NetworkingConfig{}, nil, "echotest")
|
||||
assert.NilError(c, err)
|
||||
out, _ := dockerCmd(c, "start", "-a", "echotest")
|
||||
assert.Equal(c, strings.TrimSpace(out), "hello world")
|
||||
|
@ -1342,7 +1342,7 @@ func (s *DockerSuite) TestPostContainersCreateWithStringOrSliceCapAddDrop(c *tes
|
|||
assert.NilError(c, err)
|
||||
defer cli.Close()
|
||||
|
||||
_, err = cli.ContainerCreate(context.Background(), &config2, &hostConfig, &networktypes.NetworkingConfig{}, "capaddtest1")
|
||||
_, err = cli.ContainerCreate(context.Background(), &config2, &hostConfig, &networktypes.NetworkingConfig{}, nil, "capaddtest1")
|
||||
assert.NilError(c, err)
|
||||
}
|
||||
|
||||
|
@ -1356,7 +1356,7 @@ func (s *DockerSuite) TestContainerAPICreateNoHostConfig118(c *testing.T) {
|
|||
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithVersion("v1.18"))
|
||||
assert.NilError(c, err)
|
||||
|
||||
_, err = cli.ContainerCreate(context.Background(), &config, &containertypes.HostConfig{}, &networktypes.NetworkingConfig{}, "")
|
||||
_, err = cli.ContainerCreate(context.Background(), &config, &containertypes.HostConfig{}, &networktypes.NetworkingConfig{}, nil, "")
|
||||
assert.NilError(c, err)
|
||||
}
|
||||
|
||||
|
@ -1407,7 +1407,7 @@ func (s *DockerSuite) TestPostContainersCreateWithWrongCpusetValues(c *testing.T
|
|||
}
|
||||
name := "wrong-cpuset-cpus"
|
||||
|
||||
_, err = cli.ContainerCreate(context.Background(), &config, &hostConfig1, &networktypes.NetworkingConfig{}, name)
|
||||
_, err = cli.ContainerCreate(context.Background(), &config, &hostConfig1, &networktypes.NetworkingConfig{}, nil, name)
|
||||
expected := "Invalid value 1-42,, for cpuset cpus"
|
||||
assert.ErrorContains(c, err, expected)
|
||||
|
||||
|
@ -1417,7 +1417,7 @@ func (s *DockerSuite) TestPostContainersCreateWithWrongCpusetValues(c *testing.T
|
|||
},
|
||||
}
|
||||
name = "wrong-cpuset-mems"
|
||||
_, err = cli.ContainerCreate(context.Background(), &config, &hostConfig2, &networktypes.NetworkingConfig{}, name)
|
||||
_, err = cli.ContainerCreate(context.Background(), &config, &hostConfig2, &networktypes.NetworkingConfig{}, nil, name)
|
||||
expected = "Invalid value 42-3,1-- for cpuset mems"
|
||||
assert.ErrorContains(c, err, expected)
|
||||
}
|
||||
|
@ -1436,7 +1436,7 @@ func (s *DockerSuite) TestPostContainersCreateShmSizeNegative(c *testing.T) {
|
|||
assert.NilError(c, err)
|
||||
defer cli.Close()
|
||||
|
||||
_, err = cli.ContainerCreate(context.Background(), &config, &hostConfig, &networktypes.NetworkingConfig{}, "")
|
||||
_, err = cli.ContainerCreate(context.Background(), &config, &hostConfig, &networktypes.NetworkingConfig{}, nil, "")
|
||||
assert.ErrorContains(c, err, "SHM size can not be less than 0")
|
||||
}
|
||||
|
||||
|
@ -1453,7 +1453,7 @@ func (s *DockerSuite) TestPostContainersCreateShmSizeHostConfigOmitted(c *testin
|
|||
assert.NilError(c, err)
|
||||
defer cli.Close()
|
||||
|
||||
container, err := cli.ContainerCreate(context.Background(), &config, &containertypes.HostConfig{}, &networktypes.NetworkingConfig{}, "")
|
||||
container, err := cli.ContainerCreate(context.Background(), &config, &containertypes.HostConfig{}, &networktypes.NetworkingConfig{}, nil, "")
|
||||
assert.NilError(c, err)
|
||||
|
||||
containerJSON, err := cli.ContainerInspect(context.Background(), container.ID)
|
||||
|
@ -1480,7 +1480,7 @@ func (s *DockerSuite) TestPostContainersCreateShmSizeOmitted(c *testing.T) {
|
|||
assert.NilError(c, err)
|
||||
defer cli.Close()
|
||||
|
||||
container, err := cli.ContainerCreate(context.Background(), &config, &containertypes.HostConfig{}, &networktypes.NetworkingConfig{}, "")
|
||||
container, err := cli.ContainerCreate(context.Background(), &config, &containertypes.HostConfig{}, &networktypes.NetworkingConfig{}, nil, "")
|
||||
assert.NilError(c, err)
|
||||
|
||||
containerJSON, err := cli.ContainerInspect(context.Background(), container.ID)
|
||||
|
@ -1511,7 +1511,7 @@ func (s *DockerSuite) TestPostContainersCreateWithShmSize(c *testing.T) {
|
|||
assert.NilError(c, err)
|
||||
defer cli.Close()
|
||||
|
||||
container, err := cli.ContainerCreate(context.Background(), &config, &hostConfig, &networktypes.NetworkingConfig{}, "")
|
||||
container, err := cli.ContainerCreate(context.Background(), &config, &hostConfig, &networktypes.NetworkingConfig{}, nil, "")
|
||||
assert.NilError(c, err)
|
||||
|
||||
containerJSON, err := cli.ContainerInspect(context.Background(), container.ID)
|
||||
|
@ -1537,7 +1537,7 @@ func (s *DockerSuite) TestPostContainersCreateMemorySwappinessHostConfigOmitted(
|
|||
assert.NilError(c, err)
|
||||
defer cli.Close()
|
||||
|
||||
container, err := cli.ContainerCreate(context.Background(), &config, &containertypes.HostConfig{}, &networktypes.NetworkingConfig{}, "")
|
||||
container, err := cli.ContainerCreate(context.Background(), &config, &containertypes.HostConfig{}, &networktypes.NetworkingConfig{}, nil, "")
|
||||
assert.NilError(c, err)
|
||||
|
||||
containerJSON, err := cli.ContainerInspect(context.Background(), container.ID)
|
||||
|
@ -1568,7 +1568,7 @@ func (s *DockerSuite) TestPostContainersCreateWithOomScoreAdjInvalidRange(c *tes
|
|||
defer cli.Close()
|
||||
|
||||
name := "oomscoreadj-over"
|
||||
_, err = cli.ContainerCreate(context.Background(), &config, &hostConfig, &networktypes.NetworkingConfig{}, name)
|
||||
_, err = cli.ContainerCreate(context.Background(), &config, &hostConfig, &networktypes.NetworkingConfig{}, nil, name)
|
||||
|
||||
expected := "Invalid value 1001, range for oom score adj is [-1000, 1000]"
|
||||
assert.ErrorContains(c, err, expected)
|
||||
|
@ -1578,7 +1578,7 @@ func (s *DockerSuite) TestPostContainersCreateWithOomScoreAdjInvalidRange(c *tes
|
|||
}
|
||||
|
||||
name = "oomscoreadj-low"
|
||||
_, err = cli.ContainerCreate(context.Background(), &config, &hostConfig, &networktypes.NetworkingConfig{}, name)
|
||||
_, err = cli.ContainerCreate(context.Background(), &config, &hostConfig, &networktypes.NetworkingConfig{}, nil, name)
|
||||
|
||||
expected = "Invalid value -1001, range for oom score adj is [-1000, 1000]"
|
||||
assert.ErrorContains(c, err, expected)
|
||||
|
@ -1610,7 +1610,7 @@ func (s *DockerSuite) TestContainerAPIStatsWithNetworkDisabled(c *testing.T) {
|
|||
assert.NilError(c, err)
|
||||
defer cli.Close()
|
||||
|
||||
_, err = cli.ContainerCreate(context.Background(), &config, &containertypes.HostConfig{}, &networktypes.NetworkingConfig{}, name)
|
||||
_, err = cli.ContainerCreate(context.Background(), &config, &containertypes.HostConfig{}, &networktypes.NetworkingConfig{}, nil, name)
|
||||
assert.NilError(c, err)
|
||||
|
||||
err = cli.ContainerStart(context.Background(), name, types.ContainerStartOptions{})
|
||||
|
@ -1926,7 +1926,7 @@ func (s *DockerSuite) TestContainersAPICreateMountsValidation(c *testing.T) {
|
|||
for i, x := range cases {
|
||||
x := x
|
||||
c.Run(fmt.Sprintf("case %d", i), func(c *testing.T) {
|
||||
_, err = apiClient.ContainerCreate(context.Background(), &x.config, &x.hostConfig, &networktypes.NetworkingConfig{}, "")
|
||||
_, err = apiClient.ContainerCreate(context.Background(), &x.config, &x.hostConfig, &networktypes.NetworkingConfig{}, nil, "")
|
||||
if len(x.msg) > 0 {
|
||||
assert.ErrorContains(c, err, x.msg, "%v", cases[i].config)
|
||||
} else {
|
||||
|
@ -1959,7 +1959,7 @@ func (s *DockerSuite) TestContainerAPICreateMountsBindRead(c *testing.T) {
|
|||
assert.NilError(c, err)
|
||||
defer cli.Close()
|
||||
|
||||
_, err = cli.ContainerCreate(context.Background(), &config, &hostConfig, &networktypes.NetworkingConfig{}, "test")
|
||||
_, err = cli.ContainerCreate(context.Background(), &config, &hostConfig, &networktypes.NetworkingConfig{}, nil, "test")
|
||||
assert.NilError(c, err)
|
||||
|
||||
out, _ := dockerCmd(c, "start", "-a", "test")
|
||||
|
@ -2106,6 +2106,7 @@ func (s *DockerSuite) TestContainersAPICreateMountsCreate(c *testing.T) {
|
|||
&containertypes.Config{Image: testImg},
|
||||
&containertypes.HostConfig{Mounts: []mounttypes.Mount{x.spec}},
|
||||
&networktypes.NetworkingConfig{},
|
||||
nil,
|
||||
"")
|
||||
assert.NilError(c, err)
|
||||
|
||||
|
@ -2213,7 +2214,7 @@ func (s *DockerSuite) TestContainersAPICreateMountsTmpfs(c *testing.T) {
|
|||
Mounts: []mounttypes.Mount{x.cfg},
|
||||
}
|
||||
|
||||
_, err = cli.ContainerCreate(context.Background(), &config, &hostConfig, &networktypes.NetworkingConfig{}, cName)
|
||||
_, err = cli.ContainerCreate(context.Background(), &config, &hostConfig, &networktypes.NetworkingConfig{}, nil, cName)
|
||||
assert.NilError(c, err)
|
||||
out, _ := dockerCmd(c, "start", "-a", cName)
|
||||
for _, option := range x.expectedOptions {
|
||||
|
|
|
@ -65,7 +65,7 @@ func (s *DockerSuite) TestContainersAPICreateMountsBindNamedPipe(c *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
nil, name)
|
||||
nil, nil, name)
|
||||
assert.NilError(c, err)
|
||||
|
||||
err = client.ContainerStart(ctx, name, types.ContainerStartOptions{})
|
||||
|
|
|
@ -578,7 +578,7 @@ func (s *DockerSuite) TestDuplicateMountpointsForVolumesFromAndMounts(c *testing
|
|||
},
|
||||
},
|
||||
}
|
||||
_, err = cli.ContainerCreate(context.Background(), &config, &hostConfig, &network.NetworkingConfig{}, "app")
|
||||
_, err = cli.ContainerCreate(context.Background(), &config, &hostConfig, &network.NetworkingConfig{}, nil, "app")
|
||||
|
||||
assert.NilError(c, err)
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
containertypes "github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/network"
|
||||
"github.com/docker/docker/api/types/versions"
|
||||
"github.com/docker/docker/client"
|
||||
|
@ -17,6 +18,7 @@ import (
|
|||
ctr "github.com/docker/docker/integration/internal/container"
|
||||
"github.com/docker/docker/oci"
|
||||
"github.com/docker/docker/testutil/request"
|
||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"gotest.tools/v3/assert"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
"gotest.tools/v3/poll"
|
||||
|
@ -57,6 +59,7 @@ func TestCreateFailsWhenIdentifierDoesNotExist(t *testing.T) {
|
|||
&container.Config{Image: tc.image},
|
||||
&container.HostConfig{},
|
||||
&network.NetworkingConfig{},
|
||||
nil,
|
||||
"",
|
||||
)
|
||||
assert.Check(t, is.ErrorContains(err, tc.expectedError))
|
||||
|
@ -81,6 +84,7 @@ func TestCreateLinkToNonExistingContainer(t *testing.T) {
|
|||
Links: []string{"no-such-container"},
|
||||
},
|
||||
&network.NetworkingConfig{},
|
||||
nil,
|
||||
"",
|
||||
)
|
||||
assert.Check(t, is.ErrorContains(err, "could not get container for no-such-container"))
|
||||
|
@ -120,6 +124,7 @@ func TestCreateWithInvalidEnv(t *testing.T) {
|
|||
},
|
||||
&container.HostConfig{},
|
||||
&network.NetworkingConfig{},
|
||||
nil,
|
||||
"",
|
||||
)
|
||||
assert.Check(t, is.ErrorContains(err, tc.expectedError))
|
||||
|
@ -166,6 +171,7 @@ func TestCreateTmpfsMountsTarget(t *testing.T) {
|
|||
Tmpfs: map[string]string{tc.target: ""},
|
||||
},
|
||||
&network.NetworkingConfig{},
|
||||
nil,
|
||||
"",
|
||||
)
|
||||
assert.Check(t, is.ErrorContains(err, tc.expectedError))
|
||||
|
@ -235,6 +241,7 @@ func TestCreateWithCustomMaskedPaths(t *testing.T) {
|
|||
&config,
|
||||
&hc,
|
||||
&network.NetworkingConfig{},
|
||||
nil,
|
||||
name,
|
||||
)
|
||||
assert.NilError(t, err)
|
||||
|
@ -361,6 +368,7 @@ func TestCreateWithCapabilities(t *testing.T) {
|
|||
&container.Config{Image: "busybox"},
|
||||
&tc.hostConfig,
|
||||
&network.NetworkingConfig{},
|
||||
nil,
|
||||
"",
|
||||
)
|
||||
if tc.expectedError == "" {
|
||||
|
@ -439,6 +447,7 @@ func TestCreateWithCustomReadonlyPaths(t *testing.T) {
|
|||
&config,
|
||||
&hc,
|
||||
&network.NetworkingConfig{},
|
||||
nil,
|
||||
name,
|
||||
)
|
||||
assert.NilError(t, err)
|
||||
|
@ -522,7 +531,7 @@ func TestCreateWithInvalidHealthcheckParams(t *testing.T) {
|
|||
cfg.Healthcheck.StartPeriod = tc.startPeriod
|
||||
}
|
||||
|
||||
resp, err := client.ContainerCreate(ctx, &cfg, &container.HostConfig{}, nil, "")
|
||||
resp, err := client.ContainerCreate(ctx, &cfg, &container.HostConfig{}, nil, nil, "")
|
||||
assert.Check(t, is.Equal(len(resp.Warnings), 0))
|
||||
|
||||
if versions.LessThan(testEnv.DaemonAPIVersion(), "1.32") {
|
||||
|
@ -581,3 +590,34 @@ func TestCreateTmpfsOverrideAnonymousVolume(t *testing.T) {
|
|||
assert.NilError(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Test that if the referenced image platform does not match the requested platform on container create that we get an
|
||||
// error.
|
||||
func TestCreateDifferentPlatform(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
c := testEnv.APIClient()
|
||||
ctx := context.Background()
|
||||
|
||||
img, _, err := c.ImageInspectWithRaw(ctx, "busybox:latest")
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, img.Architecture != "")
|
||||
|
||||
t.Run("different os", func(t *testing.T) {
|
||||
p := specs.Platform{
|
||||
OS: img.Os + "DifferentOS",
|
||||
Architecture: img.Architecture,
|
||||
Variant: img.Variant,
|
||||
}
|
||||
_, err := c.ContainerCreate(ctx, &containertypes.Config{Image: "busybox:latest"}, &containertypes.HostConfig{}, nil, &p, "")
|
||||
assert.Assert(t, client.IsErrNotFound(err), err)
|
||||
})
|
||||
t.Run("different cpu arch", func(t *testing.T) {
|
||||
p := specs.Platform{
|
||||
OS: img.Os,
|
||||
Architecture: img.Architecture + "DifferentArch",
|
||||
Variant: img.Variant,
|
||||
}
|
||||
_, err := c.ContainerCreate(ctx, &containertypes.Config{Image: "busybox:latest"}, &containertypes.HostConfig{}, nil, &p, "")
|
||||
assert.Assert(t, client.IsErrNotFound(err), err)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ func testIpcNonePrivateShareable(t *testing.T, mode string, mustBeMounted bool,
|
|||
client := testEnv.APIClient()
|
||||
ctx := context.Background()
|
||||
|
||||
resp, err := client.ContainerCreate(ctx, &cfg, &hostCfg, nil, "")
|
||||
resp, err := client.ContainerCreate(ctx, &cfg, &hostCfg, nil, nil, "")
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(len(resp.Warnings), 0))
|
||||
|
||||
|
@ -138,7 +138,7 @@ func testIpcContainer(t *testing.T, donorMode string, mustWork bool) {
|
|||
client := testEnv.APIClient()
|
||||
|
||||
// create and start the "donor" container
|
||||
resp, err := client.ContainerCreate(ctx, &cfg, &hostCfg, nil, "")
|
||||
resp, err := client.ContainerCreate(ctx, &cfg, &hostCfg, nil, nil, "")
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(len(resp.Warnings), 0))
|
||||
name1 := resp.ID
|
||||
|
@ -148,7 +148,7 @@ func testIpcContainer(t *testing.T, donorMode string, mustWork bool) {
|
|||
|
||||
// create and start the second container
|
||||
hostCfg.IpcMode = containertypes.IpcMode("container:" + name1)
|
||||
resp, err = client.ContainerCreate(ctx, &cfg, &hostCfg, nil, "")
|
||||
resp, err = client.ContainerCreate(ctx, &cfg, &hostCfg, nil, nil, "")
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(len(resp.Warnings), 0))
|
||||
name2 := resp.ID
|
||||
|
@ -204,7 +204,7 @@ func TestAPIIpcModeHost(t *testing.T) {
|
|||
ctx := context.Background()
|
||||
|
||||
client := testEnv.APIClient()
|
||||
resp, err := client.ContainerCreate(ctx, &cfg, &hostCfg, nil, "")
|
||||
resp, err := client.ContainerCreate(ctx, &cfg, &hostCfg, nil, nil, "")
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(len(resp.Warnings), 0))
|
||||
name := resp.ID
|
||||
|
@ -241,7 +241,7 @@ func testDaemonIpcPrivateShareable(t *testing.T, mustBeShared bool, arg ...strin
|
|||
}
|
||||
ctx := context.Background()
|
||||
|
||||
resp, err := c.ContainerCreate(ctx, &cfg, &containertypes.HostConfig{}, nil, "")
|
||||
resp, err := c.ContainerCreate(ctx, &cfg, &containertypes.HostConfig{}, nil, nil, "")
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(len(resp.Warnings), 0))
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ func TestContainerNetworkMountsNoChown(t *testing.T) {
|
|||
assert.NilError(t, err)
|
||||
defer cli.Close()
|
||||
|
||||
ctrCreate, err := cli.ContainerCreate(ctx, &config, &hostConfig, &network.NetworkingConfig{}, "")
|
||||
ctrCreate, err := cli.ContainerCreate(ctx, &config, &hostConfig, &network.NetworkingConfig{}, nil, "")
|
||||
assert.NilError(t, err)
|
||||
// container will exit immediately because of no tty, but we only need the start sequence to test the condition
|
||||
err = cli.ContainerStart(ctx, ctrCreate.ID, types.ContainerStartOptions{})
|
||||
|
@ -174,7 +174,7 @@ func TestMountDaemonRoot(t *testing.T) {
|
|||
c, err := client.ContainerCreate(ctx, &containertypes.Config{
|
||||
Image: "busybox",
|
||||
Cmd: []string{"true"},
|
||||
}, hc, nil, "")
|
||||
}, hc, nil, nil, "")
|
||||
|
||||
if err != nil {
|
||||
if test.expected != "" {
|
||||
|
|
|
@ -76,7 +76,7 @@ func TestDaemonRestartKillContainers(t *testing.T) {
|
|||
defer d.Stop(t)
|
||||
ctx := context.Background()
|
||||
|
||||
resp, err := client.ContainerCreate(ctx, c.config, c.hostConfig, nil, "")
|
||||
resp, err := client.ContainerCreate(ctx, c.config, c.hostConfig, nil, nil, "")
|
||||
assert.NilError(t, err)
|
||||
defer client.ContainerRemove(ctx, resp.ID, types.ContainerRemoveOptions{Force: true})
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/network"
|
||||
"github.com/docker/docker/client"
|
||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
|
||||
|
@ -19,6 +20,7 @@ type TestContainerConfig struct {
|
|||
Config *container.Config
|
||||
HostConfig *container.HostConfig
|
||||
NetworkingConfig *network.NetworkingConfig
|
||||
Platform *specs.Platform
|
||||
}
|
||||
|
||||
// create creates a container with the specified options
|
||||
|
@ -41,7 +43,7 @@ func create(ctx context.Context, t *testing.T, client client.APIClient, ops ...f
|
|||
op(config)
|
||||
}
|
||||
|
||||
return client.ContainerCreate(ctx, config.Config, config.HostConfig, config.NetworkingConfig, config.Name)
|
||||
return client.ContainerCreate(ctx, config.Config, config.HostConfig, config.NetworkingConfig, config.Platform, config.Name)
|
||||
}
|
||||
|
||||
// Create creates a container with the specified options, asserting that there was no error
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
networktypes "github.com/docker/docker/api/types/network"
|
||||
"github.com/docker/docker/api/types/strslice"
|
||||
"github.com/docker/go-connections/nat"
|
||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// WithName sets the name of the container
|
||||
|
@ -205,3 +206,10 @@ func WithExtraHost(extraHost string) func(*TestContainerConfig) {
|
|||
c.HostConfig.ExtraHosts = append(c.HostConfig.ExtraHosts, extraHost)
|
||||
}
|
||||
}
|
||||
|
||||
// WithPlatform specifies the desired platform the image should have.
|
||||
func WithPlatform(p *specs.Platform) func(*TestContainerConfig) {
|
||||
return func(c *TestContainerConfig) {
|
||||
c.Platform = p
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ func TestReadPluginNoRead(t *testing.T) {
|
|||
cfg,
|
||||
&container.HostConfig{LogConfig: container.LogConfig{Type: "test"}},
|
||||
nil,
|
||||
nil,
|
||||
"",
|
||||
)
|
||||
assert.Assert(t, err)
|
||||
|
|
|
@ -155,7 +155,7 @@ COPY . /static`); err != nil {
|
|||
// Start the container
|
||||
b, err := c.ContainerCreate(context.Background(), &containertypes.Config{
|
||||
Image: image,
|
||||
}, &containertypes.HostConfig{}, nil, container)
|
||||
}, &containertypes.HostConfig{}, nil, nil, container)
|
||||
assert.NilError(t, err)
|
||||
err = c.ContainerStart(context.Background(), b.ID, types.ContainerStartOptions{})
|
||||
assert.NilError(t, err)
|
||||
|
|
Loading…
Add table
Reference in a new issue