From dd98e3cc641fafe7e6184af3f60e79a57d162388 Mon Sep 17 00:00:00 2001 From: Ashley Cui Date: Thu, 13 Oct 2022 19:36:18 -0400 Subject: [PATCH] Add --quiet and --no-info flags to podman machine start 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 --- cmd/podman/machine/start.go | 19 ++++- .../source/markdown/podman-machine-start.1.md | 8 ++ pkg/machine/config.go | 6 +- pkg/machine/e2e/config_start_test.go | 18 +++++ pkg/machine/e2e/start_test.go | 20 +++++ pkg/machine/e2e/stop_test.go | 1 - pkg/machine/qemu/machine.go | 77 +++++++++++-------- pkg/machine/wsl/machine.go | 45 ++++++----- 8 files changed, 134 insertions(+), 60 deletions(-) diff --git a/cmd/podman/machine/start.go b/cmd/podman/machine/start.go index 15a75522a3..d7a642536a 100644 --- a/cmd/podman/machine/start.go +++ b/cmd/podman/machine/start.go @@ -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, @@ -23,6 +23,7 @@ var ( Example: `podman machine start myvm`, ValidArgsFunction: autocompleteMachine, } + startOpts = machine.StartOptions{} ) func init() { @@ -30,6 +31,13 @@ func init() { 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 { @@ -37,6 +45,9 @@ func start(_ *cobra.Command, args []string) error { err error vm machine.VM ) + + startOpts.NoInfo = startOpts.Quiet || startOpts.NoInfo + vmName := defaultMachineName if len(args) > 0 && len(args[0]) > 0 { vmName = args[0] @@ -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) diff --git a/docs/source/markdown/podman-machine-start.1.md b/docs/source/markdown/podman-machine-start.1.md index aa356a3744..f6400104ee 100644 --- a/docs/source/markdown/podman-machine-start.1.md +++ b/docs/source/markdown/podman-machine-start.1.md @@ -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 ``` diff --git a/pkg/machine/config.go b/pkg/machine/config.go index ee22be3dea..1cb02badb2 100644 --- a/pkg/machine/config.go +++ b/pkg/machine/config.go @@ -114,7 +114,11 @@ type SSHOptions struct { Username string Args []string } -type StartOptions struct{} + +type StartOptions struct { + NoInfo bool + Quiet bool +} type StopOptions struct{} diff --git a/pkg/machine/e2e/config_start_test.go b/pkg/machine/e2e/config_start_test.go index d9efbf4891..57c09bc3b4 100644 --- a/pkg/machine/e2e/config_start_test.go +++ b/pkg/machine/e2e/config_start_test.go @@ -4,6 +4,8 @@ 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 { @@ -11,5 +13,21 @@ func (s startMachine) buildCmd(m *machineTestBuilder) []string { 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 +} diff --git a/pkg/machine/e2e/start_test.go b/pkg/machine/e2e/start_test.go index 1f94055699..e6f31b7789 100644 --- a/pkg/machine/e2e/start_test.go +++ b/pkg/machine/e2e/start_test.go @@ -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)) }) }) diff --git a/pkg/machine/e2e/stop_test.go b/pkg/machine/e2e/stop_test.go index 621bbdb165..0e146cfa27 100644 --- a/pkg/machine/e2e/stop_test.go +++ b/pkg/machine/e2e/stop_test.go @@ -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)) diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go index 8fc2ad0e0f..6a9d86b2f5 100644 --- a/pkg/machine/qemu/machine.go +++ b/pkg/machine/qemu/machine.go @@ -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 @@ -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 @@ -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 @@ -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 } @@ -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 @@ -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) + } } } diff --git a/pkg/machine/wsl/machine.go b/pkg/machine/wsl/machine.go index 8cd2aa8c81..5db6ab255c 100644 --- a/pkg/machine/wsl/machine.go +++ b/pkg/machine/wsl/machine.go @@ -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 @@ -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") @@ -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 } @@ -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") @@ -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") + } } }