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*