diff options
author | Brent Baude <bbaude@redhat.com> | 2020-03-15 11:53:59 -0500 |
---|---|---|
committer | Brent Baude <bbaude@redhat.com> | 2020-04-06 12:45:42 -0500 |
commit | e20ecc733c878f0c4b67a21204f0d5ae11929bf0 (patch) | |
tree | 8686fd9c9f123cbed11f0589655caaa128b12061 | |
parent | e318b09b6800ddb013ddf3b9a2fb99ebc55bd920 (diff) | |
download | podman-e20ecc733c878f0c4b67a21204f0d5ae11929bf0.tar.gz podman-e20ecc733c878f0c4b67a21204f0d5ae11929bf0.tar.bz2 podman-e20ecc733c878f0c4b67a21204f0d5ae11929bf0.zip |
refactor info
the current implementation of info, while typed, is very loosely done so. we need stronger types for our apiv2 implmentation and bindings.
Signed-off-by: Brent Baude <bbaude@redhat.com>
27 files changed, 608 insertions, 308 deletions
diff --git a/cmd/podman/info.go b/cmd/podman/info.go index 7361525ce..79417b85d 100644 --- a/cmd/podman/info.go +++ b/cmd/podman/info.go @@ -2,6 +2,8 @@ package main import ( "fmt" + "html/template" + "os" rt "runtime" "strings" @@ -11,7 +13,6 @@ import ( "github.com/containers/libpod/pkg/adapter" "github.com/containers/libpod/version" "github.com/pkg/errors" - "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -49,42 +50,32 @@ func init() { } func infoCmd(c *cliconfig.InfoValues) error { - info := map[string]interface{}{} - remoteClientInfo := map[string]interface{}{} - runtime, err := adapter.GetRuntime(getContext(), &c.PodmanCommand) if err != nil { return errors.Wrapf(err, "could not get runtime") } defer runtime.DeferredShutdown(false) - infoArr, err := runtime.Info() + i, err := runtime.Info() if err != nil { return errors.Wrapf(err, "error getting info") } + info := infoWithExtra{Info: i} if runtime.Remote { endpoint, err := runtime.RemoteEndpoint() if err != nil { - logrus.Errorf("Failed to obtain server connection: %s", err.Error()) - } else { - remoteClientInfo["Connection"] = endpoint.Connection - remoteClientInfo["Connection Type"] = endpoint.Type.String() + return err } - - remoteClientInfo["RemoteAPI Version"] = version.RemoteAPIVersion - remoteClientInfo["Podman Version"] = version.Version - remoteClientInfo["OS Arch"] = fmt.Sprintf("%s/%s", rt.GOOS, rt.GOARCH) - infoArr = append(infoArr, define.InfoData{Type: "client", Data: remoteClientInfo}) + info.Remote = getRemote(endpoint) } if !runtime.Remote && c.Debug { - debugInfo := debugInfo(c) - infoArr = append(infoArr, define.InfoData{Type: "debug", Data: debugInfo}) - } - - for _, currInfo := range infoArr { - info[currInfo.Type] = currInfo.Data + d, err := getDebug() + if err != nil { + return err + } + info.Debug = d } var out formats.Writer @@ -98,19 +89,58 @@ func infoCmd(c *cliconfig.InfoValues) error { case "": out = formats.YAMLStruct{Output: info} default: - out = formats.StdoutTemplate{Output: info, Template: infoOutputFormat} + tmpl, err := template.New("info").Parse(c.Format) + if err != nil { + return err + } + err = tmpl.Execute(os.Stdout, info) + return err } return out.Out() } // top-level "debug" info -func debugInfo(c *cliconfig.InfoValues) map[string]interface{} { - info := map[string]interface{}{} - info["compiler"] = rt.Compiler - info["go version"] = rt.Version() - info["podman version"] = version.Version - version, _ := define.GetVersion() - info["git commit"] = version.GitCommit - return info +func getDebug() (*debugInfo, error) { + v, err := define.GetVersion() + if err != nil { + return nil, err + } + return &debugInfo{ + Compiler: rt.Compiler, + GoVersion: rt.Version(), + PodmanVersion: v.Version, + GitCommit: v.GitCommit, + }, nil +} + +func getRemote(endpoint *adapter.Endpoint) *remoteInfo { + return &remoteInfo{ + Connection: endpoint.Connection, + ConnectionType: endpoint.Type.String(), + RemoteAPIVersion: string(version.RemoteAPIVersion), + PodmanVersion: version.Version, + OSArch: fmt.Sprintf("%s/%s", rt.GOOS, rt.GOARCH), + } +} + +type infoWithExtra struct { + *define.Info + Remote *remoteInfo `json:"remote,omitempty"` + Debug *debugInfo `json:"debug,omitempty"` +} + +type remoteInfo struct { + Connection string `json:"connection"` + ConnectionType string `json:"connectionType"` + RemoteAPIVersion string `json:"remoteAPIVersion"` + PodmanVersion string `json:"podmanVersion"` + OSArch string `json:"OSArch"` +} + +type debugInfo struct { + Compiler string `json:"compiler"` + GoVersion string `json:"goVersion"` + PodmanVersion string `json:"podmanVersion"` + GitCommit string `json:"gitCommit"` } diff --git a/docs/source/markdown/podman-info.1.md b/docs/source/markdown/podman-info.1.md index b539f1d3c..d9da4c3f8 100644 --- a/docs/source/markdown/podman-info.1.md +++ b/docs/source/markdown/podman-info.1.md @@ -156,7 +156,7 @@ Run podman info with JSON formatted response: ``` Run podman info and only get the registries information. ``` -$ podman info --format={{".registries"}} +$ podman info --format={{".Registries"}} map[registries:[docker.io quay.io registry.fedoraproject.org registry.access.redhat.com]] ``` diff --git a/libpod/define/info.go b/libpod/define/info.go new file mode 100644 index 000000000..e9809c367 --- /dev/null +++ b/libpod/define/info.go @@ -0,0 +1,101 @@ +package define + +import "github.com/containers/storage/pkg/idtools" + +// Info is the overall struct that describes the host system +// running libpod/podman +type Info struct { + Host *HostInfo `json:"host"` + Store *StoreInfo `json:"store"` + Registries map[string]interface{} `json:"registries"` +} + +//HostInfo describes the libpod host +type HostInfo struct { + Arch string `json:"arch"` + BuildahVersion string `json:"buildahVersion"` + CGroupsVersion string `json:"cgroupVersion"` + Conmon *ConmonInfo `json:"conmon"` + CPUs int `json:"cpus"` + Distribution DistributionInfo `json:"distribution"` + EventLogger string `json:"eventLogger"` + Hostname string `json:"hostname"` + IDMappings IDMappings `json:"idMappings,omitempty"` + Kernel string `json:"kernel"` + MemFree int64 `json:"memFree"` + MemTotal int64 `json:"memTotal"` + OCIRuntime *OCIRuntimeInfo `json:"ociRuntime"` + OS string `json:"os"` + Rootless bool `json:"rootless"` + RuntimeInfo map[string]interface{} `json:"runtimeInfo,omitempty"` + Slirp4NetNS SlirpInfo `json:"slirp4netns,omitempty"` + SwapFree int64 `json:"swapFree"` + SwapTotal int64 `json:"swapTotal"` + Uptime string `json:"uptime"` +} + +// SlirpInfo describes the slirp exectuable that +// is being being used. +type SlirpInfo struct { + Executable string `json:"executable"` + Package string `json:"package"` + Version string `json:"version"` +} + +// IDMappings describe the GID and UID mappings +type IDMappings struct { + GIDMap []idtools.IDMap `json:"gidmap"` + UIDMap []idtools.IDMap `json:"uidmap"` +} + +// DistributionInfo describes the host distribution +// for libpod +type DistributionInfo struct { + Distribution string `json:"distribution"` + Version string `json:"version"` +} + +// ConmonInfo describes the conmon executable being used +type ConmonInfo struct { + Package string `json:"package"` + Path string `json:"path"` + Version string `json:"version"` +} + +// OCIRuntimeInfo describes the runtime (crun or runc) being +// used with podman +type OCIRuntimeInfo struct { + Name string `json:"name"` + Package string `json:"package"` + Path string `json:"path"` + Version string `json:"version"` +} + +// StoreInfo describes the container storage and its +// attributes +type StoreInfo struct { + ConfigFile string `json:"configFile"` + ContainerStore ContainerStore `json:"containerStore"` + GraphDriverName string `json:"graphDriverName"` + GraphOptions map[string]interface{} `json:"graphOptions"` + GraphRoot string `json:"graphRoot"` + GraphStatus map[string]string `json:"graphStatus"` + ImageStore ImageStore `json:"imageStore"` + RunRoot string `json:"runRoot"` + VolumePath string `json:"volumePath"` +} + +// ImageStore describes the image store. Right now only the number +// of images present +type ImageStore struct { + Number int `json:"number"` +} + +// ContainerStore describes the quantity of containers in the +// store by status +type ContainerStore struct { + Number int `json:"number"` + Paused int `json:"paused"` + Running int `json:"running"` + Stopped int `json:"stopped"` +} diff --git a/libpod/info.go b/libpod/info.go index 8d411f0d4..3cc767be6 100644 --- a/libpod/info.go +++ b/libpod/info.go @@ -13,7 +13,9 @@ import ( "time" "github.com/containers/buildah" + "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/cgroups" + registries2 "github.com/containers/libpod/pkg/registries" "github.com/containers/libpod/pkg/rootless" "github.com/containers/storage" "github.com/containers/storage/pkg/system" @@ -21,14 +23,80 @@ import ( "github.com/sirupsen/logrus" ) +// Info returns the store and host information +func (r *Runtime) info() (*define.Info, error) { + info := define.Info{} + // get host information + hostInfo, err := r.hostInfo() + if err != nil { + return nil, errors.Wrapf(err, "error getting host info") + } + info.Host = hostInfo + + // get store information + storeInfo, err := r.storeInfo() + if err != nil { + return nil, errors.Wrapf(err, "error getting store info") + } + info.Store = storeInfo + registries := make(map[string]interface{}) + data, err := registries2.GetRegistriesData() + if err != nil { + return nil, errors.Wrapf(err, "error getting registries") + } + for _, reg := range data { + registries[reg.Prefix] = reg + } + regs, err := registries2.GetRegistries() + if err != nil { + return nil, errors.Wrapf(err, "error getting registries") + } + if len(regs) > 0 { + registries["search"] = regs + } + + info.Registries = registries + return &info, nil +} + // top-level "host" info -func (r *Runtime) hostInfo() (map[string]interface{}, error) { +func (r *Runtime) hostInfo() (*define.HostInfo, error) { // lets say OS, arch, number of cpus, amount of memory, maybe os distribution/version, hostname, kernel version, uptime - info := map[string]interface{}{} - info["os"] = runtime.GOOS - info["arch"] = runtime.GOARCH - info["cpus"] = runtime.NumCPU() - info["rootless"] = rootless.IsRootless() + mi, err := system.ReadMemInfo() + if err != nil { + return nil, errors.Wrapf(err, "error reading memory info") + } + + hostDistributionInfo := r.GetHostDistributionInfo() + + kv, err := readKernelVersion() + if err != nil { + return nil, errors.Wrapf(err, "error reading kernel version") + } + + host, err := os.Hostname() + if err != nil { + return nil, errors.Wrapf(err, "error getting hostname") + } + info := define.HostInfo{ + Arch: runtime.GOARCH, + BuildahVersion: buildah.Version, + CPUs: runtime.NumCPU(), + Distribution: hostDistributionInfo, + EventLogger: r.eventer.String(), + Hostname: host, + IDMappings: define.IDMappings{}, + Kernel: kv, + MemFree: mi.MemFree, + MemTotal: mi.MemTotal, + OS: runtime.GOOS, + Rootless: rootless.IsRootless(), + Slirp4NetNS: define.SlirpInfo{}, + SwapFree: mi.SwapFree, + SwapTotal: mi.SwapTotal, + } + + // CGroups version unified, err := cgroups.IsCgroup2UnifiedMode() if err != nil { return nil, errors.Wrapf(err, "error reading cgroups mode") @@ -37,17 +105,8 @@ func (r *Runtime) hostInfo() (map[string]interface{}, error) { if unified { cgroupVersion = "v2" } - info["CgroupVersion"] = cgroupVersion - mi, err := system.ReadMemInfo() - if err != nil { - return nil, errors.Wrapf(err, "error reading memory info") - } - // TODO this might be a place for github.com/dustin/go-humanize - info["MemTotal"] = mi.MemTotal - info["MemFree"] = mi.MemFree - info["SwapTotal"] = mi.SwapTotal - info["SwapFree"] = mi.SwapFree - hostDistributionInfo := r.GetHostDistributionInfo() + info.CGroupsVersion = cgroupVersion + if rootless.IsRootless() { if path, err := exec.LookPath("slirp4netns"); err == nil { logrus.Warnf("Failed to retrieve program version for %s: %v", path, err) @@ -55,11 +114,12 @@ func (r *Runtime) hostInfo() (map[string]interface{}, error) { if err != nil { logrus.Warnf("Failed to retrieve program version for %s: %v", path, err) } - program := map[string]interface{}{} - program["Executable"] = path - program["Version"] = version - program["Package"] = packageVersion(path) - info["slirp4netns"] = program + program := define.SlirpInfo{ + Executable: path, + Package: packageVersion(path), + Version: version, + } + info.Slirp4NetNS = program } uidmappings, err := rootless.ReadMappingsProc("/proc/self/uid_map") if err != nil { @@ -69,29 +129,19 @@ func (r *Runtime) hostInfo() (map[string]interface{}, error) { if err != nil { return nil, errors.Wrapf(err, "error reading gid mappings") } - idmappings := make(map[string]interface{}) - idmappings["uidmap"] = uidmappings - idmappings["gidmap"] = gidmappings - info["IDMappings"] = idmappings - } - info["Distribution"] = map[string]interface{}{ - "distribution": hostDistributionInfo["Distribution"], - "version": hostDistributionInfo["Version"], - } - info["BuildahVersion"] = buildah.Version - kv, err := readKernelVersion() - if err != nil { - return nil, errors.Wrapf(err, "error reading kernel version") + idmappings := define.IDMappings{ + GIDMap: gidmappings, + UIDMap: uidmappings, + } + info.IDMappings = idmappings } - info["kernel"] = kv - runtimeInfo, err := r.defaultOCIRuntime.RuntimeInfo() + conmonInfo, ociruntimeInfo, err := r.defaultOCIRuntime.RuntimeInfo() if err != nil { logrus.Errorf("Error getting info on OCI runtime %s: %v", r.defaultOCIRuntime.Name(), err) } else { - for k, v := range runtimeInfo { - info[k] = v - } + info.Conmon = conmonInfo + info.OCIRuntime = ociruntimeInfo } up, err := readUptime() @@ -105,6 +155,7 @@ func (r *Runtime) hostInfo() (map[string]interface{}, error) { return nil, errors.Wrapf(err, "error parsing system uptime") } + // TODO Isnt there a simple lib for this, something like humantime? hoursFound := false var timeBuffer bytes.Buffer var hoursBuffer bytes.Buffer @@ -121,32 +172,75 @@ func (r *Runtime) hostInfo() (map[string]interface{}, error) { } } - info["uptime"] = timeBuffer.String() + info.Uptime = timeBuffer.String() if hoursFound { hours, err := strconv.ParseFloat(hoursBuffer.String(), 64) if err == nil { days := hours / 24 - info["uptime"] = fmt.Sprintf("%s (Approximately %.2f days)", info["uptime"], days) + info.Uptime = fmt.Sprintf("%s (Approximately %.2f days)", info.Uptime, days) } } - host, err := os.Hostname() + return &info, nil +} + +func (r *Runtime) getContainerStoreInfo() (define.ContainerStore, error) { + var ( + paused, running, stopped int + ) + cs := define.ContainerStore{} + cons, err := r.GetAllContainers() if err != nil { - return nil, errors.Wrapf(err, "error getting hostname") + return cs, err } - info["hostname"] = host - info["eventlogger"] = r.eventer.String() - - return info, nil + for _, con := range cons { + state, err := con.State() + if err != nil { + return cs, err + } + switch state { + case define.ContainerStateRunning: + running += 1 + case define.ContainerStatePaused: + paused += 1 + default: + stopped += 1 + } + } + cs.Number = len(cons) + cs.Paused = paused + cs.Stopped = stopped + cs.Running = running + return cs, nil } // top-level "store" info -func (r *Runtime) storeInfo() (map[string]interface{}, error) { +func (r *Runtime) storeInfo() (*define.StoreInfo, error) { // lets say storage driver in use, number of images, number of containers - info := map[string]interface{}{} - info["GraphRoot"] = r.store.GraphRoot() - info["RunRoot"] = r.store.RunRoot() - info["GraphDriverName"] = r.store.GraphDriverName() + configFile, err := storage.DefaultConfigFile(rootless.IsRootless()) + if err != nil { + return nil, err + } + images, err := r.store.Images() + if err != nil { + return nil, errors.Wrapf(err, "error getting number of images") + } + conInfo, err := r.getContainerStoreInfo() + if err != nil { + return nil, err + } + imageInfo := define.ImageStore{Number: len(images)} + + info := define.StoreInfo{ + ImageStore: imageInfo, + ContainerStore: conInfo, + GraphRoot: r.store.GraphRoot(), + RunRoot: r.store.RunRoot(), + GraphDriverName: r.store.GraphDriverName(), + GraphOptions: nil, + VolumePath: r.config.Engine.VolumePath, + ConfigFile: configFile, + } graphOptions := map[string]interface{}{} for _, o := range r.store.GraphOptions() { split := strings.SplitN(o, "=", 2) @@ -164,14 +258,8 @@ func (r *Runtime) storeInfo() (map[string]interface{}, error) { graphOptions[split[0]] = split[1] } } - info["GraphOptions"] = graphOptions - info["VolumePath"] = r.config.Engine.VolumePath + info.GraphOptions = graphOptions - configFile, err := storage.DefaultConfigFile(rootless.IsRootless()) - if err != nil { - return nil, err - } - info["ConfigFile"] = configFile statusPairs, err := r.store.Status() if err != nil { return nil, err @@ -180,24 +268,8 @@ func (r *Runtime) storeInfo() (map[string]interface{}, error) { for _, pair := range statusPairs { status[pair[0]] = pair[1] } - info["GraphStatus"] = status - images, err := r.store.Images() - if err != nil { - return nil, errors.Wrapf(err, "error getting number of images") - } - info["ImageStore"] = map[string]interface{}{ - "number": len(images), - } - - containers, err := r.store.Containers() - if err != nil { - return nil, errors.Wrapf(err, "error getting number of containers") - } - info["ContainerStore"] = map[string]interface{}{ - "number": len(containers), - } - - return info, nil + info.GraphStatus = status + return &info, nil } func readKernelVersion() (string, error) { @@ -225,14 +297,13 @@ func readUptime() (string, error) { } // GetHostDistributionInfo returns a map containing the host's distribution and version -func (r *Runtime) GetHostDistributionInfo() map[string]string { - dist := make(map[string]string) - +func (r *Runtime) GetHostDistributionInfo() define.DistributionInfo { // Populate values in case we cannot find the values // or the file - dist["Distribution"] = "unknown" - dist["Version"] = "unknown" - + dist := define.DistributionInfo{ + Distribution: "unknown", + Version: "unknown", + } f, err := os.Open("/etc/os-release") if err != nil { return dist @@ -242,10 +313,10 @@ func (r *Runtime) GetHostDistributionInfo() map[string]string { l := bufio.NewScanner(f) for l.Scan() { if strings.HasPrefix(l.Text(), "ID=") { - dist["Distribution"] = strings.TrimPrefix(l.Text(), "ID=") + dist.Distribution = strings.TrimPrefix(l.Text(), "ID=") } if strings.HasPrefix(l.Text(), "VERSION_ID=") { - dist["Version"] = strings.Trim(strings.TrimPrefix(l.Text(), "VERSION_ID="), "\"") + dist.Version = strings.Trim(strings.TrimPrefix(l.Text(), "VERSION_ID="), "\"") } } return dist diff --git a/libpod/oci.go b/libpod/oci.go index e4fbcb62e..6adf42497 100644 --- a/libpod/oci.go +++ b/libpod/oci.go @@ -5,7 +5,6 @@ import ( "net" "github.com/containers/libpod/libpod/define" - "k8s.io/client-go/tools/remotecommand" ) @@ -122,7 +121,7 @@ type OCIRuntime interface { ExitFilePath(ctr *Container) (string, error) // RuntimeInfo returns verbose information about the runtime. - RuntimeInfo() (map[string]interface{}, error) + RuntimeInfo() (*define.ConmonInfo, *define.OCIRuntimeInfo, error) } // ExecOptions are options passed into ExecContainer. They control the command diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go index 2e96dbe57..c20e3f0b4 100644 --- a/libpod/oci_conmon_linux.go +++ b/libpod/oci_conmon_linux.go @@ -999,32 +999,30 @@ func (r *ConmonOCIRuntime) ExitFilePath(ctr *Container) (string, error) { } // RuntimeInfo provides information on the runtime. -func (r *ConmonOCIRuntime) RuntimeInfo() (map[string]interface{}, error) { +func (r *ConmonOCIRuntime) RuntimeInfo() (*define.ConmonInfo, *define.OCIRuntimeInfo, error) { runtimePackage := packageVersion(r.path) conmonPackage := packageVersion(r.conmonPath) runtimeVersion, err := r.getOCIRuntimeVersion() if err != nil { - return nil, errors.Wrapf(err, "error getting version of OCI runtime %s", r.name) + return nil, nil, errors.Wrapf(err, "error getting version of OCI runtime %s", r.name) } conmonVersion, err := r.getConmonVersion() if err != nil { - return nil, errors.Wrapf(err, "error getting conmon version") + return nil, nil, errors.Wrapf(err, "error getting conmon version") } - info := make(map[string]interface{}) - info["Conmon"] = map[string]interface{}{ - "path": r.conmonPath, - "package": conmonPackage, - "version": conmonVersion, + conmon := define.ConmonInfo{ + Package: conmonPackage, + Path: r.conmonPath, + Version: conmonVersion, } - info["OCIRuntime"] = map[string]interface{}{ - "name": r.name, - "path": r.path, - "package": runtimePackage, - "version": runtimeVersion, + ocirt := define.OCIRuntimeInfo{ + Name: r.name, + Path: r.path, + Package: runtimePackage, + Version: runtimeVersion, } - - return info, nil + return &conmon, &ocirt, nil } // makeAccessible changes the path permission and each parent directory to have --x--x--x diff --git a/libpod/oci_conmon_unsupported.go b/libpod/oci_conmon_unsupported.go index 395b6f6d9..1f9d89ff6 100644 --- a/libpod/oci_conmon_unsupported.go +++ b/libpod/oci_conmon_unsupported.go @@ -117,8 +117,8 @@ func (r *ConmonOCIRuntime) ExitFilePath(ctr *Container) (string, error) { } // RuntimeInfo is not supported on this OS. -func (r *ConmonOCIRuntime) RuntimeInfo() (map[string]interface{}, error) { - return nil, define.ErrNotImplemented +func (r *ConmonOCIRuntime) RuntimeInfo() (*define.ConmonInfo, *define.OCIRuntimeInfo, error) { + return nil, nil, define.ErrNotImplemented } // Package is not supported on this OS. diff --git a/libpod/oci_missing.go b/libpod/oci_missing.go index a5d589255..5284fb4b7 100644 --- a/libpod/oci_missing.go +++ b/libpod/oci_missing.go @@ -195,15 +195,14 @@ func (r *MissingRuntime) ExitFilePath(ctr *Container) (string, error) { } // RuntimeInfo returns information on the missing runtime -func (r *MissingRuntime) RuntimeInfo() (map[string]interface{}, error) { - info := make(map[string]interface{}) - info["OCIRuntime"] = map[string]interface{}{ - "name": r.name, - "path": "missing", - "package": "missing", - "version": "missing", +func (r *MissingRuntime) RuntimeInfo() (*define.ConmonInfo, *define.OCIRuntimeInfo, error) { + ocirt := define.OCIRuntimeInfo{ + Name: r.name, + Path: "missing", + Package: "missing", + Version: "missing", } - return info, nil + return nil, &ocirt, nil } // Return an error indicating the runtime is missing diff --git a/libpod/runtime.go b/libpod/runtime.go index 422b79359..a6032ad23 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -9,16 +9,14 @@ import ( "sync" "syscall" + "github.com/containers/common/pkg/config" is "github.com/containers/image/v5/storage" "github.com/containers/image/v5/types" - - "github.com/containers/common/pkg/config" "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/libpod/events" "github.com/containers/libpod/libpod/image" "github.com/containers/libpod/libpod/lock" "github.com/containers/libpod/pkg/cgroups" - sysreg "github.com/containers/libpod/pkg/registries" "github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/util" "github.com/containers/storage" @@ -675,40 +673,8 @@ func (r *Runtime) refresh(alivePath string) error { } // Info returns the store and host information -func (r *Runtime) Info() ([]define.InfoData, error) { - info := []define.InfoData{} - // get host information - hostInfo, err := r.hostInfo() - if err != nil { - return nil, errors.Wrapf(err, "error getting host info") - } - info = append(info, define.InfoData{Type: "host", Data: hostInfo}) - - // get store information - storeInfo, err := r.storeInfo() - if err != nil { - return nil, errors.Wrapf(err, "error getting store info") - } - info = append(info, define.InfoData{Type: "store", Data: storeInfo}) - - registries := make(map[string]interface{}) - data, err := sysreg.GetRegistriesData() - if err != nil { - return nil, errors.Wrapf(err, "error getting registries") - } - for _, reg := range data { - registries[reg.Prefix] = reg - } - regs, err := sysreg.GetRegistries() - if err != nil { - return nil, errors.Wrapf(err, "error getting registries") - } - if len(regs) > 0 { - registries["search"] = regs - } - - info = append(info, define.InfoData{Type: "registries", Data: registries}) - return info, nil +func (r *Runtime) Info() (*define.Info, error) { + return r.info() } // generateName generates a unique name for a container or pod. diff --git a/pkg/adapter/info_remote.go b/pkg/adapter/info_remote.go index 0e8fb06d1..549b01f54 100644 --- a/pkg/adapter/info_remote.go +++ b/pkg/adapter/info_remote.go @@ -3,51 +3,62 @@ package adapter import ( - "encoding/json" - "github.com/containers/libpod/libpod/define" iopodman "github.com/containers/libpod/pkg/varlink" ) // Info returns information for the host system and its components -func (r RemoteRuntime) Info() ([]define.InfoData, error) { +func (r RemoteRuntime) Info() (*define.Info, error) { // TODO the varlink implementation for info should be updated to match the output for regular info var ( - reply []define.InfoData - regInfo map[string]interface{} - hostInfo map[string]interface{} - store map[string]interface{} + reply define.Info ) info, err := iopodman.GetInfo().Call(r.Conn) if err != nil { return nil, err } - - // info.host -> map[string]interface{} - h, err := json.Marshal(info.Host) - if err != nil { - return nil, err + hostInfo := define.HostInfo{ + Arch: info.Host.Arch, + BuildahVersion: info.Host.Buildah_version, + CPUs: int(info.Host.Cpus), + Distribution: define.DistributionInfo{ + Distribution: info.Host.Distribution.Distribution, + Version: info.Host.Distribution.Version, + }, + EventLogger: info.Host.Eventlogger, + Hostname: info.Host.Hostname, + Kernel: info.Host.Kernel, + MemFree: info.Host.Mem_free, + MemTotal: info.Host.Mem_total, + OS: info.Host.Os, + SwapFree: info.Host.Swap_free, + SwapTotal: info.Host.Swap_total, + Uptime: info.Host.Uptime, } - json.Unmarshal(h, &hostInfo) - - // info.store -> map[string]interface{} - s, err := json.Marshal(info.Store) - if err != nil { - return nil, err + storeInfo := define.StoreInfo{ + ContainerStore: define.ContainerStore{ + Number: int(info.Store.Containers), + }, + GraphDriverName: info.Store.Graph_driver_name, + GraphRoot: info.Store.Graph_root, + ImageStore: define.ImageStore{ + Number: int(info.Store.Images), + }, + RunRoot: info.Store.Run_root, } - json.Unmarshal(s, &store) - - // info.Registries -> map[string]interface{} - reg, err := json.Marshal(info.Registries) - if err != nil { - return nil, err + reply.Host = &hostInfo + reply.Store = &storeInfo + regs := make(map[string]interface{}) + if len(info.Registries.Search) > 0 { + regs["search"] = info.Registries.Search } - json.Unmarshal(reg, ®Info) - - // Add everything to the reply - reply = append(reply, define.InfoData{Type: "host", Data: hostInfo}) - reply = append(reply, define.InfoData{Type: "registries", Data: regInfo}) - reply = append(reply, define.InfoData{Type: "store", Data: store}) - return reply, nil + if len(info.Registries.Blocked) > 0 { + regs["blocked"] = info.Registries.Blocked + } + if len(info.Registries.Insecure) > 0 { + regs["insecure"] = info.Registries.Insecure + } + reply.Registries = regs + return &reply, nil } diff --git a/pkg/api/handlers/compat/containers.go b/pkg/api/handlers/compat/containers.go index 2ce113d30..c53af0f26 100644 --- a/pkg/api/handlers/compat/containers.go +++ b/pkg/api/handlers/compat/containers.go @@ -94,15 +94,9 @@ func ListContainers(w http.ResponseWriter, r *http.Request) { } } // TODO filters still need to be applied - infoData, err := runtime.Info() - if err != nil { - utils.InternalServerError(w, errors.Wrapf(err, "Failed to obtain system info")) - return - } - var list = make([]*handlers.Container, len(containers)) for i, ctnr := range containers { - api, err := handlers.LibpodToContainer(ctnr, infoData, query.Size) + api, err := handlers.LibpodToContainer(ctnr, query.Size) if err != nil { utils.InternalServerError(w, err) return diff --git a/pkg/api/handlers/compat/info.go b/pkg/api/handlers/compat/info.go index 104d0793b..179b4a3e0 100644 --- a/pkg/api/handlers/compat/info.go +++ b/pkg/api/handlers/compat/info.go @@ -33,8 +33,6 @@ func GetInfo(w http.ResponseWriter, r *http.Request) { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrapf(err, "Failed to obtain system memory info")) return } - hostInfo := infoData[0].Data - storeInfo := infoData[1].Data configInfo, err := runtime.GetConfig() if err != nil { @@ -64,44 +62,44 @@ func GetInfo(w http.ResponseWriter, r *http.Request) { ClusterAdvertise: "", ClusterStore: "", ContainerdCommit: docker.Commit{}, - Containers: storeInfo["ContainerStore"].(map[string]interface{})["number"].(int), + Containers: infoData.Store.ContainerStore.Number, ContainersPaused: stateInfo[define.ContainerStatePaused], ContainersRunning: stateInfo[define.ContainerStateRunning], ContainersStopped: stateInfo[define.ContainerStateStopped] + stateInfo[define.ContainerStateExited], Debug: log.IsLevelEnabled(log.DebugLevel), DefaultRuntime: configInfo.Engine.OCIRuntime, - DockerRootDir: storeInfo["GraphRoot"].(string), - Driver: storeInfo["GraphDriverName"].(string), - DriverStatus: getGraphStatus(storeInfo), + DockerRootDir: infoData.Store.GraphRoot, + Driver: infoData.Store.GraphDriverName, + DriverStatus: getGraphStatus(infoData.Store.GraphStatus), ExperimentalBuild: true, GenericResources: nil, HTTPProxy: getEnv("http_proxy"), HTTPSProxy: getEnv("https_proxy"), ID: uuid.New().String(), IPv4Forwarding: !sysInfo.IPv4ForwardingDisabled, - Images: storeInfo["ImageStore"].(map[string]interface{})["number"].(int), + Images: infoData.Store.ImageStore.Number, IndexServerAddress: "", InitBinary: "", InitCommit: docker.Commit{}, Isolation: "", KernelMemory: sysInfo.KernelMemory, KernelMemoryTCP: false, - KernelVersion: hostInfo["kernel"].(string), + KernelVersion: infoData.Host.Kernel, Labels: nil, LiveRestoreEnabled: false, LoggingDriver: "", - MemTotal: hostInfo["MemTotal"].(int64), + MemTotal: infoData.Host.MemTotal, MemoryLimit: sysInfo.MemoryLimit, NCPU: goRuntime.NumCPU(), NEventsListener: 0, NFd: getFdCount(), NGoroutines: goRuntime.NumGoroutine(), - Name: hostInfo["hostname"].(string), + Name: infoData.Host.Hostname, NoProxy: getEnv("no_proxy"), OSType: goRuntime.GOOS, - OSVersion: hostInfo["Distribution"].(map[string]interface{})["version"].(string), + OSVersion: infoData.Host.Distribution.Version, OomKillDisable: sysInfo.OomKillDisable, - OperatingSystem: hostInfo["Distribution"].(map[string]interface{})["distribution"].(string), + OperatingSystem: infoData.Host.Distribution.Distribution, PidsLimit: sysInfo.PidsLimit, Plugins: docker.PluginsInfo{}, ProductLicense: "Apache-2.0", @@ -118,21 +116,21 @@ func GetInfo(w http.ResponseWriter, r *http.Request) { SystemTime: time.Now().Format(time.RFC3339Nano), Warnings: []string{}, }, - BuildahVersion: hostInfo["BuildahVersion"].(string), + BuildahVersion: infoData.Host.BuildahVersion, CPURealtimePeriod: sysInfo.CPURealtimePeriod, CPURealtimeRuntime: sysInfo.CPURealtimeRuntime, - CgroupVersion: hostInfo["CgroupVersion"].(string), + CgroupVersion: infoData.Host.CGroupsVersion, Rootless: rootless.IsRootless(), - SwapFree: hostInfo["SwapFree"].(int64), - SwapTotal: hostInfo["SwapTotal"].(int64), - Uptime: hostInfo["uptime"].(string), + SwapFree: infoData.Host.SwapFree, + SwapTotal: infoData.Host.SwapTotal, + Uptime: infoData.Host.Uptime, } utils.WriteResponse(w, http.StatusOK, info) } -func getGraphStatus(storeInfo map[string]interface{}) [][2]string { +func getGraphStatus(storeInfo map[string]string) [][2]string { var graphStatus [][2]string - for k, v := range storeInfo["GraphStatus"].(map[string]string) { + for k, v := range storeInfo { graphStatus = append(graphStatus, [2]string{k, v}) } return graphStatus diff --git a/pkg/api/handlers/compat/version.go b/pkg/api/handlers/compat/version.go index c7f7917ac..35a95b562 100644 --- a/pkg/api/handlers/compat/version.go +++ b/pkg/api/handlers/compat/version.go @@ -30,8 +30,6 @@ func VersionHandler(w http.ResponseWriter, r *http.Request) { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrapf(err, "Failed to obtain system memory info")) return } - hostInfo := infoData[0].Data - components := []docker.ComponentVersion{{ Name: "Podman Engine", Version: versionInfo.Version, @@ -42,7 +40,7 @@ func VersionHandler(w http.ResponseWriter, r *http.Request) { "Experimental": "true", "GitCommit": versionInfo.GitCommit, "GoVersion": versionInfo.GoVersion, - "KernelVersion": hostInfo["kernel"].(string), + "KernelVersion": infoData.Host.Kernel, "MinAPIVersion": handlers.MinimalApiVersion, "Os": goRuntime.GOOS, }, @@ -52,7 +50,7 @@ func VersionHandler(w http.ResponseWriter, r *http.Request) { Platform: struct { Name string }{ - Name: fmt.Sprintf("%s/%s/%s", goRuntime.GOOS, goRuntime.GOARCH, hostInfo["Distribution"].(map[string]interface{})["distribution"].(string)), + Name: fmt.Sprintf("%s/%s/%s-%s", goRuntime.GOOS, goRuntime.GOARCH, infoData.Host.Distribution.Distribution, infoData.Host.Distribution.Version), }, APIVersion: components[0].Details["APIVersion"], Arch: components[0].Details["Arch"], diff --git a/pkg/api/handlers/libpod/info.go b/pkg/api/handlers/libpod/info.go new file mode 100644 index 000000000..cbf03aa17 --- /dev/null +++ b/pkg/api/handlers/libpod/info.go @@ -0,0 +1,18 @@ +package libpod + +import ( + "net/http" + + "github.com/containers/libpod/libpod" + "github.com/containers/libpod/pkg/api/handlers/utils" +) + +func GetInfo(w http.ResponseWriter, r *http.Request) { + runtime := r.Context().Value("runtime").(*libpod.Runtime) + info, err := runtime.Info() + if err != nil { + utils.InternalServerError(w, err) + return + } + utils.WriteResponse(w, http.StatusOK, info) +} diff --git a/pkg/api/handlers/libpod/swagger.go b/pkg/api/handlers/libpod/swagger.go index 1fad2dd1a..5dbc33098 100644 --- a/pkg/api/handlers/libpod/swagger.go +++ b/pkg/api/handlers/libpod/swagger.go @@ -5,6 +5,7 @@ import ( "os" "github.com/containers/image/v5/manifest" + "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/api/handlers/utils" "github.com/containers/libpod/pkg/domain/entities" "github.com/pkg/errors" @@ -76,6 +77,13 @@ type swagRmPodResponse struct { Body entities.PodRmReport } +// Info +// swagger:response InfoResponse +type swagInfoResponse struct { + // in:body + Body define.Info +} + func ServeSwagger(w http.ResponseWriter, r *http.Request) { path := DefaultPodmanSwaggerSpec if p, found := os.LookupEnv("PODMAN_SWAGGER_SPEC"); found { diff --git a/pkg/api/handlers/types.go b/pkg/api/handlers/types.go index 496512f2e..f1c932ebc 100644 --- a/pkg/api/handlers/types.go +++ b/pkg/api/handlers/types.go @@ -353,7 +353,7 @@ func ImageDataToImageInspect(ctx context.Context, l *libpodImage.Image) (*ImageI } -func LibpodToContainer(l *libpod.Container, infoData []define.InfoData, sz bool) (*Container, error) { +func LibpodToContainer(l *libpod.Container, sz bool) (*Container, error) { imageId, imageName := l.Image() var ( diff --git a/pkg/api/server/register_info.go b/pkg/api/server/register_info.go index b4ab8871c..75aaa957b 100644 --- a/pkg/api/server/register_info.go +++ b/pkg/api/server/register_info.go @@ -4,14 +4,15 @@ import ( "net/http" "github.com/containers/libpod/pkg/api/handlers/compat" + "github.com/containers/libpod/pkg/api/handlers/libpod" "github.com/gorilla/mux" ) func (s *APIServer) registerInfoHandlers(r *mux.Router) error { - // swagger:operation GET /info libpod libpodGetInfo + // swagger:operation GET /info compat getInfo // --- // tags: - // - system + // - system (compat) // summary: Get info // description: Returns information on the system and libpod configuration // produces: @@ -24,5 +25,19 @@ func (s *APIServer) registerInfoHandlers(r *mux.Router) error { r.Handle(VersionedPath("/info"), s.APIHandler(compat.GetInfo)).Methods(http.MethodGet) // Added non version path to URI to support docker non versioned paths r.Handle("/info", s.APIHandler(compat.GetInfo)).Methods(http.MethodGet) + // swagger:operation GET /libpod/info libpod libpodGetInfo + // --- + // tags: + // - system + // summary: Get info + // description: Returns information on the system and libpod configuration + // produces: + // - application/json + // responses: + // 200: + // $ref: "#/responses/InfoResponse" + // 500: + // $ref: "#/responses/InternalError" + r.Handle(VersionedPath("/libpod/info"), s.APIHandler(libpod.GetInfo)).Methods(http.MethodGet) return nil } diff --git a/pkg/bindings/info.go b/pkg/bindings/info.go deleted file mode 100644 index 5f318d652..000000000 --- a/pkg/bindings/info.go +++ /dev/null @@ -1,3 +0,0 @@ -package bindings - -func (c Connection) Info() {} diff --git a/pkg/bindings/system/info.go b/pkg/bindings/system/info.go new file mode 100644 index 000000000..f8269cfd8 --- /dev/null +++ b/pkg/bindings/system/info.go @@ -0,0 +1,23 @@ +package system + +import ( + "context" + "net/http" + + "github.com/containers/libpod/libpod/define" + "github.com/containers/libpod/pkg/bindings" +) + +// Info returns information about the libpod environment and its stores +func Info(ctx context.Context) (define.Info, error) { + info := define.Info{} + conn, err := bindings.GetClient(ctx) + if err != nil { + return info, err + } + response, err := conn.DoRequest(nil, http.MethodGet, "/info", nil) + if err != nil { + return info, err + } + return info, response.Process(&info) +} diff --git a/pkg/bindings/test/info_test.go b/pkg/bindings/test/info_test.go new file mode 100644 index 000000000..d0e651134 --- /dev/null +++ b/pkg/bindings/test/info_test.go @@ -0,0 +1,73 @@ +package test_bindings + +import ( + "runtime" + "time" + + "github.com/containers/libpod/pkg/bindings/containers" + "github.com/containers/libpod/pkg/bindings/images" + "github.com/containers/libpod/pkg/bindings/system" + "github.com/containers/libpod/pkg/specgen" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "github.com/onsi/gomega/gexec" +) + +var _ = Describe("Podman info", func() { + var ( + bt *bindingTest + s *gexec.Session + t bool = true + ) + + BeforeEach(func() { + bt = newBindingTest() + bt.RestoreImagesFromCache() + s = bt.startAPIService() + time.Sleep(1 * time.Second) + err := bt.NewConnection() + Expect(err).To(BeNil()) + }) + + AfterEach(func() { + s.Kill() + bt.cleanup() + }) + + It("podman info", func() { + info, err := system.Info(bt.conn) + Expect(err).To(BeNil()) + Expect(info.Host.Arch).To(Equal(runtime.GOARCH)) + Expect(info.Host.OS).To(Equal(runtime.GOOS)) + i, err := images.List(bt.conn, &t, nil) + Expect(err).To(BeNil()) + Expect(info.Store.ImageStore.Number).To(Equal(len(i))) + }) + + It("podman info container counts", func() { + s := specgen.NewSpecGenerator(alpine.name) + _, err := containers.CreateWithSpec(bt.conn, s) + Expect(err).To(BeNil()) + + idPause, err := bt.RunTopContainer(nil, nil, nil) + Expect(err).To(BeNil()) + err = containers.Pause(bt.conn, idPause) + Expect(err).To(BeNil()) + + idStop, err := bt.RunTopContainer(nil, nil, nil) + Expect(err).To(BeNil()) + err = containers.Stop(bt.conn, idStop, nil) + Expect(err).To(BeNil()) + + _, err = bt.RunTopContainer(nil, nil, nil) + Expect(err).To(BeNil()) + + info, err := system.Info(bt.conn) + Expect(err).To(BeNil()) + + Expect(info.Store.ContainerStore.Number).To(BeNumerically("==", 4)) + Expect(info.Store.ContainerStore.Paused).To(Equal(1)) + Expect(info.Store.ContainerStore.Stopped).To(Equal(2)) + Expect(info.Store.ContainerStore.Running).To(Equal(1)) + }) +}) diff --git a/pkg/varlinkapi/system.go b/pkg/varlinkapi/system.go index 04fb9f648..7bee643c2 100644 --- a/pkg/varlinkapi/system.go +++ b/pkg/varlinkapi/system.go @@ -44,28 +44,26 @@ func (i *LibpodAPI) GetInfo(call iopodman.VarlinkCall) error { return call.ReplyErrorOccurred(err.Error()) } - host := info[0].Data distribution := iopodman.InfoDistribution{ - Distribution: host["Distribution"].(map[string]interface{})["distribution"].(string), - Version: host["Distribution"].(map[string]interface{})["version"].(string), + Distribution: info.Host.Distribution.Distribution, + Version: info.Host.Distribution.Version, } infoHost := iopodman.InfoHost{ - Buildah_version: host["BuildahVersion"].(string), + Buildah_version: info.Host.BuildahVersion, Distribution: distribution, - Mem_free: host["MemFree"].(int64), - Mem_total: host["MemTotal"].(int64), - Swap_free: host["SwapFree"].(int64), - Swap_total: host["SwapTotal"].(int64), - Arch: host["arch"].(string), - Cpus: int64(host["cpus"].(int)), - Hostname: host["hostname"].(string), - Kernel: host["kernel"].(string), - Os: host["os"].(string), - Uptime: host["uptime"].(string), - Eventlogger: host["eventlogger"].(string), + Mem_free: info.Host.MemFree, + Mem_total: info.Host.MemTotal, + Swap_free: info.Host.SwapFree, + Swap_total: info.Host.SwapTotal, + Arch: info.Host.Arch, + Cpus: int64(info.Host.CPUs), + Hostname: info.Host.Hostname, + Kernel: info.Host.Kernel, + Os: info.Host.OS, + Uptime: info.Host.Uptime, + Eventlogger: info.Host.EventLogger, } podmanInfo.Host = infoHost - store := info[1].Data pmaninfo := iopodman.InfoPodmanBinary{ Compiler: goruntime.Compiler, Go_version: goruntime.Version(), @@ -74,36 +72,33 @@ func (i *LibpodAPI) GetInfo(call iopodman.VarlinkCall) error { } graphStatus := iopodman.InfoGraphStatus{ - Backing_filesystem: store["GraphStatus"].(map[string]string)["Backing Filesystem"], - Native_overlay_diff: store["GraphStatus"].(map[string]string)["Native Overlay Diff"], - Supports_d_type: store["GraphStatus"].(map[string]string)["Supports d_type"], + Backing_filesystem: info.Store.GraphStatus["Backing Filesystem"], + Native_overlay_diff: info.Store.GraphStatus["Native Overlay Diff"], + Supports_d_type: info.Store.GraphStatus["Supports d_type"], } infoStore := iopodman.InfoStore{ - Graph_driver_name: store["GraphDriverName"].(string), - Containers: int64(store["ContainerStore"].(map[string]interface{})["number"].(int)), - Images: int64(store["ImageStore"].(map[string]interface{})["number"].(int)), - Run_root: store["RunRoot"].(string), - Graph_root: store["GraphRoot"].(string), - Graph_driver_options: fmt.Sprintf("%v", store["GraphOptions"]), + Graph_driver_name: info.Store.GraphDriverName, + Containers: int64(info.Store.ContainerStore.Number), + Images: int64(info.Store.ImageStore.Number), + Run_root: info.Store.RunRoot, + Graph_root: info.Store.GraphRoot, + Graph_driver_options: fmt.Sprintf("%v", info.Store.GraphOptions), Graph_status: graphStatus, } // Registry information if any is stored as the second list item - if len(info) > 2 { - for key, val := range info[2].Data { - if key == "search" { - podmanInfo.Registries.Search = val.([]string) - continue - } - regData := val.(sysregistriesv2.Registry) - if regData.Insecure { - podmanInfo.Registries.Insecure = append(podmanInfo.Registries.Insecure, key) - } - if regData.Blocked { - podmanInfo.Registries.Blocked = append(podmanInfo.Registries.Blocked, key) - } + for key, val := range info.Registries { + if key == "search" { + podmanInfo.Registries.Search = val.([]string) + continue + } + regData := val.(sysregistriesv2.Registry) + if regData.Insecure { + podmanInfo.Registries.Insecure = append(podmanInfo.Registries.Insecure, key) + } + if regData.Blocked { + podmanInfo.Registries.Blocked = append(podmanInfo.Registries.Blocked, key) } - } podmanInfo.Store = infoStore podmanInfo.Podman = pmaninfo diff --git a/test/e2e/info_test.go b/test/e2e/info_test.go index d16661d5b..446dbc16e 100644 --- a/test/e2e/info_test.go +++ b/test/e2e/info_test.go @@ -43,10 +43,16 @@ var _ = Describe("Podman Info", func() { Expect(session.ExitCode()).To(Equal(0)) }) - It("podman info --format GO template", func() { + It("podman info --format JSON GO template", func() { session := podmanTest.Podman([]string{"info", "--format", "{{ json .}}"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) Expect(session.IsJSONOutputValid()).To(BeTrue()) }) + + It("podman info --format GO template", func() { + session := podmanTest.Podman([]string{"info", "--format", "{{ .Store.GraphRoot }}"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + }) }) diff --git a/test/system/005-info.bats b/test/system/005-info.bats index f229b0886..c53ba8125 100644 --- a/test/system/005-info.bats +++ b/test/system/005-info.bats @@ -8,19 +8,19 @@ load helpers run_podman info expected_keys=" -BuildahVersion: *[0-9.]\\\+ -Conmon:\\\s\\\+package: -Distribution: -OCIRuntime:\\\s\\\+name: +buildahVersion: *[0-9.]\\\+ +conmon:\\\s\\\+package: +distribution: +ociRuntime:\\\s\\\+name: os: rootless: registries: store: -GraphDriverName: -GraphRoot: -GraphStatus: -ImageStore:\\\s\\\+number: 1 -RunRoot: +graphDriverName: +graphRoot: +graphStatus: +imageStore:\\\s\\\+number: 1 +runRoot: " while read expect; do is "$output" ".*$expect" "output includes '$expect'" @@ -36,13 +36,13 @@ RunRoot: expr_path="/[a-z0-9\\\/.-]\\\+\\\$" tests=" -host.BuildahVersion | [0-9.] -host.Conmon.path | $expr_path -host.OCIRuntime.path | $expr_path -store.ConfigFile | $expr_path -store.GraphDriverName | [a-z0-9]\\\+\\\$ -store.GraphRoot | $expr_path -store.ImageStore.number | 1 +host.buildahVersion | [0-9.] +host.conmon.path | $expr_path +host.ociRuntime.path | $expr_path +store.configFile | $expr_path +store.graphDriverName | [a-z0-9]\\\+\\\$ +store.graphRoot | $expr_path +store.imageStore.number | 1 " parse_table "$tests" | while read field expect; do diff --git a/test/system/030-run.bats b/test/system/030-run.bats index 98c65f788..56e9fed3b 100644 --- a/test/system/030-run.bats +++ b/test/system/030-run.bats @@ -12,7 +12,7 @@ load helpers err_no_exec_dir="Error: .*: starting container process caused .*exec:.* permission denied" # ...but check the configured runtime engine, and switch to crun as needed - run_podman info --format '{{ .host.OCIRuntime.path }}' + run_podman info --format '{{ .Host.OCIRuntime.Path }}' if expr "$output" : ".*/crun"; then err_no_such_cmd="Error: executable file not found in \$PATH: No such file or directory: OCI runtime command not found error" err_no_exec_dir="Error: open executable: Operation not permitted: OCI runtime permission denied error" diff --git a/test/system/065-cp.bats b/test/system/065-cp.bats index 0701055f9..a350c2173 100644 --- a/test/system/065-cp.bats +++ b/test/system/065-cp.bats @@ -187,7 +187,7 @@ load helpers chmod 644 $srcdir/$rand_filename # Determine path to podman storage (eg /var/lib/c/s, or $HOME/.local/...) - run_podman info --format '{{.store.GraphRoot}}' + run_podman info --format '{{.Store.GraphRoot}}' graphroot=$output # Create that directory in the container, and sleep (to keep container diff --git a/test/system/400-unprivileged-access.bats b/test/system/400-unprivileged-access.bats index 56c40e9c8..98f8b8211 100644 --- a/test/system/400-unprivileged-access.bats +++ b/test/system/400-unprivileged-access.bats @@ -70,10 +70,10 @@ EOF chmod 755 $PODMAN_TMPDIR $test_script # get podman image and container storage directories - run_podman info --format '{{.store.GraphRoot}}' + run_podman info --format '{{.Store.GraphRoot}}' is "$output" "/var/lib/containers/storage" "GraphRoot in expected place" GRAPH_ROOT="$output" - run_podman info --format '{{.store.RunRoot}}' + run_podman info --format '{{.Store.RunRoot}}' is "$output" "/var/run/containers/storage" "RunRoot in expected place" RUN_ROOT="$output" diff --git a/test/system/helpers.bash b/test/system/helpers.bash index 2e856930e..51240edc9 100644 --- a/test/system/helpers.bash +++ b/test/system/helpers.bash @@ -391,7 +391,7 @@ function random_string() { # Return exec_pid hash files if exists, otherwise, return nothing # function find_exec_pid_files() { - run_podman info --format '{{.store.RunRoot}}' + run_podman info --format '{{.Store.RunRoot}}' local storage_path="$output" if [ -d $storage_path ]; then find $storage_path -type f -iname 'exec_pid_*' |