Browse code

Merge pull request #35938 from yongtang/35931-filter-before-since

Fix `before` and `since` filter for `docker ps`

Yong Tang authored on 2018/01/25 05:06:19
Showing 2 changed files
... ...
@@ -303,7 +303,7 @@ func (daemon *Daemon) foldFilter(view container.View, config *types.ContainerLis
303 303
 	var beforeContFilter, sinceContFilter *container.Snapshot
304 304
 
305 305
 	err = psFilters.WalkValues("before", func(value string) error {
306
-		beforeContFilter, err = view.Get(value)
306
+		beforeContFilter, err = idOrNameFilter(view, value)
307 307
 		return err
308 308
 	})
309 309
 	if err != nil {
... ...
@@ -311,7 +311,7 @@ func (daemon *Daemon) foldFilter(view container.View, config *types.ContainerLis
311 311
 	}
312 312
 
313 313
 	err = psFilters.WalkValues("since", func(value string) error {
314
-		sinceContFilter, err = view.Get(value)
314
+		sinceContFilter, err = idOrNameFilter(view, value)
315 315
 		return err
316 316
 	})
317 317
 	if err != nil {
... ...
@@ -365,6 +365,30 @@ func (daemon *Daemon) foldFilter(view container.View, config *types.ContainerLis
365 365
 		names:                view.GetAllNames(),
366 366
 	}, nil
367 367
 }
368
+
369
+func idOrNameFilter(view container.View, value string) (*container.Snapshot, error) {
370
+	filter, err := view.Get(value)
371
+	switch err.(type) {
372
+	case container.NoSuchContainerError:
373
+		// Try name search instead
374
+		found := ""
375
+		for id, idNames := range view.GetAllNames() {
376
+			for _, eachName := range idNames {
377
+				if strings.TrimPrefix(value, "/") == strings.TrimPrefix(eachName, "/") {
378
+					if found != "" && found != id {
379
+						return nil, err
380
+					}
381
+					found = id
382
+				}
383
+			}
384
+		}
385
+		if found != "" {
386
+			filter, err = view.Get(found)
387
+		}
388
+	}
389
+	return filter, err
390
+}
391
+
368 392
 func portOp(key string, filter map[nat.Port]bool) func(value string) error {
369 393
 	return func(value string) error {
370 394
 		if strings.Contains(value, ":") {
371 395
new file mode 100644
... ...
@@ -0,0 +1,64 @@
0
+package container
1
+
2
+import (
3
+	"context"
4
+	"testing"
5
+
6
+	"github.com/docker/docker/api/types"
7
+	"github.com/docker/docker/api/types/container"
8
+	"github.com/docker/docker/api/types/filters"
9
+	"github.com/docker/docker/api/types/network"
10
+	"github.com/docker/docker/integration/util/request"
11
+	"github.com/stretchr/testify/assert"
12
+	"github.com/stretchr/testify/require"
13
+)
14
+
15
+func TestPsFilter(t *testing.T) {
16
+	defer setupTest(t)()
17
+	client := request.NewAPIClient(t)
18
+	ctx := context.Background()
19
+
20
+	createContainerForFilter := func(ctx context.Context, name string) string {
21
+		body, err := client.ContainerCreate(ctx,
22
+			&container.Config{
23
+				Cmd:   []string{"top"},
24
+				Image: "busybox",
25
+			},
26
+			&container.HostConfig{},
27
+			&network.NetworkingConfig{},
28
+			name,
29
+		)
30
+		require.NoError(t, err)
31
+		return body.ID
32
+	}
33
+
34
+	prev := createContainerForFilter(ctx, "prev")
35
+	createContainerForFilter(ctx, "top")
36
+	next := createContainerForFilter(ctx, "next")
37
+
38
+	containerIDs := func(containers []types.Container) []string {
39
+		entries := []string{}
40
+		for _, container := range containers {
41
+			entries = append(entries, container.ID)
42
+		}
43
+		return entries
44
+	}
45
+
46
+	f1 := filters.NewArgs()
47
+	f1.Add("since", "top")
48
+	q1, err := client.ContainerList(ctx, types.ContainerListOptions{
49
+		All:     true,
50
+		Filters: f1,
51
+	})
52
+	require.NoError(t, err)
53
+	assert.Contains(t, containerIDs(q1), next)
54
+
55
+	f2 := filters.NewArgs()
56
+	f2.Add("before", "top")
57
+	q2, err := client.ContainerList(ctx, types.ContainerListOptions{
58
+		All:     true,
59
+		Filters: f2,
60
+	})
61
+	require.NoError(t, err)
62
+	assert.Contains(t, containerIDs(q2), prev)
63
+}