Skip to content

Commit

Permalink
Add --quiet and --no-info flags to podman machine start
Browse files Browse the repository at this point in the history
Add quiet and no-info flags to podman machine start.
No-info suppresses helpful informational tips
Quiet suppresses machine start progress output, as well as informational
tips.

Signed-off-by: Ashley Cui <[email protected]>
  • Loading branch information
ashley-cui committed Nov 11, 2022
1 parent c75b059 commit dd98e3c
Show file tree
Hide file tree
Showing 8 changed files with 134 additions and 60 deletions.
19 changes: 16 additions & 3 deletions cmd/podman/machine/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (

var (
startCmd = &cobra.Command{
Use: "start [MACHINE]",
Use: "start [options] [MACHINE]",
Short: "Start an existing machine",
Long: "Start a managed virtual machine ",
PersistentPreRunE: rootlessOnly,
Expand All @@ -23,20 +23,31 @@ var (
Example: `podman machine start myvm`,
ValidArgsFunction: autocompleteMachine,
}
startOpts = machine.StartOptions{}
)

func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
Command: startCmd,
Parent: machineCmd,
})

flags := startCmd.Flags()
noInfoFlagName := "no-info"
flags.BoolVar(&startOpts.NoInfo, noInfoFlagName, false, "Suppress informational tips")

quietFlagName := "quiet"
flags.BoolVarP(&startOpts.Quiet, quietFlagName, "q", false, "Suppress machine starting status output")
}

func start(_ *cobra.Command, args []string) error {
var (
err error
vm machine.VM
)

startOpts.NoInfo = startOpts.Quiet || startOpts.NoInfo

vmName := defaultMachineName
if len(args) > 0 && len(args[0]) > 0 {
vmName = args[0]
Expand All @@ -58,8 +69,10 @@ func start(_ *cobra.Command, args []string) error {
}
return fmt.Errorf("cannot start VM %s. VM %s is currently running or starting: %w", vmName, activeName, machine.ErrMultipleActiveVM)
}
fmt.Printf("Starting machine %q\n", vmName)
if err := vm.Start(vmName, machine.StartOptions{}); err != nil {
if !startOpts.Quiet {
fmt.Printf("Starting machine %q\n", vmName)
}
if err := vm.Start(vmName, startOpts); err != nil {
return err
}
fmt.Printf("Machine %q started successfully\n", vmName)
Expand Down
8 changes: 8 additions & 0 deletions docs/source/markdown/podman-machine-start.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ Only one Podman managed VM can be active at a time. If a VM is already running,

Print usage statement.

#### **--no-info**

Suppress informational tips.

#### **--quiet**, **-q**

Suppress machine starting status output.

## EXAMPLES

```
Expand Down
6 changes: 5 additions & 1 deletion pkg/machine/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,11 @@ type SSHOptions struct {
Username string
Args []string
}
type StartOptions struct{}

type StartOptions struct {
NoInfo bool
Quiet bool
}

type StopOptions struct{}

Expand Down
18 changes: 18 additions & 0 deletions pkg/machine/e2e/config_start_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,30 @@ type startMachine struct {
/*
No command line args other than a machine vm name (also not required)
*/
quiet bool
noInfo bool
}

func (s startMachine) buildCmd(m *machineTestBuilder) []string {
cmd := []string{"machine", "start"}
if len(m.name) > 0 {
cmd = append(cmd, m.name)
}
if s.quiet {
cmd = append(cmd, "--quiet")
}
if s.noInfo {
cmd = append(cmd, "--no-info")
}
return cmd
}

func (s startMachine) withQuiet() startMachine {
s.quiet = true
return s
}

func (s startMachine) withNoInfo() startMachine {
s.noInfo = true
return s
}
20 changes: 20 additions & 0 deletions pkg/machine/e2e/start_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,25 @@ var _ = Describe("podman machine start", func() {
Expect(err).To(BeNil())
Expect(ec).To(BeZero())
Expect(info[0].State).To(Equal(machine.Running))

stop := new(stopMachine)
stopSession, err := mb.setCmd(stop).run()
Expect(err).To(BeNil())
Expect(stopSession).To(Exit(0))

// suppress output
startSession, err = mb.setCmd(s.withNoInfo()).run()
Expect(err).To(BeNil())
Expect(startSession).To(Exit(0))
Expect(startSession.outputToString()).ToNot(ContainSubstring("API forwarding"))

stopSession, err = mb.setCmd(stop).run()
Expect(err).To(BeNil())
Expect(stopSession).To(Exit(0))

startSession, err = mb.setCmd(s.withQuiet()).run()
Expect(err).To(BeNil())
Expect(startSession).To(Exit(0))
Expect(len(startSession.outputToStringSlice())).To(Equal(1))
})
})
1 change: 0 additions & 1 deletion pkg/machine/e2e/stop_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ var _ = Describe("podman machine stop", func() {
Expect(session).To(Exit(0))

stop := new(stopMachine)
// Removing a running machine should fail
stopSession, err := mb.setCmd(stop).run()
Expect(err).To(BeNil())
Expect(stopSession).To(Exit(0))
Expand Down
77 changes: 43 additions & 34 deletions pkg/machine/qemu/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ func (v *MachineVM) Set(_ string, opts machine.SetOptions) ([]error, error) {
}

// Start executes the qemu command line and forks it
func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
func (v *MachineVM) Start(name string, opts machine.StartOptions) error {
var (
conn net.Conn
err error
Expand Down Expand Up @@ -613,7 +613,11 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
}
}
defer cmd.Process.Release() //nolint:errcheck
fmt.Println("Waiting for VM ...")

if !opts.Quiet {
fmt.Println("Waiting for VM ...")
}

socketPath, err := getRuntimeDir()
if err != nil {
return err
Expand Down Expand Up @@ -659,7 +663,9 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
}
}
for _, mount := range v.Mounts {
fmt.Printf("Mounting volume... %s:%s\n", mount.Source, mount.Target)
if !opts.Quiet {
fmt.Printf("Mounting volume... %s:%s\n", mount.Source, mount.Target)
}
// create mountpoint directory if it doesn't exist
// because / is immutable, we have to monkey around with permissions
// if we dont mount in /home or /mnt
Expand Down Expand Up @@ -692,7 +698,7 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
}
}

v.waitAPIAndPrintInfo(forwardState, forwardSock)
v.waitAPIAndPrintInfo(forwardState, forwardSock, opts.NoInfo)
return nil
}

Expand Down Expand Up @@ -1439,7 +1445,7 @@ func waitAndPingAPI(sock string) {
}
}

func (v *MachineVM) waitAPIAndPrintInfo(forwardState apiForwardingState, forwardSock string) {
func (v *MachineVM) waitAPIAndPrintInfo(forwardState apiForwardingState, forwardSock string, noInfo bool) {
suffix := ""
if v.Name != machine.DefaultMachineName {
suffix = " " + v.Name
Expand Down Expand Up @@ -1467,38 +1473,41 @@ func (v *MachineVM) waitAPIAndPrintInfo(forwardState apiForwardingState, forward
}

waitAndPingAPI(forwardSock)
if !v.Rootful {
fmt.Printf("\nThis machine is currently configured in rootless mode. If your containers\n")
fmt.Printf("require root permissions (e.g. ports < 1024), or if you run into compatibility\n")
fmt.Printf("issues with non-podman clients, you can switch using the following command: \n")
fmt.Printf("\n\tpodman machine set --rootful%s\n\n", suffix)
}

fmt.Printf("API forwarding listening on: %s\n", forwardSock)
if forwardState == dockerGlobal {
fmt.Printf("Docker API clients default to this address. You do not need to set DOCKER_HOST.\n\n")
} else {
stillString := "still "
switch forwardState {
case notInstalled:
fmt.Printf("\nThe system helper service is not installed; the default Docker API socket\n")
fmt.Printf("address can't be used by podman. ")
if helper := findClaimHelper(); len(helper) > 0 {
fmt.Printf("If you would like to install it run the\nfollowing commands:\n")
fmt.Printf("\n\tsudo %s install\n", helper)
fmt.Printf("\tpodman machine stop%s; podman machine start%s\n\n", suffix, suffix)
}
case machineLocal:
fmt.Printf("\nAnother process was listening on the default Docker API socket address.\n")
case claimUnsupported:
fallthrough
default:
stillString = ""
if !noInfo {
if !v.Rootful {
fmt.Printf("\nThis machine is currently configured in rootless mode. If your containers\n")
fmt.Printf("require root permissions (e.g. ports < 1024), or if you run into compatibility\n")
fmt.Printf("issues with non-podman clients, you can switch using the following command: \n")
fmt.Printf("\n\tpodman machine set --rootful%s\n\n", suffix)
}

fmt.Printf("You can %sconnect Docker API clients by setting DOCKER_HOST using the\n", stillString)
fmt.Printf("following command in your terminal session:\n")
fmt.Printf("\n\texport DOCKER_HOST='unix://%s'\n\n", forwardSock)
fmt.Printf("API forwarding listening on: %s\n", forwardSock)
if forwardState == dockerGlobal {
fmt.Printf("Docker API clients default to this address. You do not need to set DOCKER_HOST.\n\n")
} else {
stillString := "still "
switch forwardState {
case notInstalled:
fmt.Printf("\nThe system helper service is not installed; the default Docker API socket\n")
fmt.Printf("address can't be used by podman. ")
if helper := findClaimHelper(); len(helper) > 0 {
fmt.Printf("If you would like to install it run the\nfollowing commands:\n")
fmt.Printf("\n\tsudo %s install\n", helper)
fmt.Printf("\tpodman machine stop%s; podman machine start%s\n\n", suffix, suffix)
}
case machineLocal:
fmt.Printf("\nAnother process was listening on the default Docker API socket address.\n")
case claimUnsupported:
fallthrough
default:
stillString = ""
}

fmt.Printf("You can %sconnect Docker API clients by setting DOCKER_HOST using the\n", stillString)
fmt.Printf("following command in your terminal session:\n")
fmt.Printf("\n\texport DOCKER_HOST='unix://%s'\n\n", forwardSock)
}
}
}

Expand Down
45 changes: 24 additions & 21 deletions pkg/machine/wsl/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,7 @@ func configureSystem(v *MachineVM, dist string) error {
return nil
}

func configureProxy(dist string, useProxy bool) error {
func configureProxy(dist string, useProxy bool, quiet bool) error {
if !useProxy {
_ = wslInvoke(dist, "sh", "-c", clearProxySettings)
return nil
Expand All @@ -598,8 +598,9 @@ func configureProxy(dist string, useProxy bool) error {
if exitErr, isExit := err.(*exec.ExitError); isExit && exitErr.ExitCode() != 42 {
return fmt.Errorf("%v: %w", failMessage, err)
}

fmt.Println("Installing proxy support")
if !quiet {
fmt.Println("Installing proxy support")
}
_ = wslPipe(proxyConfigSetup, dist, "sh", "-c",
"cat > /usr/local/bin/proxyinit; chmod 755 /usr/local/bin/proxyinit")

Expand Down Expand Up @@ -981,14 +982,14 @@ func (v *MachineVM) Set(_ string, opts machine.SetOptions) ([]error, error) {
return setErrors, v.writeConfig()
}

func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
func (v *MachineVM) Start(name string, opts machine.StartOptions) error {
if v.isRunning() {
return fmt.Errorf("%q is already running", name)
}

dist := toDist(name)
useProxy := setupWslProxyEnv()
if err := configureProxy(dist, useProxy); err != nil {
if err := configureProxy(dist, useProxy, opts.Quiet); err != nil {
return err
}

Expand All @@ -997,7 +998,7 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
return fmt.Errorf("the WSL bootstrap script failed: %w", err)
}

if !v.Rootful {
if !v.Rootful && !opts.NoInfo {
fmt.Printf("\nThis machine is currently configured in rootless mode. If your containers\n")
fmt.Printf("require root permissions (e.g. ports < 1024), or if you run into compatibility\n")
fmt.Printf("issues with non-podman clients, you can switch using the following command: \n")
Expand All @@ -1010,22 +1011,24 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
}

globalName, pipeName, err := launchWinProxy(v)
if err != nil {
fmt.Fprintln(os.Stderr, "API forwarding for Docker API clients is not available due to the following startup failures.")
fmt.Fprintf(os.Stderr, "\t%s\n", err.Error())
fmt.Fprintln(os.Stderr, "\nPodman clients are still able to connect.")
} else {
fmt.Printf("API forwarding listening on: %s\n", pipeName)
if globalName {
fmt.Printf("\nDocker API clients default to this address. You do not need to set DOCKER_HOST.\n")
if !opts.NoInfo {
if err != nil {
fmt.Fprintln(os.Stderr, "API forwarding for Docker API clients is not available due to the following startup failures.")
fmt.Fprintf(os.Stderr, "\t%s\n", err.Error())
fmt.Fprintln(os.Stderr, "\nPodman clients are still able to connect.")
} else {
fmt.Printf("\nAnother process was listening on the default Docker API pipe address.\n")
fmt.Printf("You can still connect Docker API clients by setting DOCKER HOST using the\n")
fmt.Printf("following powershell command in your terminal session:\n")
fmt.Printf("\n\t$Env:DOCKER_HOST = '%s'\n", pipeName)
fmt.Printf("\nOr in a classic CMD prompt:\n")
fmt.Printf("\n\tset DOCKER_HOST = '%s'\n", pipeName)
fmt.Printf("\nAlternatively terminate the other process and restart podman machine.\n")
fmt.Printf("API forwarding listening on: %s\n", pipeName)
if globalName {
fmt.Printf("\nDocker API clients default to this address. You do not need to set DOCKER_HOST.\n")
} else {
fmt.Printf("\nAnother process was listening on the default Docker API pipe address.\n")
fmt.Printf("You can still connect Docker API clients by setting DOCKER HOST using the\n")
fmt.Printf("following powershell command in your terminal session:\n")
fmt.Printf("\n\t$Env:DOCKER_HOST = '%s'\n", pipeName)
fmt.Printf("\nOr in a classic CMD prompt:\n")
fmt.Printf("\n\tset DOCKER_HOST = '%s'\n", pipeName)
fmt.Printf("\nAlternatively terminate the other process and restart podman machine.\n")
}
}
}

Expand Down

0 comments on commit dd98e3c

Please sign in to comment.