github.com/containers/libpod@v1.9.4-0.20220419124438-4284fd425507/cmd/podmanV2/images/save.go (about) 1 package images 2 3 import ( 4 "context" 5 "os" 6 "strings" 7 8 "github.com/containers/libpod/libpod/define" 9 10 "github.com/containers/libpod/cmd/podmanV2/parse" 11 "github.com/containers/libpod/cmd/podmanV2/registry" 12 "github.com/containers/libpod/pkg/domain/entities" 13 "github.com/containers/libpod/pkg/util" 14 "github.com/pkg/errors" 15 "github.com/spf13/cobra" 16 "golang.org/x/crypto/ssh/terminal" 17 ) 18 19 var validFormats = []string{define.OCIManifestDir, define.OCIArchive, define.V2s2ManifestDir, define.V2s2Archive} 20 21 var ( 22 saveDescription = `Save an image to docker-archive or oci-archive on the local machine. Default is docker-archive.` 23 24 saveCommand = &cobra.Command{ 25 Use: "save [flags] IMAGE", 26 Short: "Save image to an archive", 27 Long: saveDescription, 28 PersistentPreRunE: preRunE, 29 RunE: save, 30 Args: func(cmd *cobra.Command, args []string) error { 31 if len(args) == 0 { 32 return errors.Errorf("need at least 1 argument") 33 } 34 format, err := cmd.Flags().GetString("format") 35 if err != nil { 36 return err 37 } 38 if !util.StringInSlice(format, validFormats) { 39 return errors.Errorf("format value must be one of %s", strings.Join(validFormats, " ")) 40 } 41 return nil 42 }, 43 Example: `podman save --quiet -o myimage.tar imageID 44 podman save --format docker-dir -o ubuntu-dir ubuntu 45 podman save > alpine-all.tar alpine:latest`, 46 } 47 ) 48 49 var ( 50 saveOpts entities.ImageSaveOptions 51 ) 52 53 func init() { 54 registry.Commands = append(registry.Commands, registry.CliCommand{ 55 Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, 56 Command: saveCommand, 57 }) 58 flags := saveCommand.Flags() 59 flags.BoolVar(&saveOpts.Compress, "compress", false, "Compress tarball image layers when saving to a directory using the 'dir' transport. (default is same compression type as source)") 60 flags.StringVar(&saveOpts.Format, "format", define.V2s2Archive, "Save image to oci-archive, oci-dir (directory with oci manifest type), docker-archive, docker-dir (directory with v2s2 manifest type)") 61 flags.StringVarP(&saveOpts.Output, "output", "o", "", "Write to a specified file (default: stdout, which must be redirected)") 62 flags.BoolVarP(&saveOpts.Quiet, "quiet", "q", false, "Suppress the output") 63 64 } 65 66 func save(cmd *cobra.Command, args []string) error { 67 var ( 68 tags []string 69 ) 70 if cmd.Flag("compress").Changed && (saveOpts.Format != define.OCIManifestDir && saveOpts.Format != define.V2s2ManifestDir && saveOpts.Format == "") { 71 return errors.Errorf("--compress can only be set when --format is either 'oci-dir' or 'docker-dir'") 72 } 73 if len(saveOpts.Output) == 0 { 74 fi := os.Stdout 75 if terminal.IsTerminal(int(fi.Fd())) { 76 return errors.Errorf("refusing to save to terminal. Use -o flag or redirect") 77 } 78 saveOpts.Output = "/dev/stdout" 79 } 80 if err := parse.ValidateFileName(saveOpts.Output); err != nil { 81 return err 82 } 83 if len(args) > 1 { 84 tags = args[1:] 85 } 86 return registry.ImageEngine().Save(context.Background(), args[0], tags, saveOpts) 87 }