client: expose group network ports in env vars

Fixes #6375

Intentionally omitted IPs prior to 0.10.0 release to minimize changes
and risk.
This commit is contained in:
Michael Schurter 2019-10-18 15:42:28 -07:00
parent a05cf13d48
commit 460bd63db0
3 changed files with 93 additions and 44 deletions

View File

@ -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 { } else if alloc.TaskResources != nil {
if tr, ok := alloc.TaskResources[b.taskName]; ok { if tr, ok := alloc.TaskResources[b.taskName]; ok {
// Copy networks to prevent sharing // 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) key = fmt.Sprintf("%s%s_%s", PortPrefix, taskName, portLabel)
m[key] = strconv.Itoa(port) 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)
}

View File

@ -334,7 +334,7 @@ func TestEnvironment_AllValues(t *testing.T) {
"nested.meta.key": "a", "nested.meta.key": "a",
"invalid...metakey": "b", "invalid...metakey": "b",
} }
a := mock.Alloc() a := mock.ConnectAlloc()
a.AllocatedResources.Tasks["web"].Networks[0] = &structs.NetworkResource{ a.AllocatedResources.Tasks["web"].Networks[0] = &structs.NetworkResource{
Device: "eth0", Device: "eth0",
IP: "127.0.0.1", 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 := a.Job.TaskGroups[0].Tasks[0]
task.Env = map[string]string{ task.Env = map[string]string{
"taskEnvKey": "taskEnvVal", "taskEnvKey": "taskEnvVal",
@ -402,41 +418,47 @@ func TestEnvironment_AllValues(t *testing.T) {
"node.attr.nomad.version": "0.5.0", "node.attr.nomad.version": "0.5.0",
// Env // Env
"taskEnvKey": "taskEnvVal", "taskEnvKey": "taskEnvVal",
"NOMAD_ADDR_http": "127.0.0.1:80", "NOMAD_ADDR_http": "127.0.0.1:80",
"NOMAD_PORT_http": "80", "NOMAD_PORT_http": "80",
"NOMAD_IP_http": "127.0.0.1", "NOMAD_IP_http": "127.0.0.1",
"NOMAD_ADDR_https": "127.0.0.1:8080", "NOMAD_ADDR_https": "127.0.0.1:8080",
"NOMAD_PORT_https": "443", "NOMAD_PORT_https": "443",
"NOMAD_IP_https": "127.0.0.1", "NOMAD_IP_https": "127.0.0.1",
"NOMAD_HOST_PORT_http": "80", "NOMAD_HOST_PORT_http": "80",
"NOMAD_HOST_PORT_https": "8080", "NOMAD_HOST_PORT_https": "8080",
"NOMAD_TASK_NAME": "web", "NOMAD_TASK_NAME": "web",
"NOMAD_GROUP_NAME": "web", "NOMAD_GROUP_NAME": "web",
"NOMAD_ADDR_ssh_other": "192.168.0.100:1234", "NOMAD_ADDR_ssh_other": "192.168.0.100:1234",
"NOMAD_ADDR_ssh_ssh": "192.168.0.100:22", "NOMAD_ADDR_ssh_ssh": "192.168.0.100:22",
"NOMAD_IP_ssh_other": "192.168.0.100", "NOMAD_IP_ssh_other": "192.168.0.100",
"NOMAD_IP_ssh_ssh": "192.168.0.100", "NOMAD_IP_ssh_ssh": "192.168.0.100",
"NOMAD_PORT_ssh_other": "1234", "NOMAD_PORT_ssh_other": "1234",
"NOMAD_PORT_ssh_ssh": "22", "NOMAD_PORT_ssh_ssh": "22",
"NOMAD_CPU_LIMIT": "500", "NOMAD_CPU_LIMIT": "500",
"NOMAD_DC": "dc1", "NOMAD_DC": "dc1",
"NOMAD_NAMESPACE": "default", "NOMAD_NAMESPACE": "default",
"NOMAD_REGION": "global", "NOMAD_REGION": "global",
"NOMAD_MEMORY_LIMIT": "256", "NOMAD_MEMORY_LIMIT": "256",
"NOMAD_META_ELB_CHECK_INTERVAL": "30s", "NOMAD_META_ELB_CHECK_INTERVAL": "30s",
"NOMAD_META_ELB_CHECK_MIN": "3", "NOMAD_META_ELB_CHECK_MIN": "3",
"NOMAD_META_ELB_CHECK_TYPE": "http", "NOMAD_META_ELB_CHECK_TYPE": "http",
"NOMAD_META_FOO": "bar", "NOMAD_META_FOO": "bar",
"NOMAD_META_OWNER": "armon", "NOMAD_META_OWNER": "armon",
"NOMAD_META_elb_check_interval": "30s", "NOMAD_META_elb_check_interval": "30s",
"NOMAD_META_elb_check_min": "3", "NOMAD_META_elb_check_min": "3",
"NOMAD_META_elb_check_type": "http", "NOMAD_META_elb_check_type": "http",
"NOMAD_META_foo": "bar", "NOMAD_META_foo": "bar",
"NOMAD_META_owner": "armon", "NOMAD_META_owner": "armon",
"NOMAD_JOB_NAME": "my-job", "NOMAD_JOB_NAME": "my-job",
"NOMAD_ALLOC_ID": a.ID, "NOMAD_ALLOC_ID": a.ID,
"NOMAD_ALLOC_INDEX": "0", "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 // 0.9 style env map
`env["taskEnvKey"]`: "taskEnvVal", `env["taskEnvKey"]`: "taskEnvVal",

View File

@ -76,19 +76,21 @@ job "docs" {
- `mode` `(string: "host")` - Mode of the network. The following modes are available: - `mode` `(string: "host")` - Mode of the network. The following modes are available:
- “none” - Task group will have an isolated network without any network interfaces. - `none` - Task group will have an isolated network without any network interfaces.
- “bridge” - Task group will have an isolated network namespace with an interface - `bridge` - Task group will have an isolated network namespace with an interface
that is bridged with the host. Note that bridge networking is only that is bridged with the host. Note that bridge networking is only
currently supported for the `docker`, `exec`, `raw_exec`, and `java` task currently supported for the `docker`, `exec`, `raw_exec`, and `java` task
drivers. 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. namespace is not created. This matches the current behavior in Nomad 0.9.
### `port` Parameters ### `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 - `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. 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_<label>`
environment variable will contain the `to` value.
The label assigned to the port is used to identify the port in service The label assigned to the port is used to identify the port in service
discovery, and used in the name of the environment variable that indicates discovery, and used in the name of the environment variable that indicates
@ -210,10 +212,12 @@ network {
} }
``` ```
### Limitations
* Only one `network` stanza can be specified, when it is defined at the task group level.
* Only the `NOMAD_PORT_<label>` and `NOMAD_HOST_PORT_<label>` environment
variables are set for group network ports.
[docker-driver]: /docs/drivers/docker.html "Nomad Docker Driver" [docker-driver]: /docs/drivers/docker.html "Nomad Docker Driver"
[qemu-driver]: /docs/drivers/qemu.html "Nomad QEMU Driver" [qemu-driver]: /docs/drivers/qemu.html "Nomad QEMU Driver"
[Connect]: /docs/job-specification/connect.html "Nomad Consul Connect Integration" [Connect]: /docs/job-specification/connect.html "Nomad Consul Connect Integration"
### Limitations
Only one `network` stanza can be specified, when it is defined at the task group level.