mirror of
https://github.com/containers/podman.git
synced 2025-07-02 00:30:00 +08:00
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>
This commit is contained in:
@ -2,6 +2,8 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"html/template"
|
||||||
|
"os"
|
||||||
rt "runtime"
|
rt "runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -11,7 +13,6 @@ import (
|
|||||||
"github.com/containers/libpod/pkg/adapter"
|
"github.com/containers/libpod/pkg/adapter"
|
||||||
"github.com/containers/libpod/version"
|
"github.com/containers/libpod/version"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -49,42 +50,32 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func infoCmd(c *cliconfig.InfoValues) error {
|
func infoCmd(c *cliconfig.InfoValues) error {
|
||||||
info := map[string]interface{}{}
|
|
||||||
remoteClientInfo := map[string]interface{}{}
|
|
||||||
|
|
||||||
runtime, err := adapter.GetRuntime(getContext(), &c.PodmanCommand)
|
runtime, err := adapter.GetRuntime(getContext(), &c.PodmanCommand)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "could not get runtime")
|
return errors.Wrapf(err, "could not get runtime")
|
||||||
}
|
}
|
||||||
defer runtime.DeferredShutdown(false)
|
defer runtime.DeferredShutdown(false)
|
||||||
|
|
||||||
infoArr, err := runtime.Info()
|
i, err := runtime.Info()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "error getting info")
|
return errors.Wrapf(err, "error getting info")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
info := infoWithExtra{Info: i}
|
||||||
if runtime.Remote {
|
if runtime.Remote {
|
||||||
endpoint, err := runtime.RemoteEndpoint()
|
endpoint, err := runtime.RemoteEndpoint()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorf("Failed to obtain server connection: %s", err.Error())
|
return err
|
||||||
} else {
|
|
||||||
remoteClientInfo["Connection"] = endpoint.Connection
|
|
||||||
remoteClientInfo["Connection Type"] = endpoint.Type.String()
|
|
||||||
}
|
}
|
||||||
|
info.Remote = getRemote(endpoint)
|
||||||
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})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !runtime.Remote && c.Debug {
|
if !runtime.Remote && c.Debug {
|
||||||
debugInfo := debugInfo(c)
|
d, err := getDebug()
|
||||||
infoArr = append(infoArr, define.InfoData{Type: "debug", Data: debugInfo})
|
if err != nil {
|
||||||
}
|
return err
|
||||||
|
}
|
||||||
for _, currInfo := range infoArr {
|
info.Debug = d
|
||||||
info[currInfo.Type] = currInfo.Data
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var out formats.Writer
|
var out formats.Writer
|
||||||
@ -98,19 +89,58 @@ func infoCmd(c *cliconfig.InfoValues) error {
|
|||||||
case "":
|
case "":
|
||||||
out = formats.YAMLStruct{Output: info}
|
out = formats.YAMLStruct{Output: info}
|
||||||
default:
|
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()
|
return out.Out()
|
||||||
}
|
}
|
||||||
|
|
||||||
// top-level "debug" info
|
// top-level "debug" info
|
||||||
func debugInfo(c *cliconfig.InfoValues) map[string]interface{} {
|
func getDebug() (*debugInfo, error) {
|
||||||
info := map[string]interface{}{}
|
v, err := define.GetVersion()
|
||||||
info["compiler"] = rt.Compiler
|
if err != nil {
|
||||||
info["go version"] = rt.Version()
|
return nil, err
|
||||||
info["podman version"] = version.Version
|
}
|
||||||
version, _ := define.GetVersion()
|
return &debugInfo{
|
||||||
info["git commit"] = version.GitCommit
|
Compiler: rt.Compiler,
|
||||||
return info
|
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"`
|
||||||
}
|
}
|
||||||
|
@ -156,7 +156,7 @@ Run podman info with JSON formatted response:
|
|||||||
```
|
```
|
||||||
Run podman info and only get the registries information.
|
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]]
|
map[registries:[docker.io quay.io registry.fedoraproject.org registry.access.redhat.com]]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
101
libpod/define/info.go
Normal file
101
libpod/define/info.go
Normal file
@ -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"`
|
||||||
|
}
|
245
libpod/info.go
245
libpod/info.go
@ -13,7 +13,9 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containers/buildah"
|
"github.com/containers/buildah"
|
||||||
|
"github.com/containers/libpod/libpod/define"
|
||||||
"github.com/containers/libpod/pkg/cgroups"
|
"github.com/containers/libpod/pkg/cgroups"
|
||||||
|
registries2 "github.com/containers/libpod/pkg/registries"
|
||||||
"github.com/containers/libpod/pkg/rootless"
|
"github.com/containers/libpod/pkg/rootless"
|
||||||
"github.com/containers/storage"
|
"github.com/containers/storage"
|
||||||
"github.com/containers/storage/pkg/system"
|
"github.com/containers/storage/pkg/system"
|
||||||
@ -21,14 +23,80 @@ import (
|
|||||||
"github.com/sirupsen/logrus"
|
"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
|
// 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
|
// lets say OS, arch, number of cpus, amount of memory, maybe os distribution/version, hostname, kernel version, uptime
|
||||||
info := map[string]interface{}{}
|
mi, err := system.ReadMemInfo()
|
||||||
info["os"] = runtime.GOOS
|
if err != nil {
|
||||||
info["arch"] = runtime.GOARCH
|
return nil, errors.Wrapf(err, "error reading memory info")
|
||||||
info["cpus"] = runtime.NumCPU()
|
}
|
||||||
info["rootless"] = rootless.IsRootless()
|
|
||||||
|
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()
|
unified, err := cgroups.IsCgroup2UnifiedMode()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "error reading cgroups mode")
|
return nil, errors.Wrapf(err, "error reading cgroups mode")
|
||||||
@ -37,17 +105,8 @@ func (r *Runtime) hostInfo() (map[string]interface{}, error) {
|
|||||||
if unified {
|
if unified {
|
||||||
cgroupVersion = "v2"
|
cgroupVersion = "v2"
|
||||||
}
|
}
|
||||||
info["CgroupVersion"] = cgroupVersion
|
info.CGroupsVersion = 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()
|
|
||||||
if rootless.IsRootless() {
|
if rootless.IsRootless() {
|
||||||
if path, err := exec.LookPath("slirp4netns"); err == nil {
|
if path, err := exec.LookPath("slirp4netns"); err == nil {
|
||||||
logrus.Warnf("Failed to retrieve program version for %s: %v", path, err)
|
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 {
|
if err != nil {
|
||||||
logrus.Warnf("Failed to retrieve program version for %s: %v", path, err)
|
logrus.Warnf("Failed to retrieve program version for %s: %v", path, err)
|
||||||
}
|
}
|
||||||
program := map[string]interface{}{}
|
program := define.SlirpInfo{
|
||||||
program["Executable"] = path
|
Executable: path,
|
||||||
program["Version"] = version
|
Package: packageVersion(path),
|
||||||
program["Package"] = packageVersion(path)
|
Version: version,
|
||||||
info["slirp4netns"] = program
|
}
|
||||||
|
info.Slirp4NetNS = program
|
||||||
}
|
}
|
||||||
uidmappings, err := rootless.ReadMappingsProc("/proc/self/uid_map")
|
uidmappings, err := rootless.ReadMappingsProc("/proc/self/uid_map")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -69,29 +129,19 @@ func (r *Runtime) hostInfo() (map[string]interface{}, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "error reading gid mappings")
|
return nil, errors.Wrapf(err, "error reading gid mappings")
|
||||||
}
|
}
|
||||||
idmappings := make(map[string]interface{})
|
idmappings := define.IDMappings{
|
||||||
idmappings["uidmap"] = uidmappings
|
GIDMap: gidmappings,
|
||||||
idmappings["gidmap"] = gidmappings
|
UIDMap: uidmappings,
|
||||||
info["IDMappings"] = idmappings
|
}
|
||||||
|
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")
|
|
||||||
}
|
|
||||||
info["kernel"] = kv
|
|
||||||
|
|
||||||
runtimeInfo, err := r.defaultOCIRuntime.RuntimeInfo()
|
conmonInfo, ociruntimeInfo, err := r.defaultOCIRuntime.RuntimeInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorf("Error getting info on OCI runtime %s: %v", r.defaultOCIRuntime.Name(), err)
|
logrus.Errorf("Error getting info on OCI runtime %s: %v", r.defaultOCIRuntime.Name(), err)
|
||||||
} else {
|
} else {
|
||||||
for k, v := range runtimeInfo {
|
info.Conmon = conmonInfo
|
||||||
info[k] = v
|
info.OCIRuntime = ociruntimeInfo
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
up, err := readUptime()
|
up, err := readUptime()
|
||||||
@ -105,6 +155,7 @@ func (r *Runtime) hostInfo() (map[string]interface{}, error) {
|
|||||||
return nil, errors.Wrapf(err, "error parsing system uptime")
|
return nil, errors.Wrapf(err, "error parsing system uptime")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO Isnt there a simple lib for this, something like humantime?
|
||||||
hoursFound := false
|
hoursFound := false
|
||||||
var timeBuffer bytes.Buffer
|
var timeBuffer bytes.Buffer
|
||||||
var hoursBuffer 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 {
|
if hoursFound {
|
||||||
hours, err := strconv.ParseFloat(hoursBuffer.String(), 64)
|
hours, err := strconv.ParseFloat(hoursBuffer.String(), 64)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
days := hours / 24
|
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
|
||||||
if err != nil {
|
}
|
||||||
return nil, errors.Wrapf(err, "error getting hostname")
|
|
||||||
}
|
|
||||||
info["hostname"] = host
|
|
||||||
info["eventlogger"] = r.eventer.String()
|
|
||||||
|
|
||||||
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 cs, err
|
||||||
|
}
|
||||||
|
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
|
// 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
|
// lets say storage driver in use, number of images, number of containers
|
||||||
info := map[string]interface{}{}
|
configFile, err := storage.DefaultConfigFile(rootless.IsRootless())
|
||||||
info["GraphRoot"] = r.store.GraphRoot()
|
if err != nil {
|
||||||
info["RunRoot"] = r.store.RunRoot()
|
return nil, err
|
||||||
info["GraphDriverName"] = r.store.GraphDriverName()
|
}
|
||||||
|
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{}{}
|
graphOptions := map[string]interface{}{}
|
||||||
for _, o := range r.store.GraphOptions() {
|
for _, o := range r.store.GraphOptions() {
|
||||||
split := strings.SplitN(o, "=", 2)
|
split := strings.SplitN(o, "=", 2)
|
||||||
@ -164,14 +258,8 @@ func (r *Runtime) storeInfo() (map[string]interface{}, error) {
|
|||||||
graphOptions[split[0]] = split[1]
|
graphOptions[split[0]] = split[1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
info["GraphOptions"] = graphOptions
|
info.GraphOptions = graphOptions
|
||||||
info["VolumePath"] = r.config.Engine.VolumePath
|
|
||||||
|
|
||||||
configFile, err := storage.DefaultConfigFile(rootless.IsRootless())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
info["ConfigFile"] = configFile
|
|
||||||
statusPairs, err := r.store.Status()
|
statusPairs, err := r.store.Status()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -180,24 +268,8 @@ func (r *Runtime) storeInfo() (map[string]interface{}, error) {
|
|||||||
for _, pair := range statusPairs {
|
for _, pair := range statusPairs {
|
||||||
status[pair[0]] = pair[1]
|
status[pair[0]] = pair[1]
|
||||||
}
|
}
|
||||||
info["GraphStatus"] = status
|
info.GraphStatus = status
|
||||||
images, err := r.store.Images()
|
return &info, nil
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func readKernelVersion() (string, error) {
|
func readKernelVersion() (string, error) {
|
||||||
@ -225,14 +297,13 @@ func readUptime() (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetHostDistributionInfo returns a map containing the host's distribution and version
|
// GetHostDistributionInfo returns a map containing the host's distribution and version
|
||||||
func (r *Runtime) GetHostDistributionInfo() map[string]string {
|
func (r *Runtime) GetHostDistributionInfo() define.DistributionInfo {
|
||||||
dist := make(map[string]string)
|
|
||||||
|
|
||||||
// Populate values in case we cannot find the values
|
// Populate values in case we cannot find the values
|
||||||
// or the file
|
// or the file
|
||||||
dist["Distribution"] = "unknown"
|
dist := define.DistributionInfo{
|
||||||
dist["Version"] = "unknown"
|
Distribution: "unknown",
|
||||||
|
Version: "unknown",
|
||||||
|
}
|
||||||
f, err := os.Open("/etc/os-release")
|
f, err := os.Open("/etc/os-release")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return dist
|
return dist
|
||||||
@ -242,10 +313,10 @@ func (r *Runtime) GetHostDistributionInfo() map[string]string {
|
|||||||
l := bufio.NewScanner(f)
|
l := bufio.NewScanner(f)
|
||||||
for l.Scan() {
|
for l.Scan() {
|
||||||
if strings.HasPrefix(l.Text(), "ID=") {
|
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=") {
|
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
|
return dist
|
||||||
|
@ -5,7 +5,6 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
|
|
||||||
"github.com/containers/libpod/libpod/define"
|
"github.com/containers/libpod/libpod/define"
|
||||||
|
|
||||||
"k8s.io/client-go/tools/remotecommand"
|
"k8s.io/client-go/tools/remotecommand"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -122,7 +121,7 @@ type OCIRuntime interface {
|
|||||||
ExitFilePath(ctr *Container) (string, error)
|
ExitFilePath(ctr *Container) (string, error)
|
||||||
|
|
||||||
// RuntimeInfo returns verbose information about the runtime.
|
// 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
|
// ExecOptions are options passed into ExecContainer. They control the command
|
||||||
|
@ -999,32 +999,30 @@ func (r *ConmonOCIRuntime) ExitFilePath(ctr *Container) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RuntimeInfo provides information on the runtime.
|
// 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)
|
runtimePackage := packageVersion(r.path)
|
||||||
conmonPackage := packageVersion(r.conmonPath)
|
conmonPackage := packageVersion(r.conmonPath)
|
||||||
runtimeVersion, err := r.getOCIRuntimeVersion()
|
runtimeVersion, err := r.getOCIRuntimeVersion()
|
||||||
if err != nil {
|
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()
|
conmonVersion, err := r.getConmonVersion()
|
||||||
if err != nil {
|
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{})
|
conmon := define.ConmonInfo{
|
||||||
info["Conmon"] = map[string]interface{}{
|
Package: conmonPackage,
|
||||||
"path": r.conmonPath,
|
Path: r.conmonPath,
|
||||||
"package": conmonPackage,
|
Version: conmonVersion,
|
||||||
"version": conmonVersion,
|
|
||||||
}
|
}
|
||||||
info["OCIRuntime"] = map[string]interface{}{
|
ocirt := define.OCIRuntimeInfo{
|
||||||
"name": r.name,
|
Name: r.name,
|
||||||
"path": r.path,
|
Path: r.path,
|
||||||
"package": runtimePackage,
|
Package: runtimePackage,
|
||||||
"version": runtimeVersion,
|
Version: runtimeVersion,
|
||||||
}
|
}
|
||||||
|
return &conmon, &ocirt, nil
|
||||||
return info, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// makeAccessible changes the path permission and each parent directory to have --x--x--x
|
// makeAccessible changes the path permission and each parent directory to have --x--x--x
|
||||||
|
@ -117,8 +117,8 @@ func (r *ConmonOCIRuntime) ExitFilePath(ctr *Container) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RuntimeInfo is not supported on this OS.
|
// RuntimeInfo is not supported on this OS.
|
||||||
func (r *ConmonOCIRuntime) RuntimeInfo() (map[string]interface{}, error) {
|
func (r *ConmonOCIRuntime) RuntimeInfo() (*define.ConmonInfo, *define.OCIRuntimeInfo, error) {
|
||||||
return nil, define.ErrNotImplemented
|
return nil, nil, define.ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
// Package is not supported on this OS.
|
// Package is not supported on this OS.
|
||||||
|
@ -195,15 +195,14 @@ func (r *MissingRuntime) ExitFilePath(ctr *Container) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RuntimeInfo returns information on the missing runtime
|
// RuntimeInfo returns information on the missing runtime
|
||||||
func (r *MissingRuntime) RuntimeInfo() (map[string]interface{}, error) {
|
func (r *MissingRuntime) RuntimeInfo() (*define.ConmonInfo, *define.OCIRuntimeInfo, error) {
|
||||||
info := make(map[string]interface{})
|
ocirt := define.OCIRuntimeInfo{
|
||||||
info["OCIRuntime"] = map[string]interface{}{
|
Name: r.name,
|
||||||
"name": r.name,
|
Path: "missing",
|
||||||
"path": "missing",
|
Package: "missing",
|
||||||
"package": "missing",
|
Version: "missing",
|
||||||
"version": "missing",
|
|
||||||
}
|
}
|
||||||
return info, nil
|
return nil, &ocirt, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return an error indicating the runtime is missing
|
// Return an error indicating the runtime is missing
|
||||||
|
@ -9,16 +9,14 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/containers/common/pkg/config"
|
||||||
is "github.com/containers/image/v5/storage"
|
is "github.com/containers/image/v5/storage"
|
||||||
"github.com/containers/image/v5/types"
|
"github.com/containers/image/v5/types"
|
||||||
|
|
||||||
"github.com/containers/common/pkg/config"
|
|
||||||
"github.com/containers/libpod/libpod/define"
|
"github.com/containers/libpod/libpod/define"
|
||||||
"github.com/containers/libpod/libpod/events"
|
"github.com/containers/libpod/libpod/events"
|
||||||
"github.com/containers/libpod/libpod/image"
|
"github.com/containers/libpod/libpod/image"
|
||||||
"github.com/containers/libpod/libpod/lock"
|
"github.com/containers/libpod/libpod/lock"
|
||||||
"github.com/containers/libpod/pkg/cgroups"
|
"github.com/containers/libpod/pkg/cgroups"
|
||||||
sysreg "github.com/containers/libpod/pkg/registries"
|
|
||||||
"github.com/containers/libpod/pkg/rootless"
|
"github.com/containers/libpod/pkg/rootless"
|
||||||
"github.com/containers/libpod/pkg/util"
|
"github.com/containers/libpod/pkg/util"
|
||||||
"github.com/containers/storage"
|
"github.com/containers/storage"
|
||||||
@ -675,40 +673,8 @@ func (r *Runtime) refresh(alivePath string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Info returns the store and host information
|
// Info returns the store and host information
|
||||||
func (r *Runtime) Info() ([]define.InfoData, error) {
|
func (r *Runtime) Info() (*define.Info, error) {
|
||||||
info := []define.InfoData{}
|
return r.info()
|
||||||
// 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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// generateName generates a unique name for a container or pod.
|
// generateName generates a unique name for a container or pod.
|
||||||
|
@ -3,51 +3,62 @@
|
|||||||
package adapter
|
package adapter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
|
|
||||||
"github.com/containers/libpod/libpod/define"
|
"github.com/containers/libpod/libpod/define"
|
||||||
iopodman "github.com/containers/libpod/pkg/varlink"
|
iopodman "github.com/containers/libpod/pkg/varlink"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Info returns information for the host system and its components
|
// 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
|
// TODO the varlink implementation for info should be updated to match the output for regular info
|
||||||
var (
|
var (
|
||||||
reply []define.InfoData
|
reply define.Info
|
||||||
regInfo map[string]interface{}
|
|
||||||
hostInfo map[string]interface{}
|
|
||||||
store map[string]interface{}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
info, err := iopodman.GetInfo().Call(r.Conn)
|
info, err := iopodman.GetInfo().Call(r.Conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
hostInfo := define.HostInfo{
|
||||||
// info.host -> map[string]interface{}
|
Arch: info.Host.Arch,
|
||||||
h, err := json.Marshal(info.Host)
|
BuildahVersion: info.Host.Buildah_version,
|
||||||
if err != nil {
|
CPUs: int(info.Host.Cpus),
|
||||||
return nil, err
|
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)
|
storeInfo := define.StoreInfo{
|
||||||
|
ContainerStore: define.ContainerStore{
|
||||||
// info.store -> map[string]interface{}
|
Number: int(info.Store.Containers),
|
||||||
s, err := json.Marshal(info.Store)
|
},
|
||||||
if err != nil {
|
GraphDriverName: info.Store.Graph_driver_name,
|
||||||
return nil, err
|
GraphRoot: info.Store.Graph_root,
|
||||||
|
ImageStore: define.ImageStore{
|
||||||
|
Number: int(info.Store.Images),
|
||||||
|
},
|
||||||
|
RunRoot: info.Store.Run_root,
|
||||||
}
|
}
|
||||||
json.Unmarshal(s, &store)
|
reply.Host = &hostInfo
|
||||||
|
reply.Store = &storeInfo
|
||||||
// info.Registries -> map[string]interface{}
|
regs := make(map[string]interface{})
|
||||||
reg, err := json.Marshal(info.Registries)
|
if len(info.Registries.Search) > 0 {
|
||||||
if err != nil {
|
regs["search"] = info.Registries.Search
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
json.Unmarshal(reg, ®Info)
|
if len(info.Registries.Blocked) > 0 {
|
||||||
|
regs["blocked"] = info.Registries.Blocked
|
||||||
// Add everything to the reply
|
}
|
||||||
reply = append(reply, define.InfoData{Type: "host", Data: hostInfo})
|
if len(info.Registries.Insecure) > 0 {
|
||||||
reply = append(reply, define.InfoData{Type: "registries", Data: regInfo})
|
regs["insecure"] = info.Registries.Insecure
|
||||||
reply = append(reply, define.InfoData{Type: "store", Data: store})
|
}
|
||||||
return reply, nil
|
reply.Registries = regs
|
||||||
|
return &reply, nil
|
||||||
}
|
}
|
||||||
|
@ -94,15 +94,9 @@ func ListContainers(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO filters still need to be applied
|
// 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))
|
var list = make([]*handlers.Container, len(containers))
|
||||||
for i, ctnr := range containers {
|
for i, ctnr := range containers {
|
||||||
api, err := handlers.LibpodToContainer(ctnr, infoData, query.Size)
|
api, err := handlers.LibpodToContainer(ctnr, query.Size)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.InternalServerError(w, err)
|
utils.InternalServerError(w, err)
|
||||||
return
|
return
|
||||||
|
@ -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"))
|
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrapf(err, "Failed to obtain system memory info"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
hostInfo := infoData[0].Data
|
|
||||||
storeInfo := infoData[1].Data
|
|
||||||
|
|
||||||
configInfo, err := runtime.GetConfig()
|
configInfo, err := runtime.GetConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -64,44 +62,44 @@ func GetInfo(w http.ResponseWriter, r *http.Request) {
|
|||||||
ClusterAdvertise: "",
|
ClusterAdvertise: "",
|
||||||
ClusterStore: "",
|
ClusterStore: "",
|
||||||
ContainerdCommit: docker.Commit{},
|
ContainerdCommit: docker.Commit{},
|
||||||
Containers: storeInfo["ContainerStore"].(map[string]interface{})["number"].(int),
|
Containers: infoData.Store.ContainerStore.Number,
|
||||||
ContainersPaused: stateInfo[define.ContainerStatePaused],
|
ContainersPaused: stateInfo[define.ContainerStatePaused],
|
||||||
ContainersRunning: stateInfo[define.ContainerStateRunning],
|
ContainersRunning: stateInfo[define.ContainerStateRunning],
|
||||||
ContainersStopped: stateInfo[define.ContainerStateStopped] + stateInfo[define.ContainerStateExited],
|
ContainersStopped: stateInfo[define.ContainerStateStopped] + stateInfo[define.ContainerStateExited],
|
||||||
Debug: log.IsLevelEnabled(log.DebugLevel),
|
Debug: log.IsLevelEnabled(log.DebugLevel),
|
||||||
DefaultRuntime: configInfo.Engine.OCIRuntime,
|
DefaultRuntime: configInfo.Engine.OCIRuntime,
|
||||||
DockerRootDir: storeInfo["GraphRoot"].(string),
|
DockerRootDir: infoData.Store.GraphRoot,
|
||||||
Driver: storeInfo["GraphDriverName"].(string),
|
Driver: infoData.Store.GraphDriverName,
|
||||||
DriverStatus: getGraphStatus(storeInfo),
|
DriverStatus: getGraphStatus(infoData.Store.GraphStatus),
|
||||||
ExperimentalBuild: true,
|
ExperimentalBuild: true,
|
||||||
GenericResources: nil,
|
GenericResources: nil,
|
||||||
HTTPProxy: getEnv("http_proxy"),
|
HTTPProxy: getEnv("http_proxy"),
|
||||||
HTTPSProxy: getEnv("https_proxy"),
|
HTTPSProxy: getEnv("https_proxy"),
|
||||||
ID: uuid.New().String(),
|
ID: uuid.New().String(),
|
||||||
IPv4Forwarding: !sysInfo.IPv4ForwardingDisabled,
|
IPv4Forwarding: !sysInfo.IPv4ForwardingDisabled,
|
||||||
Images: storeInfo["ImageStore"].(map[string]interface{})["number"].(int),
|
Images: infoData.Store.ImageStore.Number,
|
||||||
IndexServerAddress: "",
|
IndexServerAddress: "",
|
||||||
InitBinary: "",
|
InitBinary: "",
|
||||||
InitCommit: docker.Commit{},
|
InitCommit: docker.Commit{},
|
||||||
Isolation: "",
|
Isolation: "",
|
||||||
KernelMemory: sysInfo.KernelMemory,
|
KernelMemory: sysInfo.KernelMemory,
|
||||||
KernelMemoryTCP: false,
|
KernelMemoryTCP: false,
|
||||||
KernelVersion: hostInfo["kernel"].(string),
|
KernelVersion: infoData.Host.Kernel,
|
||||||
Labels: nil,
|
Labels: nil,
|
||||||
LiveRestoreEnabled: false,
|
LiveRestoreEnabled: false,
|
||||||
LoggingDriver: "",
|
LoggingDriver: "",
|
||||||
MemTotal: hostInfo["MemTotal"].(int64),
|
MemTotal: infoData.Host.MemTotal,
|
||||||
MemoryLimit: sysInfo.MemoryLimit,
|
MemoryLimit: sysInfo.MemoryLimit,
|
||||||
NCPU: goRuntime.NumCPU(),
|
NCPU: goRuntime.NumCPU(),
|
||||||
NEventsListener: 0,
|
NEventsListener: 0,
|
||||||
NFd: getFdCount(),
|
NFd: getFdCount(),
|
||||||
NGoroutines: goRuntime.NumGoroutine(),
|
NGoroutines: goRuntime.NumGoroutine(),
|
||||||
Name: hostInfo["hostname"].(string),
|
Name: infoData.Host.Hostname,
|
||||||
NoProxy: getEnv("no_proxy"),
|
NoProxy: getEnv("no_proxy"),
|
||||||
OSType: goRuntime.GOOS,
|
OSType: goRuntime.GOOS,
|
||||||
OSVersion: hostInfo["Distribution"].(map[string]interface{})["version"].(string),
|
OSVersion: infoData.Host.Distribution.Version,
|
||||||
OomKillDisable: sysInfo.OomKillDisable,
|
OomKillDisable: sysInfo.OomKillDisable,
|
||||||
OperatingSystem: hostInfo["Distribution"].(map[string]interface{})["distribution"].(string),
|
OperatingSystem: infoData.Host.Distribution.Distribution,
|
||||||
PidsLimit: sysInfo.PidsLimit,
|
PidsLimit: sysInfo.PidsLimit,
|
||||||
Plugins: docker.PluginsInfo{},
|
Plugins: docker.PluginsInfo{},
|
||||||
ProductLicense: "Apache-2.0",
|
ProductLicense: "Apache-2.0",
|
||||||
@ -118,21 +116,21 @@ func GetInfo(w http.ResponseWriter, r *http.Request) {
|
|||||||
SystemTime: time.Now().Format(time.RFC3339Nano),
|
SystemTime: time.Now().Format(time.RFC3339Nano),
|
||||||
Warnings: []string{},
|
Warnings: []string{},
|
||||||
},
|
},
|
||||||
BuildahVersion: hostInfo["BuildahVersion"].(string),
|
BuildahVersion: infoData.Host.BuildahVersion,
|
||||||
CPURealtimePeriod: sysInfo.CPURealtimePeriod,
|
CPURealtimePeriod: sysInfo.CPURealtimePeriod,
|
||||||
CPURealtimeRuntime: sysInfo.CPURealtimeRuntime,
|
CPURealtimeRuntime: sysInfo.CPURealtimeRuntime,
|
||||||
CgroupVersion: hostInfo["CgroupVersion"].(string),
|
CgroupVersion: infoData.Host.CGroupsVersion,
|
||||||
Rootless: rootless.IsRootless(),
|
Rootless: rootless.IsRootless(),
|
||||||
SwapFree: hostInfo["SwapFree"].(int64),
|
SwapFree: infoData.Host.SwapFree,
|
||||||
SwapTotal: hostInfo["SwapTotal"].(int64),
|
SwapTotal: infoData.Host.SwapTotal,
|
||||||
Uptime: hostInfo["uptime"].(string),
|
Uptime: infoData.Host.Uptime,
|
||||||
}
|
}
|
||||||
utils.WriteResponse(w, http.StatusOK, info)
|
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
|
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})
|
graphStatus = append(graphStatus, [2]string{k, v})
|
||||||
}
|
}
|
||||||
return graphStatus
|
return graphStatus
|
||||||
|
@ -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"))
|
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrapf(err, "Failed to obtain system memory info"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
hostInfo := infoData[0].Data
|
|
||||||
|
|
||||||
components := []docker.ComponentVersion{{
|
components := []docker.ComponentVersion{{
|
||||||
Name: "Podman Engine",
|
Name: "Podman Engine",
|
||||||
Version: versionInfo.Version,
|
Version: versionInfo.Version,
|
||||||
@ -42,7 +40,7 @@ func VersionHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
"Experimental": "true",
|
"Experimental": "true",
|
||||||
"GitCommit": versionInfo.GitCommit,
|
"GitCommit": versionInfo.GitCommit,
|
||||||
"GoVersion": versionInfo.GoVersion,
|
"GoVersion": versionInfo.GoVersion,
|
||||||
"KernelVersion": hostInfo["kernel"].(string),
|
"KernelVersion": infoData.Host.Kernel,
|
||||||
"MinAPIVersion": handlers.MinimalApiVersion,
|
"MinAPIVersion": handlers.MinimalApiVersion,
|
||||||
"Os": goRuntime.GOOS,
|
"Os": goRuntime.GOOS,
|
||||||
},
|
},
|
||||||
@ -52,7 +50,7 @@ func VersionHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
Platform: struct {
|
Platform: struct {
|
||||||
Name string
|
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"],
|
APIVersion: components[0].Details["APIVersion"],
|
||||||
Arch: components[0].Details["Arch"],
|
Arch: components[0].Details["Arch"],
|
||||||
|
18
pkg/api/handlers/libpod/info.go
Normal file
18
pkg/api/handlers/libpod/info.go
Normal file
@ -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)
|
||||||
|
}
|
@ -5,6 +5,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/containers/image/v5/manifest"
|
"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/api/handlers/utils"
|
||||||
"github.com/containers/libpod/pkg/domain/entities"
|
"github.com/containers/libpod/pkg/domain/entities"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@ -76,6 +77,13 @@ type swagRmPodResponse struct {
|
|||||||
Body entities.PodRmReport
|
Body entities.PodRmReport
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Info
|
||||||
|
// swagger:response InfoResponse
|
||||||
|
type swagInfoResponse struct {
|
||||||
|
// in:body
|
||||||
|
Body define.Info
|
||||||
|
}
|
||||||
|
|
||||||
func ServeSwagger(w http.ResponseWriter, r *http.Request) {
|
func ServeSwagger(w http.ResponseWriter, r *http.Request) {
|
||||||
path := DefaultPodmanSwaggerSpec
|
path := DefaultPodmanSwaggerSpec
|
||||||
if p, found := os.LookupEnv("PODMAN_SWAGGER_SPEC"); found {
|
if p, found := os.LookupEnv("PODMAN_SWAGGER_SPEC"); found {
|
||||||
|
@ -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()
|
imageId, imageName := l.Image()
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -4,14 +4,15 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/containers/libpod/pkg/api/handlers/compat"
|
"github.com/containers/libpod/pkg/api/handlers/compat"
|
||||||
|
"github.com/containers/libpod/pkg/api/handlers/libpod"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *APIServer) registerInfoHandlers(r *mux.Router) error {
|
func (s *APIServer) registerInfoHandlers(r *mux.Router) error {
|
||||||
// swagger:operation GET /info libpod libpodGetInfo
|
// swagger:operation GET /info compat getInfo
|
||||||
// ---
|
// ---
|
||||||
// tags:
|
// tags:
|
||||||
// - system
|
// - system (compat)
|
||||||
// summary: Get info
|
// summary: Get info
|
||||||
// description: Returns information on the system and libpod configuration
|
// description: Returns information on the system and libpod configuration
|
||||||
// produces:
|
// produces:
|
||||||
@ -24,5 +25,19 @@ func (s *APIServer) registerInfoHandlers(r *mux.Router) error {
|
|||||||
r.Handle(VersionedPath("/info"), s.APIHandler(compat.GetInfo)).Methods(http.MethodGet)
|
r.Handle(VersionedPath("/info"), s.APIHandler(compat.GetInfo)).Methods(http.MethodGet)
|
||||||
// Added non version path to URI to support docker non versioned paths
|
// Added non version path to URI to support docker non versioned paths
|
||||||
r.Handle("/info", s.APIHandler(compat.GetInfo)).Methods(http.MethodGet)
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
package bindings
|
|
||||||
|
|
||||||
func (c Connection) Info() {}
|
|
23
pkg/bindings/system/info.go
Normal file
23
pkg/bindings/system/info.go
Normal file
@ -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)
|
||||||
|
}
|
73
pkg/bindings/test/info_test.go
Normal file
73
pkg/bindings/test/info_test.go
Normal file
@ -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))
|
||||||
|
})
|
||||||
|
})
|
@ -44,28 +44,26 @@ func (i *LibpodAPI) GetInfo(call iopodman.VarlinkCall) error {
|
|||||||
return call.ReplyErrorOccurred(err.Error())
|
return call.ReplyErrorOccurred(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
host := info[0].Data
|
|
||||||
distribution := iopodman.InfoDistribution{
|
distribution := iopodman.InfoDistribution{
|
||||||
Distribution: host["Distribution"].(map[string]interface{})["distribution"].(string),
|
Distribution: info.Host.Distribution.Distribution,
|
||||||
Version: host["Distribution"].(map[string]interface{})["version"].(string),
|
Version: info.Host.Distribution.Version,
|
||||||
}
|
}
|
||||||
infoHost := iopodman.InfoHost{
|
infoHost := iopodman.InfoHost{
|
||||||
Buildah_version: host["BuildahVersion"].(string),
|
Buildah_version: info.Host.BuildahVersion,
|
||||||
Distribution: distribution,
|
Distribution: distribution,
|
||||||
Mem_free: host["MemFree"].(int64),
|
Mem_free: info.Host.MemFree,
|
||||||
Mem_total: host["MemTotal"].(int64),
|
Mem_total: info.Host.MemTotal,
|
||||||
Swap_free: host["SwapFree"].(int64),
|
Swap_free: info.Host.SwapFree,
|
||||||
Swap_total: host["SwapTotal"].(int64),
|
Swap_total: info.Host.SwapTotal,
|
||||||
Arch: host["arch"].(string),
|
Arch: info.Host.Arch,
|
||||||
Cpus: int64(host["cpus"].(int)),
|
Cpus: int64(info.Host.CPUs),
|
||||||
Hostname: host["hostname"].(string),
|
Hostname: info.Host.Hostname,
|
||||||
Kernel: host["kernel"].(string),
|
Kernel: info.Host.Kernel,
|
||||||
Os: host["os"].(string),
|
Os: info.Host.OS,
|
||||||
Uptime: host["uptime"].(string),
|
Uptime: info.Host.Uptime,
|
||||||
Eventlogger: host["eventlogger"].(string),
|
Eventlogger: info.Host.EventLogger,
|
||||||
}
|
}
|
||||||
podmanInfo.Host = infoHost
|
podmanInfo.Host = infoHost
|
||||||
store := info[1].Data
|
|
||||||
pmaninfo := iopodman.InfoPodmanBinary{
|
pmaninfo := iopodman.InfoPodmanBinary{
|
||||||
Compiler: goruntime.Compiler,
|
Compiler: goruntime.Compiler,
|
||||||
Go_version: goruntime.Version(),
|
Go_version: goruntime.Version(),
|
||||||
@ -74,36 +72,33 @@ func (i *LibpodAPI) GetInfo(call iopodman.VarlinkCall) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
graphStatus := iopodman.InfoGraphStatus{
|
graphStatus := iopodman.InfoGraphStatus{
|
||||||
Backing_filesystem: store["GraphStatus"].(map[string]string)["Backing Filesystem"],
|
Backing_filesystem: info.Store.GraphStatus["Backing Filesystem"],
|
||||||
Native_overlay_diff: store["GraphStatus"].(map[string]string)["Native Overlay Diff"],
|
Native_overlay_diff: info.Store.GraphStatus["Native Overlay Diff"],
|
||||||
Supports_d_type: store["GraphStatus"].(map[string]string)["Supports d_type"],
|
Supports_d_type: info.Store.GraphStatus["Supports d_type"],
|
||||||
}
|
}
|
||||||
infoStore := iopodman.InfoStore{
|
infoStore := iopodman.InfoStore{
|
||||||
Graph_driver_name: store["GraphDriverName"].(string),
|
Graph_driver_name: info.Store.GraphDriverName,
|
||||||
Containers: int64(store["ContainerStore"].(map[string]interface{})["number"].(int)),
|
Containers: int64(info.Store.ContainerStore.Number),
|
||||||
Images: int64(store["ImageStore"].(map[string]interface{})["number"].(int)),
|
Images: int64(info.Store.ImageStore.Number),
|
||||||
Run_root: store["RunRoot"].(string),
|
Run_root: info.Store.RunRoot,
|
||||||
Graph_root: store["GraphRoot"].(string),
|
Graph_root: info.Store.GraphRoot,
|
||||||
Graph_driver_options: fmt.Sprintf("%v", store["GraphOptions"]),
|
Graph_driver_options: fmt.Sprintf("%v", info.Store.GraphOptions),
|
||||||
Graph_status: graphStatus,
|
Graph_status: graphStatus,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Registry information if any is stored as the second list item
|
// Registry information if any is stored as the second list item
|
||||||
if len(info) > 2 {
|
for key, val := range info.Registries {
|
||||||
for key, val := range info[2].Data {
|
if key == "search" {
|
||||||
if key == "search" {
|
podmanInfo.Registries.Search = val.([]string)
|
||||||
podmanInfo.Registries.Search = val.([]string)
|
continue
|
||||||
continue
|
}
|
||||||
}
|
regData := val.(sysregistriesv2.Registry)
|
||||||
regData := val.(sysregistriesv2.Registry)
|
if regData.Insecure {
|
||||||
if regData.Insecure {
|
podmanInfo.Registries.Insecure = append(podmanInfo.Registries.Insecure, key)
|
||||||
podmanInfo.Registries.Insecure = append(podmanInfo.Registries.Insecure, key)
|
}
|
||||||
}
|
if regData.Blocked {
|
||||||
if regData.Blocked {
|
podmanInfo.Registries.Blocked = append(podmanInfo.Registries.Blocked, key)
|
||||||
podmanInfo.Registries.Blocked = append(podmanInfo.Registries.Blocked, key)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
podmanInfo.Store = infoStore
|
podmanInfo.Store = infoStore
|
||||||
podmanInfo.Podman = pmaninfo
|
podmanInfo.Podman = pmaninfo
|
||||||
|
@ -43,10 +43,16 @@ var _ = Describe("Podman Info", func() {
|
|||||||
Expect(session.ExitCode()).To(Equal(0))
|
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 := podmanTest.Podman([]string{"info", "--format", "{{ json .}}"})
|
||||||
session.WaitWithDefaultTimeout()
|
session.WaitWithDefaultTimeout()
|
||||||
Expect(session.ExitCode()).To(Equal(0))
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
Expect(session.IsJSONOutputValid()).To(BeTrue())
|
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))
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -8,19 +8,19 @@ load helpers
|
|||||||
run_podman info
|
run_podman info
|
||||||
|
|
||||||
expected_keys="
|
expected_keys="
|
||||||
BuildahVersion: *[0-9.]\\\+
|
buildahVersion: *[0-9.]\\\+
|
||||||
Conmon:\\\s\\\+package:
|
conmon:\\\s\\\+package:
|
||||||
Distribution:
|
distribution:
|
||||||
OCIRuntime:\\\s\\\+name:
|
ociRuntime:\\\s\\\+name:
|
||||||
os:
|
os:
|
||||||
rootless:
|
rootless:
|
||||||
registries:
|
registries:
|
||||||
store:
|
store:
|
||||||
GraphDriverName:
|
graphDriverName:
|
||||||
GraphRoot:
|
graphRoot:
|
||||||
GraphStatus:
|
graphStatus:
|
||||||
ImageStore:\\\s\\\+number: 1
|
imageStore:\\\s\\\+number: 1
|
||||||
RunRoot:
|
runRoot:
|
||||||
"
|
"
|
||||||
while read expect; do
|
while read expect; do
|
||||||
is "$output" ".*$expect" "output includes '$expect'"
|
is "$output" ".*$expect" "output includes '$expect'"
|
||||||
@ -36,13 +36,13 @@ RunRoot:
|
|||||||
expr_path="/[a-z0-9\\\/.-]\\\+\\\$"
|
expr_path="/[a-z0-9\\\/.-]\\\+\\\$"
|
||||||
|
|
||||||
tests="
|
tests="
|
||||||
host.BuildahVersion | [0-9.]
|
host.buildahVersion | [0-9.]
|
||||||
host.Conmon.path | $expr_path
|
host.conmon.path | $expr_path
|
||||||
host.OCIRuntime.path | $expr_path
|
host.ociRuntime.path | $expr_path
|
||||||
store.ConfigFile | $expr_path
|
store.configFile | $expr_path
|
||||||
store.GraphDriverName | [a-z0-9]\\\+\\\$
|
store.graphDriverName | [a-z0-9]\\\+\\\$
|
||||||
store.GraphRoot | $expr_path
|
store.graphRoot | $expr_path
|
||||||
store.ImageStore.number | 1
|
store.imageStore.number | 1
|
||||||
"
|
"
|
||||||
|
|
||||||
parse_table "$tests" | while read field expect; do
|
parse_table "$tests" | while read field expect; do
|
||||||
|
@ -12,7 +12,7 @@ load helpers
|
|||||||
err_no_exec_dir="Error: .*: starting container process caused .*exec:.* permission denied"
|
err_no_exec_dir="Error: .*: starting container process caused .*exec:.* permission denied"
|
||||||
|
|
||||||
# ...but check the configured runtime engine, and switch to crun as needed
|
# ...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
|
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_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"
|
err_no_exec_dir="Error: open executable: Operation not permitted: OCI runtime permission denied error"
|
||||||
|
@ -187,7 +187,7 @@ load helpers
|
|||||||
chmod 644 $srcdir/$rand_filename
|
chmod 644 $srcdir/$rand_filename
|
||||||
|
|
||||||
# Determine path to podman storage (eg /var/lib/c/s, or $HOME/.local/...)
|
# 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
|
graphroot=$output
|
||||||
|
|
||||||
# Create that directory in the container, and sleep (to keep container
|
# Create that directory in the container, and sleep (to keep container
|
||||||
|
@ -70,10 +70,10 @@ EOF
|
|||||||
chmod 755 $PODMAN_TMPDIR $test_script
|
chmod 755 $PODMAN_TMPDIR $test_script
|
||||||
|
|
||||||
# get podman image and container storage directories
|
# 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"
|
is "$output" "/var/lib/containers/storage" "GraphRoot in expected place"
|
||||||
GRAPH_ROOT="$output"
|
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"
|
is "$output" "/var/run/containers/storage" "RunRoot in expected place"
|
||||||
RUN_ROOT="$output"
|
RUN_ROOT="$output"
|
||||||
|
|
||||||
|
@ -391,7 +391,7 @@ function random_string() {
|
|||||||
# Return exec_pid hash files if exists, otherwise, return nothing
|
# Return exec_pid hash files if exists, otherwise, return nothing
|
||||||
#
|
#
|
||||||
function find_exec_pid_files() {
|
function find_exec_pid_files() {
|
||||||
run_podman info --format '{{.store.RunRoot}}'
|
run_podman info --format '{{.Store.RunRoot}}'
|
||||||
local storage_path="$output"
|
local storage_path="$output"
|
||||||
if [ -d $storage_path ]; then
|
if [ -d $storage_path ]; then
|
||||||
find $storage_path -type f -iname 'exec_pid_*'
|
find $storage_path -type f -iname 'exec_pid_*'
|
||||||
|
Reference in New Issue
Block a user