aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pkg/api/handlers/compat/containers.go49
-rw-r--r--test/apiv2/20-containers.at9
2 files changed, 46 insertions, 12 deletions
diff --git a/pkg/api/handlers/compat/containers.go b/pkg/api/handlers/compat/containers.go
index 7a3e5dd84..0f89c859e 100644
--- a/pkg/api/handlers/compat/containers.go
+++ b/pkg/api/handlers/compat/containers.go
@@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
"net/http"
+ "sort"
"strconv"
"strings"
"syscall"
@@ -13,6 +14,8 @@ import (
"github.com/containers/podman/v2/libpod/define"
"github.com/containers/podman/v2/pkg/api/handlers"
"github.com/containers/podman/v2/pkg/api/handlers/utils"
+ "github.com/containers/podman/v2/pkg/domain/filters"
+ "github.com/containers/podman/v2/pkg/ps"
"github.com/containers/podman/v2/pkg/signal"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
@@ -78,10 +81,6 @@ func RemoveContainer(w http.ResponseWriter, r *http.Request) {
}
func ListContainers(w http.ResponseWriter, r *http.Request) {
- var (
- containers []*libpod.Container
- err error
- )
runtime := r.Context().Value("runtime").(*libpod.Runtime)
decoder := r.Context().Value("decoder").(*schema.Decoder)
query := struct {
@@ -97,22 +96,48 @@ func ListContainers(w http.ResponseWriter, r *http.Request) {
utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
- if query.All {
- containers, err = runtime.GetAllContainers()
- } else {
- containers, err = runtime.GetRunningContainers()
+
+ filterFuncs := make([]libpod.ContainerFilter, 0, len(query.Filters))
+ all := query.All || query.Limit > 0
+ if len(query.Filters) > 0 {
+ for k, v := range query.Filters {
+ generatedFunc, err := filters.GenerateContainerFilterFuncs(k, v, 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 := filters.GenerateContainerFilterFuncs("status", []string{define.ContainerStateRunning.String()}, runtime)
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+ filterFuncs = append(filterFuncs, runningOnly)
+ }
+
+ containers, err := runtime.GetContainers(filterFuncs...)
if err != nil {
utils.InternalServerError(w, err)
return
}
if _, found := r.URL.Query()["limit"]; found && query.Limit > 0 {
- last := query.Limit
- if len(containers) > last {
- containers = containers[len(containers)-last:]
+ // Sort the libpod containers
+ sort.Sort(ps.SortCreateTime{SortContainers: containers})
+ // we should perform the lopping before we start getting
+ // the expensive information on containers
+ if len(containers) > query.Limit {
+ containers = containers[:query.Limit]
}
}
- // TODO filters still need to be applied
var list = make([]*handlers.Container, len(containers))
for i, ctnr := range containers {
api, err := LibpodToContainer(ctnr, query.Size)
diff --git a/test/apiv2/20-containers.at b/test/apiv2/20-containers.at
index bc6efc20d..decdc4754 100644
--- a/test/apiv2/20-containers.at
+++ b/test/apiv2/20-containers.at
@@ -203,6 +203,15 @@ t GET 'containers/json?limit=0&all=1' 200 \
.[0].Id~[0-9a-f]\\{64\\} \
.[1].Id~[0-9a-f]\\{64\\}
+t GET containers/json?limit=2 200 length=2
+
+# Filter with two ids should return both container
+t GET "containers/json?filters=%7B%22id%22%3A%5B%22${cid}%22%2C%22${cid_top}%22%5D%7D&all=1" 200 length=2
+# Filter with two ids and status running should return only 1 container
+t GET "containers/json?filters=%7B%22id%22%3A%5B%22${cid}%22%2C%22${cid_top}%22%5D%2C%22status%22%3A%5B%22running%22%5D%7D&all=1" 200 \
+ length=1 \
+ .[0].Id=${cid_top}
+
t POST containers/${cid_top}/stop "" 204
t DELETE containers/$cid 204