From 6f821634ad47f44a89ab5da3493dd674357bed86 Mon Sep 17 00:00:00 2001 From: Toshiki Sonoda Date: Tue, 13 Jun 2023 09:15:57 +0900 Subject: [PATCH] libpod: Podman info output more network information podman info prints the network information about binary path, package version, program version and DNS information. Fixes: #18443 Signed-off-by: Toshiki Sonoda --- docs/source/markdown/podman-info.1.md | 25 ++++++++++++ libpod/define/info.go | 44 ++++++++++---------- libpod/info.go | 42 ++++++++++--------- libpod/info_linux.go | 9 +++-- libpod/oci_conmon_common.go | 4 +- libpod/util.go | 58 --------------------------- test/e2e/info_test.go | 5 +++ test/system/005-info.bats | 1 + 8 files changed, 83 insertions(+), 105 deletions(-) diff --git a/docs/source/markdown/podman-info.1.md b/docs/source/markdown/podman-info.1.md index 7e099d2d4b..9858706cb2 100644 --- a/docs/source/markdown/podman-info.1.md +++ b/docs/source/markdown/podman-info.1.md @@ -77,6 +77,20 @@ host: logDriver: journald memFree: 1833385984 memTotal: 16401895424 + networkBackend: cni + networkBackendInfo: + backend: cni + dns: + package: podman-plugins-3.4.4-1.fc34.x86_64 + path: /usr/libexec/cni/dnsname + version: |- + CNI dnsname plugin + version: 1.3.1 + commit: unknown + package: |- + containernetworking-plugins-1.0.1-1.fc34.x86_64 + podman-plugins-3.4.4-1.fc34.x86_64 + path: /usr/libexec/cni ociRuntime: name: crun package: crun-1.0-1.fc34.x86_64 @@ -220,6 +234,17 @@ $ podman info --format json "logDriver": "journald", "memFree": 1785753600, "memTotal": 16401895424, + "networkBackend": "cni", + "networkBackendInfo": { + "backend": "cni", + "package": "containernetworking-plugins-1.0.1-1.fc34.x86_64\npodman-plugins-3.4.4-1.fc34.x86_64", + "path": "/usr/libexec/cni", + "dns": { + "version": "CNI dnsname plugin\nversion: 1.3.1\ncommit: unknown", + "package": "podman-plugins-3.4.4-1.fc34.x86_64", + "path": "/usr/libexec/cni/dnsname" + } + }, "ociRuntime": { "name": "crun", "package": "crun-1.0-1.fc34.x86_64", diff --git a/libpod/define/info.go b/libpod/define/info.go index 69f86c92c8..9354ae31a9 100644 --- a/libpod/define/info.go +++ b/libpod/define/info.go @@ -1,6 +1,7 @@ package define import ( + "github.com/containers/common/libnetwork/types" "github.com/containers/storage/pkg/idtools" ) @@ -27,27 +28,28 @@ type SecurityInfo struct { // HostInfo describes the libpod host type HostInfo struct { - Arch string `json:"arch"` - BuildahVersion string `json:"buildahVersion"` - CgroupManager string `json:"cgroupManager"` - CgroupsVersion string `json:"cgroupVersion"` - CgroupControllers []string `json:"cgroupControllers"` - Conmon *ConmonInfo `json:"conmon"` - CPUs int `json:"cpus"` - CPUUtilization *CPUUsage `json:"cpuUtilization"` - DatabaseBackend string `json:"databaseBackend"` - Distribution DistributionInfo `json:"distribution"` - EventLogger string `json:"eventLogger"` - FreeLocks *uint32 `json:"freeLocks,omitempty"` - Hostname string `json:"hostname"` - IDMappings IDMappings `json:"idMappings,omitempty"` - Kernel string `json:"kernel"` - LogDriver string `json:"logDriver"` - MemFree int64 `json:"memFree"` - MemTotal int64 `json:"memTotal"` - NetworkBackend string `json:"networkBackend"` - OCIRuntime *OCIRuntimeInfo `json:"ociRuntime"` - OS string `json:"os"` + Arch string `json:"arch"` + BuildahVersion string `json:"buildahVersion"` + CgroupManager string `json:"cgroupManager"` + CgroupsVersion string `json:"cgroupVersion"` + CgroupControllers []string `json:"cgroupControllers"` + Conmon *ConmonInfo `json:"conmon"` + CPUs int `json:"cpus"` + CPUUtilization *CPUUsage `json:"cpuUtilization"` + DatabaseBackend string `json:"databaseBackend"` + Distribution DistributionInfo `json:"distribution"` + EventLogger string `json:"eventLogger"` + FreeLocks *uint32 `json:"freeLocks,omitempty"` + Hostname string `json:"hostname"` + IDMappings IDMappings `json:"idMappings,omitempty"` + Kernel string `json:"kernel"` + LogDriver string `json:"logDriver"` + MemFree int64 `json:"memFree"` + MemTotal int64 `json:"memTotal"` + NetworkBackend string `json:"networkBackend"` + NetworkBackendInfo types.NetworkInfo `json:"networkBackendInfo"` + OCIRuntime *OCIRuntimeInfo `json:"ociRuntime"` + OS string `json:"os"` // RemoteSocket returns the UNIX domain socket the Podman service is listening on RemoteSocket *RemoteSocket `json:"remoteSocket,omitempty"` RuntimeInfo map[string]interface{} `json:"runtimeInfo,omitempty"` diff --git a/libpod/info.go b/libpod/info.go index e746fbdf95..877fdc918d 100644 --- a/libpod/info.go +++ b/libpod/info.go @@ -14,6 +14,7 @@ import ( "github.com/containers/buildah" "github.com/containers/buildah/pkg/util" + cutil "github.com/containers/common/pkg/util" "github.com/containers/image/v5/pkg/sysregistriesv2" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/libpod/linkmode" @@ -106,24 +107,25 @@ func (r *Runtime) hostInfo() (*define.HostInfo, error) { } info := define.HostInfo{ - Arch: runtime.GOARCH, - BuildahVersion: buildah.Version, - DatabaseBackend: r.config.Engine.DBBackend, - Linkmode: linkmode.Linkmode(), - CPUs: runtime.NumCPU(), - CPUUtilization: cpuUtil, - Distribution: hostDistributionInfo, - FreeLocks: locksFree, - LogDriver: r.config.Containers.LogDriver, - EventLogger: r.eventer.String(), - Hostname: host, - Kernel: kv, - MemFree: mi.MemFree, - MemTotal: mi.MemTotal, - NetworkBackend: r.config.Network.NetworkBackend, - OS: runtime.GOOS, - SwapFree: mi.SwapFree, - SwapTotal: mi.SwapTotal, + Arch: runtime.GOARCH, + BuildahVersion: buildah.Version, + DatabaseBackend: r.config.Engine.DBBackend, + Linkmode: linkmode.Linkmode(), + CPUs: runtime.NumCPU(), + CPUUtilization: cpuUtil, + Distribution: hostDistributionInfo, + LogDriver: r.config.Containers.LogDriver, + EventLogger: r.eventer.String(), + FreeLocks: locksFree, + Hostname: host, + Kernel: kv, + MemFree: mi.MemFree, + MemTotal: mi.MemTotal, + NetworkBackend: r.config.Network.NetworkBackend, + NetworkBackendInfo: r.network.NetworkInfo(), + OS: runtime.GOOS, + SwapFree: mi.SwapFree, + SwapTotal: mi.SwapTotal, } if err := r.setPlatformHostInfo(&info); err != nil { return nil, err @@ -241,14 +243,14 @@ func (r *Runtime) storeInfo() (*define.StoreInfo, error) { for _, o := range r.store.GraphOptions() { split := strings.SplitN(o, "=", 2) if strings.HasSuffix(split[0], "mount_program") { - version, err := programVersion(split[1]) + version, err := cutil.ProgramVersion(split[1]) if err != nil { logrus.Warnf("Failed to retrieve program version for %s: %v", split[1], err) } program := map[string]interface{}{} program["Executable"] = split[1] program["Version"] = version - program["Package"] = packageVersion(split[1]) + program["Package"] = cutil.PackageVersion(split[1]) graphOptions[split[0]] = program } else { graphOptions[split[0]] = split[1] diff --git a/libpod/info_linux.go b/libpod/info_linux.go index 221085da25..25104fc43e 100644 --- a/libpod/info_linux.go +++ b/libpod/info_linux.go @@ -11,6 +11,7 @@ import ( "github.com/containers/common/pkg/apparmor" "github.com/containers/common/pkg/cgroups" "github.com/containers/common/pkg/seccomp" + "github.com/containers/common/pkg/util" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/rootless" "github.com/opencontainers/selinux/go-selinux" @@ -59,13 +60,13 @@ func (r *Runtime) setPlatformHostInfo(info *define.HostInfo) error { slirp4netnsPath, _ = r.config.FindHelperBinary(slirp4netnsBinaryName, true) } if slirp4netnsPath != "" { - version, err := programVersion(slirp4netnsPath) + version, err := util.ProgramVersion(slirp4netnsPath) if err != nil { logrus.Warnf("Failed to retrieve program version for %s: %v", slirp4netnsPath, err) } program := define.SlirpInfo{ Executable: slirp4netnsPath, - Package: packageVersion(slirp4netnsPath), + Package: util.PackageVersion(slirp4netnsPath), Version: version, } info.Slirp4NetNS = program @@ -73,13 +74,13 @@ func (r *Runtime) setPlatformHostInfo(info *define.HostInfo) error { pastaPath, _ := r.config.FindHelperBinary(pastaBinaryName, true) if pastaPath != "" { - version, err := programVersion(pastaPath) + version, err := util.ProgramVersion(pastaPath) if err != nil { logrus.Warnf("Failed to retrieve program version for %s: %v", pastaPath, err) } program := define.PastaInfo{ Executable: pastaPath, - Package: packageVersion(pastaPath), + Package: util.PackageVersion(pastaPath), Version: version, } info.Pasta = program diff --git a/libpod/oci_conmon_common.go b/libpod/oci_conmon_common.go index 95065bf28c..f87866195d 100644 --- a/libpod/oci_conmon_common.go +++ b/libpod/oci_conmon_common.go @@ -945,8 +945,8 @@ func (r *ConmonOCIRuntime) ExitFilePath(ctr *Container) (string, error) { // RuntimeInfo provides information on the runtime. func (r *ConmonOCIRuntime) RuntimeInfo() (*define.ConmonInfo, *define.OCIRuntimeInfo, error) { - runtimePackage := packageVersion(r.path) - conmonPackage := packageVersion(r.conmonPath) + runtimePackage := cutil.PackageVersion(r.path) + conmonPackage := cutil.PackageVersion(r.conmonPath) runtimeVersion, err := r.getOCIRuntimeVersion() if err != nil { return nil, nil, fmt.Errorf("getting version of OCI runtime %s: %w", r.name, err) diff --git a/libpod/util.go b/libpod/util.go index 1047a523be..2ecd9661fa 100644 --- a/libpod/util.go +++ b/libpod/util.go @@ -7,7 +7,6 @@ import ( "io" "net/http" "os" - "os/exec" "path/filepath" "sort" "strings" @@ -16,18 +15,12 @@ import ( "github.com/containers/common/libnetwork/types" "github.com/containers/common/pkg/config" "github.com/containers/podman/v4/libpod/define" - "github.com/containers/podman/v4/utils" "github.com/fsnotify/fsnotify" spec "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/selinux/go-selinux/label" "github.com/sirupsen/logrus" ) -// Runtime API constants -const ( - unknownPackage = "Unknown" -) - // FuncTimer helps measure the execution time of a function // For debug purposes, do not leave in code // used like defer FuncTimer("foo") @@ -145,57 +138,6 @@ func JSONDeepCopy(from, to interface{}) error { return json.Unmarshal(tmp, to) } -func queryPackageVersion(cmdArg ...string) string { - output := unknownPackage - if 1 < len(cmdArg) { - cmd := exec.Command(cmdArg[0], cmdArg[1:]...) - if outp, err := cmd.Output(); err == nil { - output = string(outp) - if cmdArg[0] == "/usr/bin/dpkg" { - r := strings.Split(output, ": ") - queryFormat := `${Package}_${Version}_${Architecture}` - cmd = exec.Command("/usr/bin/dpkg-query", "-f", queryFormat, "-W", r[0]) - if outp, err := cmd.Output(); err == nil { - output = string(outp) - } - } - } - if cmdArg[0] == "/sbin/apk" { - prefix := cmdArg[len(cmdArg)-1] + " is owned by " - output = strings.Replace(output, prefix, "", 1) - } - } - return strings.Trim(output, "\n") -} - -func packageVersion(program string) string { // program is full path - packagers := [][]string{ - {"/usr/bin/rpm", "-q", "-f"}, - {"/usr/bin/dpkg", "-S"}, // Debian, Ubuntu - {"/usr/bin/pacman", "-Qo"}, // Arch - {"/usr/bin/qfile", "-qv"}, // Gentoo (quick) - {"/usr/bin/equery", "b"}, // Gentoo (slow) - {"/sbin/apk", "info", "-W"}, // Alpine - {"/usr/local/sbin/pkg", "which", "-q"}, // FreeBSD - } - - for _, cmd := range packagers { - cmd = append(cmd, program) - if out := queryPackageVersion(cmd...); out != unknownPackage { - return out - } - } - return unknownPackage -} - -func programVersion(mountProgram string) (string, error) { - output, err := utils.ExecCmd(mountProgram, "--version") - if err != nil { - return "", err - } - return strings.TrimSuffix(output, "\n"), nil -} - // DefaultSeccompPath returns the path to the default seccomp.json file // if it exists, first it checks OverrideSeccomp and then default. // If neither exist function returns "" diff --git a/test/e2e/info_test.go b/test/e2e/info_test.go index cc13766aab..93f7a46f2a 100644 --- a/test/e2e/info_test.go +++ b/test/e2e/info_test.go @@ -160,6 +160,11 @@ var _ = Describe("Podman Info", func() { session.WaitWithDefaultTimeout() Expect(session).To(Exit(0)) Expect(session.OutputToString()).To(Equal(want)) + + session = podmanTest.Podman([]string{"info", "--format", "{{.Host.NetworkBackendInfo.Backend}}"}) + session.WaitWithDefaultTimeout() + Expect(session).To(Exit(0)) + Expect(session.OutputToString()).To(Equal(want)) }) It("Podman info: check desired database backend", func() { diff --git a/test/system/005-info.bats b/test/system/005-info.bats index 2f974439d0..54ee820cf0 100644 --- a/test/system/005-info.bats +++ b/test/system/005-info.bats @@ -42,6 +42,7 @@ host.conmon.path | $expr_path host.conmon.package | .*conmon.* host.cgroupManager | \\\(systemd\\\|cgroupfs\\\) host.cgroupVersion | v[12] +host.networkBackendInfo | .*dns.*package.* host.ociRuntime.path | $expr_path host.pasta | .*executable.*package.* store.configFile | $expr_path