Remove slash prefix when matching name filters (Fixes #37453)

* Regex name filters were display undesired behavior due to
  names containing the trailing slash when being compared
* Adjusted filterByNameIDMatches and includeContainerInList to
  strip the slash prefix before doing name comparisons
* Added test case and helper functions for the test to list_test
* Force failed tests during development to ensure there were
  no false positives

Signed-off-by: Chris White <me@cwprogram.com>
This commit is contained in:
Chris White 2018-07-15 05:34:18 -05:00
parent 17dc10123f
commit 5c8da2e967
2 changed files with 101 additions and 2 deletions

View File

@ -146,7 +146,7 @@ func (daemon *Daemon) filterByNameIDMatches(view container.View, ctx *listContex
continue
}
for _, eachName := range idNames {
if ctx.filters.Match("name", eachName) {
if ctx.filters.Match("name", strings.TrimPrefix(eachName, "/")) {
matches[id] = true
}
}
@ -429,7 +429,7 @@ func includeContainerInList(container *container.Snapshot, ctx *listContext) ite
}
// Do not include container if the name doesn't match
if !ctx.filters.Match("name", container.Name) {
if !ctx.filters.Match("name", strings.TrimPrefix(container.Name, "/")) {
return excludeContainer
}

View File

@ -1,15 +1,82 @@
package daemon
import (
"io/ioutil"
"os"
"path/filepath"
"strings"
"testing"
"github.com/docker/docker/api/types"
containertypes "github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/container"
"github.com/docker/docker/image"
"github.com/opencontainers/go-digest"
"github.com/pborman/uuid"
"gotest.tools/assert"
is "gotest.tools/assert/cmp"
)
var root string
func TestMain(m *testing.M) {
var err error
root, err = ioutil.TempDir("", "docker-container-test-")
if err != nil {
panic(err)
}
defer os.RemoveAll(root)
os.Exit(m.Run())
}
// This sets up a container with a name so that name filters
// 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 {
var (
id = uuid.New()
computedImageID = digest.FromString(id)
cRoot = filepath.Join(root, id)
)
if err := os.MkdirAll(cRoot, 0755); err != nil {
t.Fatal(err)
}
c := container.NewBaseContainer(id, cRoot)
// these are for passing includeContainerInList
c.Name = name
c.Running = true
c.HostConfig = &containertypes.HostConfig{}
// these are for passing the refreshImage reducer
c.ImageID = image.IDFromDigest(computedImageID)
c.Config = &containertypes.Config{
Image: computedImageID.String(),
}
// this is done here to avoid requiring these
// operations n x number of containers in the
// calling function
daemon.containersReplica.Save(c)
daemon.reserveName(id, name)
return c
}
func containerListContainsName(containers []*types.Container, name string) bool {
for _, container := range containers {
for _, containerName := range container.Names {
if strings.TrimPrefix(containerName, "/") == name {
return true
}
}
}
return false
}
func TestListInvalidFilter(t *testing.T) {
db, err := container.NewViewDB()
assert.Assert(t, err == nil)
@ -24,3 +91,35 @@ func TestListInvalidFilter(t *testing.T) {
})
assert.Assert(t, is.Error(err, "Invalid filter 'invalid'"))
}
func TestNameFilter(t *testing.T) {
db, err := container.NewViewDB()
assert.Assert(t, err == nil)
d := &Daemon{
containersReplica: db,
}
var (
one = setupContainerWithName(t, "a1", d)
two = setupContainerWithName(t, "a2", d)
three = setupContainerWithName(t, "b1", d)
)
// moby/moby #37453 - ^ regex not working due to prefix slash
// not being stripped
containerList, err := d.Containers(&types.ContainerListOptions{
Filters: filters.NewArgs(filters.Arg("name", "^a")),
})
assert.Assert(t, err == nil)
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 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.Assert(t, is.Len(containerList, 1))
assert.Assert(t, containerListContainsName(containerList, three.Name))
}