summaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-rw-r--r--pkg/adapter/info_remote.go73
-rw-r--r--pkg/adapter/pods.go18
-rw-r--r--pkg/api/handlers/compat/containers.go8
-rw-r--r--pkg/api/handlers/compat/info.go36
-rw-r--r--pkg/api/handlers/compat/version.go6
-rw-r--r--pkg/api/handlers/libpod/containers.go185
-rw-r--r--pkg/api/handlers/libpod/info.go18
-rw-r--r--pkg/api/handlers/libpod/swagger.go10
-rw-r--r--pkg/api/handlers/libpod/types.go82
-rw-r--r--pkg/api/handlers/types.go2
-rw-r--r--pkg/api/server/register_info.go19
-rw-r--r--pkg/bindings/containers/containers.go6
-rw-r--r--pkg/bindings/info.go3
-rw-r--r--pkg/bindings/system/info.go23
-rw-r--r--pkg/bindings/test/info_test.go73
-rw-r--r--pkg/domain/entities/container_ps.go174
-rw-r--r--pkg/domain/entities/containers.go38
-rw-r--r--pkg/domain/entities/engine_container.go2
-rw-r--r--pkg/domain/infra/abi/containers.go113
-rw-r--r--pkg/domain/infra/abi/pods.go5
-rw-r--r--pkg/domain/infra/tunnel/containers.go13
-rw-r--r--pkg/domain/infra/tunnel/helpers.go5
-rw-r--r--pkg/ps/ps.go189
-rw-r--r--pkg/varlinkapi/system.go73
24 files changed, 795 insertions, 379 deletions
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, &regInfo)
-
- // 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/adapter/pods.go b/pkg/adapter/pods.go
index 102eabd8b..7c2a84cc7 100644
--- a/pkg/adapter/pods.go
+++ b/pkg/adapter/pods.go
@@ -343,7 +343,7 @@ func (r *LocalRuntime) CreatePod(ctx context.Context, cli *cliconfig.PodCreateVa
logrus.Debugf("Pod will use host networking")
options = append(options, libpod.WithPodHostNetwork())
case "":
- return "", errors.Errorf("invalid value passed to --net: must provide a comma-separated list of CNI networks or host")
+ return "", errors.Errorf("invalid value passed to --network: must provide a comma-separated list of CNI networks or host")
default:
// We'll assume this is a comma-separated list of CNI
// networks.
@@ -595,6 +595,22 @@ func (r *LocalRuntime) PlayKubeYAML(ctx context.Context, c *cliconfig.KubePlayVa
podPorts := getPodPorts(podYAML.Spec.Containers)
podOptions = append(podOptions, libpod.WithInfraContainerPorts(podPorts))
+ if c.Flag("network").Changed {
+ netValue := c.String("network")
+ switch strings.ToLower(netValue) {
+ case "bridge", "host":
+ return nil, errors.Errorf("invalid value passed to --network: bridge or host networking must be configured in YAML")
+ case "":
+ return nil, errors.Errorf("invalid value passed to --network: must provide a comma-separated list of CNI networks")
+ default:
+ // We'll assume this is a comma-separated list of CNI
+ // networks.
+ networks := strings.Split(netValue, ",")
+ logrus.Debugf("Pod joining CNI networks: %v", networks)
+ podOptions = append(podOptions, libpod.WithPodNetworks(networks))
+ }
+ }
+
// Create the Pod
pod, err = r.NewPod(ctx, podOptions...)
if err != 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/containers.go b/pkg/api/handlers/libpod/containers.go
index fde72552b..5cbfb11eb 100644
--- a/pkg/api/handlers/libpod/containers.go
+++ b/pkg/api/handlers/libpod/containers.go
@@ -4,21 +4,16 @@ import (
"io/ioutil"
"net/http"
"os"
- "path/filepath"
- "sort"
"strconv"
- "time"
- "github.com/containers/libpod/pkg/api/handlers/compat"
-
- "github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/define"
+ "github.com/containers/libpod/pkg/api/handlers/compat"
"github.com/containers/libpod/pkg/api/handlers/utils"
"github.com/containers/libpod/pkg/domain/entities"
+ "github.com/containers/libpod/pkg/ps"
"github.com/gorilla/schema"
"github.com/pkg/errors"
- "github.com/sirupsen/logrus"
)
func ContainerExists(w http.ResponseWriter, r *http.Request) {
@@ -38,8 +33,8 @@ func ContainerExists(w http.ResponseWriter, r *http.Request) {
func ListContainers(w http.ResponseWriter, r *http.Request) {
var (
- filterFuncs []libpod.ContainerFilter
- pss []ListContainer
+ //filterFuncs []libpod.ContainerFilter
+ //pss []entities.ListContainer
)
decoder := r.Context().Value("decoder").(*schema.Decoder)
query := struct {
@@ -61,66 +56,19 @@ func ListContainers(w http.ResponseWriter, r *http.Request) {
}
runtime := r.Context().Value("runtime").(*libpod.Runtime)
- opts := shared.PsOptions{
+ opts := entities.ContainerListOptions{
All: query.All,
Last: query.Last,
Size: query.Size,
Sort: "",
Namespace: query.Namespace,
- NoTrunc: true,
Pod: query.Pod,
Sync: query.Sync,
}
-
- all := query.All
- if len(query.Filters) > 0 {
- for k, v := range query.Filters {
- for _, val := range v {
- generatedFunc, err := shared.GenerateContainerFilterFuncs(k, val, runtime)
- if err != nil {
- utils.InternalServerError(w, err)
- return
- }
- filterFuncs = append(filterFuncs, generatedFunc)
- }
- }
- }
-
- // Docker thinks that if status is given as an input, then we should override
- // the all setting and always deal with all containers.
- if len(query.Filters["status"]) > 0 {
- all = true
- }
- if !all {
- runningOnly, err := shared.GenerateContainerFilterFuncs("status", define.ContainerStateRunning.String(), runtime)
- if err != nil {
- utils.InternalServerError(w, err)
- return
- }
- filterFuncs = append(filterFuncs, runningOnly)
- }
-
- cons, err := runtime.GetContainers(filterFuncs...)
+ pss, err := ps.GetContainerLists(runtime, opts)
if err != nil {
utils.InternalServerError(w, err)
- }
- if query.Last > 0 {
- // Sort the containers we got
- sort.Sort(psSortCreateTime{cons})
- // we should perform the lopping before we start getting
- // the expensive information on containers
- if query.Last < len(cons) {
- cons = cons[len(cons)-query.Last:]
- }
- }
- for _, con := range cons {
- listCon, err := ListContainerBatch(runtime, con, opts)
- if err != nil {
- utils.InternalServerError(w, err)
- return
- }
- pss = append(pss, listCon)
-
+ return
}
utils.WriteResponse(w, http.StatusOK, pss)
}
@@ -212,125 +160,6 @@ func ShowMountedContainers(w http.ResponseWriter, r *http.Request) {
utils.WriteResponse(w, http.StatusOK, response)
}
-// BatchContainerOp is used in ps to reduce performance hits by "batching"
-// locks.
-func ListContainerBatch(rt *libpod.Runtime, ctr *libpod.Container, opts shared.PsOptions) (ListContainer, error) {
- var (
- conConfig *libpod.ContainerConfig
- conState define.ContainerStatus
- err error
- exitCode int32
- exited bool
- pid int
- size *shared.ContainerSize
- startedTime time.Time
- exitedTime time.Time
- cgroup, ipc, mnt, net, pidns, user, uts string
- )
-
- batchErr := ctr.Batch(func(c *libpod.Container) error {
- conConfig = c.Config()
- conState, err = c.State()
- if err != nil {
- return errors.Wrapf(err, "unable to obtain container state")
- }
-
- exitCode, exited, err = c.ExitCode()
- if err != nil {
- return errors.Wrapf(err, "unable to obtain container exit code")
- }
- startedTime, err = c.StartedTime()
- if err != nil {
- logrus.Errorf("error getting started time for %q: %v", c.ID(), err)
- }
- exitedTime, err = c.FinishedTime()
- if err != nil {
- logrus.Errorf("error getting exited time for %q: %v", c.ID(), err)
- }
-
- if !opts.Size && !opts.Namespace {
- return nil
- }
-
- if opts.Namespace {
- pid, err = c.PID()
- if err != nil {
- return errors.Wrapf(err, "unable to obtain container pid")
- }
- ctrPID := strconv.Itoa(pid)
- cgroup, _ = shared.GetNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "cgroup"))
- ipc, _ = shared.GetNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "ipc"))
- mnt, _ = shared.GetNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "mnt"))
- net, _ = shared.GetNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "net"))
- pidns, _ = shared.GetNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "pid"))
- user, _ = shared.GetNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "user"))
- uts, _ = shared.GetNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "uts"))
- }
- if opts.Size {
- size = new(shared.ContainerSize)
-
- rootFsSize, err := c.RootFsSize()
- if err != nil {
- logrus.Errorf("error getting root fs size for %q: %v", c.ID(), err)
- }
-
- rwSize, err := c.RWSize()
- if err != nil {
- logrus.Errorf("error getting rw size for %q: %v", c.ID(), err)
- }
-
- size.RootFsSize = rootFsSize
- size.RwSize = rwSize
- }
- return nil
- })
-
- if batchErr != nil {
- return ListContainer{}, batchErr
- }
-
- ps := ListContainer{
- Command: conConfig.Command,
- Created: conConfig.CreatedTime.Unix(),
- Exited: exited,
- ExitCode: exitCode,
- ExitedAt: exitedTime.Unix(),
- ID: conConfig.ID,
- Image: conConfig.RootfsImageName,
- IsInfra: conConfig.IsInfra,
- Labels: conConfig.Labels,
- Mounts: ctr.UserVolumes(),
- Names: []string{conConfig.Name},
- Pid: pid,
- Pod: conConfig.Pod,
- Ports: conConfig.PortMappings,
- Size: size,
- StartedAt: startedTime.Unix(),
- State: conState.String(),
- }
- if opts.Pod && len(conConfig.Pod) > 0 {
- pod, err := rt.GetPod(conConfig.Pod)
- if err != nil {
- return ListContainer{}, err
- }
- ps.PodName = pod.Name()
- }
-
- if opts.Namespace {
- ns := ListContainerNamespaces{
- Cgroup: cgroup,
- IPC: ipc,
- MNT: mnt,
- NET: net,
- PIDNS: pidns,
- User: user,
- UTS: uts,
- }
- ps.Namespaces = ns
- }
- return ps, nil
-}
-
func Checkpoint(w http.ResponseWriter, r *http.Request) {
var targetFile string
decoder := r.Context().Value("decoder").(*schema.Decoder)
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..ed19462c6 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"
@@ -17,7 +18,7 @@ const DefaultPodmanSwaggerSpec = "/usr/share/containers/podman/swagger.yaml"
// swagger:response ListContainers
type swagInspectPodResponse struct {
// in:body
- Body []ListContainer
+ Body []entities.ListContainer
}
// Inspect Manifest
@@ -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/libpod/types.go b/pkg/api/handlers/libpod/types.go
deleted file mode 100644
index 0949b2a72..000000000
--- a/pkg/api/handlers/libpod/types.go
+++ /dev/null
@@ -1,82 +0,0 @@
-package libpod
-
-import (
- "github.com/containers/libpod/cmd/podman/shared"
- "github.com/containers/libpod/libpod"
- "github.com/cri-o/ocicni/pkg/ocicni"
-)
-
-// Listcontainer describes a container suitable for listing
-type ListContainer struct {
- // Container command
- Command []string
- // Container creation time
- Created int64
- // If container has exited/stopped
- Exited bool
- // Time container exited
- ExitedAt int64
- // If container has exited, the return code from the command
- ExitCode int32
- // The unique identifier for the container
- ID string `json:"Id"`
- // Container image
- Image string
- // If this container is a Pod infra container
- IsInfra bool
- // Labels for container
- Labels map[string]string
- // User volume mounts
- Mounts []string
- // The names assigned to the container
- Names []string
- // Namespaces the container belongs to. Requires the
- // namespace boolean to be true
- Namespaces ListContainerNamespaces
- // The process id of the container
- Pid int
- // If the container is part of Pod, the Pod ID. Requires the pod
- // boolean to be set
- Pod string
- // If the container is part of Pod, the Pod name. Requires the pod
- // boolean to be set
- PodName string
- // Port mappings
- Ports []ocicni.PortMapping
- // Size of the container rootfs. Requires the size boolean to be true
- Size *shared.ContainerSize
- // Time when container started
- StartedAt int64
- // State of container
- State string
-}
-
-// ListContainer Namespaces contains the identifiers of the container's Linux namespaces
-type ListContainerNamespaces struct {
- // Mount namespace
- MNT string `json:"Mnt,omitempty"`
- // Cgroup namespace
- Cgroup string `json:"Cgroup,omitempty"`
- // IPC namespace
- IPC string `json:"Ipc,omitempty"`
- // Network namespace
- NET string `json:"Net,omitempty"`
- // PID namespace
- PIDNS string `json:"Pidns,omitempty"`
- // UTS namespace
- UTS string `json:"Uts,omitempty"`
- // User namespace
- User string `json:"User,omitempty"`
-}
-
-// sortContainers helps us set-up ability to sort by createTime
-type sortContainers []*libpod.Container
-
-func (a sortContainers) Len() int { return len(a) }
-func (a sortContainers) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
-
-type psSortCreateTime struct{ sortContainers }
-
-func (a psSortCreateTime) Less(i, j int) bool {
- return a.sortContainers[i].CreatedTime().Before(a.sortContainers[j].CreatedTime())
-}
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/containers/containers.go b/pkg/bindings/containers/containers.go
index 49a2dfd58..a188d73a0 100644
--- a/pkg/bindings/containers/containers.go
+++ b/pkg/bindings/containers/containers.go
@@ -10,8 +10,8 @@ import (
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/pkg/api/handlers"
- lpapiv2 "github.com/containers/libpod/pkg/api/handlers/libpod"
"github.com/containers/libpod/pkg/bindings"
+ "github.com/containers/libpod/pkg/domain/entities"
)
// List obtains a list of containers in local storage. All parameters to this method are optional.
@@ -19,12 +19,12 @@ import (
// the most recent number of containers. The pod and size booleans indicate that pod information and rootfs
// size information should also be included. Finally, the sync bool synchronizes the OCI runtime and
// container state.
-func List(ctx context.Context, filters map[string][]string, all *bool, last *int, pod, size, sync *bool) ([]lpapiv2.ListContainer, error) { // nolint:typecheck
+func List(ctx context.Context, filters map[string][]string, all *bool, last *int, pod, size, sync *bool) ([]entities.ListContainer, error) { // nolint:typecheck
conn, err := bindings.GetClient(ctx)
if err != nil {
return nil, err
}
- var containers []lpapiv2.ListContainer
+ var containers []entities.ListContainer
params := url.Values{}
if all != nil {
params.Set("all", strconv.FormatBool(*all))
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/domain/entities/container_ps.go b/pkg/domain/entities/container_ps.go
new file mode 100644
index 000000000..ceafecebc
--- /dev/null
+++ b/pkg/domain/entities/container_ps.go
@@ -0,0 +1,174 @@
+package entities
+
+import (
+ "sort"
+ "strings"
+
+ "github.com/containers/libpod/cmd/podman/shared"
+ "github.com/containers/libpod/libpod"
+ "github.com/cri-o/ocicni/pkg/ocicni"
+ "github.com/pkg/errors"
+)
+
+// Listcontainer describes a container suitable for listing
+type ListContainer struct {
+ // Container command
+ Command []string
+ // Container creation time
+ Created int64
+ // If container has exited/stopped
+ Exited bool
+ // Time container exited
+ ExitedAt int64
+ // If container has exited, the return code from the command
+ ExitCode int32
+ // The unique identifier for the container
+ ID string `json:"Id"`
+ // Container image
+ Image string
+ // If this container is a Pod infra container
+ IsInfra bool
+ // Labels for container
+ Labels map[string]string
+ // User volume mounts
+ Mounts []string
+ // The names assigned to the container
+ Names []string
+ // Namespaces the container belongs to. Requires the
+ // namespace boolean to be true
+ Namespaces ListContainerNamespaces
+ // The process id of the container
+ Pid int
+ // If the container is part of Pod, the Pod ID. Requires the pod
+ // boolean to be set
+ Pod string
+ // If the container is part of Pod, the Pod name. Requires the pod
+ // boolean to be set
+ PodName string
+ // Port mappings
+ Ports []ocicni.PortMapping
+ // Size of the container rootfs. Requires the size boolean to be true
+ Size *shared.ContainerSize
+ // Time when container started
+ StartedAt int64
+ // State of container
+ State string
+}
+
+// ListContainer Namespaces contains the identifiers of the container's Linux namespaces
+type ListContainerNamespaces struct {
+ // Mount namespace
+ MNT string `json:"Mnt,omitempty"`
+ // Cgroup namespace
+ Cgroup string `json:"Cgroup,omitempty"`
+ // IPC namespace
+ IPC string `json:"Ipc,omitempty"`
+ // Network namespace
+ NET string `json:"Net,omitempty"`
+ // PID namespace
+ PIDNS string `json:"Pidns,omitempty"`
+ // UTS namespace
+ UTS string `json:"Uts,omitempty"`
+ // User namespace
+ User string `json:"User,omitempty"`
+}
+
+// SortContainers helps us set-up ability to sort by createTime
+type SortContainers []*libpod.Container
+
+func (a SortContainers) Len() int { return len(a) }
+func (a SortContainers) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+
+type SortCreateTime struct{ SortContainers }
+
+func (a SortCreateTime) Less(i, j int) bool {
+ return a.SortContainers[i].CreatedTime().Before(a.SortContainers[j].CreatedTime())
+}
+
+type SortListContainers []ListContainer
+
+func (a SortListContainers) Len() int { return len(a) }
+func (a SortListContainers) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+
+type psSortedCommand struct{ SortListContainers }
+
+func (a psSortedCommand) Less(i, j int) bool {
+ return strings.Join(a.SortListContainers[i].Command, " ") < strings.Join(a.SortListContainers[j].Command, " ")
+}
+
+type psSortedId struct{ SortListContainers }
+
+func (a psSortedId) Less(i, j int) bool {
+ return a.SortListContainers[i].ID < a.SortListContainers[j].ID
+}
+
+type psSortedImage struct{ SortListContainers }
+
+func (a psSortedImage) Less(i, j int) bool {
+ return a.SortListContainers[i].Image < a.SortListContainers[j].Image
+}
+
+type psSortedNames struct{ SortListContainers }
+
+func (a psSortedNames) Less(i, j int) bool {
+ return a.SortListContainers[i].Names[0] < a.SortListContainers[j].Names[0]
+}
+
+type psSortedPod struct{ SortListContainers }
+
+func (a psSortedPod) Less(i, j int) bool {
+ return a.SortListContainers[i].Pod < a.SortListContainers[j].Pod
+}
+
+type psSortedRunningFor struct{ SortListContainers }
+
+func (a psSortedRunningFor) Less(i, j int) bool {
+ return a.SortListContainers[i].StartedAt < a.SortListContainers[j].StartedAt
+}
+
+type psSortedStatus struct{ SortListContainers }
+
+func (a psSortedStatus) Less(i, j int) bool {
+ return a.SortListContainers[i].State < a.SortListContainers[j].State
+}
+
+type psSortedSize struct{ SortListContainers }
+
+func (a psSortedSize) Less(i, j int) bool {
+ if a.SortListContainers[i].Size == nil || a.SortListContainers[j].Size == nil {
+ return false
+ }
+ return a.SortListContainers[i].Size.RootFsSize < a.SortListContainers[j].Size.RootFsSize
+}
+
+type PsSortedCreateTime struct{ SortListContainers }
+
+func (a PsSortedCreateTime) Less(i, j int) bool {
+ return a.SortListContainers[i].Created < a.SortListContainers[j].Created
+}
+
+func SortPsOutput(sortBy string, psOutput SortListContainers) (SortListContainers, error) {
+ switch sortBy {
+ case "id":
+ sort.Sort(psSortedId{psOutput})
+ case "image":
+ sort.Sort(psSortedImage{psOutput})
+ case "command":
+ sort.Sort(psSortedCommand{psOutput})
+ case "runningfor":
+ sort.Sort(psSortedRunningFor{psOutput})
+ case "status":
+ sort.Sort(psSortedStatus{psOutput})
+ case "size":
+ sort.Sort(psSortedSize{psOutput})
+ case "names":
+ sort.Sort(psSortedNames{psOutput})
+ case "created":
+ sort.Sort(PsSortedCreateTime{psOutput})
+ case "pod":
+ sort.Sort(psSortedPod{psOutput})
+ default:
+ return nil, errors.Errorf("invalid option for --sort, options are: command, created, id, image, names, runningfor, size, or status")
+ }
+ return psOutput, nil
+}
diff --git a/pkg/domain/entities/containers.go b/pkg/domain/entities/containers.go
index cf907eb1b..4f94e009f 100644
--- a/pkg/domain/entities/containers.go
+++ b/pkg/domain/entities/containers.go
@@ -186,3 +186,41 @@ type ExecOptions struct {
User string
WorkDir string
}
+
+// ContainerStartOptions describes the val from the
+// CLI needed to start a container
+type ContainerStartOptions struct {
+ Attach bool
+ DetachKeys string
+ Interactive bool
+ Latest bool
+ SigProxy bool
+ Stdout *os.File
+ Stderr *os.File
+ Stdin *os.File
+}
+
+// ContainerStartReport describes the response from starting
+// containers from the cli
+type ContainerStartReport struct {
+ Id string
+ Err error
+ ExitCode int
+}
+
+// ContainerListOptions describes the CLI options
+// for listing containers
+type ContainerListOptions struct {
+ All bool
+ Filters map[string][]string
+ Format string
+ Last int
+ Latest bool
+ Namespace bool
+ Pod bool
+ Quiet bool
+ Size bool
+ Sort string
+ Sync bool
+ Watch uint
+}
diff --git a/pkg/domain/entities/engine_container.go b/pkg/domain/entities/engine_container.go
index 9bf3d51de..36c20c38d 100644
--- a/pkg/domain/entities/engine_container.go
+++ b/pkg/domain/entities/engine_container.go
@@ -19,8 +19,10 @@ type ContainerEngine interface {
ContainerExport(ctx context.Context, nameOrId string, options ContainerExportOptions) error
ContainerKill(ctx context.Context, namesOrIds []string, options KillOptions) ([]*KillReport, error)
ContainerPause(ctx context.Context, namesOrIds []string, options PauseUnPauseOptions) ([]*PauseUnpauseReport, error)
+ ContainerList(ctx context.Context, options ContainerListOptions) ([]ListContainer, error)
ContainerRestart(ctx context.Context, namesOrIds []string, options RestartOptions) ([]*RestartReport, error)
ContainerRm(ctx context.Context, namesOrIds []string, options RmOptions) ([]*RmReport, error)
+ ContainerStart(ctx context.Context, namesOrIds []string, options ContainerStartOptions) ([]*ContainerStartReport, error)
ContainerStop(ctx context.Context, namesOrIds []string, options StopOptions) ([]*StopReport, error)
ContainerTop(ctx context.Context, options TopOptions) (*StringSliceReport, error)
ContainerUnpause(ctx context.Context, namesOrIds []string, options PauseUnPauseOptions) ([]*PauseUnpauseReport, error)
diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go
index b93e7665a..54f91a189 100644
--- a/pkg/domain/infra/abi/containers.go
+++ b/pkg/domain/infra/abi/containers.go
@@ -12,10 +12,12 @@ import (
"github.com/containers/image/v5/manifest"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/define"
+ "github.com/containers/libpod/libpod/events"
"github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/checkpoint"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/containers/libpod/pkg/domain/infra/abi/terminal"
+ "github.com/containers/libpod/pkg/ps"
"github.com/containers/libpod/pkg/signal"
"github.com/containers/libpod/pkg/specgen"
"github.com/containers/libpod/pkg/specgen/generate"
@@ -509,3 +511,114 @@ func (ic *ContainerEngine) ContainerExec(ctx context.Context, nameOrId string, o
ec, err = terminal.ExecAttachCtr(ctx, ctr, options.Tty, options.Privileged, options.Envs, options.Cmd, options.User, options.WorkDir, &options.Streams, options.PreserveFDs, options.DetachKeys)
return define.TranslateExecErrorToExitCode(ec, err), err
}
+
+func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []string, options entities.ContainerStartOptions) ([]*entities.ContainerStartReport, error) {
+ var reports []*entities.ContainerStartReport
+ var exitCode = define.ExecErrorCodeGeneric
+ ctrs, err := getContainersByContext(false, options.Latest, namesOrIds, ic.Libpod)
+ if err != nil {
+ return nil, err
+ }
+ // There can only be one container if attach was used
+ for _, ctr := range ctrs {
+ ctrState, err := ctr.State()
+ if err != nil {
+ return nil, err
+ }
+ ctrRunning := ctrState == define.ContainerStateRunning
+
+ if options.Attach {
+ err = terminal.StartAttachCtr(ctx, ctr, options.Stdout, options.Stderr, options.Stdin, options.DetachKeys, options.SigProxy, !ctrRunning, ctr.PodID() != "")
+ if errors.Cause(err) == define.ErrDetach {
+ // User manually detached
+ // Exit cleanly immediately
+ reports = append(reports, &entities.ContainerStartReport{
+ Id: ctr.ID(),
+ Err: nil,
+ ExitCode: 0,
+ })
+ return reports, nil
+ }
+
+ if errors.Cause(err) == define.ErrWillDeadlock {
+ logrus.Debugf("Deadlock error: %v", err)
+ reports = append(reports, &entities.ContainerStartReport{
+ Id: ctr.ID(),
+ Err: err,
+ ExitCode: define.ExitCode(err),
+ })
+ return reports, errors.Errorf("attempting to start container %s would cause a deadlock; please run 'podman system renumber' to resolve", ctr.ID())
+ }
+
+ if ctrRunning {
+ reports = append(reports, &entities.ContainerStartReport{
+ Id: ctr.ID(),
+ Err: nil,
+ ExitCode: 0,
+ })
+ return reports, err
+ }
+
+ if err != nil {
+ reports = append(reports, &entities.ContainerStartReport{
+ Id: ctr.ID(),
+ Err: err,
+ ExitCode: exitCode,
+ })
+ return reports, errors.Wrapf(err, "unable to start container %s", ctr.ID())
+ }
+
+ if ecode, err := ctr.Wait(); err != nil {
+ if errors.Cause(err) == define.ErrNoSuchCtr {
+ // Check events
+ event, err := ic.Libpod.GetLastContainerEvent(ctr.ID(), events.Exited)
+ if err != nil {
+ logrus.Errorf("Cannot get exit code: %v", err)
+ exitCode = define.ExecErrorCodeNotFound
+ } else {
+ exitCode = event.ContainerExitCode
+ }
+ }
+ } else {
+ exitCode = int(ecode)
+ }
+ reports = append(reports, &entities.ContainerStartReport{
+ Id: ctr.ID(),
+ Err: err,
+ ExitCode: exitCode,
+ })
+ return reports, nil
+ } // end attach
+
+ // Start the container if it's not running already.
+ if !ctrRunning {
+ // Handle non-attach start
+ // If the container is in a pod, also set to recursively start dependencies
+ report := &entities.ContainerStartReport{
+ Id: ctr.ID(),
+ ExitCode: 125,
+ }
+ if err := ctr.Start(ctx, ctr.PodID() != ""); err != nil {
+ //if lastError != nil {
+ // fmt.Fprintln(os.Stderr, lastError)
+ //}
+ report.Err = err
+ if errors.Cause(err) == define.ErrWillDeadlock {
+ report.Err = errors.Wrapf(err, "please run 'podman system renumber' to resolve deadlocks")
+ reports = append(reports, report)
+ continue
+ }
+ report.Err = errors.Wrapf(err, "unable to start container %q", ctr.ID())
+ reports = append(reports, report)
+ continue
+ }
+ report.ExitCode = 0
+ reports = append(reports, report)
+ }
+ }
+ return reports, nil
+}
+
+func (ic *ContainerEngine) ContainerList(ctx context.Context, options entities.ContainerListOptions) ([]entities.ListContainer, error) {
+ return ps.GetContainerLists(ic.Libpod, options)
+}
diff --git a/pkg/domain/infra/abi/pods.go b/pkg/domain/infra/abi/pods.go
index 073cd8d5c..c3e5d59bc 100644
--- a/pkg/domain/infra/abi/pods.go
+++ b/pkg/domain/infra/abi/pods.go
@@ -5,9 +5,10 @@ package abi
import (
"context"
+ lpfilters "github.com/containers/libpod/libpod/filters"
+
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/define"
- "github.com/containers/libpod/libpod/podfilters"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/containers/libpod/pkg/signal"
"github.com/containers/libpod/pkg/specgen"
@@ -281,7 +282,7 @@ func (ic *ContainerEngine) PodPs(ctx context.Context, options entities.PodPSOpti
)
for k, v := range options.Filters {
for _, filter := range v {
- f, err := podfilters.GeneratePodFilterFunc(k, filter)
+ f, err := lpfilters.GeneratePodFilterFunc(k, filter)
if err != nil {
return nil, err
}
diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go
index 1e71cba2c..b6807d5b6 100644
--- a/pkg/domain/infra/tunnel/containers.go
+++ b/pkg/domain/infra/tunnel/containers.go
@@ -7,7 +7,6 @@ import (
"github.com/containers/image/v5/docker/reference"
"github.com/containers/libpod/libpod/define"
- "github.com/containers/libpod/pkg/api/handlers/libpod"
"github.com/containers/libpod/pkg/bindings/containers"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/containers/libpod/pkg/specgen"
@@ -233,7 +232,7 @@ func (ic *ContainerEngine) ContainerCheckpoint(ctx context.Context, namesOrIds [
var (
reports []*entities.CheckpointReport
err error
- ctrs []libpod.ListContainer
+ ctrs []entities.ListContainer
)
if options.All {
@@ -268,7 +267,7 @@ func (ic *ContainerEngine) ContainerRestore(ctx context.Context, namesOrIds []st
var (
reports []*entities.RestoreReport
err error
- ctrs []libpod.ListContainer
+ ctrs []entities.ListContainer
)
if options.All {
allCtrs, err := getContainersByContext(ic.ClientCxt, true, []string{})
@@ -313,3 +312,11 @@ func (ic *ContainerEngine) ContainerAttach(ctx context.Context, nameOrId string,
func (ic *ContainerEngine) ContainerExec(ctx context.Context, nameOrId string, options entities.ExecOptions) (int, error) {
return 125, errors.New("not implemented")
}
+
+func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []string, options entities.ContainerStartOptions) ([]*entities.ContainerStartReport, error) {
+ return nil, errors.New("not implemented")
+}
+
+func (ic *ContainerEngine) ContainerList(ctx context.Context, options entities.ContainerListOptions) ([]entities.ListContainer, error) {
+ return containers.List(ic.ClientCxt, options.Filters, &options.All, &options.Last, &options.Pod, &options.Size, &options.Sync)
+}
diff --git a/pkg/domain/infra/tunnel/helpers.go b/pkg/domain/infra/tunnel/helpers.go
index f9183c955..682d60d6a 100644
--- a/pkg/domain/infra/tunnel/helpers.go
+++ b/pkg/domain/infra/tunnel/helpers.go
@@ -5,7 +5,6 @@ import (
"strings"
"github.com/containers/libpod/libpod/define"
- "github.com/containers/libpod/pkg/api/handlers/libpod"
"github.com/containers/libpod/pkg/bindings"
"github.com/containers/libpod/pkg/bindings/containers"
"github.com/containers/libpod/pkg/bindings/pods"
@@ -14,9 +13,9 @@ import (
"github.com/pkg/errors"
)
-func getContainersByContext(contextWithConnection context.Context, all bool, namesOrIds []string) ([]libpod.ListContainer, error) {
+func getContainersByContext(contextWithConnection context.Context, all bool, namesOrIds []string) ([]entities.ListContainer, error) {
var (
- cons []libpod.ListContainer
+ cons []entities.ListContainer
)
if all && len(namesOrIds) > 0 {
return nil, errors.New("cannot lookup containers and all")
diff --git a/pkg/ps/ps.go b/pkg/ps/ps.go
new file mode 100644
index 000000000..58fcc2c21
--- /dev/null
+++ b/pkg/ps/ps.go
@@ -0,0 +1,189 @@
+package ps
+
+import (
+ "path/filepath"
+ "sort"
+ "strconv"
+ "time"
+
+ "github.com/containers/libpod/cmd/podman/shared"
+ "github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/libpod/define"
+ lpfilters "github.com/containers/libpod/libpod/filters"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
+)
+
+func GetContainerLists(runtime *libpod.Runtime, options entities.ContainerListOptions) ([]entities.ListContainer, error) {
+ var (
+ filterFuncs []libpod.ContainerFilter
+ pss []entities.ListContainer
+ )
+ all := options.All
+ if len(options.Filters) > 0 {
+ for k, v := range options.Filters {
+ for _, val := range v {
+ generatedFunc, err := lpfilters.GenerateContainerFilterFuncs(k, val, runtime)
+ if err != nil {
+ return nil, err
+ }
+ filterFuncs = append(filterFuncs, generatedFunc)
+ }
+ }
+ }
+
+ // Docker thinks that if status is given as an input, then we should override
+ // the all setting and always deal with all containers.
+ if len(options.Filters["status"]) > 0 {
+ all = true
+ }
+ if !all {
+ runningOnly, err := lpfilters.GenerateContainerFilterFuncs("status", define.ContainerStateRunning.String(), runtime)
+ if err != nil {
+ return nil, err
+ }
+ filterFuncs = append(filterFuncs, runningOnly)
+ }
+
+ cons, err := runtime.GetContainers(filterFuncs...)
+ if err != nil {
+ return nil, err
+ }
+ if options.Last > 0 {
+ // Sort the containers we got
+ sort.Sort(entities.SortCreateTime{SortContainers: cons})
+ // we should perform the lopping before we start getting
+ // the expensive information on containers
+ if options.Last < len(cons) {
+ cons = cons[len(cons)-options.Last:]
+ }
+ }
+ for _, con := range cons {
+ listCon, err := ListContainerBatch(runtime, con, options)
+ if err != nil {
+ return nil, err
+ }
+ pss = append(pss, listCon)
+
+ }
+ return pss, nil
+}
+
+// BatchContainerOp is used in ps to reduce performance hits by "batching"
+// locks.
+func ListContainerBatch(rt *libpod.Runtime, ctr *libpod.Container, opts entities.ContainerListOptions) (entities.ListContainer, error) {
+ var (
+ conConfig *libpod.ContainerConfig
+ conState define.ContainerStatus
+ err error
+ exitCode int32
+ exited bool
+ pid int
+ size *shared.ContainerSize
+ startedTime time.Time
+ exitedTime time.Time
+ cgroup, ipc, mnt, net, pidns, user, uts string
+ )
+
+ batchErr := ctr.Batch(func(c *libpod.Container) error {
+ conConfig = c.Config()
+ conState, err = c.State()
+ if err != nil {
+ return errors.Wrapf(err, "unable to obtain container state")
+ }
+
+ exitCode, exited, err = c.ExitCode()
+ if err != nil {
+ return errors.Wrapf(err, "unable to obtain container exit code")
+ }
+ startedTime, err = c.StartedTime()
+ if err != nil {
+ logrus.Errorf("error getting started time for %q: %v", c.ID(), err)
+ }
+ exitedTime, err = c.FinishedTime()
+ if err != nil {
+ logrus.Errorf("error getting exited time for %q: %v", c.ID(), err)
+ }
+
+ if !opts.Size && !opts.Namespace {
+ return nil
+ }
+
+ if opts.Namespace {
+ pid, err = c.PID()
+ if err != nil {
+ return errors.Wrapf(err, "unable to obtain container pid")
+ }
+ ctrPID := strconv.Itoa(pid)
+ cgroup, _ = shared.GetNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "cgroup"))
+ ipc, _ = shared.GetNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "ipc"))
+ mnt, _ = shared.GetNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "mnt"))
+ net, _ = shared.GetNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "net"))
+ pidns, _ = shared.GetNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "pid"))
+ user, _ = shared.GetNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "user"))
+ uts, _ = shared.GetNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "uts"))
+ }
+ if opts.Size {
+ size = new(shared.ContainerSize)
+
+ rootFsSize, err := c.RootFsSize()
+ if err != nil {
+ logrus.Errorf("error getting root fs size for %q: %v", c.ID(), err)
+ }
+
+ rwSize, err := c.RWSize()
+ if err != nil {
+ logrus.Errorf("error getting rw size for %q: %v", c.ID(), err)
+ }
+
+ size.RootFsSize = rootFsSize
+ size.RwSize = rwSize
+ }
+ return nil
+ })
+
+ if batchErr != nil {
+ return entities.ListContainer{}, batchErr
+ }
+
+ ps := entities.ListContainer{
+ Command: conConfig.Command,
+ Created: conConfig.CreatedTime.Unix(),
+ Exited: exited,
+ ExitCode: exitCode,
+ ExitedAt: exitedTime.Unix(),
+ ID: conConfig.ID,
+ Image: conConfig.RootfsImageName,
+ IsInfra: conConfig.IsInfra,
+ Labels: conConfig.Labels,
+ Mounts: ctr.UserVolumes(),
+ Names: []string{conConfig.Name},
+ Pid: pid,
+ Pod: conConfig.Pod,
+ Ports: conConfig.PortMappings,
+ Size: size,
+ StartedAt: startedTime.Unix(),
+ State: conState.String(),
+ }
+ if opts.Pod && len(conConfig.Pod) > 0 {
+ pod, err := rt.GetPod(conConfig.Pod)
+ if err != nil {
+ return entities.ListContainer{}, err
+ }
+ ps.PodName = pod.Name()
+ }
+
+ if opts.Namespace {
+ ps.Namespaces = entities.ListContainerNamespaces{
+ Cgroup: cgroup,
+ IPC: ipc,
+ MNT: mnt,
+ NET: net,
+ PIDNS: pidns,
+ User: user,
+ UTS: uts,
+ }
+ }
+ return ps, nil
+}
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