From 795d84e08f0131d40eb7a0e724f8bb1841ce2d26 Mon Sep 17 00:00:00 2001 From: Wim Date: Wed, 24 Jan 2018 14:39:50 +0100 Subject: [PATCH 1/7] Service registration for IPv6 docker addresses --- client/driver/docker.go | 7 ++ website/source/docs/drivers/docker.html.md | 5 ++ .../docs/job-specification/service.html.md | 70 +++++++++++++++++++ 3 files changed, 82 insertions(+) diff --git a/client/driver/docker.go b/client/driver/docker.go index 5f2dedc29d4..34d2f5c5ec6 100644 --- a/client/driver/docker.go +++ b/client/driver/docker.go @@ -217,6 +217,7 @@ type DockerDriverConfig struct { CapAdd []string `mapstructure:"cap_add"` // Flags to pass directly to cap-add CapDrop []string `mapstructure:"cap_drop"` // Flags to pass directly to cap-drop ReadonlyRootfs bool `mapstructure:"readonly_rootfs"` // Mount the container’s root filesystem as read only + UseIPv6Address bool `mapstructure:"use_ipv6_address"` // Flag to use the GlobalIPv6Address from the container as the detected IP } func sliceMergeUlimit(ulimitsRaw map[string]string) ([]docker.ULimit, error) { @@ -674,6 +675,9 @@ func (d *DockerDriver) Validate(config map[string]interface{}) error { "readonly_rootfs": { Type: fields.TypeBool, }, + "use_ipv6_address": { + Type: fields.TypeBool, + }, }, } @@ -884,6 +888,9 @@ func (d *DockerDriver) detectIP(c *docker.Container) (string, bool) { } ip = net.IPAddress + if d.driverConfig.UseIPv6Address { + ip = net.GlobalIPv6Address + } ipName = name // Don't auto-advertise IPs for default networks (bridge on diff --git a/website/source/docs/drivers/docker.html.md b/website/source/docs/drivers/docker.html.md index c75238dfd29..0eca3537d28 100644 --- a/website/source/docs/drivers/docker.html.md +++ b/website/source/docs/drivers/docker.html.md @@ -355,6 +355,11 @@ The `docker` driver supports the following configuration in the job spec. Only ] } ``` +* `use_ipv6_address` - (Optional) `true` or `false` (default). Use IPv6 Address + will use the containers IPv6 address (GlobalIPv6Address) when registering service checks and using + `address_mode = driver`. + See [service](/docs/job-specification/service.html) for details. + * `readonly_rootfs` - (Optional) `true` or `false` (default). Mount the container's filesystem as read only. diff --git a/website/source/docs/job-specification/service.html.md b/website/source/docs/job-specification/service.html.md index 54f42907565..21d485352ed 100644 --- a/website/source/docs/job-specification/service.html.md +++ b/website/source/docs/job-specification/service.html.md @@ -104,6 +104,9 @@ does not automatically enable service discovery. `address_mode="driver"`. Numeric ports may be used when in driver addressing mode. + Docker and IPv6 containers: This setting is required if you want to register + the port of the (IPv6) service. See [below for examples.](#IPv6 docker containers) + - `tags` `(array: [])` - Specifies the list of tags to associate with this service. If this is not supplied, no tags will be assigned to the service when it is registered. @@ -124,6 +127,10 @@ does not automatically enable service discovery. addresses. Task will fail if driver network cannot be determined. Only implemented for Docker and rkt. + Docker and IPv6 containers: If you want to register the IPv6 address + of the container you'll have to enable this and specify `use_ipv6_address` + in the docker driver configuration. See [below for examples.](#IPv6 docker containers) + - `host` - Use the host IP and port. ### `check` Parameters @@ -140,6 +147,10 @@ scripts. [below for details.](#using-driver-address-mode) Unlike `port`, this setting is *not* inherited from the `service`. + Docker and IPv6 containers: If you want to check the IPv6 address + of the container you'll have to enable this and specify `use_ipv6_address` + in the docker driver configuration. See [below for examples.](#IPv6 docker containers) + - `args` `(array: [])` - Specifies additional arguments to the `command`. This only applies to script-based health checks. @@ -186,6 +197,9 @@ scripts. default. In Nomad 0.7.1 or later numeric ports may be used if `address_mode="driver"` is set on the check. + Docker and IPv6 containers: Using a numeric port is required if you want to + check the port of (IPv6) service. See [below for examples.](#IPv6 docker containers) + - `protocol` `(string: "http")` - Specifies the protocol for the http-based health checks. Valid options are `http` and `https`. @@ -463,6 +477,62 @@ In this case Nomad doesn't need to assign Redis any host ports. The `service` and `check` stanzas can both specify the port number to advertise and check directly since Nomad isn't managing any port assignments. +### IPv6 docker containers + +The [Docker](/docs/drivers/docker.html#use_ipv6_address) driver support the +`use_ipv6_address` parameter in it's configuration. + +Besides enabling this parameter you have to set `address_mode` parameter in +both `service` and `check` stanzas to `driver`. + +You also have explicily specify the `port` that will be registered and checked. + +For example + +```hcl +job "example" { + datacenters = ["dc1"] + group "cache" { + + task "redis" { + driver = "docker" + + config { + image = "redis:3.2" + use_ipv6_address = true + # No port map required! + } + + resources { + cpu = 500 # 500 MHz + memory = 256 # 256MB + network { + mbits = 10 + } + } + + service { + name = "ipv6-redis" + port = 6379 + address_mode = "driver" + check { + name = "ipv6-redis-check" + type = "tcp" + interval = "10s" + timeout = "2s" + port = 6379 + address_mode = "driver" + } + } + } + } +} +``` + +With IPv6 Nomad doesn't need to assign Redis any host ports. The `service` +and `check` stanzas can both specify the port number to advertise and check +directly since Nomad isn't managing any port assignments. + - - - From dea460bb5aaeb31f16c59fefd08da91292a4f811 Mon Sep 17 00:00:00 2001 From: Wim Date: Thu, 1 Feb 2018 00:01:25 +0100 Subject: [PATCH 2/7] * Change use_ipv6_address to advertise_ipv6_address. * Set autoadvertise to true. * Update documentation. --- client/driver/docker.go | 95 ++++++++++--------- website/source/docs/drivers/docker.html.md | 8 +- .../docs/job-specification/service.html.md | 83 +++++++++++----- 3 files changed, 109 insertions(+), 77 deletions(-) diff --git a/client/driver/docker.go b/client/driver/docker.go index 34d2f5c5ec6..70511e81d99 100644 --- a/client/driver/docker.go +++ b/client/driver/docker.go @@ -173,51 +173,51 @@ type DockerVolumeDriverConfig struct { // DockerDriverConfig defines the user specified config block in a jobspec type DockerDriverConfig struct { - ImageName string `mapstructure:"image"` // Container's Image Name - LoadImage string `mapstructure:"load"` // LoadImage is a path to an image archive file - Command string `mapstructure:"command"` // The Command to run when the container starts up - Args []string `mapstructure:"args"` // The arguments to the Command - Entrypoint []string `mapstructure:"entrypoint"` // Override the containers entrypoint - IpcMode string `mapstructure:"ipc_mode"` // The IPC mode of the container - host and none - NetworkMode string `mapstructure:"network_mode"` // The network mode of the container - host, nat and none - NetworkAliases []string `mapstructure:"network_aliases"` // The network-scoped alias for the container - IPv4Address string `mapstructure:"ipv4_address"` // The container ipv4 address - IPv6Address string `mapstructure:"ipv6_address"` // the container ipv6 address - PidMode string `mapstructure:"pid_mode"` // The PID mode of the container - host and none - UTSMode string `mapstructure:"uts_mode"` // The UTS mode of the container - host and none - UsernsMode string `mapstructure:"userns_mode"` // The User namespace mode of the container - host and none - PortMapRaw []map[string]string `mapstructure:"port_map"` // - PortMap map[string]int `mapstructure:"-"` // A map of host port labels and the ports exposed on the container - Privileged bool `mapstructure:"privileged"` // Flag to run the container in privileged mode - SysctlRaw []map[string]string `mapstructure:"sysctl"` // - Sysctl map[string]string `mapstructure:"-"` // The sysctl custom configurations - UlimitRaw []map[string]string `mapstructure:"ulimit"` // - Ulimit []docker.ULimit `mapstructure:"-"` // The ulimit custom configurations - DNSServers []string `mapstructure:"dns_servers"` // DNS Server for containers - DNSSearchDomains []string `mapstructure:"dns_search_domains"` // DNS Search domains for containers - DNSOptions []string `mapstructure:"dns_options"` // DNS Options - ExtraHosts []string `mapstructure:"extra_hosts"` // Add host to /etc/hosts (host:IP) - Hostname string `mapstructure:"hostname"` // Hostname for containers - LabelsRaw []map[string]string `mapstructure:"labels"` // - Labels map[string]string `mapstructure:"-"` // Labels to set when the container starts up - Auth []DockerDriverAuth `mapstructure:"auth"` // Authentication credentials for a private Docker registry - AuthSoftFail bool `mapstructure:"auth_soft_fail"` // Soft-fail if auth creds are provided but fail - TTY bool `mapstructure:"tty"` // Allocate a Pseudo-TTY - Interactive bool `mapstructure:"interactive"` // Keep STDIN open even if not attached - ShmSize int64 `mapstructure:"shm_size"` // Size of /dev/shm of the container in bytes - WorkDir string `mapstructure:"work_dir"` // Working directory inside the container - Logging []DockerLoggingOpts `mapstructure:"logging"` // Logging options for syslog server - Volumes []string `mapstructure:"volumes"` // Host-Volumes to mount in, syntax: /path/to/host/directory:/destination/path/in/container - Mounts []DockerMount `mapstructure:"mounts"` // Docker volumes to mount - VolumeDriver string `mapstructure:"volume_driver"` // Docker volume driver used for the container's volumes - ForcePull bool `mapstructure:"force_pull"` // Always force pull before running image, useful if your tags are mutable - MacAddress string `mapstructure:"mac_address"` // Pin mac address to container - SecurityOpt []string `mapstructure:"security_opt"` // Flags to pass directly to security-opt - Devices []DockerDevice `mapstructure:"devices"` // To allow mounting USB or other serial control devices - CapAdd []string `mapstructure:"cap_add"` // Flags to pass directly to cap-add - CapDrop []string `mapstructure:"cap_drop"` // Flags to pass directly to cap-drop - ReadonlyRootfs bool `mapstructure:"readonly_rootfs"` // Mount the container’s root filesystem as read only - UseIPv6Address bool `mapstructure:"use_ipv6_address"` // Flag to use the GlobalIPv6Address from the container as the detected IP + ImageName string `mapstructure:"image"` // Container's Image Name + LoadImage string `mapstructure:"load"` // LoadImage is a path to an image archive file + Command string `mapstructure:"command"` // The Command to run when the container starts up + Args []string `mapstructure:"args"` // The arguments to the Command + Entrypoint []string `mapstructure:"entrypoint"` // Override the containers entrypoint + IpcMode string `mapstructure:"ipc_mode"` // The IPC mode of the container - host and none + NetworkMode string `mapstructure:"network_mode"` // The network mode of the container - host, nat and none + NetworkAliases []string `mapstructure:"network_aliases"` // The network-scoped alias for the container + IPv4Address string `mapstructure:"ipv4_address"` // The container ipv4 address + IPv6Address string `mapstructure:"ipv6_address"` // the container ipv6 address + PidMode string `mapstructure:"pid_mode"` // The PID mode of the container - host and none + UTSMode string `mapstructure:"uts_mode"` // The UTS mode of the container - host and none + UsernsMode string `mapstructure:"userns_mode"` // The User namespace mode of the container - host and none + PortMapRaw []map[string]string `mapstructure:"port_map"` // + PortMap map[string]int `mapstructure:"-"` // A map of host port labels and the ports exposed on the container + Privileged bool `mapstructure:"privileged"` // Flag to run the container in privileged mode + SysctlRaw []map[string]string `mapstructure:"sysctl"` // + Sysctl map[string]string `mapstructure:"-"` // The sysctl custom configurations + UlimitRaw []map[string]string `mapstructure:"ulimit"` // + Ulimit []docker.ULimit `mapstructure:"-"` // The ulimit custom configurations + DNSServers []string `mapstructure:"dns_servers"` // DNS Server for containers + DNSSearchDomains []string `mapstructure:"dns_search_domains"` // DNS Search domains for containers + DNSOptions []string `mapstructure:"dns_options"` // DNS Options + ExtraHosts []string `mapstructure:"extra_hosts"` // Add host to /etc/hosts (host:IP) + Hostname string `mapstructure:"hostname"` // Hostname for containers + LabelsRaw []map[string]string `mapstructure:"labels"` // + Labels map[string]string `mapstructure:"-"` // Labels to set when the container starts up + Auth []DockerDriverAuth `mapstructure:"auth"` // Authentication credentials for a private Docker registry + AuthSoftFail bool `mapstructure:"auth_soft_fail"` // Soft-fail if auth creds are provided but fail + TTY bool `mapstructure:"tty"` // Allocate a Pseudo-TTY + Interactive bool `mapstructure:"interactive"` // Keep STDIN open even if not attached + ShmSize int64 `mapstructure:"shm_size"` // Size of /dev/shm of the container in bytes + WorkDir string `mapstructure:"work_dir"` // Working directory inside the container + Logging []DockerLoggingOpts `mapstructure:"logging"` // Logging options for syslog server + Volumes []string `mapstructure:"volumes"` // Host-Volumes to mount in, syntax: /path/to/host/directory:/destination/path/in/container + Mounts []DockerMount `mapstructure:"mounts"` // Docker volumes to mount + VolumeDriver string `mapstructure:"volume_driver"` // Docker volume driver used for the container's volumes + ForcePull bool `mapstructure:"force_pull"` // Always force pull before running image, useful if your tags are mutable + MacAddress string `mapstructure:"mac_address"` // Pin mac address to container + SecurityOpt []string `mapstructure:"security_opt"` // Flags to pass directly to security-opt + Devices []DockerDevice `mapstructure:"devices"` // To allow mounting USB or other serial control devices + CapAdd []string `mapstructure:"cap_add"` // Flags to pass directly to cap-add + CapDrop []string `mapstructure:"cap_drop"` // Flags to pass directly to cap-drop + ReadonlyRootfs bool `mapstructure:"readonly_rootfs"` // Mount the container’s root filesystem as read only + AdvertiseIPv6Address bool `mapstructure:"advertise_ipv6_address"` // Flag to use the GlobalIPv6Address from the container as the detected IP } func sliceMergeUlimit(ulimitsRaw map[string]string) ([]docker.ULimit, error) { @@ -675,7 +675,7 @@ func (d *DockerDriver) Validate(config map[string]interface{}) error { "readonly_rootfs": { Type: fields.TypeBool, }, - "use_ipv6_address": { + "advertise_ipv6_address": { Type: fields.TypeBool, }, }, @@ -888,8 +888,9 @@ func (d *DockerDriver) detectIP(c *docker.Container) (string, bool) { } ip = net.IPAddress - if d.driverConfig.UseIPv6Address { + if d.driverConfig.AdvertiseIPv6Address { ip = net.GlobalIPv6Address + auto = true } ipName = name diff --git a/website/source/docs/drivers/docker.html.md b/website/source/docs/drivers/docker.html.md index 0eca3537d28..99ef6de58ac 100644 --- a/website/source/docs/drivers/docker.html.md +++ b/website/source/docs/drivers/docker.html.md @@ -355,11 +355,9 @@ The `docker` driver supports the following configuration in the job spec. Only ] } ``` -* `use_ipv6_address` - (Optional) `true` or `false` (default). Use IPv6 Address - will use the containers IPv6 address (GlobalIPv6Address) when registering service checks and using - `address_mode = driver`. - See [service](/docs/job-specification/service.html) for details. - +* `advertise_ipv6_address` - (Optional) `true` or `false` (default). Use the container's + IPv6 address (GlobalIPv6Address in Docker) when registering services and checks. + See [IPv6 Docker containers](/docs/job-specification/service.html#IPv6 Docker containers) for details. * `readonly_rootfs` - (Optional) `true` or `false` (default). Mount the container's filesystem as read only. diff --git a/website/source/docs/job-specification/service.html.md b/website/source/docs/job-specification/service.html.md index 21d485352ed..ff5fcdba5a1 100644 --- a/website/source/docs/job-specification/service.html.md +++ b/website/source/docs/job-specification/service.html.md @@ -104,9 +104,6 @@ does not automatically enable service discovery. `address_mode="driver"`. Numeric ports may be used when in driver addressing mode. - Docker and IPv6 containers: This setting is required if you want to register - the port of the (IPv6) service. See [below for examples.](#IPv6 docker containers) - - `tags` `(array: [])` - Specifies the list of tags to associate with this service. If this is not supplied, no tags will be assigned to the service when it is registered. @@ -127,10 +124,6 @@ does not automatically enable service discovery. addresses. Task will fail if driver network cannot be determined. Only implemented for Docker and rkt. - Docker and IPv6 containers: If you want to register the IPv6 address - of the container you'll have to enable this and specify `use_ipv6_address` - in the docker driver configuration. See [below for examples.](#IPv6 docker containers) - - `host` - Use the host IP and port. ### `check` Parameters @@ -147,10 +140,6 @@ scripts. [below for details.](#using-driver-address-mode) Unlike `port`, this setting is *not* inherited from the `service`. - Docker and IPv6 containers: If you want to check the IPv6 address - of the container you'll have to enable this and specify `use_ipv6_address` - in the docker driver configuration. See [below for examples.](#IPv6 docker containers) - - `args` `(array: [])` - Specifies additional arguments to the `command`. This only applies to script-based health checks. @@ -197,9 +186,6 @@ scripts. default. In Nomad 0.7.1 or later numeric ports may be used if `address_mode="driver"` is set on the check. - Docker and IPv6 containers: Using a numeric port is required if you want to - check the port of (IPv6) service. See [below for examples.](#IPv6 docker containers) - - `protocol` `(string: "http")` - Specifies the protocol for the http-based health checks. Valid options are `http` and `https`. @@ -477,17 +463,21 @@ In this case Nomad doesn't need to assign Redis any host ports. The `service` and `check` stanzas can both specify the port number to advertise and check directly since Nomad isn't managing any port assignments. -### IPv6 docker containers +### IPv6 Docker containers + +The [Docker](/docs/drivers/docker.html#advertise_ipv6_address) driver supports the +`advertise_ipv6_address` parameter in it's configuration. -The [Docker](/docs/drivers/docker.html#use_ipv6_address) driver support the -`use_ipv6_address` parameter in it's configuration. +For the `service`stanza is no explicit `address_mode` required. +Services default to the `auto` address mode. -Besides enabling this parameter you have to set `address_mode` parameter in -both `service` and `check` stanzas to `driver`. +Unlike services, checks do not have an `auto` address mode as there's no way +for Nomad to know which is the best address to use for checks. Consul needs +access to the address for any HTTP or TCP checks. -You also have explicily specify the `port` that will be registered and checked. +So you have to set `address_mode` parameter in the `check` stanza to `driver`. -For example +For example using `auto` address mode: ```hcl job "example" { @@ -499,7 +489,51 @@ job "example" { config { image = "redis:3.2" - use_ipv6_address = true + advertise_ipv6_address = true + port_map { + db = 6379 + } + } + + resources { + cpu = 500 # 500 MHz + memory = 256 # 256MB + network { + mbits = 10 + port "db" {} + } + } + + service { + name = "ipv6-redis" + port = db + check { + name = "ipv6-redis-check" + type = "tcp" + interval = "10s" + timeout = "2s" + port = db + address_mode = "driver" + } + } + } + } +} +``` + +Or using `address_mode=driver` for `service` and `check` with numeric ports: + +```hcl +job "example" { + datacenters = ["dc1"] + group "cache" { + + task "redis" { + driver = "docker" + + config { + image = "redis:3.2" + advertise_ipv6_address = true # No port map required! } @@ -529,9 +563,8 @@ job "example" { } ``` -With IPv6 Nomad doesn't need to assign Redis any host ports. The `service` -and `check` stanzas can both specify the port number to advertise and check -directly since Nomad isn't managing any port assignments. +The `service` and `check` stanzas can both specify the port number to +advertise and check directly since Nomad isn't managing any port assignments. - - - From cdd55e45919adaca5703f5f010629d8e3a26ce48 Mon Sep 17 00:00:00 2001 From: Wim Date: Thu, 1 Feb 2018 14:25:14 +0100 Subject: [PATCH 3/7] Update documentation --- website/source/docs/job-specification/service.html.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/source/docs/job-specification/service.html.md b/website/source/docs/job-specification/service.html.md index ff5fcdba5a1..6d04e81321a 100644 --- a/website/source/docs/job-specification/service.html.md +++ b/website/source/docs/job-specification/service.html.md @@ -468,8 +468,8 @@ directly since Nomad isn't managing any port assignments. The [Docker](/docs/drivers/docker.html#advertise_ipv6_address) driver supports the `advertise_ipv6_address` parameter in it's configuration. -For the `service`stanza is no explicit `address_mode` required. -Services default to the `auto` address mode. +Services will automatically advertise the IPv6 address when `advertise_ipv6_address` +is used. Unlike services, checks do not have an `auto` address mode as there's no way for Nomad to know which is the best address to use for checks. Consul needs From d0dd6ef22f1ecd436a2dbe4eb32af262e24c00b5 Mon Sep 17 00:00:00 2001 From: Wim Date: Thu, 1 Feb 2018 23:21:28 +0100 Subject: [PATCH 4/7] Add IPv6 support to travis docker --- scripts/travis-linux.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/travis-linux.sh b/scripts/travis-linux.sh index 4c402b797a2..4d5986788e0 100644 --- a/scripts/travis-linux.sh +++ b/scripts/travis-linux.sh @@ -2,6 +2,10 @@ set -o errexit +#enable ipv6 +echo '{"ipv6":true, "fixed-cidr-v6":"2001:db8:1::/64"}' | sudo tee /etc/docker/daemon.json +sudo service docker restart + apt-get update apt-get install -y liblxc1 lxc-dev lxc shellcheck apt-get install -y qemu From 51bf06f468197175dcf705588e65913423a1f093 Mon Sep 17 00:00:00 2001 From: Wim Date: Thu, 1 Feb 2018 23:21:47 +0100 Subject: [PATCH 5/7] Add AdvertiseIPv6Address test --- client/driver/docker_test.go | 71 ++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/client/driver/docker_test.go b/client/driver/docker_test.go index 6dc5d97c5c1..922083ce2bd 100644 --- a/client/driver/docker_test.go +++ b/client/driver/docker_test.go @@ -2269,3 +2269,74 @@ func TestDockerDriver_ReadonlyRootfs(t *testing.T) { assert.True(t, container.HostConfig.ReadonlyRootfs, "ReadonlyRootfs option not set") } + +func TestDockerDriver_AdvertiseIPv6Address(t *testing.T) { + if !tu.IsTravis() { + t.Parallel() + } + if !testutil.DockerIsConnected(t) { + t.Skip("Docker not connected") + } + expectedPrefix := "2001:db8:1::242:ac11" + expectedAdvertise := true + task := &structs.Task{ + Name: "nc-demo", + Driver: "docker", + Config: map[string]interface{}{ + "image": "busybox", + "load": "busybox.tar", + "command": "/bin/nc", + "args": []string{"-l", "127.0.0.1", "-p", "0"}, + "advertise_ipv6_address": expectedAdvertise, + }, + Resources: &structs.Resources{ + MemoryMB: 256, + CPU: 512, + }, + LogConfig: &structs.LogConfig{ + MaxFiles: 10, + MaxFileSizeMB: 10, + }, + } + + client := newTestDockerClient(t) + tctx := testDockerDriverContexts(t, task) + driver := NewDockerDriver(tctx.DriverCtx) + copyImage(t, tctx.ExecCtx.TaskDir, "busybox.tar") + defer tctx.AllocDir.Destroy() + + presp, err := driver.Prestart(tctx.ExecCtx, task) + defer driver.Cleanup(tctx.ExecCtx, presp.CreatedResources) + if err != nil { + t.Fatalf("Error in prestart: %v", err) + } + + sresp, err := driver.Start(tctx.ExecCtx, task) + if err != nil { + t.Fatalf("Error in start: %v", err) + } + + if sresp.Handle == nil { + t.Fatalf("handle is nil\nStack\n%s", debug.Stack()) + } + + assert.Equal(t, expectedAdvertise, sresp.Network.AutoAdvertise, "Wrong autoadvertise. Expect: %s, got: %s", expectedAdvertise, sresp.Network.AutoAdvertise) + + if !strings.HasPrefix(sresp.Network.IP, expectedPrefix) { + t.Fatalf("Got IP address %s want ip address with prefix %s", sresp.Network.IP, expectedPrefix) + } + + defer sresp.Handle.Kill() + handle := sresp.Handle.(*DockerHandle) + + waitForExist(t, client, handle) + + container, err := client.InspectContainer(handle.ContainerID()) + if err != nil { + t.Fatalf("Error inspecting container: %v", err) + } + + if !strings.HasPrefix(container.NetworkSettings.GlobalIPv6Address, expectedPrefix) { + t.Fatalf("Got GlobalIPv6address %s want GlobalIPv6address with prefix %s", expectedPrefix, container.NetworkSettings.GlobalIPv6Address) + } +} From e486a27a4e65fd635519deea828112f47b80e0e8 Mon Sep 17 00:00:00 2001 From: Michael Schurter Date: Mon, 5 Feb 2018 16:24:30 -0800 Subject: [PATCH 6/7] docker: Skip IPv6 test if IPv6 disabled --- client/driver/docker_test.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/client/driver/docker_test.go b/client/driver/docker_test.go index 922083ce2bd..db5273d027d 100644 --- a/client/driver/docker_test.go +++ b/client/driver/docker_test.go @@ -2277,6 +2277,7 @@ func TestDockerDriver_AdvertiseIPv6Address(t *testing.T) { if !testutil.DockerIsConnected(t) { t.Skip("Docker not connected") } + expectedPrefix := "2001:db8:1::242:ac11" expectedAdvertise := true task := &structs.Task{ @@ -2300,6 +2301,16 @@ func TestDockerDriver_AdvertiseIPv6Address(t *testing.T) { } client := newTestDockerClient(t) + + // Make sure IPv6 is enabled + net, err := client.NetworkInfo("bridge") + if err != nil { + t.Skip("error retrieving bridge network information, skipping") + } + if net == nil || !net.EnableIPv6 { + t.Skip("IPv6 not enabled on bridge network, skipping") + } + tctx := testDockerDriverContexts(t, task) driver := NewDockerDriver(tctx.DriverCtx) copyImage(t, tctx.ExecCtx.TaskDir, "busybox.tar") @@ -2323,7 +2334,7 @@ func TestDockerDriver_AdvertiseIPv6Address(t *testing.T) { assert.Equal(t, expectedAdvertise, sresp.Network.AutoAdvertise, "Wrong autoadvertise. Expect: %s, got: %s", expectedAdvertise, sresp.Network.AutoAdvertise) if !strings.HasPrefix(sresp.Network.IP, expectedPrefix) { - t.Fatalf("Got IP address %s want ip address with prefix %s", sresp.Network.IP, expectedPrefix) + t.Fatalf("Got IP address %q want ip address with prefix %q", sresp.Network.IP, expectedPrefix) } defer sresp.Handle.Kill() From 5ff86f0d2abfa07f2f9d6f07e4e7c4a24655aca2 Mon Sep 17 00:00:00 2001 From: Michael Schurter Date: Mon, 5 Feb 2018 16:29:29 -0800 Subject: [PATCH 7/7] Add changelog entry for #3790 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f5a2ca22aa4..aa29452e8a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ IMPROVEMENTS: * client: Allow '.' in environment variable names [[GH-3760](https://github.com/hashicorp/nomad/issues/3760)] * discovery: Allow `check_restart` to be specified in the `service` stanza. [[GH-3718](https://github.com/hashicorp/nomad/issues/3718)] + * driver/docker: Support advertising IPv6 addresses [[GH-3790](https://github.com/hashicorp/nomad/issues/3790)] * driver/docker; Support overriding image entrypoint [[GH-3788](https://github.com/hashicorp/nomad/issues/3788)] * driver/docker: Support adding or dropping capabilities [[GH-3754](https://github.com/hashicorp/nomad/issues/3754)] * driver/docker: Support mounting root filesystem as read-only [[GH-3802](https://github.com/hashicorp/nomad/issues/3802)]