From 38bf16d2ef1a3a44edcb61830fadf3051b60043e Mon Sep 17 00:00:00 2001 From: Michael Schurter Date: Fri, 7 Jul 2017 10:14:10 -0700 Subject: [PATCH 1/4] Add driver.docker.bridge_ip node attribute Fixes #2785 --- client/driver/docker.go | 21 +++++++++++++++++++++ client/driver/docker_test.go | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/client/driver/docker.go b/client/driver/docker.go index 9a75cc660966..a7a4ba033379 100644 --- a/client/driver/docker.go +++ b/client/driver/docker.go @@ -319,6 +319,9 @@ func (d *DockerDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool d.fingerprintSuccess = helper.BoolToPtr(false) return false, nil } + for i, v := range *env { + d.logger.Printf("[DEBUG] driver.docker: %d %s", i, v) + } node.Attributes[dockerDriverAttr] = "1" node.Attributes["driver.docker.version"] = env.Get("Version") @@ -333,6 +336,24 @@ func (d *DockerDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool node.Attributes["driver."+dockerVolumesConfigOption] = "1" } + // Detect bridge IP address - #2785 + if nets, err := client.ListNetworks(); err != nil { + d.logger.Printf("[WARN] driver.docker: error discovering bridge IP: %v", err) + } else { + for _, n := range nets { + if n.Name != "bridge" { + continue + } + + if len(n.IPAM.Config) == 0 { + d.logger.Printf("[WARN] driver.docker: no IPAM config for bridge network") + break + } + + node.Attributes["driver.docker.bridge_ip"] = n.IPAM.Config[0].Gateway + } + } + d.fingerprintSuccess = helper.BoolToPtr(true) return true, nil } diff --git a/client/driver/docker_test.go b/client/driver/docker_test.go index 404b9513797e..872852ba96dd 100644 --- a/client/driver/docker_test.go +++ b/client/driver/docker_test.go @@ -15,6 +15,7 @@ import ( "time" docker "github.com/fsouza/go-dockerclient" + sockaddr "github.com/hashicorp/go-sockaddr" "github.com/hashicorp/nomad/client/allocdir" "github.com/hashicorp/nomad/client/config" "github.com/hashicorp/nomad/client/driver/env" @@ -177,6 +178,40 @@ func TestDockerDriver_Fingerprint(t *testing.T) { t.Logf("Found docker version %s", node.Attributes["driver.docker.version"]) } +// TestDockerDriver_Fingerprint_Bridge asserts that if Docker is running we set +// the bridge network's IP as a node attribute. See #2785 +func TestDockerDriver_Fingerprint_Bridge(t *testing.T) { + if !testutil.DockerIsConnected(t) { + t.Skip("requires Docker") + } + + // This seems fragile, so we might need to reconsider this test if it + // proves flaky + expectedAddr, err := sockaddr.GetInterfaceIP("docker0") + if err != nil { + t.Fatalf("unable to get ip for docker0: %v", err) + } + if expectedAddr == "" { + t.Fatalf("unable to get ip for docker bridge") + } + + conf := testConfig() + conf.Node = mock.Node() + dd := NewDockerDriver(NewDriverContext("", "", conf, conf.Node, testLogger(), nil)) + ok, err := dd.Fingerprint(conf, conf.Node) + if err != nil { + t.Fatalf("error fingerprinting docker: %v", err) + } + if !ok { + t.Fatalf("expected Docker to be enabled but false was returned") + } + + if found := conf.Node.Attributes["driver.docker.bridge_ip"]; found != expectedAddr { + t.Fatalf("expected bridge ip %q but found: %q", expectedAddr, found) + } + t.Logf("docker bridge ip: %q", conf.Node.Attributes["driver.docker.bridge_ip"]) +} + func TestDockerDriver_StartOpen_Wait(t *testing.T) { if !testutil.DockerIsConnected(t) { t.SkipNow() From 3094fed32ffe6e7e566e6739fed979f981c6f3f1 Mon Sep 17 00:00:00 2001 From: Michael Schurter Date: Fri, 7 Jul 2017 10:16:36 -0700 Subject: [PATCH 2/4] Add changelog entry for #2797 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a6b1fbe082ef..e2e2e6a9e8f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ IMPROVEMENTS: * driver/docker: Allow setting seccomp profiles [GH-2658] * driver/docker: Support Docker credential helpers [GH-2651] * driver/docker: Auth failures can optionally be ignored [GH-2786] + * driver/docker: Add `driver.docker.bridge_ip` node attribute [GH-2797] * driver/docker: Allow setting container IP with user defined networks [GH-2535] * driver/rkt: Support `no_overlay` [GH-2702] From 2c612ca2bf3fd70e69144743ea4d70fa7dbd77a2 Mon Sep 17 00:00:00 2001 From: Michael Schurter Date: Fri, 7 Jul 2017 10:17:44 -0700 Subject: [PATCH 3/4] Document `driver.docker.bridge_ip` node attribute --- website/source/docs/drivers/docker.html.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/website/source/docs/drivers/docker.html.md b/website/source/docs/drivers/docker.html.md index ae1844cba8ce..060274ee823c 100644 --- a/website/source/docs/drivers/docker.html.md +++ b/website/source/docs/drivers/docker.html.md @@ -529,6 +529,8 @@ The `docker` driver will set the following client attributes: * `driver.docker` - This will be set to "1", indicating the driver is available. +* `driver.docker.bridge_ip` - The IP of the Docker bridge network if one + exists. * `driver.docker.version` - This will be set to version of the docker server. Here is an example of using these properties in a job file: From 024d5a8edc0eec25274159e88711fb21ed11ede7 Mon Sep 17 00:00:00 2001 From: Michael Schurter Date: Fri, 7 Jul 2017 16:19:42 -0700 Subject: [PATCH 4/4] Remove debug logging --- client/driver/docker.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/client/driver/docker.go b/client/driver/docker.go index a7a4ba033379..b49cd8ccc464 100644 --- a/client/driver/docker.go +++ b/client/driver/docker.go @@ -319,9 +319,6 @@ func (d *DockerDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool d.fingerprintSuccess = helper.BoolToPtr(false) return false, nil } - for i, v := range *env { - d.logger.Printf("[DEBUG] driver.docker: %d %s", i, v) - } node.Attributes[dockerDriverAttr] = "1" node.Attributes["driver.docker.version"] = env.Get("Version")