Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 4 additions & 20 deletions cli/command/container/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,9 @@ import (
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/completion"
"github.com/docker/cli/cli/command/image"
"github.com/docker/cli/cli/config/configfile"
"github.com/docker/cli/cli/config/types"
"github.com/docker/cli/cli/streams"
"github.com/docker/cli/cli/trust"
"github.com/docker/cli/internal/jsonstream"
"github.com/docker/cli/opts"
"github.com/moby/moby/api/types/mount"
Expand All @@ -41,7 +39,6 @@ const (
type createOptions struct {
name string
platform string
untrusted bool
pull string // always, missing, never
quiet bool
useAPISocket bool
Expand Down Expand Up @@ -88,7 +85,9 @@ func newCreateCommand(dockerCLI command.Cli) *cobra.Command {
_ = flags.SetAnnotation("platform", "version", []string{"1.32"})
_ = cmd.RegisterFlagCompletionFunc("platform", completion.Platforms())

flags.BoolVar(&options.untrusted, "disable-content-trust", !trust.Enabled(), "Skip image verification")
// TODO(thaJeztah): DEPRECATED: remove in v29.1 or v30
flags.Bool("disable-content-trust", true, "Skip image verification (deprecated)")
_ = flags.MarkDeprecated("disable-content-trust", "support for docker content trust was removed")
copts = addFlags(flags)

addCompletions(cmd, dockerCLI)
Expand Down Expand Up @@ -213,10 +212,7 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerCfg *c
hostConfig := containerCfg.HostConfig
networkingConfig := containerCfg.NetworkingConfig

var (
trustedRef reference.Canonical
namedRef reference.Named
)
var namedRef reference.Named

// TODO(thaJeztah): add a platform option-type / flag-type.
if options.platform != "" {
Expand All @@ -240,15 +236,6 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerCfg *c
}
if named, ok := ref.(reference.Named); ok {
namedRef = reference.TagNameOnly(named)

if taggedRef, ok := namedRef.(reference.NamedTagged); ok && !options.untrusted {
var err error
trustedRef, err = image.TrustedReference(ctx, dockerCli, taggedRef)
if err != nil {
return "", err
}
config.Image = reference.FamiliarString(trustedRef)
}
}

const dockerConfigPathInContainer = "/run/secrets/docker/config.json"
Expand Down Expand Up @@ -331,9 +318,6 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerCfg *c
if err := pullImage(ctx, dockerCli, config.Image, options); err != nil {
return err
}
if taggedRef, ok := namedRef.(reference.NamedTagged); ok && trustedRef != nil {
return trust.TagTrusted(ctx, dockerCli.Client(), dockerCli.Err(), trustedRef, taggedRef)
}
return nil
}

Expand Down
53 changes: 3 additions & 50 deletions cli/command/container/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/config/configfile"
"github.com/docker/cli/internal/test"
"github.com/docker/cli/internal/test/notary"
"github.com/google/go-cmp/cmp"
"github.com/moby/moby/api/types/container"
"github.com/moby/moby/api/types/system"
Expand Down Expand Up @@ -136,10 +135,9 @@ func TestCreateContainerImagePullPolicy(t *testing.T) {
}
fakeCLI := test.NewFakeCli(apiClient)
id, err := createContainer(context.Background(), fakeCLI, config, &createOptions{
name: "name",
platform: runtime.GOOS,
untrusted: true,
pull: tc.PullPolicy,
name: "name",
platform: runtime.GOOS,
pull: tc.PullPolicy,
})

if tc.ExpectedErrMsg != "" {
Expand Down Expand Up @@ -215,51 +213,6 @@ func TestCreateContainerValidateFlags(t *testing.T) {
}
}

func TestNewCreateCommandWithContentTrustErrors(t *testing.T) {
testCases := []struct {
name string
args []string
expectedError string
notaryFunc test.NotaryClientFuncType
}{
{
name: "offline-notary-server",
notaryFunc: notary.GetOfflineNotaryRepository,
expectedError: "client is offline",
args: []string{"image:tag"},
},
{
name: "uninitialized-notary-server",
notaryFunc: notary.GetUninitializedNotaryRepository,
expectedError: "remote trust data does not exist",
args: []string{"image:tag"},
},
{
name: "empty-notary-server",
notaryFunc: notary.GetEmptyTargetsNotaryRepository,
expectedError: "No valid trust data for tag",
args: []string{"image:tag"},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
t.Setenv("DOCKER_CONTENT_TRUST", "true")
fakeCLI := test.NewFakeCli(&fakeClient{
createContainerFunc: func(options client.ContainerCreateOptions) (client.ContainerCreateResult, error) {
return client.ContainerCreateResult{}, errors.New("shouldn't try to pull image")
},
})
fakeCLI.SetNotaryClient(tc.notaryFunc)
cmd := newCreateCommand(fakeCLI)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
cmd.SetArgs(tc.args)
err := cmd.Execute()
assert.ErrorContains(t, err, tc.expectedError)
})
}
}

func TestNewCreateCommandWithWarnings(t *testing.T) {
testCases := []struct {
name string
Expand Down
6 changes: 4 additions & 2 deletions cli/command/container/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/completion"
"github.com/docker/cli/cli/trust"
"github.com/docker/cli/opts"
"github.com/moby/moby/api/types/container"
"github.com/moby/moby/client"
Expand Down Expand Up @@ -73,7 +72,10 @@ func newRunCommand(dockerCLI command.Cli) *cobra.Command {
// TODO(thaJeztah): consider adding platform as "image create option" on containerOptions
flags.StringVar(&options.platform, "platform", os.Getenv("DOCKER_DEFAULT_PLATFORM"), "Set platform if server is multi-platform capable")
_ = flags.SetAnnotation("platform", "version", []string{"1.32"})
flags.BoolVar(&options.untrusted, "disable-content-trust", !trust.Enabled(), "Skip image verification")

// TODO(thaJeztah): DEPRECATED: remove in v29.1 or v30
flags.Bool("disable-content-trust", true, "Skip image verification (deprecated)")
_ = flags.MarkDeprecated("disable-content-trust", "support for docker content trust was removed")
copts = addFlags(flags)

_ = cmd.RegisterFlagCompletionFunc("detach-keys", completeDetachKeys)
Expand Down
49 changes: 0 additions & 49 deletions cli/command/container/run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/streams"
"github.com/docker/cli/internal/test"
"github.com/docker/cli/internal/test/notary"
"github.com/moby/moby/api/types"
"github.com/moby/moby/api/types/container"
"github.com/moby/moby/client"
Expand Down Expand Up @@ -295,54 +294,6 @@ func TestRunPullTermination(t *testing.T) {
}
}

func TestRunCommandWithContentTrustErrors(t *testing.T) {
testCases := []struct {
name string
args []string
expectedError string
notaryFunc test.NotaryClientFuncType
}{
{
name: "offline-notary-server",
notaryFunc: notary.GetOfflineNotaryRepository,
expectedError: "client is offline",
args: []string{"image:tag"},
},
{
name: "uninitialized-notary-server",
notaryFunc: notary.GetUninitializedNotaryRepository,
expectedError: "remote trust data does not exist",
args: []string{"image:tag"},
},
{
name: "empty-notary-server",
notaryFunc: notary.GetEmptyTargetsNotaryRepository,
expectedError: "No valid trust data for tag",
args: []string{"image:tag"},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
t.Setenv("DOCKER_CONTENT_TRUST", "true")
fakeCLI := test.NewFakeCli(&fakeClient{
createContainerFunc: func(options client.ContainerCreateOptions) (client.ContainerCreateResult, error) {
return client.ContainerCreateResult{}, errors.New("shouldn't try to pull image")
},
})
fakeCLI.SetNotaryClient(tc.notaryFunc)
cmd := newRunCommand(fakeCLI)
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
err := cmd.Execute()
statusErr := cli.StatusError{}
assert.Check(t, errors.As(err, &statusErr))
assert.Check(t, is.Equal(statusErr.StatusCode, 125))
assert.Check(t, is.ErrorContains(err, tc.expectedError))
})
}
}

func TestRunContainerImagePullPolicyInvalid(t *testing.T) {
cases := []struct {
PullPolicy string
Expand Down
3 changes: 2 additions & 1 deletion cli/command/image/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,9 @@ func newBuildCommand(dockerCLI command.Cli) *cobra.Command {
flags.SetAnnotation("target", annotation.ExternalURL, []string{"https://docs.docker.com/reference/cli/docker/buildx/build/#target"})
flags.StringVar(&options.imageIDFile, "iidfile", "", "Write the image ID to the file")

// TODO(thaJeztah): DEPRECATED: remove in v29.1 or v30
flags.Bool("disable-content-trust", true, "Skip image verification (deprecated)")
_ = flags.MarkHidden("disable-content-trust")
_ = flags.MarkDeprecated("disable-content-trust", "support for docker content trust was removed")

flags.StringVar(&options.platform, "platform", os.Getenv("DOCKER_DEFAULT_PLATFORM"), "Set platform if server is multi-platform capable")
flags.SetAnnotation("platform", "version", []string{"1.38"})
Expand Down
60 changes: 20 additions & 40 deletions cli/command/image/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,18 @@ import (
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/completion"
"github.com/docker/cli/cli/streams"
"github.com/docker/cli/cli/trust"
"github.com/docker/cli/internal/jsonstream"
"github.com/moby/moby/api/pkg/authconfig"
registrytypes "github.com/moby/moby/api/types/registry"
"github.com/moby/moby/client"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/spf13/cobra"
)

// pullOptions defines what and how to pull.
type pullOptions struct {
remote string
all bool
platform string
quiet bool
untrusted bool
remote string
all bool
platform string
quiet bool
}

// newPullCommand creates a new `docker pull` command
Expand Down Expand Up @@ -57,7 +53,11 @@ func newPullCommand(dockerCLI command.Cli) *cobra.Command {

flags.BoolVarP(&opts.all, "all-tags", "a", false, "Download all tagged images in the repository")
flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Suppress verbose output")
flags.BoolVar(&opts.untrusted, "disable-content-trust", !trust.Enabled(), "Skip image verification")

// TODO(thaJeztah): DEPRECATED: remove in v29.1 or v30
flags.Bool("disable-content-trust", true, "Skip image verification (deprecated)")
_ = flags.MarkDeprecated("disable-content-trust", "support for docker content trust was removed")

flags.StringVar(&opts.platform, "platform", os.Getenv("DOCKER_DEFAULT_PLATFORM"), "Set platform if server is multi-platform capable")
_ = flags.SetAnnotation("platform", "version", []string{"1.32"})
_ = cmd.RegisterFlagCompletionFunc("platform", completion.Platforms())
Expand All @@ -80,46 +80,22 @@ func runPull(ctx context.Context, dockerCLI command.Cli, opts pullOptions) error
}
}

var ociPlatforms []ocispec.Platform
if opts.platform != "" {
// TODO(thaJeztah): add a platform option-type / flag-type.
if _, err = platforms.Parse(opts.platform); err != nil {
p, err := platforms.Parse(opts.platform)
if err != nil {
return err
}
ociPlatforms = append(ociPlatforms, p)
}

imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, authResolver(dockerCLI), distributionRef.String())
encodedAuth, err := command.RetrieveAuthTokenFromImage(dockerCLI.ConfigFile(), distributionRef.String())
if err != nil {
return err
}

// Check if reference has a digest
_, isCanonical := distributionRef.(reference.Canonical)
if !opts.untrusted && !isCanonical {
if err := trustedPull(ctx, dockerCLI, imgRefAndAuth, opts); err != nil {
return err
}
} else {
if err := imagePullPrivileged(ctx, dockerCLI, imgRefAndAuth.Reference(), imgRefAndAuth.AuthConfig(), opts); err != nil {
return err
}
}
_, _ = fmt.Fprintln(dockerCLI.Out(), imgRefAndAuth.Reference().String())
return nil
}

// imagePullPrivileged pulls the image and displays it to the output
func imagePullPrivileged(ctx context.Context, dockerCLI command.Cli, ref reference.Named, authConfig *registrytypes.AuthConfig, opts pullOptions) error {
encodedAuth, err := authconfig.Encode(*authConfig)
if err != nil {
return err
}
var ociPlatforms []ocispec.Platform
if opts.platform != "" {
// Already validated.
ociPlatforms = append(ociPlatforms, platforms.MustParse(opts.platform))
}

responseBody, err := dockerCLI.Client().ImagePull(ctx, reference.FamiliarString(ref), client.ImagePullOptions{
responseBody, err := dockerCLI.Client().ImagePull(ctx, reference.FamiliarString(distributionRef), client.ImagePullOptions{
RegistryAuth: encodedAuth,
PrivilegeFunc: nil,
All: opts.all,
Expand All @@ -134,5 +110,9 @@ func imagePullPrivileged(ctx context.Context, dockerCLI command.Cli, ref referen
if opts.quiet {
out = streams.NewOut(io.Discard)
}
return jsonstream.Display(ctx, responseBody, out)
if err := jsonstream.Display(ctx, responseBody, out); err != nil {
return err
}
_, _ = fmt.Fprintln(dockerCLI.Out(), distributionRef.String())
return nil
}
47 changes: 0 additions & 47 deletions cli/command/image/pull_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"testing"

"github.com/docker/cli/internal/test"
"github.com/docker/cli/internal/test/notary"
"github.com/moby/moby/client"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
Expand Down Expand Up @@ -89,49 +88,3 @@ func TestNewPullCommandSuccess(t *testing.T) {
})
}
}

func TestNewPullCommandWithContentTrustErrors(t *testing.T) {
testCases := []struct {
name string
args []string
expectedError string
notaryFunc test.NotaryClientFuncType
}{
{
name: "offline-notary-server",
notaryFunc: notary.GetOfflineNotaryRepository,
expectedError: "client is offline",
args: []string{"image:tag"},
},
{
name: "uninitialized-notary-server",
notaryFunc: notary.GetUninitializedNotaryRepository,
expectedError: "remote trust data does not exist",
args: []string{"image:tag"},
},
{
name: "empty-notary-server",
notaryFunc: notary.GetEmptyTargetsNotaryRepository,
expectedError: "No valid trust data for tag",
args: []string{"image:tag"},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
t.Setenv("DOCKER_CONTENT_TRUST", "true")
cli := test.NewFakeCli(&fakeClient{
imagePullFunc: func(ref string, options client.ImagePullOptions) (client.ImagePullResponse, error) {
// FIXME(thaJeztah): how to mock this?
return fakeStreamResult{ReadCloser: http.NoBody}, nil
},
})
cli.SetNotaryClient(tc.notaryFunc)
cmd := newPullCommand(cli)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
cmd.SetArgs(tc.args)
err := cmd.Execute()
assert.ErrorContains(t, err, tc.expectedError)
})
}
}
Loading
Loading