98 lines
3.0 KiB
Go
98 lines
3.0 KiB
Go
package volumes
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/containers/podman/v4/cmd/podman/common"
|
|
"github.com/containers/podman/v4/cmd/podman/inspect"
|
|
"github.com/containers/podman/v4/cmd/podman/parse"
|
|
"github.com/containers/podman/v4/cmd/podman/registry"
|
|
"github.com/containers/podman/v4/pkg/domain/entities"
|
|
"github.com/containers/podman/v4/utils"
|
|
"github.com/pkg/errors"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
var (
|
|
importDescription = `Imports contents into a podman volume from specified tarball (.tar, .tar.gz, .tgz, .bzip, .tar.xz, .txz).`
|
|
importCommand = &cobra.Command{
|
|
Annotations: map[string]string{registry.EngineMode: registry.ABIMode},
|
|
Use: "import VOLUME [SOURCE]",
|
|
Short: "Import a tarball contents into a podman volume",
|
|
Long: importDescription,
|
|
RunE: importVol,
|
|
Args: cobra.ExactArgs(2),
|
|
ValidArgsFunction: common.AutocompleteVolumes,
|
|
Example: `podman volume import my_vol /home/user/import.tar
|
|
cat ctr.tar | podman import volume my_vol -`,
|
|
}
|
|
)
|
|
|
|
func init() {
|
|
registry.Commands = append(registry.Commands, registry.CliCommand{
|
|
Command: importCommand,
|
|
Parent: volumeCmd,
|
|
})
|
|
}
|
|
|
|
func importVol(cmd *cobra.Command, args []string) error {
|
|
var inspectOpts entities.InspectOptions
|
|
var tarFile *os.File
|
|
containerEngine := registry.ContainerEngine()
|
|
ctx := registry.Context()
|
|
// create a slice of volumes since inspect expects slice as arg
|
|
volumes := []string{args[0]}
|
|
tarPath := args[1]
|
|
|
|
if tarPath != "-" {
|
|
err := parse.ValidateFileName(tarPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// open tar file
|
|
tarFile, err = os.Open(tarPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
} else {
|
|
tarFile = os.Stdin
|
|
}
|
|
|
|
inspectOpts.Type = inspect.VolumeType
|
|
volumeData, _, err := containerEngine.VolumeInspect(ctx, volumes, 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)
|
|
}
|
|
}
|
|
}
|
|
// dont care if volume is mounted or not we are gonna import everything to mountPoint
|
|
return utils.UntarToFileSystem(mountPoint, tarFile, nil)
|
|
}
|