Fix incorrect container name gathered in docker input (#4391)

This commit is contained in:
Greg 2018-07-12 19:41:49 -06:00 committed by Daniel Nelson
parent 8ff63a4b79
commit 0da94a1b3c
3 changed files with 107 additions and 127 deletions

View File

@ -365,10 +365,18 @@ func (d *Docker) gatherContainer(
) error { ) error {
var v *types.StatsJSON var v *types.StatsJSON
// Parse container name // Parse container name
cname := "unknown" var cname string
if len(container.Names) > 0 { for _, name := range container.Names {
// Not sure what to do with other names, just take the first. trimmedName := strings.TrimPrefix(name, "/")
cname = strings.TrimPrefix(container.Names[0], "/") match := d.containerFilter.Match(trimmedName)
if match {
cname = trimmedName
break
}
}
if cname == "" {
return nil
} }
// the image name sometimes has a version part, or a private repo // the image name sometimes has a version part, or a private repo
@ -391,10 +399,6 @@ func (d *Docker) gatherContainer(
"container_version": imageVersion, "container_version": imageVersion,
} }
if !d.containerFilter.Match(cname) {
return nil
}
ctx, cancel := context.WithTimeout(context.Background(), d.Timeout.Duration) ctx, cancel := context.WithTimeout(context.Background(), d.Timeout.Duration)
defer cancel() defer cancel()
r, err := d.client.ContainerStats(ctx, container.ID, false) r, err := d.client.ContainerStats(ctx, container.ID, false)
@ -411,6 +415,9 @@ func (d *Docker) gatherContainer(
} }
daemonOSType := r.OSType daemonOSType := r.OSType
// use common (printed at `docker ps`) name for container
tags["container_name"] = strings.TrimPrefix(v.Name, "/")
// Add labels to tags // Add labels to tags
for k, label := range container.Labels { for k, label := range container.Labels {
if d.labelFilter.Match(k) { if d.labelFilter.Match(k) {
@ -461,12 +468,12 @@ func (d *Docker) gatherContainer(
acc.AddFields("docker_container_health", healthfields, tags, time.Now()) acc.AddFields("docker_container_health", healthfields, tags, time.Now())
} }
gatherContainerStats(v, acc, tags, container.ID, d.PerDevice, d.Total, daemonOSType) parseContainerStats(v, acc, tags, container.ID, d.PerDevice, d.Total, daemonOSType)
return nil return nil
} }
func gatherContainerStats( func parseContainerStats(
stat *types.StatsJSON, stat *types.StatsJSON,
acc telegraf.Accumulator, acc telegraf.Accumulator,
tags map[string]string, tags map[string]string,

View File

@ -77,8 +77,8 @@ var baseClient = MockClient{
ContainerListF: func(context.Context, types.ContainerListOptions) ([]types.Container, error) { ContainerListF: func(context.Context, types.ContainerListOptions) ([]types.Container, error) {
return containerList, nil return containerList, nil
}, },
ContainerStatsF: func(context.Context, string, bool) (types.ContainerStats, error) { ContainerStatsF: func(c context.Context, s string, b bool) (types.ContainerStats, error) {
return containerStats(), nil return containerStats(s), nil
}, },
ContainerInspectF: func(context.Context, string) (types.ContainerJSON, error) { ContainerInspectF: func(context.Context, string) (types.ContainerJSON, error) {
return containerInspect, nil return containerInspect, nil
@ -107,7 +107,7 @@ func TestDockerGatherContainerStats(t *testing.T) {
"container_image": "redis/image", "container_image": "redis/image",
} }
gatherContainerStats(stats, &acc, tags, "123456789", true, true, "linux") parseContainerStats(stats, &acc, tags, "123456789", true, true, "linux")
// test docker_container_net measurement // test docker_container_net measurement
netfields := map[string]interface{}{ netfields := map[string]interface{}{
@ -290,11 +290,9 @@ func TestContainerLabels(t *testing.T) {
}{ }{
{ {
name: "Nil filters matches all", name: "Nil filters matches all",
container: types.Container{ container: genContainerLabeled(map[string]string{
Labels: map[string]string{ "a": "x",
"a": "x", }),
},
},
include: nil, include: nil,
exclude: nil, exclude: nil,
expected: map[string]string{ expected: map[string]string{
@ -303,11 +301,9 @@ func TestContainerLabels(t *testing.T) {
}, },
{ {
name: "Empty filters matches all", name: "Empty filters matches all",
container: types.Container{ container: genContainerLabeled(map[string]string{
Labels: map[string]string{ "a": "x",
"a": "x", }),
},
},
include: []string{}, include: []string{},
exclude: []string{}, exclude: []string{},
expected: map[string]string{ expected: map[string]string{
@ -316,12 +312,10 @@ func TestContainerLabels(t *testing.T) {
}, },
{ {
name: "Must match include", name: "Must match include",
container: types.Container{ container: genContainerLabeled(map[string]string{
Labels: map[string]string{ "a": "x",
"a": "x", "b": "y",
"b": "y", }),
},
},
include: []string{"a"}, include: []string{"a"},
exclude: []string{}, exclude: []string{},
expected: map[string]string{ expected: map[string]string{
@ -330,12 +324,10 @@ func TestContainerLabels(t *testing.T) {
}, },
{ {
name: "Must not match exclude", name: "Must not match exclude",
container: types.Container{ container: genContainerLabeled(map[string]string{
Labels: map[string]string{ "a": "x",
"a": "x", "b": "y",
"b": "y", }),
},
},
include: []string{}, include: []string{},
exclude: []string{"b"}, exclude: []string{"b"},
expected: map[string]string{ expected: map[string]string{
@ -344,13 +336,11 @@ func TestContainerLabels(t *testing.T) {
}, },
{ {
name: "Include Glob", name: "Include Glob",
container: types.Container{ container: genContainerLabeled(map[string]string{
Labels: map[string]string{ "aa": "x",
"aa": "x", "ab": "y",
"ab": "y", "bb": "z",
"bb": "z", }),
},
},
include: []string{"a*"}, include: []string{"a*"},
exclude: []string{}, exclude: []string{},
expected: map[string]string{ expected: map[string]string{
@ -360,13 +350,11 @@ func TestContainerLabels(t *testing.T) {
}, },
{ {
name: "Exclude Glob", name: "Exclude Glob",
container: types.Container{ container: genContainerLabeled(map[string]string{
Labels: map[string]string{ "aa": "x",
"aa": "x", "ab": "y",
"ab": "y", "bb": "z",
"bb": "z", }),
},
},
include: []string{}, include: []string{},
exclude: []string{"a*"}, exclude: []string{"a*"},
expected: map[string]string{ expected: map[string]string{
@ -375,13 +363,11 @@ func TestContainerLabels(t *testing.T) {
}, },
{ {
name: "Excluded Includes", name: "Excluded Includes",
container: types.Container{ container: genContainerLabeled(map[string]string{
Labels: map[string]string{ "aa": "x",
"aa": "x", "ab": "y",
"ab": "y", "bb": "z",
"bb": "z", }),
},
},
include: []string{"a*"}, include: []string{"a*"},
exclude: []string{"*b"}, exclude: []string{"*b"},
expected: map[string]string{ expected: map[string]string{
@ -425,6 +411,12 @@ func TestContainerLabels(t *testing.T) {
} }
} }
func genContainerLabeled(labels map[string]string) types.Container {
c := containerList[0]
c.Labels = labels
return c
}
func TestContainerNames(t *testing.T) { func TestContainerNames(t *testing.T) {
var tests = []struct { var tests = []struct {
name string name string
@ -434,112 +426,67 @@ func TestContainerNames(t *testing.T) {
expected []string expected []string
}{ }{
{ {
name: "Nil filters matches all", name: "Nil filters matches all",
containers: [][]string{
{"/etcd"},
{"/etcd2"},
},
include: nil, include: nil,
exclude: nil, exclude: nil,
expected: []string{"etcd", "etcd2"}, expected: []string{"etcd", "etcd2", "acme", "acme-test", "foo"},
}, },
{ {
name: "Empty filters matches all", name: "Empty filters matches all",
containers: [][]string{
{"/etcd"},
{"/etcd2"},
},
include: []string{}, include: []string{},
exclude: []string{}, exclude: []string{},
expected: []string{"etcd", "etcd2"}, expected: []string{"etcd", "etcd2", "acme", "acme-test", "foo"},
}, },
{ {
name: "Match all containers", name: "Match all containers",
containers: [][]string{
{"/etcd"},
{"/etcd2"},
},
include: []string{"*"}, include: []string{"*"},
exclude: []string{}, exclude: []string{},
expected: []string{"etcd", "etcd2"}, expected: []string{"etcd", "etcd2", "acme", "acme-test", "foo"},
}, },
{ {
name: "Include prefix match", name: "Include prefix match",
containers: [][]string{
{"/etcd"},
{"/etcd2"},
},
include: []string{"etc*"}, include: []string{"etc*"},
exclude: []string{}, exclude: []string{},
expected: []string{"etcd", "etcd2"}, expected: []string{"etcd", "etcd2"},
}, },
{ {
name: "Exact match", name: "Exact match",
containers: [][]string{
{"/etcd"},
{"/etcd2"},
},
include: []string{"etcd"}, include: []string{"etcd"},
exclude: []string{}, exclude: []string{},
expected: []string{"etcd"}, expected: []string{"etcd"},
}, },
{ {
name: "Star matches zero length", name: "Star matches zero length",
containers: [][]string{
{"/etcd"},
{"/etcd2"},
},
include: []string{"etcd2*"}, include: []string{"etcd2*"},
exclude: []string{}, exclude: []string{},
expected: []string{"etcd2"}, expected: []string{"etcd2"},
}, },
{ {
name: "Exclude matches all", name: "Exclude matches all",
containers: [][]string{
{"/etcd"},
{"/etcd2"},
},
include: []string{}, include: []string{},
exclude: []string{"etc*"}, exclude: []string{"etc*"},
expected: []string{}, expected: []string{"acme", "acme-test", "foo"},
}, },
{ {
name: "Exclude single", name: "Exclude single",
containers: [][]string{
{"/etcd"},
{"/etcd2"},
},
include: []string{}, include: []string{},
exclude: []string{"etcd"}, exclude: []string{"etcd"},
expected: []string{"etcd2"}, expected: []string{"etcd2", "acme", "acme-test", "foo"},
}, },
{ {
name: "Exclude all", name: "Exclude all",
containers: [][]string{
{"/etcd"},
{"/etcd2"},
},
include: []string{"*"}, include: []string{"*"},
exclude: []string{"*"}, exclude: []string{"*"},
expected: []string{}, expected: []string{},
}, },
{ {
name: "Exclude item matching include", name: "Exclude item matching include",
containers: [][]string{
{"acme"},
{"foo"},
{"acme-test"},
},
include: []string{"acme*"}, include: []string{"acme*"},
exclude: []string{"*test*"}, exclude: []string{"*test*"},
expected: []string{"acme"}, expected: []string{"acme"},
}, },
{ {
name: "Exclude item no wildcards", name: "Exclude item no wildcards",
containers: [][]string{
{"acme"},
{"acme-test"},
},
include: []string{"acme*"}, include: []string{"acme*"},
exclude: []string{"test"}, exclude: []string{"test"},
expected: []string{"acme", "acme-test"}, expected: []string{"acme", "acme-test"},
@ -552,14 +499,12 @@ func TestContainerNames(t *testing.T) {
newClientFunc := func(host string, tlsConfig *tls.Config) (Client, error) { newClientFunc := func(host string, tlsConfig *tls.Config) (Client, error) {
client := baseClient client := baseClient
client.ContainerListF = func(context.Context, types.ContainerListOptions) ([]types.Container, error) { client.ContainerListF = func(context.Context, types.ContainerListOptions) ([]types.Container, error) {
var containers []types.Container return containerList, nil
for _, names := range tt.containers {
containers = append(containers, types.Container{
Names: names,
})
}
return containers, nil
} }
client.ContainerStatsF = func(c context.Context, s string, b bool) (types.ContainerStats, error) {
return containerStats(s), nil
}
return &client, nil return &client, nil
} }

View File

@ -1,6 +1,7 @@
package docker package docker
import ( import (
"fmt"
"io/ioutil" "io/ioutil"
"strings" "strings"
"time" "time"
@ -133,6 +134,18 @@ var containerList = []types.Container{
SizeRw: 0, SizeRw: 0,
SizeRootFs: 0, SizeRootFs: 0,
}, },
types.Container{
ID: "e8a713dd90604f5a257b97c15945e047ab60ed5b2c4397c5a6b5bf40e1bd2791",
Names: []string{"/acme"},
},
types.Container{
ID: "9bc6faf9ba8106fae32e8faafd38a1dd6f6d262bec172398cc10bc03c0d6841a",
Names: []string{"/acme-test"},
},
types.Container{
ID: "d4ccced494a1d5fe8ebdb0a86335a0dab069319912221e5838a132ab18a8bc84",
Names: []string{"/foo"},
},
} }
var two = uint64(2) var two = uint64(2)
@ -208,10 +221,25 @@ var NodeList = []swarm.Node{
}, },
} }
func containerStats() types.ContainerStats { func containerStats(s string) types.ContainerStats {
var stat types.ContainerStats var stat types.ContainerStats
jsonStat := ` var name string
switch s {
case "e2173b9478a6ae55e237d4d74f8bbb753f0817192b5081334dc78476296b7dfb":
name = "etcd"
case "b7dfbb9478a6ae55e237d4d74f8bbb753f0817192b5081334dc78476296e2173":
name = "etcd2"
case "e8a713dd90604f5a257b97c15945e047ab60ed5b2c4397c5a6b5bf40e1bd2791":
name = "/acme"
case "9bc6faf9ba8106fae32e8faafd38a1dd6f6d262bec172398cc10bc03c0d6841a":
name = "/acme-test"
case "d4ccced494a1d5fe8ebdb0a86335a0dab069319912221e5838a132ab18a8bc84":
name = "/foo"
}
jsonStat := fmt.Sprintf(`
{ {
"name": "%s",
"blkio_stats": { "blkio_stats": {
"io_service_bytes_recursive": [ "io_service_bytes_recursive": [
{ {
@ -315,7 +343,7 @@ func containerStats() types.ContainerStats {
"throttling_data": {} "throttling_data": {}
}, },
"read": "2016-02-24T11:42:27.472459608-05:00" "read": "2016-02-24T11:42:27.472459608-05:00"
}` }`, name)
stat.Body = ioutil.NopCloser(strings.NewReader(jsonStat)) stat.Body = ioutil.NopCloser(strings.NewReader(jsonStat))
return stat return stat
} }