diff --git a/CHANGELOG.md b/CHANGELOG.md index b54737e4c..f0485267f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Features - [#2773](https://github.com/influxdata/telegraf/pull/2773): Add support for self-signed certs to InfluxDB input plugin +- [#2581](https://github.com/influxdata/telegraf/pull/2581): Add Docker container environment variables as tags. Only whitelisted ### Bugfixes diff --git a/plugins/inputs/docker/README.md b/plugins/inputs/docker/README.md index c6b14bdc2..12741d940 100644 --- a/plugins/inputs/docker/README.md +++ b/plugins/inputs/docker/README.md @@ -36,6 +36,8 @@ for the stat structure can be found docker_label_include = [] docker_label_exclude = [] + ## Which environment variables should we use as a tag + tag_env = ["JAVA_HOME", "HEAP_SIZE"] ``` ### Measurements & Fields: diff --git a/plugins/inputs/docker/docker.go b/plugins/inputs/docker/docker.go index a439af068..13ade3945 100644 --- a/plugins/inputs/docker/docker.go +++ b/plugins/inputs/docker/docker.go @@ -31,6 +31,7 @@ type Docker struct { Timeout internal.Duration PerDevice bool `toml:"perdevice"` Total bool `toml:"total"` + TagEnvironment []string `toml:"tag_env"` LabelInclude []string `toml:"docker_label_include"` LabelExclude []string `toml:"docker_label_exclude"` @@ -79,6 +80,18 @@ func statsWrapper( return fc.ContainerStats(ctx, containerID, stream) } +func inspectWrapper( + c *client.Client, + ctx context.Context, + containerID string, +) (types.ContainerJSON, error) { + if c != nil { + return c.ContainerInspect(ctx, containerID) + } + fc := FakeDockerClient{} + return fc.ContainerInspect(ctx, containerID) +} + // KB, MB, GB, TB, PB...human friendly const ( KB = 1000 @@ -107,6 +120,8 @@ var sampleConfig = ` perdevice = true ## Whether to report for each container total blkio and network stats or not total = false + ## Which environment variables should we use as a tag + ##tag_env = ["JAVA_HOME", "HEAP_SIZE"] ## docker labels to include and exclude as tags. Globs accepted. ## Note that an empty array for both will include all labels as tags @@ -321,6 +336,23 @@ func (d *Docker) gatherContainer( } } + // Add whitelisted environment variables to tags + if len(d.TagEnvironment) > 0 { + info, err := inspectWrapper(d.client, ctx, container.ID) + if err != nil { + return fmt.Errorf("Error inspecting docker container: %s", err.Error()) + } + for _, envvar := range info.Config.Env { + for _, configvar := range d.TagEnvironment { + dock_env := strings.SplitN(envvar, "=", 2) + //check for presence of tag in whitelist + if len(dock_env) == 2 && len(strings.TrimSpace(dock_env[1])) != 0 && configvar == dock_env[0] { + tags[dock_env[0]] = dock_env[1] + } + } + } + } + gatherContainerStats(v, acc, tags, container.ID, d.PerDevice, d.Total) return nil diff --git a/plugins/inputs/docker/docker_test.go b/plugins/inputs/docker/docker_test.go index cc385bd5d..025d482fe 100644 --- a/plugins/inputs/docker/docker_test.go +++ b/plugins/inputs/docker/docker_test.go @@ -300,6 +300,8 @@ func TestDockerGatherInfo(t *testing.T) { d := Docker{ client: nil, testing: true, + TagEnvironment: []string{"ENVVAR1", "ENVVAR2", "ENVVAR3", "ENVVAR5", + "ENVVAR6", "ENVVAR7", "ENVVAR8", "ENVVAR9"}, } err := acc.GatherError(d.Gather) @@ -345,6 +347,10 @@ func TestDockerGatherInfo(t *testing.T) { "cpu": "cpu3", "container_version": "v2.2.2", "engine_host": "absol", + "ENVVAR1": "loremipsum", + "ENVVAR2": "dolorsitamet", + "ENVVAR3": "=ubuntu:10.04", + "ENVVAR7": "ENVVAR8=ENVVAR9", "label1": "test_value_1", "label2": "test_value_2", }, @@ -393,6 +399,10 @@ func TestDockerGatherInfo(t *testing.T) { "container_name": "etcd2", "container_image": "quay.io:4443/coreos/etcd", "container_version": "v2.2.2", + "ENVVAR1": "loremipsum", + "ENVVAR2": "dolorsitamet", + "ENVVAR3": "=ubuntu:10.04", + "ENVVAR7": "ENVVAR8=ENVVAR9", "label1": "test_value_1", "label2": "test_value_2", }, diff --git a/plugins/inputs/docker/fake_client.go b/plugins/inputs/docker/fake_client.go index dcca6f235..f53afe1b1 100644 --- a/plugins/inputs/docker/fake_client.go +++ b/plugins/inputs/docker/fake_client.go @@ -6,6 +6,7 @@ import ( "strings" "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/registry" ) @@ -149,3 +150,23 @@ func (d FakeDockerClient) ContainerStats(ctx context.Context, containerID string stat.Body = ioutil.NopCloser(strings.NewReader(jsonStat)) return stat, nil } + +func (d FakeDockerClient) ContainerInspect(ctx context.Context, containerID string) (types.ContainerJSON, error) { + json := types.ContainerJSON{ + Config: &container.Config{ + Env: []string{ + "ENVVAR1=loremipsum", + "ENVVAR1FOO=loremipsum", + "ENVVAR2=dolorsitamet", + "ENVVAR3==ubuntu:10.04", + "ENVVAR4", + "ENVVAR5=", + "ENVVAR6= ", + "ENVVAR7=ENVVAR8=ENVVAR9", + "PATH=/bin:/sbin", + }, + }, + } + + return json, nil +}