summaryrefslogtreecommitdiff
path: root/pkg/adapter
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/adapter')
-rw-r--r--pkg/adapter/containers.go48
-rw-r--r--pkg/adapter/containers_remote.go51
-rw-r--r--pkg/adapter/pods.go60
-rw-r--r--pkg/adapter/pods_remote.go108
-rw-r--r--pkg/adapter/runtime.go5
-rw-r--r--pkg/adapter/runtime_remote.go5
6 files changed, 277 insertions, 0 deletions
diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go
index 7514f30d2..756369196 100644
--- a/pkg/adapter/containers.go
+++ b/pkg/adapter/containers.go
@@ -4,6 +4,9 @@ package adapter
import (
"context"
+ "strconv"
+ "syscall"
+ "time"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/libpod"
@@ -79,3 +82,48 @@ func (r *LocalRuntime) StopContainers(ctx context.Context, cli *cliconfig.StopVa
}
return ok, failures, nil
}
+
+// KillContainers sends signal to container(s) based on CLI inputs.
+// Returns list of successful id(s), map of failed id(s) + error, or error not from container
+func (r *LocalRuntime) KillContainers(ctx context.Context, cli *cliconfig.KillValues, signal syscall.Signal) ([]string, map[string]error, error) {
+ var (
+ ok = []string{}
+ failures = map[string]error{}
+ )
+
+ ctrs, err := shortcuts.GetContainersByContext(cli.All, cli.Latest, cli.InputArgs, r.Runtime)
+ if err != nil {
+ return ok, failures, err
+ }
+
+ for _, c := range ctrs {
+ if err := c.Kill(uint(signal)); err == nil {
+ ok = append(ok, c.ID())
+ } else {
+ failures[c.ID()] = err
+ }
+ }
+ return ok, failures, nil
+}
+
+// WaitOnContainers waits for all given container(s) to stop
+func (r *LocalRuntime) WaitOnContainers(ctx context.Context, cli *cliconfig.WaitValues, interval time.Duration) ([]string, map[string]error, error) {
+ var (
+ ok = []string{}
+ failures = map[string]error{}
+ )
+
+ ctrs, err := shortcuts.GetContainersByContext(false, cli.Latest, cli.InputArgs, r.Runtime)
+ if err != nil {
+ return ok, failures, err
+ }
+
+ for _, c := range ctrs {
+ if returnCode, err := c.WaitWithInterval(interval); err == nil {
+ ok = append(ok, strconv.Itoa(int(returnCode)))
+ } else {
+ failures[c.ID()] = err
+ }
+ }
+ return ok, failures, err
+}
diff --git a/pkg/adapter/containers_remote.go b/pkg/adapter/containers_remote.go
index df40c8efd..5646d2297 100644
--- a/pkg/adapter/containers_remote.go
+++ b/pkg/adapter/containers_remote.go
@@ -6,6 +6,9 @@ import (
"context"
"encoding/json"
"errors"
+ "strconv"
+ "syscall"
+ "time"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/shared"
@@ -148,6 +151,54 @@ func (r *LocalRuntime) StopContainers(ctx context.Context, cli *cliconfig.StopVa
return ok, failures, nil
}
+// KillContainers sends signal to container(s) based on CLI inputs.
+// Returns list of successful id(s), map of failed id(s) + error, or error not from container
+func (r *LocalRuntime) KillContainers(ctx context.Context, cli *cliconfig.KillValues, signal syscall.Signal) ([]string, map[string]error, error) {
+ var (
+ ok = []string{}
+ failures = map[string]error{}
+ )
+
+ ids, err := iopodman.GetContainersByContext().Call(r.Conn, cli.All, cli.Latest, cli.InputArgs)
+ if err != nil {
+ return ok, failures, err
+ }
+
+ for _, id := range ids {
+ killed, err := iopodman.KillContainer().Call(r.Conn, id, int64(signal))
+ if err != nil {
+ failures[id] = err
+ } else {
+ ok = append(ok, killed)
+ }
+ }
+ return ok, failures, nil
+}
+
+// WaitOnContainers waits for all given container(s) to stop.
+// interval is currently ignored.
+func (r *LocalRuntime) WaitOnContainers(ctx context.Context, cli *cliconfig.WaitValues, interval time.Duration) ([]string, map[string]error, error) {
+ var (
+ ok = []string{}
+ failures = map[string]error{}
+ )
+
+ ids, err := iopodman.GetContainersByContext().Call(r.Conn, false, cli.Latest, cli.InputArgs)
+ if err != nil {
+ return ok, failures, err
+ }
+
+ for _, id := range ids {
+ stopped, err := iopodman.WaitContainer().Call(r.Conn, id, int64(interval))
+ if err != nil {
+ failures[id] = err
+ } else {
+ ok = append(ok, strconv.FormatInt(stopped, 10))
+ }
+ }
+ return ok, failures, nil
+}
+
// BatchContainerOp is wrapper func to mimic shared's function with a similar name meant for libpod
func BatchContainerOp(ctr *Container, opts shared.PsOptions) (shared.BatchContainerStruct, error) {
// TODO If pod ps ever shows container's sizes, re-enable this code; otherwise it isn't needed
diff --git a/pkg/adapter/pods.go b/pkg/adapter/pods.go
index 706a8fe96..669971789 100644
--- a/pkg/adapter/pods.go
+++ b/pkg/adapter/pods.go
@@ -4,6 +4,7 @@ package adapter
import (
"context"
+ "github.com/pkg/errors"
"strings"
"github.com/containers/libpod/cmd/podman/cliconfig"
@@ -17,6 +18,13 @@ type Pod struct {
*libpod.Pod
}
+// PodContainerStats is struct containing an adapter Pod and a libpod
+// ContainerStats and is used primarily for outputing pod stats.
+type PodContainerStats struct {
+ Pod *Pod
+ ContainerStats map[string]*libpod.ContainerStats
+}
+
// RemovePods ...
func (r *LocalRuntime) RemovePods(ctx context.Context, cli *cliconfig.PodRmValues) ([]string, []error) {
var (
@@ -321,3 +329,55 @@ func (r *LocalRuntime) RestartPods(ctx context.Context, c *cliconfig.PodRestartV
return restartIDs, containerErrors, restartErrors
}
+
+// PodTop is a wrapper function to call GetPodPidInformation in libpod and return its results
+// for output
+func (r *LocalRuntime) PodTop(c *cliconfig.PodTopValues, descriptors []string) ([]string, error) {
+ var (
+ pod *Pod
+ err error
+ )
+
+ if c.Latest {
+ pod, err = r.GetLatestPod()
+ } else {
+ pod, err = r.LookupPod(c.InputArgs[0])
+ }
+ if err != nil {
+ return nil, errors.Wrapf(err, "unable to lookup requested container")
+ }
+ podStatus, err := pod.GetPodStatus()
+ if err != nil {
+ return nil, errors.Wrapf(err, "unable to get status for pod %s", pod.ID())
+ }
+ if podStatus != "Running" {
+ return nil, errors.Errorf("pod top can only be used on pods with at least one running container")
+ }
+ return pod.GetPodPidInformation(descriptors)
+}
+
+// GetStatPods returns pods for use in pod stats
+func (r *LocalRuntime) GetStatPods(c *cliconfig.PodStatsValues) ([]*Pod, error) {
+ var (
+ adapterPods []*Pod
+ pods []*libpod.Pod
+ err error
+ )
+
+ if len(c.InputArgs) > 0 || c.Latest || c.All {
+ pods, err = shortcuts.GetPodsByContext(c.All, c.Latest, c.InputArgs, r.Runtime)
+ } else {
+ pods, err = r.Runtime.GetRunningPods()
+ }
+ if err != nil {
+ return nil, err
+ }
+ // convert libpod pods to adapter pods
+ for _, p := range pods {
+ adapterPod := Pod{
+ p,
+ }
+ adapterPods = append(adapterPods, &adapterPod)
+ }
+ return adapterPods, nil
+}
diff --git a/pkg/adapter/pods_remote.go b/pkg/adapter/pods_remote.go
index 220f7163f..ef8de90a6 100644
--- a/pkg/adapter/pods_remote.go
+++ b/pkg/adapter/pods_remote.go
@@ -12,6 +12,7 @@ import (
"github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/cmd/podman/varlink"
"github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/pkg/varlinkapi"
"github.com/pkg/errors"
"github.com/ulule/deepcopier"
)
@@ -21,6 +22,13 @@ type Pod struct {
remotepod
}
+// PodContainerStats is struct containing an adapter Pod and a libpod
+// ContainerStats and is used primarily for outputing pod stats.
+type PodContainerStats struct {
+ Pod *Pod
+ ContainerStats map[string]*libpod.ContainerStats
+}
+
type remotepod struct {
config *libpod.PodConfig
state *libpod.PodInspectState
@@ -399,3 +407,103 @@ func (r *LocalRuntime) RestartPods(ctx context.Context, c *cliconfig.PodRestartV
}
return restartIDs, nil, restartErrors
}
+
+// PodTop gets top statistics for a pod
+func (r *LocalRuntime) PodTop(c *cliconfig.PodTopValues, descriptors []string) ([]string, error) {
+ var (
+ latest bool
+ podName string
+ )
+ if c.Latest {
+ latest = true
+ } else {
+ podName = c.InputArgs[0]
+ }
+ return iopodman.TopPod().Call(r.Conn, podName, latest, descriptors)
+}
+
+// GetStatPods returns pods for use in pod stats
+func (r *LocalRuntime) GetStatPods(c *cliconfig.PodStatsValues) ([]*Pod, error) {
+ var (
+ pods []*Pod
+ err error
+ podIDs []string
+ running bool
+ )
+
+ if len(c.InputArgs) > 0 || c.Latest || c.All {
+ podIDs, err = iopodman.GetPodsByContext().Call(r.Conn, c.All, c.Latest, c.InputArgs)
+ } else {
+ podIDs, err = iopodman.GetPodsByContext().Call(r.Conn, true, false, []string{})
+ running = true
+ }
+ if err != nil {
+ return nil, err
+ }
+ for _, p := range podIDs {
+ pod, err := r.Inspect(p)
+ if err != nil {
+ return nil, err
+ }
+ if running {
+ status, err := pod.GetPodStatus()
+ if err != nil {
+ // if we cannot get the status of the pod, skip and move on
+ continue
+ }
+ if strings.ToUpper(status) != "RUNNING" {
+ // if the pod is not running, skip and move on as well
+ continue
+ }
+ }
+ pods = append(pods, pod)
+ }
+ return pods, nil
+}
+
+// GetPodStats returns the stats for each of its containers
+func (p *Pod) GetPodStats(previousContainerStats map[string]*libpod.ContainerStats) (map[string]*libpod.ContainerStats, error) {
+ var (
+ ok bool
+ prevStat *libpod.ContainerStats
+ )
+ newContainerStats := make(map[string]*libpod.ContainerStats)
+ containers, err := p.AllContainers()
+ if err != nil {
+ return nil, err
+ }
+ for _, c := range containers {
+ if prevStat, ok = previousContainerStats[c.ID()]; !ok {
+ prevStat = &libpod.ContainerStats{ContainerID: c.ID()}
+ }
+ cStats := iopodman.ContainerStats{
+ Id: prevStat.ContainerID,
+ Name: prevStat.Name,
+ Cpu: prevStat.CPU,
+ Cpu_nano: int64(prevStat.CPUNano),
+ System_nano: int64(prevStat.SystemNano),
+ Mem_usage: int64(prevStat.MemUsage),
+ Mem_limit: int64(prevStat.MemLimit),
+ Mem_perc: prevStat.MemPerc,
+ Net_input: int64(prevStat.NetInput),
+ Net_output: int64(prevStat.NetOutput),
+ Block_input: int64(prevStat.BlockInput),
+ Block_output: int64(prevStat.BlockOutput),
+ Pids: int64(prevStat.PIDs),
+ }
+ stats, err := iopodman.GetContainerStatsWithHistory().Call(p.Runtime.Conn, cStats)
+ if err != nil {
+ return nil, err
+ }
+ newStats := varlinkapi.ContainerStatsToLibpodContainerStats(stats)
+ // If the container wasn't running, don't include it
+ // but also suppress the error
+ if err != nil && errors.Cause(err) != libpod.ErrCtrStateInvalid {
+ return nil, err
+ }
+ if err == nil {
+ newContainerStats[c.ID()] = &newStats
+ }
+ }
+ return newContainerStats, nil
+}
diff --git a/pkg/adapter/runtime.go b/pkg/adapter/runtime.go
index 5be2ca150..732b89530 100644
--- a/pkg/adapter/runtime.go
+++ b/pkg/adapter/runtime.go
@@ -332,3 +332,8 @@ func IsImageNotFound(err error) bool {
}
return false
}
+
+// HealthCheck is a wrapper to same named function in libpod
+func (r *LocalRuntime) HealthCheck(c *cliconfig.HealthCheckValues) (libpod.HealthCheckStatus, error) {
+ return r.Runtime.HealthCheck(c.InputArgs[0])
+}
diff --git a/pkg/adapter/runtime_remote.go b/pkg/adapter/runtime_remote.go
index 14cda7bff..10c25c3f3 100644
--- a/pkg/adapter/runtime_remote.go
+++ b/pkg/adapter/runtime_remote.go
@@ -746,3 +746,8 @@ func IsImageNotFound(err error) bool {
}
return false
}
+
+// HealthCheck executes a container's healthcheck over a varlink connection
+func (r *LocalRuntime) HealthCheck(c *cliconfig.HealthCheckValues) (libpod.HealthCheckStatus, error) {
+ return -1, libpod.ErrNotImplemented
+}