mirror of
https://github.com/kemko/nomad.git
synced 2026-01-04 17:35:43 +03:00
Merge pull request #704 from iverberk/f-env-ports
Pass a combination of ip and port to the task environment.
This commit is contained in:
@@ -341,15 +341,8 @@ func (d *DockerDriver) createContainer(ctx *ExecContext, task *structs.Task, dri
|
||||
d.logger.Printf("[DEBUG] driver.docker: exposed port %s", containerPort)
|
||||
}
|
||||
|
||||
// This was set above in a call to GetTaskEnv but if we
|
||||
// have mapped any ports we will need to override them.
|
||||
//
|
||||
// TODO refactor the implementation in GetTaskEnv to match
|
||||
// the 0.2 ports world view. Docker seems to be the only place where
|
||||
// this is actually needed, but this is kinda hacky.
|
||||
if len(driverConfig.PortMap) > 0 {
|
||||
d.taskEnv.SetPorts(network.MapLabelToValues(driverConfig.PortMap))
|
||||
}
|
||||
d.taskEnv.SetPortMap(driverConfig.PortMap)
|
||||
|
||||
hostConfig.PortBindings = publishedPorts
|
||||
config.ExposedPorts = exposedPorts
|
||||
}
|
||||
|
||||
@@ -551,8 +551,8 @@ func TestDockerPortsNoMap(t *testing.T) {
|
||||
}
|
||||
|
||||
expectedEnvironment := map[string]string{
|
||||
"NOMAD_PORT_main": fmt.Sprintf("%d", res),
|
||||
"NOMAD_PORT_REDIS": fmt.Sprintf("%d", dyn),
|
||||
"NOMAD_ADDR_main": fmt.Sprintf("127.0.0.1:%d", res),
|
||||
"NOMAD_ADDR_REDIS": fmt.Sprintf("127.0.0.1:%d", dyn),
|
||||
}
|
||||
|
||||
for key, val := range expectedEnvironment {
|
||||
@@ -606,8 +606,9 @@ func TestDockerPortsMapping(t *testing.T) {
|
||||
}
|
||||
|
||||
expectedEnvironment := map[string]string{
|
||||
"NOMAD_PORT_main": "8080",
|
||||
"NOMAD_PORT_REDIS": "6379",
|
||||
"NOMAD_ADDR_main": "127.0.0.1:8080",
|
||||
"NOMAD_ADDR_REDIS": "127.0.0.1:6379",
|
||||
"NOMAD_HOST_PORT_main": "8080",
|
||||
}
|
||||
|
||||
for key, val := range expectedEnvironment {
|
||||
|
||||
@@ -148,12 +148,7 @@ func GetTaskEnv(alloc *allocdir.AllocDir, node *structs.Node, task *structs.Task
|
||||
if task.Resources != nil {
|
||||
env.SetMemLimit(task.Resources.MemoryMB)
|
||||
env.SetCpuLimit(task.Resources.CPU)
|
||||
|
||||
if len(task.Resources.Networks) > 0 {
|
||||
network := task.Resources.Networks[0]
|
||||
env.SetTaskIp(network.IP)
|
||||
env.SetPorts(network.MapLabelToValues(nil))
|
||||
}
|
||||
env.SetNetworks(task.Resources.Networks)
|
||||
}
|
||||
|
||||
return env.Build(), nil
|
||||
|
||||
@@ -113,13 +113,12 @@ func TestDriver_GetTaskEnv(t *testing.T) {
|
||||
exp := map[string]string{
|
||||
"NOMAD_CPU_LIMIT": "1000",
|
||||
"NOMAD_MEMORY_LIMIT": "500",
|
||||
"NOMAD_IP": "1.2.3.4",
|
||||
"NOMAD_PORT_one": "80",
|
||||
"NOMAD_PORT_two": "443",
|
||||
"NOMAD_PORT_three": "8080",
|
||||
"NOMAD_PORT_four": "12345",
|
||||
"NOMAD_PORT_admin": "8081",
|
||||
"NOMAD_PORT_web": "8086",
|
||||
"NOMAD_ADDR_one": "1.2.3.4:80",
|
||||
"NOMAD_ADDR_two": "1.2.3.4:443",
|
||||
"NOMAD_ADDR_three": "1.2.3.4:8080",
|
||||
"NOMAD_ADDR_four": "1.2.3.4:12345",
|
||||
"NOMAD_ADDR_admin": "1.2.3.4:8081",
|
||||
"NOMAD_ADDR_web": "1.2.3.4:8086",
|
||||
"NOMAD_META_CHOCOLATE": "cake",
|
||||
"NOMAD_META_STRAWBERRY": "icecream",
|
||||
"HELLO": "world",
|
||||
|
||||
45
client/driver/env/env.go
vendored
45
client/driver/env/env.go
vendored
@@ -30,8 +30,11 @@ const (
|
||||
|
||||
// Prefix for passing both dynamic and static port allocations to
|
||||
// tasks.
|
||||
// E.g. $NOMAD_PORT_1 or $NOMAD_PORT_http
|
||||
PortPrefix = "NOMAD_PORT_"
|
||||
// E.g. $NOMAD_IP_1=127.0.0.1:1 or $NOMAD_IP_http=127.0.0.1:80
|
||||
AddrPrefix = "NOMAD_ADDR_"
|
||||
|
||||
// Prefix for passing the host port when a portmap is specified.
|
||||
HostPortPrefix = "NOMAD_HOST_PORT_"
|
||||
|
||||
// Prefix for passing task meta data.
|
||||
MetaPrefix = "NOMAD_META_"
|
||||
@@ -54,13 +57,13 @@ const (
|
||||
type TaskEnvironment struct {
|
||||
env map[string]string
|
||||
meta map[string]string
|
||||
ports map[string]int
|
||||
allocDir string
|
||||
taskDir string
|
||||
cpuLimit int
|
||||
memLimit int
|
||||
ip string
|
||||
node *structs.Node
|
||||
networks []*structs.NetworkResource
|
||||
portMap map[string]int
|
||||
|
||||
// taskEnv is the variables that will be set in the tasks environment
|
||||
taskEnv map[string]string
|
||||
@@ -103,8 +106,16 @@ func (t *TaskEnvironment) Build() *TaskEnvironment {
|
||||
}
|
||||
|
||||
// Build the ports
|
||||
for label, port := range t.ports {
|
||||
t.taskEnv[fmt.Sprintf("%s%s", PortPrefix, label)] = strconv.Itoa(port)
|
||||
for _, network := range t.networks {
|
||||
for label, value := range network.MapLabelToValues(t.portMap) {
|
||||
IPPort := fmt.Sprintf("%s:%d", network.IP, value)
|
||||
t.taskEnv[fmt.Sprintf("%s%s", AddrPrefix, label)] = IPPort
|
||||
|
||||
// Pass an explicit port mapping to the environment
|
||||
if port, ok := t.portMap[label]; ok {
|
||||
t.taskEnv[fmt.Sprintf("%s%s", HostPortPrefix, label)] = strconv.Itoa(port)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build the directories
|
||||
@@ -123,11 +134,6 @@ func (t *TaskEnvironment) Build() *TaskEnvironment {
|
||||
t.taskEnv[CpuLimit] = strconv.Itoa(t.cpuLimit)
|
||||
}
|
||||
|
||||
// Build the IP
|
||||
if t.ip != "" {
|
||||
t.taskEnv[TaskIP] = t.ip
|
||||
}
|
||||
|
||||
// Build the node
|
||||
if t.node != nil {
|
||||
// Set up the node values.
|
||||
@@ -221,24 +227,23 @@ func (t *TaskEnvironment) ClearCpuLimit() *TaskEnvironment {
|
||||
return t
|
||||
}
|
||||
|
||||
func (t *TaskEnvironment) SetTaskIp(ip string) *TaskEnvironment {
|
||||
t.ip = ip
|
||||
func (t *TaskEnvironment) SetNetworks(networks []*structs.NetworkResource) *TaskEnvironment {
|
||||
t.networks = networks
|
||||
return t
|
||||
}
|
||||
|
||||
func (t *TaskEnvironment) ClearTaskIp() *TaskEnvironment {
|
||||
t.ip = ""
|
||||
func (t *TaskEnvironment) clearNetworks() *TaskEnvironment {
|
||||
t.networks = nil
|
||||
return t
|
||||
}
|
||||
|
||||
// Takes a map of port labels to their port value.
|
||||
func (t *TaskEnvironment) SetPorts(ports map[string]int) *TaskEnvironment {
|
||||
t.ports = ports
|
||||
func (t *TaskEnvironment) SetPortMap(portMap map[string]int) *TaskEnvironment {
|
||||
t.portMap = portMap
|
||||
return t
|
||||
}
|
||||
|
||||
func (t *TaskEnvironment) ClearPorts() *TaskEnvironment {
|
||||
t.ports = nil
|
||||
func (t *TaskEnvironment) clearPortMap() *TaskEnvironment {
|
||||
t.portMap = nil
|
||||
return t
|
||||
}
|
||||
|
||||
|
||||
42
client/driver/env/env_test.go
vendored
42
client/driver/env/env_test.go
vendored
@@ -7,6 +7,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/nomad/nomad/mock"
|
||||
"github.com/hashicorp/nomad/nomad/structs"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -25,6 +26,20 @@ const (
|
||||
envTwoVal = ":80"
|
||||
)
|
||||
|
||||
var (
|
||||
// Networks that tests can rely on
|
||||
networks = []*structs.NetworkResource{
|
||||
&structs.NetworkResource{
|
||||
IP: "127.0.0.1",
|
||||
ReservedPorts: []structs.Port{{"http", 80}},
|
||||
DynamicPorts: []structs.Port{{"https", 8080}},
|
||||
},
|
||||
}
|
||||
portMap = map[string]int{
|
||||
"https": 443,
|
||||
}
|
||||
)
|
||||
|
||||
func testTaskEnvironment() *TaskEnvironment {
|
||||
n := mock.Node()
|
||||
n.Attributes = map[string]string{
|
||||
@@ -121,11 +136,17 @@ func TestEnvironment_ReplaceEnv_Mixed(t *testing.T) {
|
||||
func TestEnvironment_AsList(t *testing.T) {
|
||||
n := mock.Node()
|
||||
env := NewTaskEnvironment(n).
|
||||
SetTaskIp("127.0.0.1").SetPorts(map[string]int{"http": 80}).
|
||||
SetNetworks(networks).
|
||||
SetPortMap(portMap).
|
||||
SetMeta(map[string]string{"foo": "baz"}).Build()
|
||||
|
||||
act := env.EnvList()
|
||||
exp := []string{"NOMAD_IP=127.0.0.1", "NOMAD_PORT_http=80", "NOMAD_META_FOO=baz"}
|
||||
exp := []string{
|
||||
"NOMAD_ADDR_http=127.0.0.1:80",
|
||||
"NOMAD_ADDR_https=127.0.0.1:443",
|
||||
"NOMAD_HOST_PORT_https=443",
|
||||
"NOMAD_META_FOO=baz",
|
||||
}
|
||||
sort.Strings(act)
|
||||
sort.Strings(exp)
|
||||
if !reflect.DeepEqual(act, exp) {
|
||||
@@ -136,11 +157,18 @@ func TestEnvironment_AsList(t *testing.T) {
|
||||
func TestEnvironment_ClearEnvvars(t *testing.T) {
|
||||
n := mock.Node()
|
||||
env := NewTaskEnvironment(n).
|
||||
SetTaskIp("127.0.0.1").
|
||||
SetNetworks(networks).
|
||||
SetPortMap(portMap).
|
||||
SetEnvvars(map[string]string{"foo": "baz", "bar": "bang"}).Build()
|
||||
|
||||
act := env.EnvList()
|
||||
exp := []string{"NOMAD_IP=127.0.0.1", "bar=bang", "foo=baz"}
|
||||
exp := []string{
|
||||
"NOMAD_ADDR_http=127.0.0.1:80",
|
||||
"NOMAD_ADDR_https=127.0.0.1:443",
|
||||
"NOMAD_HOST_PORT_https=443",
|
||||
"bar=bang",
|
||||
"foo=baz",
|
||||
}
|
||||
sort.Strings(act)
|
||||
sort.Strings(exp)
|
||||
if !reflect.DeepEqual(act, exp) {
|
||||
@@ -151,7 +179,11 @@ func TestEnvironment_ClearEnvvars(t *testing.T) {
|
||||
env.ClearEnvvars().Build()
|
||||
|
||||
act = env.EnvList()
|
||||
exp = []string{"NOMAD_IP=127.0.0.1"}
|
||||
exp = []string{
|
||||
"NOMAD_ADDR_http=127.0.0.1:80",
|
||||
"NOMAD_ADDR_https=127.0.0.1:443",
|
||||
"NOMAD_HOST_PORT_https=443",
|
||||
}
|
||||
sort.Strings(act)
|
||||
sort.Strings(exp)
|
||||
if !reflect.DeepEqual(act, exp) {
|
||||
|
||||
@@ -89,10 +89,10 @@ port "http" {}
|
||||
```
|
||||
|
||||
When the task is started, it is passed an environment variable named
|
||||
`NOMAD_PORT_http` which indicates the port.
|
||||
`NOMAD_ADDR_http` which indicates a combination of the interface IP and port.
|
||||
|
||||
```
|
||||
NOMAD_PORT_http=53423 ./start-command
|
||||
NOMAD_ADDR_http=127.0.0.1:53423 ./start-command
|
||||
```
|
||||
|
||||
### Mapped Ports
|
||||
@@ -118,4 +118,8 @@ The above example is for the Docker driver. The service is listening on port
|
||||
`8080` inside the container. The driver will automatically map the dynamic port
|
||||
to this service.
|
||||
|
||||
When the task is started, it is passed an additional environment variable named
|
||||
`NOMAD_HOST_PORT_http` which indicates the host port that the http service is
|
||||
bound to.
|
||||
|
||||
Please refer to the [Docker](/docs/drivers/docker.html) and [QEMU](/docs/drivers/qemu.html) drivers for additional information.
|
||||
|
||||
Reference in New Issue
Block a user