mirror of https://github.com/docker/cli.git
Set platform on container create API.
Previously we only set the platform when performing a pull, which is only initiated if pull always is set, or if the image reference does not exist in the daemon. The daemon now supports specifying which platform you wanted on container create so it can validate the image reference is the platform you thought you were getting. Signed-off-by: Brian Goff <cpuguy83@gmail.com>
This commit is contained in:
parent
8c986d3ff2
commit
ccd9d633bb
|
@ -8,6 +8,7 @@ import (
|
||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/docker/api/types/network"
|
"github.com/docker/docker/api/types/network"
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
|
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
type fakeClient struct {
|
type fakeClient struct {
|
||||||
|
@ -18,6 +19,7 @@ type fakeClient struct {
|
||||||
createContainerFunc func(config *container.Config,
|
createContainerFunc func(config *container.Config,
|
||||||
hostConfig *container.HostConfig,
|
hostConfig *container.HostConfig,
|
||||||
networkingConfig *network.NetworkingConfig,
|
networkingConfig *network.NetworkingConfig,
|
||||||
|
platform *specs.Platform,
|
||||||
containerName string) (container.ContainerCreateCreatedBody, error)
|
containerName string) (container.ContainerCreateCreatedBody, error)
|
||||||
containerStartFunc func(container string, options types.ContainerStartOptions) error
|
containerStartFunc func(container string, options types.ContainerStartOptions) error
|
||||||
imageCreateFunc func(parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error)
|
imageCreateFunc func(parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error)
|
||||||
|
@ -69,10 +71,11 @@ func (f *fakeClient) ContainerCreate(
|
||||||
config *container.Config,
|
config *container.Config,
|
||||||
hostConfig *container.HostConfig,
|
hostConfig *container.HostConfig,
|
||||||
networkingConfig *network.NetworkingConfig,
|
networkingConfig *network.NetworkingConfig,
|
||||||
|
platform *specs.Platform,
|
||||||
containerName string,
|
containerName string,
|
||||||
) (container.ContainerCreateCreatedBody, error) {
|
) (container.ContainerCreateCreatedBody, error) {
|
||||||
if f.createContainerFunc != nil {
|
if f.createContainerFunc != nil {
|
||||||
return f.createContainerFunc(config, hostConfig, networkingConfig, containerName)
|
return f.createContainerFunc(config, hostConfig, networkingConfig, platform, containerName)
|
||||||
}
|
}
|
||||||
return container.ContainerCreateCreatedBody{}, nil
|
return container.ContainerCreateCreatedBody{}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/platforms"
|
||||||
"github.com/docker/cli/cli"
|
"github.com/docker/cli/cli"
|
||||||
"github.com/docker/cli/cli/command"
|
"github.com/docker/cli/cli/command"
|
||||||
"github.com/docker/cli/cli/command/image"
|
"github.com/docker/cli/cli/command/image"
|
||||||
|
@ -14,9 +15,11 @@ import (
|
||||||
"github.com/docker/distribution/reference"
|
"github.com/docker/distribution/reference"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
|
"github.com/docker/docker/api/types/versions"
|
||||||
apiclient "github.com/docker/docker/client"
|
apiclient "github.com/docker/docker/client"
|
||||||
"github.com/docker/docker/pkg/jsonmessage"
|
"github.com/docker/docker/pkg/jsonmessage"
|
||||||
"github.com/docker/docker/registry"
|
"github.com/docker/docker/registry"
|
||||||
|
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
|
@ -233,13 +236,26 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerConfig
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var platform *specs.Platform
|
||||||
|
// Engine API version 1.41 first introduced the option to specify platform on
|
||||||
|
// create. It will produce an error if you try to set a platform on older API
|
||||||
|
// versions, so check the API version here to maintain backwards
|
||||||
|
// compatibility for CLI users.
|
||||||
|
if opts.platform != "" && versions.GreaterThanOrEqualTo(dockerCli.Client().ClientVersion(), "1.41") {
|
||||||
|
p, err := platforms.Parse(opts.platform)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "error parsing specified platform")
|
||||||
|
}
|
||||||
|
platform = &p
|
||||||
|
}
|
||||||
|
|
||||||
if opts.pull == PullImageAlways {
|
if opts.pull == PullImageAlways {
|
||||||
if err := pullAndTagImage(); err != nil {
|
if err := pullAndTagImage(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
response, err := dockerCli.Client().ContainerCreate(ctx, config, hostConfig, networkingConfig, opts.name)
|
response, err := dockerCli.Client().ContainerCreate(ctx, config, hostConfig, networkingConfig, platform, opts.name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Pull image if it does not exist locally and we have the PullImageMissing option. Default behavior.
|
// Pull image if it does not exist locally and we have the PullImageMissing option. Default behavior.
|
||||||
if apiclient.IsErrNotFound(err) && namedRef != nil && opts.pull == PullImageMissing {
|
if apiclient.IsErrNotFound(err) && namedRef != nil && opts.pull == PullImageMissing {
|
||||||
|
@ -250,7 +266,7 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
var retryErr error
|
var retryErr error
|
||||||
response, retryErr = dockerCli.Client().ContainerCreate(ctx, config, hostConfig, networkingConfig, opts.name)
|
response, retryErr = dockerCli.Client().ContainerCreate(ctx, config, hostConfig, networkingConfig, platform, opts.name)
|
||||||
if retryErr != nil {
|
if retryErr != nil {
|
||||||
return nil, retryErr
|
return nil, retryErr
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/docker/api/types/network"
|
"github.com/docker/docker/api/types/network"
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
|
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
"gotest.tools/v3/assert"
|
"gotest.tools/v3/assert"
|
||||||
is "gotest.tools/v3/assert/cmp"
|
is "gotest.tools/v3/assert/cmp"
|
||||||
"gotest.tools/v3/fs"
|
"gotest.tools/v3/fs"
|
||||||
|
@ -116,6 +117,7 @@ func TestCreateContainerImagePullPolicy(t *testing.T) {
|
||||||
config *container.Config,
|
config *container.Config,
|
||||||
hostConfig *container.HostConfig,
|
hostConfig *container.HostConfig,
|
||||||
networkingConfig *network.NetworkingConfig,
|
networkingConfig *network.NetworkingConfig,
|
||||||
|
platform *specs.Platform,
|
||||||
containerName string,
|
containerName string,
|
||||||
) (container.ContainerCreateCreatedBody, error) {
|
) (container.ContainerCreateCreatedBody, error) {
|
||||||
defer func() { c.ResponseCounter++ }()
|
defer func() { c.ResponseCounter++ }()
|
||||||
|
@ -184,6 +186,7 @@ func TestNewCreateCommandWithContentTrustErrors(t *testing.T) {
|
||||||
createContainerFunc: func(config *container.Config,
|
createContainerFunc: func(config *container.Config,
|
||||||
hostConfig *container.HostConfig,
|
hostConfig *container.HostConfig,
|
||||||
networkingConfig *network.NetworkingConfig,
|
networkingConfig *network.NetworkingConfig,
|
||||||
|
platform *specs.Platform,
|
||||||
containerName string,
|
containerName string,
|
||||||
) (container.ContainerCreateCreatedBody, error) {
|
) (container.ContainerCreateCreatedBody, error) {
|
||||||
return container.ContainerCreateCreatedBody{}, fmt.Errorf("shouldn't try to pull image")
|
return container.ContainerCreateCreatedBody{}, fmt.Errorf("shouldn't try to pull image")
|
||||||
|
@ -244,6 +247,7 @@ func TestNewCreateCommandWithWarnings(t *testing.T) {
|
||||||
createContainerFunc: func(config *container.Config,
|
createContainerFunc: func(config *container.Config,
|
||||||
hostConfig *container.HostConfig,
|
hostConfig *container.HostConfig,
|
||||||
networkingConfig *network.NetworkingConfig,
|
networkingConfig *network.NetworkingConfig,
|
||||||
|
platform *specs.Platform,
|
||||||
containerName string,
|
containerName string,
|
||||||
) (container.ContainerCreateCreatedBody, error) {
|
) (container.ContainerCreateCreatedBody, error) {
|
||||||
return container.ContainerCreateCreatedBody{}, nil
|
return container.ContainerCreateCreatedBody{}, nil
|
||||||
|
@ -280,6 +284,7 @@ func TestCreateContainerWithProxyConfig(t *testing.T) {
|
||||||
createContainerFunc: func(config *container.Config,
|
createContainerFunc: func(config *container.Config,
|
||||||
hostConfig *container.HostConfig,
|
hostConfig *container.HostConfig,
|
||||||
networkingConfig *network.NetworkingConfig,
|
networkingConfig *network.NetworkingConfig,
|
||||||
|
platform *specs.Platform,
|
||||||
containerName string,
|
containerName string,
|
||||||
) (container.ContainerCreateCreatedBody, error) {
|
) (container.ContainerCreateCreatedBody, error) {
|
||||||
sort.Strings(config.Env)
|
sort.Strings(config.Env)
|
||||||
|
|
|
@ -9,13 +9,14 @@ import (
|
||||||
"github.com/docker/cli/internal/test/notary"
|
"github.com/docker/cli/internal/test/notary"
|
||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/docker/api/types/network"
|
"github.com/docker/docker/api/types/network"
|
||||||
|
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
"gotest.tools/v3/assert"
|
"gotest.tools/v3/assert"
|
||||||
is "gotest.tools/v3/assert/cmp"
|
is "gotest.tools/v3/assert/cmp"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRunLabel(t *testing.T) {
|
func TestRunLabel(t *testing.T) {
|
||||||
cli := test.NewFakeCli(&fakeClient{
|
cli := test.NewFakeCli(&fakeClient{
|
||||||
createContainerFunc: func(_ *container.Config, _ *container.HostConfig, _ *network.NetworkingConfig, _ string) (container.ContainerCreateCreatedBody, error) {
|
createContainerFunc: func(_ *container.Config, _ *container.HostConfig, _ *network.NetworkingConfig, _ *specs.Platform, _ string) (container.ContainerCreateCreatedBody, error) {
|
||||||
return container.ContainerCreateCreatedBody{
|
return container.ContainerCreateCreatedBody{
|
||||||
ID: "id",
|
ID: "id",
|
||||||
}, nil
|
}, nil
|
||||||
|
@ -58,6 +59,7 @@ func TestRunCommandWithContentTrustErrors(t *testing.T) {
|
||||||
createContainerFunc: func(config *container.Config,
|
createContainerFunc: func(config *container.Config,
|
||||||
hostConfig *container.HostConfig,
|
hostConfig *container.HostConfig,
|
||||||
networkingConfig *network.NetworkingConfig,
|
networkingConfig *network.NetworkingConfig,
|
||||||
|
platform *specs.Platform,
|
||||||
containerName string,
|
containerName string,
|
||||||
) (container.ContainerCreateCreatedBody, error) {
|
) (container.ContainerCreateCreatedBody, error) {
|
||||||
return container.ContainerCreateCreatedBody{}, fmt.Errorf("shouldn't try to pull image")
|
return container.ContainerCreateCreatedBody{}, fmt.Errorf("shouldn't try to pull image")
|
||||||
|
|
Loading…
Reference in New Issue