diff options
Diffstat (limited to 'cmd')
-rw-r--r-- | cmd/podman/common/completion.go | 8 | ||||
-rw-r--r-- | cmd/podman/containers/run.go | 6 | ||||
-rw-r--r-- | cmd/podman/images/prune.go | 12 | ||||
-rw-r--r-- | cmd/podman/machine/init.go | 99 | ||||
-rw-r--r-- | cmd/podman/machine/machine.go | 32 | ||||
-rw-r--r-- | cmd/podman/machine/machine_unsupported.go | 5 | ||||
-rw-r--r-- | cmd/podman/machine/remove.go | 88 | ||||
-rw-r--r-- | cmd/podman/machine/ssh.go | 70 | ||||
-rw-r--r-- | cmd/podman/machine/start.go | 48 | ||||
-rw-r--r-- | cmd/podman/machine/stop.go | 49 | ||||
-rw-r--r-- | cmd/podman/main.go | 1 | ||||
-rw-r--r-- | cmd/podman/system/prune.go | 32 |
12 files changed, 438 insertions, 12 deletions
diff --git a/cmd/podman/common/completion.go b/cmd/podman/common/completion.go index bc106263c..6bed5e0c6 100644 --- a/cmd/podman/common/completion.go +++ b/cmd/podman/common/completion.go @@ -1092,3 +1092,11 @@ func AutocompleteVolumeFilters(cmd *cobra.Command, args []string, toComplete str } return completeKeyValues(toComplete, kv) } + +// AutocompleteMachineSSH - Autocomplete machine ssh command. +func AutocompleteMachineSSH(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + if len(args) == 0 { + return nil, cobra.ShellCompDirectiveNoFileComp + } + return nil, cobra.ShellCompDirectiveDefault +} diff --git a/cmd/podman/containers/run.go b/cmd/podman/containers/run.go index 83a5d7b8a..db7180ca9 100644 --- a/cmd/podman/containers/run.go +++ b/cmd/podman/containers/run.go @@ -17,6 +17,7 @@ import ( "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/spf13/cobra" + "golang.org/x/crypto/ssh/terminal" ) var ( @@ -106,6 +107,11 @@ func run(cmd *cobra.Command, args []string) error { return err } + // TODO: Breaking change should be made fatal in next major Release + if cliVals.TTY && cliVals.Interactive && !terminal.IsTerminal(int(os.Stdin.Fd())) { + logrus.Warnf("The input device is not a TTY. The --tty and --interactive flags might not work properly") + } + if af := cliVals.Authfile; len(af) > 0 { if _, err := os.Stat(af); err != nil { return err diff --git a/cmd/podman/images/prune.go b/cmd/podman/images/prune.go index 78e107a97..8231e5c57 100644 --- a/cmd/podman/images/prune.go +++ b/cmd/podman/images/prune.go @@ -53,9 +53,7 @@ func init() { func prune(cmd *cobra.Command, args []string) error { if !force { reader := bufio.NewReader(os.Stdin) - fmt.Printf(` -WARNING! This will remove all dangling images. -Are you sure you want to continue? [y/N] `) + fmt.Printf("%s", createPruneWarningMessage(pruneOpts)) answer, err := reader.ReadString('\n') if err != nil { return err @@ -72,3 +70,11 @@ Are you sure you want to continue? [y/N] `) return utils.PrintImagePruneResults(results, false) } + +func createPruneWarningMessage(pruneOpts entities.ImagePruneOptions) string { + question := "Are you sure you want to continue? [y/N] " + if pruneOpts.All { + return "WARNING! This will remove all images without at least one container associated to them.\n" + question + } + return "WARNING! This will remove all dangling images.\n" + question +} diff --git a/cmd/podman/machine/init.go b/cmd/podman/machine/init.go new file mode 100644 index 000000000..900f67e2f --- /dev/null +++ b/cmd/podman/machine/init.go @@ -0,0 +1,99 @@ +// +build amd64,linux amd64,darwin arm64,darwin + +package machine + +import ( + "github.com/containers/common/pkg/completion" + "github.com/containers/podman/v3/cmd/podman/registry" + "github.com/containers/podman/v3/pkg/domain/entities" + "github.com/containers/podman/v3/pkg/machine" + "github.com/containers/podman/v3/pkg/machine/qemu" + "github.com/spf13/cobra" +) + +var ( + initCmd = &cobra.Command{ + Use: "init [options] [NAME]", + Short: "initialize a vm", + Long: "initialize a virtual machine for Podman to run on. Virtual machines are used to run Podman.", + RunE: initMachine, + Args: cobra.MaximumNArgs(1), + Example: `podman machine init myvm`, + ValidArgsFunction: completion.AutocompleteNone, + } +) + +type InitCLIOptions struct { + CPUS uint64 + Memory uint64 + Devices []string + ImagePath string + IgnitionPath string + Name string +} + +var ( + initOpts = InitCLIOptions{} + defaultMachineName string = "podman-machine-default" +) + +func init() { + registry.Commands = append(registry.Commands, registry.CliCommand{ + Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, + Command: initCmd, + Parent: machineCmd, + }) + flags := initCmd.Flags() + + cpusFlagName := "cpus" + flags.Uint64Var( + &initOpts.CPUS, + cpusFlagName, 1, + "Number of CPUs. The default is 1.", + ) + _ = initCmd.RegisterFlagCompletionFunc(cpusFlagName, completion.AutocompleteNone) + + memoryFlagName := "memory" + flags.Uint64VarP( + &initOpts.Memory, + memoryFlagName, "m", 2048, + "Memory (in MB)", + ) + _ = initCmd.RegisterFlagCompletionFunc(memoryFlagName, completion.AutocompleteNone) + + ImagePathFlagName := "image-path" + flags.StringVar(&initOpts.ImagePath, ImagePathFlagName, "", "Path to qcow image") + _ = initCmd.RegisterFlagCompletionFunc(ImagePathFlagName, completion.AutocompleteDefault) + + IgnitionPathFlagName := "ignition-path" + flags.StringVar(&initOpts.IgnitionPath, IgnitionPathFlagName, "", "Path to ignition file") + _ = initCmd.RegisterFlagCompletionFunc(IgnitionPathFlagName, completion.AutocompleteDefault) +} + +// TODO should we allow for a users to append to the qemu cmdline? +func initMachine(cmd *cobra.Command, args []string) error { + initOpts.Name = defaultMachineName + if len(args) > 0 { + initOpts.Name = args[0] + } + vmOpts := machine.InitOptions{ + CPUS: initOpts.CPUS, + Memory: initOpts.Memory, + IgnitionPath: initOpts.IgnitionPath, + ImagePath: initOpts.ImagePath, + Name: initOpts.Name, + } + var ( + vm machine.VM + vmType string + err error + ) + switch vmType { + default: // qemu is the default + vm, err = qemu.NewMachine(vmOpts) + } + if err != nil { + return err + } + return vm.Init(vmOpts) +} diff --git a/cmd/podman/machine/machine.go b/cmd/podman/machine/machine.go new file mode 100644 index 000000000..ed284ee10 --- /dev/null +++ b/cmd/podman/machine/machine.go @@ -0,0 +1,32 @@ +// +build amd64,linux amd64,darwin arm64,darwin + +package machine + +import ( + "github.com/containers/podman/v3/cmd/podman/registry" + "github.com/containers/podman/v3/cmd/podman/validate" + "github.com/containers/podman/v3/pkg/domain/entities" + "github.com/spf13/cobra" +) + +var ( + noOp = func(cmd *cobra.Command, args []string) error { + return nil + } + // Command: podman _machine_ + machineCmd = &cobra.Command{ + Use: "machine", + Short: "Manage a virtual machine", + Long: "Manage a virtual machine. Virtual machines are used to run Podman.", + PersistentPreRunE: noOp, + PersistentPostRunE: noOp, + RunE: validate.SubCommandExists, + } +) + +func init() { + registry.Commands = append(registry.Commands, registry.CliCommand{ + Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, + Command: machineCmd, + }) +} diff --git a/cmd/podman/machine/machine_unsupported.go b/cmd/podman/machine/machine_unsupported.go new file mode 100644 index 000000000..cb1636419 --- /dev/null +++ b/cmd/podman/machine/machine_unsupported.go @@ -0,0 +1,5 @@ +// +build !amd64 arm64,linux amd64,windows + +package machine + +func init() {} diff --git a/cmd/podman/machine/remove.go b/cmd/podman/machine/remove.go new file mode 100644 index 000000000..f6ce9e326 --- /dev/null +++ b/cmd/podman/machine/remove.go @@ -0,0 +1,88 @@ +// +build amd64,linux amd64,darwin arm64,darwin + +package machine + +import ( + "bufio" + "fmt" + "os" + "strings" + + "github.com/containers/common/pkg/completion" + "github.com/containers/podman/v3/cmd/podman/registry" + "github.com/containers/podman/v3/pkg/domain/entities" + "github.com/containers/podman/v3/pkg/machine" + "github.com/containers/podman/v3/pkg/machine/qemu" + "github.com/spf13/cobra" +) + +var ( + removeCmd = &cobra.Command{ + Use: "remove [options] NAME", + Short: "Remove an existing machine", + Long: "Remove an existing machine ", + RunE: remove, + Args: cobra.ExactArgs(1), + Example: `podman machine remove myvm`, + ValidArgsFunction: completion.AutocompleteNone, + } +) + +var ( + destoryOptions machine.RemoveOptions +) + +func init() { + registry.Commands = append(registry.Commands, registry.CliCommand{ + Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, + Command: removeCmd, + Parent: machineCmd, + }) + + flags := removeCmd.Flags() + formatFlagName := "force" + flags.BoolVar(&destoryOptions.Force, formatFlagName, false, "Do not prompt before removeing") + + keysFlagName := "save-keys" + flags.BoolVar(&destoryOptions.SaveKeys, keysFlagName, false, "Do not delete SSH keys") + + ignitionFlagName := "save-ignition" + flags.BoolVar(&destoryOptions.SaveIgnition, ignitionFlagName, false, "Do not delete ignition file") + + imageFlagName := "save-image" + flags.BoolVar(&destoryOptions.SaveImage, imageFlagName, false, "Do not delete the image file") +} + +func remove(cmd *cobra.Command, args []string) error { + var ( + err error + vm machine.VM + vmType string + ) + switch vmType { + default: + vm, err = qemu.LoadVMByName(args[0]) + } + if err != nil { + return err + } + confirmationMessage, doIt, err := vm.Remove(args[0], machine.RemoveOptions{}) + if err != nil { + return err + } + + if !destoryOptions.Force { + // Warn user + fmt.Println(confirmationMessage) + reader := bufio.NewReader(os.Stdin) + fmt.Print("Are you sure you want to continue? [y/N] ") + answer, err := reader.ReadString('\n') + if err != nil { + return err + } + if strings.ToLower(answer)[0] != 'y' { + return nil + } + } + return doIt() +} diff --git a/cmd/podman/machine/ssh.go b/cmd/podman/machine/ssh.go new file mode 100644 index 000000000..a7111a195 --- /dev/null +++ b/cmd/podman/machine/ssh.go @@ -0,0 +1,70 @@ +// +build amd64,linux amd64,darwin arm64,darwin + +package machine + +import ( + "github.com/containers/podman/v3/cmd/podman/common" + "github.com/containers/podman/v3/cmd/podman/registry" + "github.com/containers/podman/v3/pkg/domain/entities" + "github.com/containers/podman/v3/pkg/machine" + "github.com/containers/podman/v3/pkg/machine/qemu" + "github.com/pkg/errors" + "github.com/spf13/cobra" +) + +var ( + sshCmd = &cobra.Command{ + Use: "ssh [options] NAME [COMMAND [ARG ...]]", + Short: "SSH into a virtual machine", + Long: "SSH into a virtual machine ", + RunE: ssh, + Args: cobra.MinimumNArgs(1), + Example: `podman machine ssh myvm + podman machine ssh -e myvm echo hello`, + + ValidArgsFunction: common.AutocompleteMachineSSH, + } +) + +var ( + sshOpts machine.SSHOptions +) + +func init() { + registry.Commands = append(registry.Commands, registry.CliCommand{ + Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, + Command: sshCmd, + Parent: machineCmd, + }) + + flags := sshCmd.Flags() + executeFlagName := "execute" + flags.BoolVarP(&sshOpts.Execute, executeFlagName, "e", false, "Execute command from args") +} + +func ssh(cmd *cobra.Command, args []string) error { + var ( + err error + vm machine.VM + vmType string + ) + sshOpts.Args = args[1:] + + // Error if no execute but args given + if !sshOpts.Execute && len(sshOpts.Args) > 0 { + return errors.New("too many args: to execute commands via ssh, use -e flag") + } + // Error if execute but no args given + if sshOpts.Execute && len(sshOpts.Args) < 1 { + return errors.New("must proivde at least one command to execute") + } + + switch vmType { + default: + vm, err = qemu.LoadVMByName(args[0]) + } + if err != nil { + return errors.Wrapf(err, "vm %s not found", args[0]) + } + return vm.SSH(args[0], sshOpts) +} diff --git a/cmd/podman/machine/start.go b/cmd/podman/machine/start.go new file mode 100644 index 000000000..44ade2850 --- /dev/null +++ b/cmd/podman/machine/start.go @@ -0,0 +1,48 @@ +// +build amd64,linux amd64,darwin arm64,darwin + +package machine + +import ( + "github.com/containers/common/pkg/completion" + "github.com/containers/podman/v3/cmd/podman/registry" + "github.com/containers/podman/v3/pkg/domain/entities" + "github.com/containers/podman/v3/pkg/machine" + "github.com/containers/podman/v3/pkg/machine/qemu" + "github.com/spf13/cobra" +) + +var ( + startCmd = &cobra.Command{ + Use: "start NAME", + Short: "Start an existing machine", + Long: "Start an existing machine ", + RunE: start, + Args: cobra.ExactArgs(1), + Example: `podman machine start myvm`, + ValidArgsFunction: completion.AutocompleteNone, + } +) + +func init() { + registry.Commands = append(registry.Commands, registry.CliCommand{ + Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, + Command: startCmd, + Parent: machineCmd, + }) +} + +func start(cmd *cobra.Command, args []string) error { + var ( + err error + vm machine.VM + vmType string + ) + switch vmType { + default: + vm, err = qemu.LoadVMByName(args[0]) + } + if err != nil { + return err + } + return vm.Start(args[0], machine.StartOptions{}) +} diff --git a/cmd/podman/machine/stop.go b/cmd/podman/machine/stop.go new file mode 100644 index 000000000..35fd4ff95 --- /dev/null +++ b/cmd/podman/machine/stop.go @@ -0,0 +1,49 @@ +// +build amd64,linux amd64,darwin arm64,darwin + +package machine + +import ( + "github.com/containers/common/pkg/completion" + "github.com/containers/podman/v3/cmd/podman/registry" + "github.com/containers/podman/v3/pkg/domain/entities" + "github.com/containers/podman/v3/pkg/machine" + "github.com/containers/podman/v3/pkg/machine/qemu" + "github.com/spf13/cobra" +) + +var ( + stopCmd = &cobra.Command{ + Use: "stop NAME", + Short: "Stop an existing machine", + Long: "Stop an existing machine ", + RunE: stop, + Args: cobra.ExactArgs(1), + Example: `podman machine stop myvm`, + ValidArgsFunction: completion.AutocompleteNone, + } +) + +func init() { + registry.Commands = append(registry.Commands, registry.CliCommand{ + Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, + Command: stopCmd, + Parent: machineCmd, + }) +} + +// TODO Name shouldnt be required, need to create a default vm +func stop(cmd *cobra.Command, args []string) error { + var ( + err error + vm machine.VM + vmType string + ) + switch vmType { + default: + vm, err = qemu.LoadVMByName(args[0]) + } + if err != nil { + return err + } + return vm.Stop(args[0], machine.StopOptions{}) +} diff --git a/cmd/podman/main.go b/cmd/podman/main.go index 561459c31..5219da26d 100644 --- a/cmd/podman/main.go +++ b/cmd/podman/main.go @@ -9,6 +9,7 @@ import ( _ "github.com/containers/podman/v3/cmd/podman/generate" _ "github.com/containers/podman/v3/cmd/podman/healthcheck" _ "github.com/containers/podman/v3/cmd/podman/images" + _ "github.com/containers/podman/v3/cmd/podman/machine" _ "github.com/containers/podman/v3/cmd/podman/manifest" _ "github.com/containers/podman/v3/cmd/podman/networks" _ "github.com/containers/podman/v3/cmd/podman/play" diff --git a/cmd/podman/system/prune.go b/cmd/podman/system/prune.go index 136c15304..3020a541b 100644 --- a/cmd/podman/system/prune.go +++ b/cmd/podman/system/prune.go @@ -55,22 +55,17 @@ func init() { func prune(cmd *cobra.Command, args []string) error { var err error - // Prompt for confirmation if --force is not set if !force { reader := bufio.NewReader(os.Stdin) volumeString := "" if pruneOptions.Volume { volumeString = ` - - all volumes not used by at least one container` + - all volumes not used by at least one container` } - fmt.Printf(` -WARNING! This will remove: - - all stopped containers%s - - all stopped pods - - all dangling images - - all build cache -Are you sure you want to continue? [y/N] `, volumeString) + + fmt.Printf(createPruneWarningMessage(pruneOptions), volumeString, "Are you sure you want to continue? [y/N] ") + answer, err := reader.ReadString('\n') if err != nil { return err @@ -115,3 +110,22 @@ Are you sure you want to continue? [y/N] `, volumeString) fmt.Printf("Total reclaimed space: %s\n", units.HumanSize((float64)(response.ReclaimedSpace))) return nil } + +func createPruneWarningMessage(pruneOpts entities.SystemPruneOptions) string { + if pruneOpts.All { + return `WARNING! This will remove: + - all stopped containers + - all networks not used by at least one container%s + - all images without at least one container associated to them + - all build cache + +%s` + } + return `WARNING! This will remove: + - all stopped containers + - all networks not used by at least one container%s + - all dangling images + - all dangling build cache + +%s` +} |