From 68b3c3dd7ce6abece00a59b4c28ce6fd61487721 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Tue, 28 Aug 2018 21:40:13 +0200 Subject: [PATCH] Fix regression when filtering container names using a leading slash Commit 5c8da2e96738addd8a175e5b9a23b8c37d4a4dfe updated the filtering behavior to match container-names without having to specify the leading slash. This change caused a regression in situations where a regex was provided as filter, using an explicit leading slash (`--filter name=^/mycontainername`). This fix changes the filters to match containers both with, and without the leading slash, effectively making the leading slash optional when filtering. With this fix, filters with and without a leading slash produce the same result: $ docker ps --filter name=^a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 21afd6362b0c busybox "sh" 2 minutes ago Up 2 minutes a2 56e53770e316 busybox "sh" 2 minutes ago Up 2 minutes a1 $ docker ps --filter name=^/a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 21afd6362b0c busybox "sh" 2 minutes ago Up 2 minutes a2 56e53770e316 busybox "sh" 3 minutes ago Up 3 minutes a1 $ docker ps --filter name=^b CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b69003b6a6fe busybox "sh" About a minute ago Up About a minute b1 $ docker ps --filter name=^/b CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b69003b6a6fe busybox "sh" 56 seconds ago Up 54 seconds b1 $ docker ps --filter name=/a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 21afd6362b0c busybox "sh" 3 minutes ago Up 3 minutes a2 56e53770e316 busybox "sh" 4 minutes ago Up 4 minutes a1 $ docker ps --filter name=a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 21afd6362b0c busybox "sh" 3 minutes ago Up 3 minutes a2 56e53770e316 busybox "sh" 4 minutes ago Up 4 minutes a1 Signed-off-by: Sebastiaan van Stijn (cherry picked from commit 6f9b5ba810e9314ab9335490cd41316940a32b5e) Signed-off-by: Sebastiaan van Stijn Upstream-commit: 5fa80da2d385520f2c3c91e8ce23d181e4f93097 Component: engine --- components/engine/daemon/list.go | 5 +++-- components/engine/daemon/list_test.go | 28 +++++++++++++++++++++++---- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/components/engine/daemon/list.go b/components/engine/daemon/list.go index 563bc076be5..0a0cf221fe9 100644 --- a/components/engine/daemon/list.go +++ b/components/engine/daemon/list.go @@ -146,7 +146,8 @@ func (daemon *Daemon) filterByNameIDMatches(view container.View, ctx *listContex continue } for _, eachName := range idNames { - if ctx.filters.Match("name", strings.TrimPrefix(eachName, "/")) { + // match both on container name with, and without slash-prefix + if ctx.filters.Match("name", eachName) || ctx.filters.Match("name", strings.TrimPrefix(eachName, "/")) { matches[id] = true } } @@ -429,7 +430,7 @@ func includeContainerInList(container *container.Snapshot, ctx *listContext) ite } // Do not include container if the name doesn't match - if !ctx.filters.Match("name", strings.TrimPrefix(container.Name, "/")) { + if !ctx.filters.Match("name", container.Name) && !ctx.filters.Match("name", strings.TrimPrefix(container.Name, "/")) { return excludeContainer } diff --git a/components/engine/daemon/list_test.go b/components/engine/daemon/list_test.go index 34eef43ded4..2fdb266c4ab 100644 --- a/components/engine/daemon/list_test.go +++ b/components/engine/daemon/list_test.go @@ -4,7 +4,6 @@ import ( "io/ioutil" "os" "path/filepath" - "strings" "testing" "github.com/docker/docker/api/types" @@ -35,6 +34,7 @@ func TestMain(m *testing.M) { // work against it. It takes in a pointer to Daemon so that // minor operations are not repeated by the caller func setupContainerWithName(t *testing.T, name string, daemon *Daemon) *container.Container { + t.Helper() var ( id = uuid.New() computedImageID = digest.FromString(id) @@ -46,6 +46,9 @@ func setupContainerWithName(t *testing.T, name string, daemon *Daemon) *containe c := container.NewBaseContainer(id, cRoot) // these are for passing includeContainerInList + if name[0] != '/' { + name = "/" + name + } c.Name = name c.Running = true c.HostConfig = &containertypes.HostConfig{} @@ -68,7 +71,7 @@ func setupContainerWithName(t *testing.T, name string, daemon *Daemon) *containe func containerListContainsName(containers []*types.Container, name string) bool { for _, container := range containers { for _, containerName := range container.Names { - if strings.TrimPrefix(containerName, "/") == name { + if containerName == name { return true } } @@ -110,16 +113,33 @@ func TestNameFilter(t *testing.T) { containerList, err := d.Containers(&types.ContainerListOptions{ Filters: filters.NewArgs(filters.Arg("name", "^a")), }) - assert.Assert(t, err == nil) + assert.NilError(t, err) assert.Assert(t, is.Len(containerList, 2)) assert.Assert(t, containerListContainsName(containerList, one.Name)) assert.Assert(t, containerListContainsName(containerList, two.Name)) + // Same as above but with slash prefix should produce the same result + containerListWithPrefix, err := d.Containers(&types.ContainerListOptions{ + Filters: filters.NewArgs(filters.Arg("name", "^/a")), + }) + assert.NilError(t, err) + assert.Assert(t, is.Len(containerListWithPrefix, 2)) + assert.Assert(t, containerListContainsName(containerListWithPrefix, one.Name)) + assert.Assert(t, containerListContainsName(containerListWithPrefix, two.Name)) + // Same as above but make sure it works for exact names containerList, err = d.Containers(&types.ContainerListOptions{ Filters: filters.NewArgs(filters.Arg("name", "b1")), }) - assert.Assert(t, err == nil) + assert.NilError(t, err) assert.Assert(t, is.Len(containerList, 1)) assert.Assert(t, containerListContainsName(containerList, three.Name)) + + // Same as above but with slash prefix should produce the same result + containerListWithPrefix, err = d.Containers(&types.ContainerListOptions{ + Filters: filters.NewArgs(filters.Arg("name", "/b1")), + }) + assert.NilError(t, err) + assert.Assert(t, is.Len(containerListWithPrefix, 1)) + assert.Assert(t, containerListContainsName(containerListWithPrefix, three.Name)) }