From 9833332dba5cba3709c5d78c28d3dbc52e49bfa9 Mon Sep 17 00:00:00 2001 From: Yong Tang Date: Fri, 5 Jan 2018 01:47:53 +0000 Subject: [PATCH 1/2] Fix `before` and `since` filter for `docker ps` This fix tries to address the issue raised in 35931 where `before` and `since` filter for `docker ps` does not work and returns an error ``` Error response from daemon: no such container ``` The issue was that `before` and `since` filter are matched with `view.Get()` which does not take into considerations of name match. This fix fixes the issue by adding additional logic for name match. This fix fixes 35931. Signed-off-by: Yong Tang --- daemon/list.go | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/daemon/list.go b/daemon/list.go index c87dd6ec1e..c41db5ade7 100644 --- a/daemon/list.go +++ b/daemon/list.go @@ -302,7 +302,7 @@ func (daemon *Daemon) foldFilter(view container.View, config *types.ContainerLis var beforeContFilter, sinceContFilter *container.Snapshot err = psFilters.WalkValues("before", func(value string) error { - beforeContFilter, err = view.Get(value) + beforeContFilter, err = idOrNameFilter(view, value) return err }) if err != nil { @@ -310,7 +310,7 @@ func (daemon *Daemon) foldFilter(view container.View, config *types.ContainerLis } err = psFilters.WalkValues("since", func(value string) error { - sinceContFilter, err = view.Get(value) + sinceContFilter, err = idOrNameFilter(view, value) return err }) if err != nil { @@ -364,6 +364,30 @@ func (daemon *Daemon) foldFilter(view container.View, config *types.ContainerLis names: view.GetAllNames(), }, nil } + +func idOrNameFilter(view container.View, value string) (*container.Snapshot, error) { + filter, err := view.Get(value) + switch err.(type) { + case container.NoSuchContainerError: + // Try name search instead + found := "" + for id, idNames := range view.GetAllNames() { + for _, eachName := range idNames { + if strings.TrimPrefix(value, "/") == strings.TrimPrefix(eachName, "/") { + if found != "" && found != id { + return nil, err + } + found = id + } + } + } + if found != "" { + filter, err = view.Get(found) + } + } + return filter, err +} + func portOp(key string, filter map[nat.Port]bool) func(value string) error { return func(value string) error { if strings.Contains(value, ":") { From 52b44b98161872f704f7e3eea16e0f3177ca4e42 Mon Sep 17 00:00:00 2001 From: Yong Tang Date: Fri, 5 Jan 2018 01:50:58 +0000 Subject: [PATCH 2/2] Add test case for `before` and `since` filter for `docker ps` This fix adds an integration test for `before` and `since` filter for `docker ps` Signed-off-by: Yong Tang --- integration/container/ps_test.go | 64 ++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 integration/container/ps_test.go diff --git a/integration/container/ps_test.go b/integration/container/ps_test.go new file mode 100644 index 0000000000..b7eaa72f44 --- /dev/null +++ b/integration/container/ps_test.go @@ -0,0 +1,64 @@ +package container + +import ( + "context" + "testing" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" + "github.com/docker/docker/api/types/filters" + "github.com/docker/docker/api/types/network" + "github.com/docker/docker/integration/util/request" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestPsFilter(t *testing.T) { + defer setupTest(t)() + client := request.NewAPIClient(t) + ctx := context.Background() + + createContainerForFilter := func(ctx context.Context, name string) string { + body, err := client.ContainerCreate(ctx, + &container.Config{ + Cmd: []string{"top"}, + Image: "busybox", + }, + &container.HostConfig{}, + &network.NetworkingConfig{}, + name, + ) + require.NoError(t, err) + return body.ID + } + + prev := createContainerForFilter(ctx, "prev") + createContainerForFilter(ctx, "top") + next := createContainerForFilter(ctx, "next") + + containerIDs := func(containers []types.Container) []string { + entries := []string{} + for _, container := range containers { + entries = append(entries, container.ID) + } + return entries + } + + f1 := filters.NewArgs() + f1.Add("since", "top") + q1, err := client.ContainerList(ctx, types.ContainerListOptions{ + All: true, + Filters: f1, + }) + require.NoError(t, err) + assert.Contains(t, containerIDs(q1), next) + + f2 := filters.NewArgs() + f2.Add("before", "top") + q2, err := client.ContainerList(ctx, types.ContainerListOptions{ + All: true, + Filters: f2, + }) + require.NoError(t, err) + assert.Contains(t, containerIDs(q2), prev) +}