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