From f0bd69d904f3ffdc9a959463442210b7a459f2cc Mon Sep 17 00:00:00 2001 From: Daniel Nelson Date: Thu, 27 Jul 2017 17:18:44 -0700 Subject: [PATCH] Add tls options to docker input (#3063) --- Godeps | 2 ++ plugins/inputs/docker/README.md | 21 ++++++++-------- plugins/inputs/docker/client.go | 18 ++++++++++++-- plugins/inputs/docker/docker.go | 36 ++++++++++++++++++++-------- plugins/inputs/docker/docker_test.go | 5 ++-- 5 files changed, 58 insertions(+), 24 deletions(-) diff --git a/Godeps b/Godeps index aa4a5b0e8005d..b021911e8d103 100644 --- a/Godeps +++ b/Godeps @@ -12,6 +12,7 @@ github.com/couchbase/gomemcached 4a25d2f4e1dea9ea7dd76dfd943407abf9b07d29 github.com/couchbase/goutils 5823a0cbaaa9008406021dc5daf80125ea30bba6 github.com/davecgh/go-spew 346938d642f2ec3594ed81d874461961cd0faa76 github.com/docker/docker f5ec1e2936dcbe7b5001c2b817188b095c700c27 +github.com/docker/go-connections 990a1a1a70b0da4c4cb70e117971a4f0babfbf1a github.com/eapache/go-resiliency b86b1ec0dd4209a588dc1285cdd471e73525c0b3 github.com/eapache/go-xerial-snappy bb955e01b9346ac19dc29eb16586c90ded99a98c github.com/eapache/queue 44cc805cf13205b55f69e14bcb69867d1ae92f98 @@ -37,6 +38,7 @@ github.com/nats-io/go-nats ea9585611a4ab58a205b9b125ebd74c389a6b898 github.com/nats-io/nats ea9585611a4ab58a205b9b125ebd74c389a6b898 github.com/nats-io/nuid 289cccf02c178dc782430d534e3c1f5b72af807f github.com/nsqio/go-nsq a53d495e81424aaf7a7665a9d32a97715c40e953 +github.com/opencontainers/runc 89ab7f2ccc1e45ddf6485eaa802c35dcf321dfc8 github.com/pierrec/lz4 5c9560bfa9ace2bf86080bf40d46b34ae44604df github.com/pierrec/xxHash 5a004441f897722c627870a981d02b29924215fa github.com/pkg/errors 645ef00459ed84a119197bfb8d8205042c6df63d diff --git a/plugins/inputs/docker/README.md b/plugins/inputs/docker/README.md index 8fb0c3753ffe8..06847bae9e7e5 100644 --- a/plugins/inputs/docker/README.md +++ b/plugins/inputs/docker/README.md @@ -1,15 +1,11 @@ # Docker Input Plugin -The docker plugin uses the docker remote API to gather metrics on running -docker containers. You can read Docker's documentation for their remote API -[here](https://docs.docker.com/engine/reference/api/docker_remote_api_v1.20/#get-container-stats-based-on-resource-usage) +The docker plugin uses the Docker Engine API to gather metrics on running +docker containers. -The docker plugin uses the excellent -[docker engine-api](https://github.com/docker/engine-api) library to -gather stats. Documentation for the library can be found -[here](https://godoc.org/github.com/docker/engine-api) and documentation -for the stat structure can be found -[here](https://godoc.org/github.com/docker/engine-api/types#Stats) +The docker plugin uses the [Official Docker Client](https://github.com/moby/moby/tree/master/client) +to gather stats from the [Engine API](https://docs.docker.com/engine/api/v1.20/). +[Library Documentation](https://godoc.org/github.com/moby/moby/client) ### Configuration: @@ -47,7 +43,7 @@ for the stat structure can be found ## Note that an empty array for both will include all labels as tags docker_label_include = [] docker_label_exclude = [] - + ## Which environment variables should we use as a tag tag_env = ["JAVA_HOME", "HEAP_SIZE"] @@ -59,6 +55,11 @@ for the stat structure can be found # insecure_skip_verify = false ``` +#### Environment Configuration + +When using the `"ENV"` endpoint, the connection is configured using the +[cli Docker environment variables](https://godoc.org/github.com/moby/moby/client#NewEnvClient). + ### Measurements & Fields: Every effort was made to preserve the names based on the JSON response from the diff --git a/plugins/inputs/docker/client.go b/plugins/inputs/docker/client.go index b30a6666b97fd..e918231a030f6 100644 --- a/plugins/inputs/docker/client.go +++ b/plugins/inputs/docker/client.go @@ -2,9 +2,12 @@ package docker import ( "context" + "crypto/tls" + "net/http" "github.com/docker/docker/api/types" docker "github.com/docker/docker/client" + "github.com/docker/go-connections/sockets" ) var ( @@ -27,8 +30,19 @@ func NewEnvClient() (Client, error) { return &SocketClient{client}, nil } -func NewClient(host string) (Client, error) { - client, err := docker.NewClient(host, version, nil, defaultHeaders) +func NewClient(host string, tlsConfig *tls.Config) (Client, error) { + proto, addr, _, err := docker.ParseHost(host) + if err != nil { + return nil, err + } + + transport := &http.Transport{ + TLSClientConfig: tlsConfig, + } + sockets.ConfigureTransport(transport, proto, addr) + httpClient := &http.Client{Transport: transport} + + client, err := docker.NewClient(host, version, httpClient, defaultHeaders) if err != nil { return nil, err } diff --git a/plugins/inputs/docker/docker.go b/plugins/inputs/docker/docker.go index b0d0e4953cc18..3634e596ff353 100644 --- a/plugins/inputs/docker/docker.go +++ b/plugins/inputs/docker/docker.go @@ -2,9 +2,11 @@ package docker import ( "context" + "crypto/tls" "encoding/json" "fmt" "io" + "net/http" "regexp" "strconv" "strings" @@ -45,10 +47,16 @@ type Docker struct { ContainerExclude []string `toml:"container_name_exclude"` ContainerFilter DockerContainerFilter + SSLCA string `toml:"ssl_ca"` + SSLCert string `toml:"ssl_cert"` + SSLKey string `toml:"ssl_key"` + InsecureSkipVerify bool + newEnvClient func() (Client, error) - newClient func(host string) (Client, error) + newClient func(string, *tls.Config) (Client, error) client Client + httpClient *http.Client engine_host string filtersCreated bool } @@ -60,6 +68,8 @@ const ( GB = 1000 * MB TB = 1000 * GB PB = 1000 * TB + + defaultEndpoint = "unix:///var/run/docker.sock" ) var ( @@ -95,6 +105,13 @@ var sampleConfig = ` ## Note that an empty array for both will include all labels as tags docker_label_include = [] docker_label_exclude = [] + + ## Optional SSL Config + # ssl_ca = "/etc/telegraf/ca.pem" + # ssl_cert = "/etc/telegraf/cert.pem" + # ssl_key = "/etc/telegraf/key.pem" + ## Use SSL but skip chain & host verification + # insecure_skip_verify = false ` func (d *Docker) Description() string { @@ -109,19 +126,17 @@ func (d *Docker) Gather(acc telegraf.Accumulator) error { var err error if d.Endpoint == "ENV" { c, err = d.newEnvClient() - if err != nil { - return err - } - } else if d.Endpoint == "" { - c, err = d.newClient("unix:///var/run/docker.sock") - if err != nil { - return err - } } else { - c, err = d.newClient(d.Endpoint) + tlsConfig, err := internal.GetTLSConfig( + d.SSLCert, d.SSLKey, d.SSLCA, d.InsecureSkipVerify) if err != nil { return err } + + c, err = d.newClient(d.Endpoint, tlsConfig) + } + if err != nil { + return err } d.client = c } @@ -699,6 +714,7 @@ func init() { return &Docker{ PerDevice: true, Timeout: internal.Duration{Duration: time.Second * 5}, + Endpoint: defaultEndpoint, newEnvClient: NewEnvClient, newClient: NewClient, filtersCreated: false, diff --git a/plugins/inputs/docker/docker_test.go b/plugins/inputs/docker/docker_test.go index b64eeb1ee6ae2..95adfcf8e6757 100644 --- a/plugins/inputs/docker/docker_test.go +++ b/plugins/inputs/docker/docker_test.go @@ -2,6 +2,7 @@ package docker import ( "context" + "crypto/tls" "testing" "github.com/influxdata/telegraf/testutil" @@ -43,7 +44,7 @@ func (c *MockClient) ContainerInspect( return c.ContainerInspectF(ctx, containerID) } -func newClient(host string) (Client, error) { +func newClient(host string, tlsConfig *tls.Config) (Client, error) { return &MockClient{ InfoF: func(context.Context) (types.Info, error) { return info, nil @@ -212,7 +213,7 @@ func TestDocker_WindowsMemoryContainerStats(t *testing.T) { var acc testutil.Accumulator d := Docker{ - newClient: func(string) (Client, error) { + newClient: func(string, *tls.Config) (Client, error) { return &MockClient{ InfoF: func(ctx context.Context) (types.Info, error) { return info, nil