280 lines
6.7 KiB
Go
280 lines
6.7 KiB
Go
package env
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
|
|
hargs "github.com/hashicorp/nomad/helper/args"
|
|
"github.com/hashicorp/nomad/nomad/structs"
|
|
)
|
|
|
|
// A set of environment variables that are exported by each driver.
|
|
const (
|
|
// The path to the alloc directory that is shared across tasks within a task
|
|
// group.
|
|
AllocDir = "NOMAD_ALLOC_DIR"
|
|
|
|
// The path to the tasks local directory where it can store data that is
|
|
// persisted to the alloc is removed.
|
|
TaskLocalDir = "NOMAD_TASK_DIR"
|
|
|
|
// The tasks memory limit in MBs.
|
|
MemLimit = "NOMAD_MEMORY_LIMIT"
|
|
|
|
// The tasks limit in MHz.
|
|
CpuLimit = "NOMAD_CPU_LIMIT"
|
|
|
|
// Prefix for passing both dynamic and static port allocations to
|
|
// tasks.
|
|
// 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_"
|
|
)
|
|
|
|
// The node values that can be interpreted.
|
|
const (
|
|
nodeIdKey = "node.unique.id"
|
|
nodeDcKey = "node.datacenter"
|
|
nodeNameKey = "node.unique.name"
|
|
nodeClassKey = "node.class"
|
|
|
|
// Prefixes used for lookups.
|
|
nodeAttributePrefix = "attr."
|
|
nodeMetaPrefix = "meta."
|
|
)
|
|
|
|
// TaskEnvironment is used to expose information to a task via environment
|
|
// variables and provide interpolation of Nomad variables.
|
|
type TaskEnvironment struct {
|
|
env map[string]string
|
|
meta map[string]string
|
|
allocDir string
|
|
taskDir string
|
|
cpuLimit int
|
|
memLimit int
|
|
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
|
|
|
|
// nodeValues is the values that are allowed for interprolation from the
|
|
// node.
|
|
nodeValues map[string]string
|
|
}
|
|
|
|
func NewTaskEnvironment(node *structs.Node) *TaskEnvironment {
|
|
return &TaskEnvironment{node: node}
|
|
}
|
|
|
|
// ParseAndReplace takes the user supplied args replaces any instance of an
|
|
// environment variable or nomad variable in the args with the actual value.
|
|
func (t *TaskEnvironment) ParseAndReplace(args []string) []string {
|
|
replaced := make([]string, len(args))
|
|
for i, arg := range args {
|
|
replaced[i] = hargs.ReplaceEnv(arg, t.taskEnv, t.nodeValues)
|
|
}
|
|
|
|
return replaced
|
|
}
|
|
|
|
// ReplaceEnv takes an arg and replaces all occurences of environment variables
|
|
// and nomad variables. If the variable is found in the passed map it is
|
|
// replaced, otherwise the original string is returned.
|
|
func (t *TaskEnvironment) ReplaceEnv(arg string) string {
|
|
return hargs.ReplaceEnv(arg, t.taskEnv, t.nodeValues)
|
|
}
|
|
|
|
// Build must be called after all the tasks environment values have been set.
|
|
func (t *TaskEnvironment) Build() *TaskEnvironment {
|
|
t.nodeValues = make(map[string]string)
|
|
t.taskEnv = make(map[string]string)
|
|
|
|
// Build the task metadata
|
|
for k, v := range t.meta {
|
|
t.taskEnv[fmt.Sprintf("%s%s", MetaPrefix, strings.ToUpper(k))] = v
|
|
}
|
|
|
|
// Build the ports
|
|
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
|
|
if t.allocDir != "" {
|
|
t.taskEnv[AllocDir] = t.allocDir
|
|
}
|
|
if t.taskDir != "" {
|
|
t.taskEnv[TaskLocalDir] = t.taskDir
|
|
}
|
|
|
|
// Build the resource limits
|
|
if t.memLimit != 0 {
|
|
t.taskEnv[MemLimit] = strconv.Itoa(t.memLimit)
|
|
}
|
|
if t.cpuLimit != 0 {
|
|
t.taskEnv[CpuLimit] = strconv.Itoa(t.cpuLimit)
|
|
}
|
|
|
|
// Build the node
|
|
if t.node != nil {
|
|
// Set up the node values.
|
|
t.nodeValues[nodeIdKey] = t.node.ID
|
|
t.nodeValues[nodeDcKey] = t.node.Datacenter
|
|
t.nodeValues[nodeNameKey] = t.node.Name
|
|
t.nodeValues[nodeClassKey] = t.node.NodeClass
|
|
|
|
// Set up the attributes.
|
|
for k, v := range t.node.Attributes {
|
|
t.nodeValues[fmt.Sprintf("%s%s", nodeAttributePrefix, k)] = v
|
|
}
|
|
|
|
// Set up the meta.
|
|
for k, v := range t.node.Meta {
|
|
t.nodeValues[fmt.Sprintf("%s%s", nodeMetaPrefix, k)] = v
|
|
}
|
|
}
|
|
|
|
// Interpret the environment variables
|
|
interpreted := make(map[string]string, len(t.env))
|
|
for k, v := range t.env {
|
|
interpreted[k] = hargs.ReplaceEnv(v, t.nodeValues, t.taskEnv)
|
|
}
|
|
|
|
for k, v := range interpreted {
|
|
t.taskEnv[k] = v
|
|
}
|
|
|
|
return t
|
|
}
|
|
|
|
// EnvList returns a list of strings with NAME=value pairs.
|
|
func (t *TaskEnvironment) EnvList() []string {
|
|
env := []string{}
|
|
for k, v := range t.taskEnv {
|
|
env = append(env, fmt.Sprintf("%s=%s", k, v))
|
|
}
|
|
|
|
return env
|
|
}
|
|
|
|
// EnvMap returns a copy of the tasks environment variables.
|
|
func (t *TaskEnvironment) EnvMap() map[string]string {
|
|
m := make(map[string]string, len(t.taskEnv))
|
|
for k, v := range t.taskEnv {
|
|
m[k] = v
|
|
}
|
|
|
|
return m
|
|
}
|
|
|
|
// Builder methods to build the TaskEnvironment
|
|
func (t *TaskEnvironment) SetAllocDir(dir string) *TaskEnvironment {
|
|
t.allocDir = dir
|
|
return t
|
|
}
|
|
|
|
func (t *TaskEnvironment) ClearAllocDir() *TaskEnvironment {
|
|
t.allocDir = ""
|
|
return t
|
|
}
|
|
|
|
func (t *TaskEnvironment) SetTaskLocalDir(dir string) *TaskEnvironment {
|
|
t.taskDir = dir
|
|
return t
|
|
}
|
|
|
|
func (t *TaskEnvironment) ClearTaskLocalDir() *TaskEnvironment {
|
|
t.taskDir = ""
|
|
return t
|
|
}
|
|
|
|
func (t *TaskEnvironment) SetMemLimit(limit int) *TaskEnvironment {
|
|
t.memLimit = limit
|
|
return t
|
|
}
|
|
|
|
func (t *TaskEnvironment) ClearMemLimit() *TaskEnvironment {
|
|
t.memLimit = 0
|
|
return t
|
|
}
|
|
|
|
func (t *TaskEnvironment) SetCpuLimit(limit int) *TaskEnvironment {
|
|
t.cpuLimit = limit
|
|
return t
|
|
}
|
|
|
|
func (t *TaskEnvironment) ClearCpuLimit() *TaskEnvironment {
|
|
t.cpuLimit = 0
|
|
return t
|
|
}
|
|
|
|
func (t *TaskEnvironment) SetNetworks(networks []*structs.NetworkResource) *TaskEnvironment {
|
|
t.networks = networks
|
|
return t
|
|
}
|
|
|
|
func (t *TaskEnvironment) clearNetworks() *TaskEnvironment {
|
|
t.networks = nil
|
|
return t
|
|
}
|
|
|
|
func (t *TaskEnvironment) SetPortMap(portMap map[string]int) *TaskEnvironment {
|
|
t.portMap = portMap
|
|
return t
|
|
}
|
|
|
|
func (t *TaskEnvironment) clearPortMap() *TaskEnvironment {
|
|
t.portMap = nil
|
|
return t
|
|
}
|
|
|
|
// Takes a map of meta values to be passed to the task. The keys are capatilized
|
|
// when the environent variable is set.
|
|
func (t *TaskEnvironment) SetMeta(m map[string]string) *TaskEnvironment {
|
|
t.meta = m
|
|
return t
|
|
}
|
|
|
|
func (t *TaskEnvironment) ClearMeta() *TaskEnvironment {
|
|
t.meta = nil
|
|
return t
|
|
}
|
|
|
|
func (t *TaskEnvironment) SetEnvvars(m map[string]string) *TaskEnvironment {
|
|
t.env = m
|
|
return t
|
|
}
|
|
|
|
// Appends the given environment variables.
|
|
func (t *TaskEnvironment) AppendEnvvars(m map[string]string) *TaskEnvironment {
|
|
if t.env == nil {
|
|
t.env = make(map[string]string, len(m))
|
|
}
|
|
|
|
for k, v := range m {
|
|
t.env[k] = v
|
|
}
|
|
return t
|
|
}
|
|
|
|
func (t *TaskEnvironment) ClearEnvvars() *TaskEnvironment {
|
|
t.env = nil
|
|
return t
|
|
}
|