From 5a6818510e11ee8840b9dd667eff01cf5380563a Mon Sep 17 00:00:00 2001 From: Michael Schurter Date: Fri, 18 Oct 2019 15:42:28 -0700 Subject: [PATCH] client: expose group network ports in env vars Fixes #6375 Intentionally omitted IPs prior to 0.10.0 release to minimize changes and risk. --- client/taskenv/env.go | 23 +++++ client/taskenv/env_test.go | 94 ++++++++++++------- .../docs/job-specification/network.html.md | 20 ++-- 3 files changed, 93 insertions(+), 44 deletions(-) diff --git a/client/taskenv/env.go b/client/taskenv/env.go index 62f6c8673..35d558250 100644 --- a/client/taskenv/env.go +++ b/client/taskenv/env.go @@ -631,6 +631,17 @@ func (b *Builder) setAlloc(alloc *structs.Allocation) *Builder { } } } + + // Add ports from group networks + //TODO Expose IPs but possibly only via variable interpolation + for _, nw := range alloc.AllocatedResources.Shared.Networks { + for _, p := range nw.ReservedPorts { + addGroupPort(b.otherPorts, p) + } + for _, p := range nw.DynamicPorts { + addGroupPort(b.otherPorts, p) + } + } } else if alloc.TaskResources != nil { if tr, ok := alloc.TaskResources[b.taskName]; ok { // Copy networks to prevent sharing @@ -849,3 +860,15 @@ func addPort(m map[string]string, taskName, ip, portLabel string, port int) { key = fmt.Sprintf("%s%s_%s", PortPrefix, taskName, portLabel) m[key] = strconv.Itoa(port) } + +// addGroupPort adds a group network port. The To value is used if one is +// specified. +func addGroupPort(m map[string]string, port structs.Port) { + if port.To > 0 { + m[PortPrefix+port.Label] = strconv.Itoa(port.To) + } else { + m[PortPrefix+port.Label] = strconv.Itoa(port.Value) + } + + m[HostPortPrefix+port.Label] = strconv.Itoa(port.Value) +} diff --git a/client/taskenv/env_test.go b/client/taskenv/env_test.go index e4f101299..4a15923bd 100644 --- a/client/taskenv/env_test.go +++ b/client/taskenv/env_test.go @@ -334,7 +334,7 @@ func TestEnvironment_AllValues(t *testing.T) { "nested.meta.key": "a", "invalid...metakey": "b", } - a := mock.Alloc() + a := mock.ConnectAlloc() a.AllocatedResources.Tasks["web"].Networks[0] = &structs.NetworkResource{ Device: "eth0", IP: "127.0.0.1", @@ -355,6 +355,22 @@ func TestEnvironment_AllValues(t *testing.T) { }, }, } + + sharedNet := a.AllocatedResources.Shared.Networks[0] + + // Add group network port with only a host port. + sharedNet.DynamicPorts = append(sharedNet.DynamicPorts, structs.Port{ + Label: "hostonly", + Value: 9998, + }) + + // Add group network reserved port with a To value. + sharedNet.ReservedPorts = append(sharedNet.ReservedPorts, structs.Port{ + Label: "static", + Value: 9997, + To: 97, + }) + task := a.Job.TaskGroups[0].Tasks[0] task.Env = map[string]string{ "taskEnvKey": "taskEnvVal", @@ -402,41 +418,47 @@ func TestEnvironment_AllValues(t *testing.T) { "node.attr.nomad.version": "0.5.0", // Env - "taskEnvKey": "taskEnvVal", - "NOMAD_ADDR_http": "127.0.0.1:80", - "NOMAD_PORT_http": "80", - "NOMAD_IP_http": "127.0.0.1", - "NOMAD_ADDR_https": "127.0.0.1:8080", - "NOMAD_PORT_https": "443", - "NOMAD_IP_https": "127.0.0.1", - "NOMAD_HOST_PORT_http": "80", - "NOMAD_HOST_PORT_https": "8080", - "NOMAD_TASK_NAME": "web", - "NOMAD_GROUP_NAME": "web", - "NOMAD_ADDR_ssh_other": "192.168.0.100:1234", - "NOMAD_ADDR_ssh_ssh": "192.168.0.100:22", - "NOMAD_IP_ssh_other": "192.168.0.100", - "NOMAD_IP_ssh_ssh": "192.168.0.100", - "NOMAD_PORT_ssh_other": "1234", - "NOMAD_PORT_ssh_ssh": "22", - "NOMAD_CPU_LIMIT": "500", - "NOMAD_DC": "dc1", - "NOMAD_NAMESPACE": "default", - "NOMAD_REGION": "global", - "NOMAD_MEMORY_LIMIT": "256", - "NOMAD_META_ELB_CHECK_INTERVAL": "30s", - "NOMAD_META_ELB_CHECK_MIN": "3", - "NOMAD_META_ELB_CHECK_TYPE": "http", - "NOMAD_META_FOO": "bar", - "NOMAD_META_OWNER": "armon", - "NOMAD_META_elb_check_interval": "30s", - "NOMAD_META_elb_check_min": "3", - "NOMAD_META_elb_check_type": "http", - "NOMAD_META_foo": "bar", - "NOMAD_META_owner": "armon", - "NOMAD_JOB_NAME": "my-job", - "NOMAD_ALLOC_ID": a.ID, - "NOMAD_ALLOC_INDEX": "0", + "taskEnvKey": "taskEnvVal", + "NOMAD_ADDR_http": "127.0.0.1:80", + "NOMAD_PORT_http": "80", + "NOMAD_IP_http": "127.0.0.1", + "NOMAD_ADDR_https": "127.0.0.1:8080", + "NOMAD_PORT_https": "443", + "NOMAD_IP_https": "127.0.0.1", + "NOMAD_HOST_PORT_http": "80", + "NOMAD_HOST_PORT_https": "8080", + "NOMAD_TASK_NAME": "web", + "NOMAD_GROUP_NAME": "web", + "NOMAD_ADDR_ssh_other": "192.168.0.100:1234", + "NOMAD_ADDR_ssh_ssh": "192.168.0.100:22", + "NOMAD_IP_ssh_other": "192.168.0.100", + "NOMAD_IP_ssh_ssh": "192.168.0.100", + "NOMAD_PORT_ssh_other": "1234", + "NOMAD_PORT_ssh_ssh": "22", + "NOMAD_CPU_LIMIT": "500", + "NOMAD_DC": "dc1", + "NOMAD_NAMESPACE": "default", + "NOMAD_REGION": "global", + "NOMAD_MEMORY_LIMIT": "256", + "NOMAD_META_ELB_CHECK_INTERVAL": "30s", + "NOMAD_META_ELB_CHECK_MIN": "3", + "NOMAD_META_ELB_CHECK_TYPE": "http", + "NOMAD_META_FOO": "bar", + "NOMAD_META_OWNER": "armon", + "NOMAD_META_elb_check_interval": "30s", + "NOMAD_META_elb_check_min": "3", + "NOMAD_META_elb_check_type": "http", + "NOMAD_META_foo": "bar", + "NOMAD_META_owner": "armon", + "NOMAD_JOB_NAME": "my-job", + "NOMAD_ALLOC_ID": a.ID, + "NOMAD_ALLOC_INDEX": "0", + "NOMAD_PORT_connect_proxy_testconnect": "9999", + "NOMAD_HOST_PORT_connect_proxy_testconnect": "9999", + "NOMAD_PORT_hostonly": "9998", + "NOMAD_HOST_PORT_hostonly": "9998", + "NOMAD_PORT_static": "97", + "NOMAD_HOST_PORT_static": "9997", // 0.9 style env map `env["taskEnvKey"]`: "taskEnvVal", diff --git a/website/source/docs/job-specification/network.html.md b/website/source/docs/job-specification/network.html.md index 08f0ae8f2..17828ce63 100644 --- a/website/source/docs/job-specification/network.html.md +++ b/website/source/docs/job-specification/network.html.md @@ -76,19 +76,21 @@ job "docs" { - `mode` `(string: "host")` - Mode of the network. The following modes are available: - - “none” - Task group will have an isolated network without any network interfaces. - - “bridge” - Task group will have an isolated network namespace with an interface + - `none` - Task group will have an isolated network without any network interfaces. + - `bridge` - Task group will have an isolated network namespace with an interface that is bridged with the host. Note that bridge networking is only currently supported for the `docker`, `exec`, `raw_exec`, and `java` task drivers. - - “host” - Each task will join the host network namespace and a shared network + - `host` - Each task will join the host network namespace and a shared network namespace is not created. This matches the current behavior in Nomad 0.9. ### `port` Parameters - `static` `(int: nil)` - Specifies the static TCP/UDP port to allocate. If omitted, a dynamic port is chosen. We **do not recommend** using static ports, except for `system` or specialized jobs like load balancers. -- `to` `(string:nil)` - Applicable when using "bridge" mode to configure port to map to inside the task's network namespace. +- `to` `(string:nil)` - Applicable when using "bridge" mode to configure port + to map to inside the task's network namespace. The `NOMAD_PORT_