Skip to content

Commit

Permalink
Negotiate Docker API version (elastic#7165)
Browse files Browse the repository at this point in the history
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 moby/moby#33989 and do it once we have
something we can vendor.
  • Loading branch information
exekias authored and ruflin committed May 24, 2018
1 parent 6b14281 commit 51d15f3
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ https://github.com/elastic/beats/compare/v6.2.3...master[Check the HEAD diff]
- Fix map overwrite panics by cloning shared structs before doing the update. {pull}6947[6947]
- Fix error if lz4 compression is used with the kafka output. {pull}7025[7025]
- Preserve the event when source matching fails in `add_docker_metadata`. {pull}7133[7133]
- Negotiate Docker API version from our client instead of using a hardcoded one. {pull}7165[7165]

*Auditbeat*

Expand Down
44 changes: 44 additions & 0 deletions libbeat/common/docker/client.go
Original file line number Diff line number Diff line change
@@ -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
}
6 changes: 2 additions & 4 deletions libbeat/common/docker/watcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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
Expand Down Expand Up @@ -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
}
Expand Down
3 changes: 2 additions & 1 deletion metricbeat/module/docker/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Expand Down Expand Up @@ -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
}
Expand Down

0 comments on commit 51d15f3

Please sign in to comment.