From b22254dc8bfdea5153761e93298182286f874bac Mon Sep 17 00:00:00 2001 From: Brent Baude Date: Sat, 4 Apr 2020 13:59:55 -0500 Subject: podmanv2 ps add the ability to list containers Signed-off-by: Brent Baude --- pkg/api/handlers/libpod/containers.go | 185 ++-------------------------------- pkg/api/handlers/libpod/swagger.go | 2 +- pkg/api/handlers/libpod/types.go | 82 --------------- 3 files changed, 8 insertions(+), 261 deletions(-) delete mode 100644 pkg/api/handlers/libpod/types.go (limited to 'pkg/api/handlers/libpod') 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/swagger.go b/pkg/api/handlers/libpod/swagger.go index 1fad2dd1a..08309b0f7 100644 --- a/pkg/api/handlers/libpod/swagger.go +++ b/pkg/api/handlers/libpod/swagger.go @@ -17,7 +17,7 @@ const DefaultPodmanSwaggerSpec = "/usr/share/containers/podman/swagger.yaml" // swagger:response ListContainers type swagInspectPodResponse struct { // in:body - Body []ListContainer + Body []entities.ListContainer } // Inspect Manifest 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()) -} -- cgit v1.2.3-54-g00ecf