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