github.com/thajeztah/cli@v0.0.0-20240223162942-dc6bfac81a8b/cli/command/image/save.go (about) 1 package image 2 3 import ( 4 "context" 5 "io" 6 7 "github.com/docker/cli/cli" 8 "github.com/docker/cli/cli/command" 9 "github.com/docker/cli/cli/command/completion" 10 "github.com/pkg/errors" 11 "github.com/spf13/cobra" 12 ) 13 14 type saveOptions struct { 15 images []string 16 output string 17 } 18 19 // NewSaveCommand creates a new `docker save` command 20 func NewSaveCommand(dockerCli command.Cli) *cobra.Command { 21 var opts saveOptions 22 23 cmd := &cobra.Command{ 24 Use: "save [OPTIONS] IMAGE [IMAGE...]", 25 Short: "Save one or more images to a tar archive (streamed to STDOUT by default)", 26 Args: cli.RequiresMinArgs(1), 27 RunE: func(cmd *cobra.Command, args []string) error { 28 opts.images = args 29 return RunSave(cmd.Context(), dockerCli, opts) 30 }, 31 Annotations: map[string]string{ 32 "aliases": "docker image save, docker save", 33 }, 34 ValidArgsFunction: completion.ImageNames(dockerCli), 35 } 36 37 flags := cmd.Flags() 38 39 flags.StringVarP(&opts.output, "output", "o", "", "Write to a file, instead of STDOUT") 40 41 return cmd 42 } 43 44 // RunSave performs a save against the engine based on the specified options 45 func RunSave(ctx context.Context, dockerCli command.Cli, opts saveOptions) error { 46 if opts.output == "" && dockerCli.Out().IsTerminal() { 47 return errors.New("cowardly refusing to save to a terminal. Use the -o flag or redirect") 48 } 49 50 if err := command.ValidateOutputPath(opts.output); err != nil { 51 return errors.Wrap(err, "failed to save image") 52 } 53 54 responseBody, err := dockerCli.Client().ImageSave(ctx, opts.images) 55 if err != nil { 56 return err 57 } 58 defer responseBody.Close() 59 60 if opts.output == "" { 61 _, err := io.Copy(dockerCli.Out(), responseBody) 62 return err 63 } 64 65 return command.CopyToFile(opts.output, responseBody) 66 }