From 0666812c55faa6bfd8e17e693f125a447331009b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20P=C3=A9rez-Aradros=20Herce?= Date: Fri, 15 Jun 2018 09:43:53 +0200 Subject: [PATCH] Cherry-pick #7165 to 6.3: Negotiate Docker API version (#7177) * Negotiate Docker API version (#7165) New Docker versions have deprecated our hardcoded client API version (1.22), this change uses an API version negotiation mechanism to ensure compatibility. We should still upgrade to a newer client in the future, let's keep an eye on https://github.com/moby/moby/issues/33989 and do it once we have something we can vendor. (cherry picked from commit 253bc71cbc7c8d76e8c8a3cd419b2d65ce2b7998) * Update CHANGELOG.asciidoc --- CHANGELOG.asciidoc | 2 ++ libbeat/common/docker/client.go | 44 ++++++++++++++++++++++++++++++ libbeat/common/docker/watcher.go | 6 ++-- metricbeat/module/docker/docker.go | 3 +- 4 files changed, 50 insertions(+), 5 deletions(-) create mode 100644 libbeat/common/docker/client.go diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index d3ba9154638e..0992a4e0d17f 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -29,6 +29,8 @@ https://github.com/elastic/beats/compare/v6.3.0...6.3[Check the HEAD diff] *Affecting all Beats* +- Negotiate Docker API version from our client instead of using a hardcoded one. {pull}7165[7165] + *Auditbeat* *Filebeat* diff --git a/libbeat/common/docker/client.go b/libbeat/common/docker/client.go new file mode 100644 index 000000000000..965fbb442c35 --- /dev/null +++ b/libbeat/common/docker/client.go @@ -0,0 +1,44 @@ +package docker + +import ( + "net/http" + + "github.com/elastic/beats/libbeat/logp" + + "github.com/docker/docker/api" + "github.com/docker/docker/api/types/versions" + "github.com/docker/docker/client" + "golang.org/x/net/context" +) + +// Select Docker API version +const dockerAPIVersion = api.DefaultVersion + +// NewClient builds and returns a new Docker client +// It uses version 1.26 by default, and negotiates it with the server so it is downgraded if 1.26 is too high +func NewClient(host string, httpClient *http.Client, httpHeaders map[string]string) (*client.Client, error) { + c, err := client.NewClient(host, dockerAPIVersion, httpClient, nil) + if err != nil { + return c, err + } + + logp.Debug("docker", "Negotiating client version") + ping, err := c.Ping(context.Background()) + if err != nil { + logp.Debug("docker", "Failed to perform ping: %s", err) + } + + // try the latest version before versioning headers existed + if ping.APIVersion == "" { + ping.APIVersion = "1.24" + } + + // if server version is lower than the client version, downgrade + if versions.LessThan(ping.APIVersion, dockerAPIVersion) { + c.UpdateClientVersion(ping.APIVersion) + } + + logp.Debug("docker", "Client version set to %s", c.ClientVersion()) + + return c, nil +} diff --git a/libbeat/common/docker/watcher.go b/libbeat/common/docker/watcher.go index 02c4a0cb11cc..5c2e03fea4cc 100644 --- a/libbeat/common/docker/watcher.go +++ b/libbeat/common/docker/watcher.go @@ -9,7 +9,6 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/events" "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/client" "github.com/docker/go-connections/tlsconfig" "golang.org/x/net/context" @@ -19,8 +18,7 @@ import ( // Select Docker API version const ( - dockerAPIVersion = "1.22" - shortIDLen = 12 + shortIDLen = 12 ) // Watcher reads docker events and keeps a list of known containers @@ -106,7 +104,7 @@ func NewWatcher(host string, tls *TLSConfig, storeShortID bool) (Watcher, error) } } - client, err := client.NewClient(host, dockerAPIVersion, httpClient, nil) + client, err := NewClient(host, httpClient, nil) if err != nil { return nil, err } diff --git a/metricbeat/module/docker/docker.go b/metricbeat/module/docker/docker.go index 1023409419cb..02408c365430 100644 --- a/metricbeat/module/docker/docker.go +++ b/metricbeat/module/docker/docker.go @@ -11,6 +11,7 @@ import ( "github.com/docker/docker/client" "github.com/docker/go-connections/tlsconfig" + "github.com/elastic/beats/libbeat/common/docker" "github.com/elastic/beats/metricbeat/mb" "github.com/elastic/beats/metricbeat/mb/parse" ) @@ -67,7 +68,7 @@ func NewDockerClient(endpoint string, config Config) (*client.Client, error) { } } - client, err := client.NewClient(endpoint, dockerAPIVersion, httpClient, nil) + client, err := docker.NewClient(endpoint, httpClient, nil) if err != nil { return nil, err }