github.com/dkerwin/nomad@v0.3.3-0.20160525181927-74554135514b/client/driver/env/env.go (about) 1 package env 2 3 import ( 4 "fmt" 5 "os" 6 "strconv" 7 "strings" 8 9 hargs "github.com/hashicorp/nomad/helper/args" 10 "github.com/hashicorp/nomad/nomad/structs" 11 ) 12 13 // A set of environment variables that are exported by each driver. 14 const ( 15 // AllocDir is the environment variable with the path to the alloc directory 16 // that is shared across tasks within a task group. 17 AllocDir = "NOMAD_ALLOC_DIR" 18 19 // TaskLocalDir is the environment variable with the path to the tasks local 20 // directory where it can store data that is persisted to the alloc is 21 // removed. 22 TaskLocalDir = "NOMAD_TASK_DIR" 23 24 // MemLimit is the environment variable with the tasks memory limit in MBs. 25 MemLimit = "NOMAD_MEMORY_LIMIT" 26 27 // CpuLimit is the environment variable with the tasks CPU limit in MHz. 28 CpuLimit = "NOMAD_CPU_LIMIT" 29 30 // AllocID is the environment variable for passing the allocation ID. 31 AllocID = "NOMAD_ALLOC_ID" 32 33 // AllocName is the environment variable for passing the allocation name. 34 AllocName = "NOMAD_ALLOC_NAME" 35 36 // TaskName is the environment variable for passing the task name. 37 TaskName = "NOMAD_TASK_NAME" 38 39 // AllocIndex is the environment variable for passing the allocation index. 40 AllocIndex = "NOMAD_ALLOC_INDEX" 41 42 // AddrPrefix is the prefix for passing both dynamic and static port 43 // allocations to tasks. 44 // E.g$NOMAD_ADDR_http=127.0.0.1:80 45 AddrPrefix = "NOMAD_ADDR_" 46 47 // IpPrefix is the prefix for passing the IP of a port allocation to a task. 48 IpPrefix = "NOMAD_IP_" 49 50 // PortPrefix is the prefix for passing the port allocation to a task. 51 PortPrefix = "NOMAD_PORT_" 52 53 // HostPortPrefix is the prefix for passing the host port when a portmap is 54 // specified. 55 HostPortPrefix = "NOMAD_HOST_PORT_" 56 57 // MetaPrefix is the prefix for passing task meta data. 58 MetaPrefix = "NOMAD_META_" 59 ) 60 61 // The node values that can be interpreted. 62 const ( 63 nodeIdKey = "node.unique.id" 64 nodeDcKey = "node.datacenter" 65 nodeNameKey = "node.unique.name" 66 nodeClassKey = "node.class" 67 68 // Prefixes used for lookups. 69 nodeAttributePrefix = "attr." 70 nodeMetaPrefix = "meta." 71 ) 72 73 // TaskEnvironment is used to expose information to a task via environment 74 // variables and provide interpolation of Nomad variables. 75 type TaskEnvironment struct { 76 Env map[string]string 77 TaskMeta map[string]string 78 TaskGroupMeta map[string]string 79 JobMeta map[string]string 80 AllocDir string 81 TaskDir string 82 CpuLimit int 83 MemLimit int 84 TaskName string 85 AllocIndex int 86 AllocId string 87 AllocName string 88 Node *structs.Node 89 Networks []*structs.NetworkResource 90 PortMap map[string]int 91 92 // taskEnv is the variables that will be set in the tasks environment 93 TaskEnv map[string]string 94 95 // nodeValues is the values that are allowed for interprolation from the 96 // node. 97 NodeValues map[string]string 98 } 99 100 func NewTaskEnvironment(node *structs.Node) *TaskEnvironment { 101 return &TaskEnvironment{Node: node, AllocIndex: -1} 102 } 103 104 // ParseAndReplace takes the user supplied args replaces any instance of an 105 // environment variable or nomad variable in the args with the actual value. 106 func (t *TaskEnvironment) ParseAndReplace(args []string) []string { 107 replaced := make([]string, len(args)) 108 for i, arg := range args { 109 replaced[i] = hargs.ReplaceEnv(arg, t.TaskEnv, t.NodeValues) 110 } 111 112 return replaced 113 } 114 115 // ReplaceEnv takes an arg and replaces all occurrences of environment variables 116 // and nomad variables. If the variable is found in the passed map it is 117 // replaced, otherwise the original string is returned. 118 func (t *TaskEnvironment) ReplaceEnv(arg string) string { 119 return hargs.ReplaceEnv(arg, t.TaskEnv, t.NodeValues) 120 } 121 122 // Build must be called after all the tasks environment values have been set. 123 func (t *TaskEnvironment) Build() *TaskEnvironment { 124 t.NodeValues = make(map[string]string) 125 t.TaskEnv = make(map[string]string) 126 127 // Build the meta with the following precedence: task, task group, job. 128 for _, meta := range []map[string]string{t.JobMeta, t.TaskGroupMeta, t.TaskMeta} { 129 for k, v := range meta { 130 t.TaskEnv[fmt.Sprintf("%s%s", MetaPrefix, strings.ToUpper(k))] = v 131 } 132 } 133 134 // Build the ports 135 for _, network := range t.Networks { 136 for label, value := range network.MapLabelToValues(t.PortMap) { 137 IPPort := fmt.Sprintf("%s:%d", network.IP, value) 138 t.TaskEnv[fmt.Sprintf("%s%s", AddrPrefix, label)] = IPPort 139 t.TaskEnv[fmt.Sprintf("%s%s", IpPrefix, label)] = network.IP 140 t.TaskEnv[fmt.Sprintf("%s%s", PortPrefix, label)] = fmt.Sprintf("%d", value) 141 142 // Pass an explicit port mapping to the environment 143 if port, ok := t.PortMap[label]; ok { 144 t.TaskEnv[fmt.Sprintf("%s%s", HostPortPrefix, label)] = strconv.Itoa(port) 145 } 146 } 147 } 148 149 // Build the directories 150 if t.AllocDir != "" { 151 t.TaskEnv[AllocDir] = t.AllocDir 152 } 153 if t.TaskDir != "" { 154 t.TaskEnv[TaskLocalDir] = t.TaskDir 155 } 156 157 // Build the resource limits 158 if t.MemLimit != 0 { 159 t.TaskEnv[MemLimit] = strconv.Itoa(t.MemLimit) 160 } 161 if t.CpuLimit != 0 { 162 t.TaskEnv[CpuLimit] = strconv.Itoa(t.CpuLimit) 163 } 164 165 // Build the tasks ids 166 if t.AllocId != "" { 167 t.TaskEnv[AllocID] = t.AllocId 168 } 169 if t.AllocName != "" { 170 t.TaskEnv[AllocName] = t.AllocName 171 } 172 if t.AllocIndex != -1 { 173 t.TaskEnv[AllocIndex] = strconv.Itoa(t.AllocIndex) 174 } 175 if t.TaskName != "" { 176 t.TaskEnv[TaskName] = t.TaskName 177 } 178 179 // Build the node 180 if t.Node != nil { 181 // Set up the node values. 182 t.NodeValues[nodeIdKey] = t.Node.ID 183 t.NodeValues[nodeDcKey] = t.Node.Datacenter 184 t.NodeValues[nodeNameKey] = t.Node.Name 185 t.NodeValues[nodeClassKey] = t.Node.NodeClass 186 187 // Set up the attributes. 188 for k, v := range t.Node.Attributes { 189 t.NodeValues[fmt.Sprintf("%s%s", nodeAttributePrefix, k)] = v 190 } 191 192 // Set up the meta. 193 for k, v := range t.Node.Meta { 194 t.NodeValues[fmt.Sprintf("%s%s", nodeMetaPrefix, k)] = v 195 } 196 } 197 198 // Interpret the environment variables 199 interpreted := make(map[string]string, len(t.Env)) 200 for k, v := range t.Env { 201 interpreted[k] = hargs.ReplaceEnv(v, t.NodeValues, t.TaskEnv) 202 } 203 204 for k, v := range interpreted { 205 t.TaskEnv[k] = v 206 } 207 208 return t 209 } 210 211 // EnvList returns a list of strings with NAME=value pairs. 212 func (t *TaskEnvironment) EnvList() []string { 213 env := []string{} 214 for k, v := range t.TaskEnv { 215 env = append(env, fmt.Sprintf("%s=%s", k, v)) 216 } 217 218 return env 219 } 220 221 // EnvMap returns a copy of the tasks environment variables. 222 func (t *TaskEnvironment) EnvMap() map[string]string { 223 m := make(map[string]string, len(t.TaskEnv)) 224 for k, v := range t.TaskEnv { 225 m[k] = v 226 } 227 228 return m 229 } 230 231 // Builder methods to build the TaskEnvironment 232 func (t *TaskEnvironment) SetAllocDir(dir string) *TaskEnvironment { 233 t.AllocDir = dir 234 return t 235 } 236 237 func (t *TaskEnvironment) ClearAllocDir() *TaskEnvironment { 238 t.AllocDir = "" 239 return t 240 } 241 242 func (t *TaskEnvironment) SetTaskLocalDir(dir string) *TaskEnvironment { 243 t.TaskDir = dir 244 return t 245 } 246 247 func (t *TaskEnvironment) ClearTaskLocalDir() *TaskEnvironment { 248 t.TaskDir = "" 249 return t 250 } 251 252 func (t *TaskEnvironment) SetMemLimit(limit int) *TaskEnvironment { 253 t.MemLimit = limit 254 return t 255 } 256 257 func (t *TaskEnvironment) ClearMemLimit() *TaskEnvironment { 258 t.MemLimit = 0 259 return t 260 } 261 262 func (t *TaskEnvironment) SetCpuLimit(limit int) *TaskEnvironment { 263 t.CpuLimit = limit 264 return t 265 } 266 267 func (t *TaskEnvironment) ClearCpuLimit() *TaskEnvironment { 268 t.CpuLimit = 0 269 return t 270 } 271 272 func (t *TaskEnvironment) SetNetworks(networks []*structs.NetworkResource) *TaskEnvironment { 273 t.Networks = networks 274 return t 275 } 276 277 func (t *TaskEnvironment) clearNetworks() *TaskEnvironment { 278 t.Networks = nil 279 return t 280 } 281 282 func (t *TaskEnvironment) SetPortMap(portMap map[string]int) *TaskEnvironment { 283 t.PortMap = portMap 284 return t 285 } 286 287 func (t *TaskEnvironment) clearPortMap() *TaskEnvironment { 288 t.PortMap = nil 289 return t 290 } 291 292 // Takes a map of meta values to be passed to the task. The keys are capatilized 293 // when the environent variable is set. 294 func (t *TaskEnvironment) SetTaskMeta(m map[string]string) *TaskEnvironment { 295 t.TaskMeta = m 296 return t 297 } 298 299 func (t *TaskEnvironment) ClearTaskMeta() *TaskEnvironment { 300 t.TaskMeta = nil 301 return t 302 } 303 304 func (t *TaskEnvironment) SetTaskGroupMeta(m map[string]string) *TaskEnvironment { 305 t.TaskGroupMeta = m 306 return t 307 } 308 309 func (t *TaskEnvironment) ClearTaskGroupMeta() *TaskEnvironment { 310 t.TaskGroupMeta = nil 311 return t 312 } 313 314 func (t *TaskEnvironment) SetJobMeta(m map[string]string) *TaskEnvironment { 315 t.JobMeta = m 316 return t 317 } 318 319 func (t *TaskEnvironment) ClearJobMeta() *TaskEnvironment { 320 t.JobMeta = nil 321 return t 322 } 323 324 func (t *TaskEnvironment) SetEnvvars(m map[string]string) *TaskEnvironment { 325 t.Env = m 326 return t 327 } 328 329 // Appends the given environment variables. 330 func (t *TaskEnvironment) AppendEnvvars(m map[string]string) *TaskEnvironment { 331 if t.Env == nil { 332 t.Env = make(map[string]string, len(m)) 333 } 334 335 for k, v := range m { 336 t.Env[k] = v 337 } 338 return t 339 } 340 341 // AppendHostEnvvars adds the host environment variables to the tasks. The 342 // filter parameter can be use to filter host environment from entering the 343 // tasks. 344 func (t *TaskEnvironment) AppendHostEnvvars(filter []string) *TaskEnvironment { 345 hostEnv := os.Environ() 346 if t.Env == nil { 347 t.Env = make(map[string]string, len(hostEnv)) 348 } 349 350 // Index the filtered environment variables. 351 index := make(map[string]struct{}, len(filter)) 352 for _, f := range filter { 353 index[f] = struct{}{} 354 } 355 356 for _, e := range hostEnv { 357 parts := strings.SplitN(e, "=", 2) 358 key, value := parts[0], parts[1] 359 360 // Skip filtered environment variables 361 if _, filtered := index[key]; filtered { 362 continue 363 } 364 365 // Don't override the tasks environment variables. 366 if _, existing := t.Env[key]; !existing { 367 t.Env[key] = value 368 } 369 } 370 371 return t 372 } 373 374 func (t *TaskEnvironment) ClearEnvvars() *TaskEnvironment { 375 t.Env = nil 376 return t 377 } 378 379 // Helper method for setting all fields from an allocation. 380 func (t *TaskEnvironment) SetAlloc(alloc *structs.Allocation) *TaskEnvironment { 381 t.AllocId = alloc.ID 382 t.AllocName = alloc.Name 383 t.AllocIndex = alloc.Index() 384 return t 385 } 386 387 // Helper method for clearing all fields from an allocation. 388 func (t *TaskEnvironment) ClearAlloc(alloc *structs.Allocation) *TaskEnvironment { 389 return t.ClearAllocId().ClearAllocName().ClearAllocIndex() 390 } 391 392 func (t *TaskEnvironment) SetAllocIndex(index int) *TaskEnvironment { 393 t.AllocIndex = index 394 return t 395 } 396 397 func (t *TaskEnvironment) ClearAllocIndex() *TaskEnvironment { 398 t.AllocIndex = -1 399 return t 400 } 401 402 func (t *TaskEnvironment) SetAllocId(id string) *TaskEnvironment { 403 t.AllocId = id 404 return t 405 } 406 407 func (t *TaskEnvironment) ClearAllocId() *TaskEnvironment { 408 t.AllocId = "" 409 return t 410 } 411 412 func (t *TaskEnvironment) SetAllocName(name string) *TaskEnvironment { 413 t.AllocName = name 414 return t 415 } 416 417 func (t *TaskEnvironment) ClearAllocName() *TaskEnvironment { 418 t.AllocName = "" 419 return t 420 } 421 422 func (t *TaskEnvironment) SetTaskName(name string) *TaskEnvironment { 423 t.TaskName = name 424 return t 425 } 426 427 func (t *TaskEnvironment) ClearTaskName() *TaskEnvironment { 428 t.TaskName = "" 429 return t 430 }