Skip to content

Commit b8bcf6f

Browse files
committed
container export: implement file-write with atomicwriter
Same functionality, but implemented with atomicwriter. There's a slight difference in error-messages produced (but can be adjusted if we want). Before: docker container export -o ./no/such/foo mycontainer failed to export container: invalid output path: directory "no/such" does not exist docker container export -o /no/permissions mycontainer failed to export container: stat /no/permissions: permission denied After: docker container export -o ./no/such/foo mycontainer failed to export container: invalid file path: stat no/such: no such file or directory docker container export -o /no/permissions mycontainer failed to export container: failed to stat output path: lstat /no/permissions: permission denied Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
1 parent d47d233 commit b8bcf6f

2 files changed

Lines changed: 20 additions & 20 deletions

File tree

cli/command/container/export.go

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"github.com/docker/cli/cli"
88
"github.com/docker/cli/cli/command"
99
"github.com/docker/cli/cli/command/completion"
10+
"github.com/moby/sys/atomicwriter"
1011
"github.com/pkg/errors"
1112
"github.com/spf13/cobra"
1213
)
@@ -41,27 +42,28 @@ func NewExportCommand(dockerCli command.Cli) *cobra.Command {
4142
return cmd
4243
}
4344

44-
func runExport(ctx context.Context, dockerCli command.Cli, opts exportOptions) error {
45-
if opts.output == "" && dockerCli.Out().IsTerminal() {
46-
return errors.New("cowardly refusing to save to a terminal. Use the -o flag or redirect")
47-
}
48-
49-
if err := command.ValidateOutputPath(opts.output); err != nil {
50-
return errors.Wrap(err, "failed to export container")
45+
func runExport(ctx context.Context, dockerCLI command.Cli, opts exportOptions) error {
46+
var output io.Writer
47+
if opts.output == "" {
48+
if dockerCLI.Out().IsTerminal() {
49+
return errors.New("cowardly refusing to save to a terminal. Use the -o flag or redirect")
50+
}
51+
output = dockerCLI.Out()
52+
} else {
53+
writer, err := atomicwriter.New(opts.output, 0o600)
54+
if err != nil {
55+
return errors.Wrap(err, "failed to export container")
56+
}
57+
defer writer.Close()
58+
output = writer
5159
}
5260

53-
clnt := dockerCli.Client()
54-
55-
responseBody, err := clnt.ContainerExport(ctx, opts.container)
61+
responseBody, err := dockerCLI.Client().ContainerExport(ctx, opts.container)
5662
if err != nil {
5763
return err
5864
}
5965
defer responseBody.Close()
6066

61-
if opts.output == "" {
62-
_, err := io.Copy(dockerCli.Out(), responseBody)
63-
return err
64-
}
65-
66-
return command.CopyToFile(opts.output, responseBody)
67+
_, err = io.Copy(output, responseBody)
68+
return err
6769
}

cli/command/container/export_test.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,6 @@ func TestContainerExportOutputToIrregularFile(t *testing.T) {
4242
cmd.SetErr(io.Discard)
4343
cmd.SetArgs([]string{"-o", "/dev/random", "container"})
4444

45-
err := cmd.Execute()
46-
assert.Assert(t, err != nil)
47-
expected := `"/dev/random" must be a directory or a regular file`
48-
assert.ErrorContains(t, err, expected)
45+
const expected = `failed to export container: cannot write to a character device file`
46+
assert.Error(t, cmd.Execute(), expected)
4947
}

0 commit comments

Comments
 (0)