Files
Qi Wang c244c347b1 podman-remote make --size optional in ps
Close #3578 Add `size` field to PsOpts in podman remote to receive size as an option.

Signed-off-by: Qi Wang <qiwan@redhat.com>
2019-07-18 09:34:19 -04:00

239 lines
6.4 KiB
Go

// +build varlink
package varlinkapi
import (
"context"
"strconv"
"strings"
"time"
"github.com/containers/buildah"
"github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/cmd/podman/varlink"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/pkg/channelwriter"
"github.com/containers/storage/pkg/archive"
)
// getContext returns a non-nil, empty context
func getContext() context.Context {
return context.TODO()
}
func makeListContainer(containerID string, batchInfo shared.BatchContainerStruct) iopodman.Container {
var (
mounts []iopodman.ContainerMount
ports []iopodman.ContainerPortMappings
)
ns := shared.GetNamespaces(batchInfo.Pid)
for _, mount := range batchInfo.ConConfig.Spec.Mounts {
m := iopodman.ContainerMount{
Destination: mount.Destination,
Type: mount.Type,
Source: mount.Source,
Options: mount.Options,
}
mounts = append(mounts, m)
}
for _, pm := range batchInfo.ConConfig.PortMappings {
p := iopodman.ContainerPortMappings{
Host_port: strconv.Itoa(int(pm.HostPort)),
Host_ip: pm.HostIP,
Protocol: pm.Protocol,
Container_port: strconv.Itoa(int(pm.ContainerPort)),
}
ports = append(ports, p)
}
// If we find this needs to be done for other container endpoints, we should
// convert this to a separate function or a generic map from struct function.
namespace := iopodman.ContainerNameSpace{
User: ns.User,
Uts: ns.UTS,
Pidns: ns.PIDNS,
Pid: ns.PID,
Cgroup: ns.Cgroup,
Net: ns.NET,
Mnt: ns.MNT,
Ipc: ns.IPC,
}
lc := iopodman.Container{
Id: containerID,
Image: batchInfo.ConConfig.RootfsImageName,
Imageid: batchInfo.ConConfig.RootfsImageID,
Command: batchInfo.ConConfig.Spec.Process.Args,
Createdat: batchInfo.ConConfig.CreatedTime.Format(time.RFC3339),
Runningfor: time.Since(batchInfo.ConConfig.CreatedTime).String(),
Status: batchInfo.ConState.String(),
Ports: ports,
Names: batchInfo.ConConfig.Name,
Labels: batchInfo.ConConfig.Labels,
Mounts: mounts,
Containerrunning: batchInfo.ConState == define.ContainerStateRunning,
Namespaces: namespace,
}
if batchInfo.Size != nil {
lc.Rootfssize = batchInfo.Size.RootFsSize
lc.Rwsize = batchInfo.Size.RwSize
}
return lc
}
func makeListPodContainers(containerID string, batchInfo shared.BatchContainerStruct) iopodman.ListPodContainerInfo {
lc := iopodman.ListPodContainerInfo{
Id: containerID,
Status: batchInfo.ConState.String(),
Name: batchInfo.ConConfig.Name,
}
return lc
}
func makeListPod(pod *libpod.Pod, batchInfo shared.PsOptions) (iopodman.ListPodData, error) {
var listPodsContainers []iopodman.ListPodContainerInfo
var errPodData = iopodman.ListPodData{}
status, err := shared.GetPodStatus(pod)
if err != nil {
return errPodData, err
}
containers, err := pod.AllContainers()
if err != nil {
return errPodData, err
}
for _, ctr := range containers {
batchInfo, err := shared.BatchContainerOp(ctr, batchInfo)
if err != nil {
return errPodData, err
}
listPodsContainers = append(listPodsContainers, makeListPodContainers(ctr.ID(), batchInfo))
}
listPod := iopodman.ListPodData{
Createdat: pod.CreatedTime().Format(time.RFC3339),
Id: pod.ID(),
Name: pod.Name(),
Status: status,
Cgroup: pod.CgroupParent(),
Numberofcontainers: strconv.Itoa(len(listPodsContainers)),
Containersinfo: listPodsContainers,
}
return listPod, nil
}
func handlePodCall(call iopodman.VarlinkCall, pod *libpod.Pod, ctrErrs map[string]error, err error) error {
if err != nil && ctrErrs == nil {
return call.ReplyErrorOccurred(err.Error())
}
if ctrErrs != nil {
containerErrs := make([]iopodman.PodContainerErrorData, len(ctrErrs))
for ctr, reason := range ctrErrs {
ctrErr := iopodman.PodContainerErrorData{Containerid: ctr, Reason: reason.Error()}
containerErrs = append(containerErrs, ctrErr)
}
return call.ReplyPodContainerError(pod.ID(), containerErrs)
}
return nil
}
func stringCompressionToArchiveType(s string) archive.Compression {
switch strings.ToUpper(s) {
case "BZIP2":
return archive.Bzip2
case "GZIP":
return archive.Gzip
case "XZ":
return archive.Xz
}
return archive.Uncompressed
}
func stringPullPolicyToType(s string) buildah.PullPolicy {
switch strings.ToUpper(s) {
case "PULLIFMISSING":
return buildah.PullIfMissing
case "PULLALWAYS":
return buildah.PullAlways
case "PULLNEVER":
return buildah.PullNever
}
return buildah.PullIfMissing
}
func derefBool(inBool *bool) bool {
if inBool == nil {
return false
}
return *inBool
}
func derefString(in *string) string {
if in == nil {
return ""
}
return *in
}
func makePsOpts(inOpts iopodman.PsOpts) shared.PsOptions {
last := 0
if inOpts.Last != nil {
lastT := *inOpts.Last
last = int(lastT)
}
return shared.PsOptions{
All: inOpts.All,
Last: last,
Latest: derefBool(inOpts.Latest),
NoTrunc: derefBool(inOpts.NoTrunc),
Pod: derefBool(inOpts.Pod),
Size: derefBool(inOpts.Size),
Sort: derefString(inOpts.Sort),
Namespace: true,
Sync: derefBool(inOpts.Sync),
}
}
// forwardOutput is a helper method for varlink endpoints that employ both more and without
// more. it is capable of sending updates as the output writer gets them or append them
// all to a log. the chan error is the error from the libpod call so we can honor
// and error event in that case.
func forwardOutput(log []string, c chan error, wantsMore bool, output *channelwriter.Writer, reply func(br iopodman.MoreResponse) error) ([]string, error) {
done := false
for {
select {
// We need to check if the libpod func being called has returned an
// error yet
case err := <-c:
if err != nil {
return nil, err
}
done = true
// if no error is found, we pull what we can from the log writer and
// append it to log string slice
case line := <-output.ByteChannel:
log = append(log, string(line))
// If the end point is being used in more mode, send what we have
if wantsMore {
br := iopodman.MoreResponse{
Logs: log,
}
if err := reply(br); err != nil {
return nil, err
}
// "reset" the log to empty because we are sending what we
// get as we get it
log = []string{}
}
}
if done {
break
}
}
return log, nil
}