From 29f5c563e41e0ca061a139bb25e71ea880847f3e Mon Sep 17 00:00:00 2001 From: Brent Baude Date: Tue, 10 Oct 2023 19:13:46 -0500 Subject: [PATCH] Show client info even if remote connection fails When people report issues, we often ask for the result of `podman info`. However, if the problem is the remote connection, it will error out with no information at all. This PR at least will report client information before disclosing the connection error. For example on Windows: > .\bin\windows\podman.exe info client: OS: windows/amd64 provider: hyperv version: 4.8.0-dev host: null Satisfies: RUN-1720 Signed-off-by: Brent Baude --- cmd/podman/client.go | 25 +++++++++++++++++++++++++ cmd/podman/client_supported.go | 16 ++++++++++++++++ cmd/podman/client_unsupported.go | 7 +++++++ cmd/podman/root.go | 10 ++++++++++ test/e2e/info_test.go | 13 +++++++++++++ test/system/272-system-connection.bats | 2 +- 6 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 cmd/podman/client.go create mode 100644 cmd/podman/client_supported.go create mode 100644 cmd/podman/client_unsupported.go diff --git a/cmd/podman/client.go b/cmd/podman/client.go new file mode 100644 index 0000000000..9fa9646330 --- /dev/null +++ b/cmd/podman/client.go @@ -0,0 +1,25 @@ +package main + +import "github.com/containers/podman/v4/libpod/define" + +type clientInfo struct { + OSArch string `json:"OS"` + Provider string `json:"provider"` + Version string `json:"version"` +} + +func getClientInfo() (*clientInfo, error) { + p, err := getProvider() + if err != nil { + return nil, err + } + vinfo, err := define.GetVersion() + if err != nil { + return nil, err + } + return &clientInfo{ + OSArch: vinfo.OsArch, + Provider: p, + Version: vinfo.Version, + }, nil +} diff --git a/cmd/podman/client_supported.go b/cmd/podman/client_supported.go new file mode 100644 index 0000000000..2d744e0230 --- /dev/null +++ b/cmd/podman/client_supported.go @@ -0,0 +1,16 @@ +//go:build amd64 || arm64 +// +build amd64 arm64 + +package main + +import ( + "github.com/containers/podman/v4/pkg/machine/provider" +) + +func getProvider() (string, error) { + p, err := provider.Get() + if err != nil { + return "", err + } + return p.VMType().String(), nil +} diff --git a/cmd/podman/client_unsupported.go b/cmd/podman/client_unsupported.go new file mode 100644 index 0000000000..7abc25bd9d --- /dev/null +++ b/cmd/podman/client_unsupported.go @@ -0,0 +1,7 @@ +//go:build !amd64 && !arm64 + +package main + +func getProvider() (string, error) { + return "", nil +} diff --git a/cmd/podman/root.go b/cmd/podman/root.go index 8f132c053f..484ea46a99 100644 --- a/cmd/podman/root.go +++ b/cmd/podman/root.go @@ -24,6 +24,7 @@ import ( "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/spf13/pflag" + "sigs.k8s.io/yaml" ) // HelpTemplate is the help template for podman commands @@ -296,6 +297,15 @@ func persistentPreRunE(cmd *cobra.Command, args []string) error { // Prep the engines if _, err := registry.NewImageEngine(cmd, args); err != nil { + // Note: this is gross, but it is the hand we are dealt + if registry.IsRemote() && errors.As(err, &bindings.ConnectError{}) && cmd.Name() == "info" && cmd.Parent() == cmd.Root() { + clientDesc, err := getClientInfo() + // we eat the error here. if this fails, they just don't any client info + if err == nil { + b, _ := yaml.Marshal(clientDesc) + fmt.Println(string(b)) + } + } return err } if _, err := registry.NewContainerEngine(cmd, args); err != nil { diff --git a/test/e2e/info_test.go b/test/e2e/info_test.go index e221caff7d..165e618cb7 100644 --- a/test/e2e/info_test.go +++ b/test/e2e/info_test.go @@ -6,6 +6,7 @@ import ( "os/exec" "os/user" "path/filepath" + "runtime" "strconv" . "github.com/containers/podman/v4/test/utils" @@ -240,4 +241,16 @@ var _ = Describe("Podman Info", func() { // Don't check absolute numbers because there is a decent chance of contamination, containers that were never removed properly, etc. Expect(free1).To(Equal(free2 + 1)) }) + + It("Podman info: check for client information when no system service", func() { + // the output for this information is not really something we can marshall + want := runtime.GOOS + "/" + runtime.GOARCH + podmanTest.StopRemoteService() + SkipIfNotRemote("Specifically testing a failed remote connection") + info := podmanTest.Podman([]string{"info"}) + info.WaitWithDefaultTimeout() + Expect(info.OutputToString()).To(ContainSubstring(want)) + Expect(info).ToNot(ExitCleanly()) + podmanTest.StartRemoteService() // Start service again so teardown runs clean + }) }) diff --git a/test/system/272-system-connection.bats b/test/system/272-system-connection.bats index a4dc9bd6e8..d146d6cd5a 100644 --- a/test/system/272-system-connection.bats +++ b/test/system/272-system-connection.bats @@ -102,7 +102,7 @@ $c2[ ]\+tcp://localhost:54321[ ]\+true" \ # when invoking podman. _run_podman_remote 125 info is "$output" \ - "Cannot connect to Podman. Please verify.*dial tcp.*connection refused" \ + "OS: .*provider:.*Cannot connect to Podman. Please verify.*dial tcp.*connection refused" \ "podman info, without active service" # Start service. Now podman info should work fine. The %%-remote*