summaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'cmd')
-rw-r--r--cmd/podman/volumes/export.go96
1 files changed, 96 insertions, 0 deletions
diff --git a/cmd/podman/volumes/export.go b/cmd/podman/volumes/export.go
new file mode 100644
index 000000000..9e4fecdfa
--- /dev/null
+++ b/cmd/podman/volumes/export.go
@@ -0,0 +1,96 @@
+package volumes
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/containers/common/pkg/completion"
+ "github.com/containers/podman/v3/cmd/podman/common"
+ "github.com/containers/podman/v3/cmd/podman/inspect"
+ "github.com/containers/podman/v3/cmd/podman/registry"
+ "github.com/containers/podman/v3/pkg/domain/entities"
+ "github.com/containers/podman/v3/utils"
+ "github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
+ "github.com/spf13/cobra"
+)
+
+var (
+ volumeExportDescription = `
+podman volume export
+
+Allow content of volume to be exported into external tar.`
+ exportCommand = &cobra.Command{
+ Annotations: map[string]string{registry.EngineMode: registry.ABIMode},
+ Use: "export [options] VOLUME",
+ Short: "Export volumes",
+ Args: cobra.ExactArgs(1),
+ Long: volumeExportDescription,
+ RunE: export,
+ ValidArgsFunction: common.AutocompleteVolumes,
+ }
+)
+
+var (
+ // Temporary struct to hold cli values.
+ cliExportOpts = struct {
+ Output string
+ }{}
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Command: exportCommand,
+ Parent: volumeCmd,
+ })
+ flags := exportCommand.Flags()
+
+ outputFlagName := "output"
+ flags.StringVarP(&cliExportOpts.Output, outputFlagName, "o", "/dev/stdout", "Write to a specified file (default: stdout, which must be redirected)")
+ _ = exportCommand.RegisterFlagCompletionFunc(outputFlagName, completion.AutocompleteDefault)
+}
+
+func export(cmd *cobra.Command, args []string) error {
+ var inspectOpts entities.InspectOptions
+ containerEngine := registry.ContainerEngine()
+ ctx := context.Background()
+
+ if cliExportOpts.Output == "" {
+ return errors.New("expects output path, use --output=[path]")
+ }
+ inspectOpts.Type = inspect.VolumeType
+ volumeData, _, err := containerEngine.VolumeInspect(ctx, args, inspectOpts)
+ if err != nil {
+ return err
+ }
+ if len(volumeData) < 1 {
+ return errors.New("no volume data found")
+ }
+ mountPoint := volumeData[0].VolumeConfigResponse.Mountpoint
+ driver := volumeData[0].VolumeConfigResponse.Driver
+ volumeOptions := volumeData[0].VolumeConfigResponse.Options
+ volumeMountStatus, err := containerEngine.VolumeMounted(ctx, args[0])
+ if err != nil {
+ return err
+ }
+ if mountPoint == "" {
+ return errors.New("volume is not mounted anywhere on host")
+ }
+ // Check if volume is using external plugin and export only if volume is mounted
+ if driver != "" && driver != "local" {
+ if !volumeMountStatus.Value {
+ return fmt.Errorf("volume is using a driver %s and volume is not mounted on %s", driver, mountPoint)
+ }
+ }
+ // Check if volume is using `local` driver and has mount options type other than tmpfs
+ if driver == "local" {
+ if mountOptionType, ok := volumeOptions["type"]; ok {
+ if mountOptionType != "tmpfs" && !volumeMountStatus.Value {
+ return fmt.Errorf("volume is using a driver %s and volume is not mounted on %s", driver, mountPoint)
+ }
+ }
+ }
+ logrus.Debugf("Exporting volume data from %s to %s", mountPoint, cliExportOpts.Output)
+ err = utils.CreateTarFromSrc(mountPoint, cliExportOpts.Output)
+ return err
+}