// 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 }
// ExpandName interpolates values of Job, Task Group and Task in the Service // Name func (s *Service) ExpandName(job string, taskGroup string, task string) { s.Name = args.ReplaceEnv(s.Name, map[string]string{ "JOB": job, "TASKGROUP": taskGroup, "TASK": task, "BASE": fmt.Sprintf("%s-%s-%s", job, taskGroup, task), }, ) }
func (e *LinuxExecutor) Start() error { // Run as "nobody" user so we don't leak root privilege to the spawned // process. if err := e.runAs("nobody"); err != nil { return err } // Parse the commands arguments and replace instances of Nomad environment // variables. envVars, err := environment.ParseFromList(e.cmd.Env) if err != nil { return err } e.cmd.Path = args.ReplaceEnv(e.cmd.Path, envVars.Map()) e.cmd.Args = args.ParseAndReplace(e.cmd.Args, envVars.Map()) spawnState := filepath.Join(e.allocDir, fmt.Sprintf("%s_%s", e.taskName, "exit_status")) e.spawn = spawn.NewSpawner(spawnState) e.spawn.SetCommand(&e.cmd) e.spawn.SetChroot(e.taskDir) e.spawn.SetLogs(&spawn.Logs{ Stdout: filepath.Join(e.taskDir, allocdir.TaskLocal, fmt.Sprintf("%v.stdout", e.taskName)), Stderr: filepath.Join(e.taskDir, allocdir.TaskLocal, fmt.Sprintf("%v.stderr", e.taskName)), Stdin: os.DevNull, }) enterCgroup := func(pid int) error { // Join the spawn-daemon to the cgroup. manager := e.getCgroupManager(e.groups) // Apply will place the spawn dameon into the created cgroups. if err := manager.Apply(pid); err != nil { return fmt.Errorf("Failed to join spawn-daemon to the cgroup (%+v): %v", e.groups, err) } return nil } return e.spawn.Spawn(enterCgroup) }
func (e *BasicExecutor) Start() error { // Parse the commands arguments and replace instances of Nomad environment // variables. envVars, err := environment.ParseFromList(e.cmd.Env) if err != nil { return err } e.cmd.Path = args.ReplaceEnv(e.cmd.Path, envVars.Map()) e.cmd.Args = args.ParseAndReplace(e.cmd.Args, envVars.Map()) spawnState := filepath.Join(e.allocDir, fmt.Sprintf("%s_%s", e.taskName, "exit_status")) e.spawn = spawn.NewSpawner(spawnState) e.spawn.SetCommand(&e.cmd) e.spawn.SetLogs(&spawn.Logs{ Stdout: filepath.Join(e.taskDir, allocdir.TaskLocal, fmt.Sprintf("%v.stdout", e.taskName)), Stderr: filepath.Join(e.taskDir, allocdir.TaskLocal, fmt.Sprintf("%v.stderr", e.taskName)), Stdin: os.DevNull, }) return e.spawn.Spawn(nil) }
// 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 meta with the following precedence: task, task group, job. for _, meta := range []map[string]string{t.JobMeta, t.TaskGroupMeta, t.TaskMeta} { for k, v := range 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(nil) { t.TaskEnv[fmt.Sprintf("%s%s", IpPrefix, label)] = network.IP t.TaskEnv[fmt.Sprintf("%s%s", HostPortPrefix, label)] = strconv.Itoa(value) if forwardedPort, ok := t.PortMap[label]; ok { value = forwardedPort } t.TaskEnv[fmt.Sprintf("%s%s", PortPrefix, label)] = fmt.Sprintf("%d", value) IPPort := fmt.Sprintf("%s:%d", network.IP, value) t.TaskEnv[fmt.Sprintf("%s%s", AddrPrefix, label)] = IPPort } } // Build the directories if t.AllocDir != "" { t.TaskEnv[AllocDir] = t.AllocDir } if t.TaskDir != "" { t.TaskEnv[TaskLocalDir] = t.TaskDir } if t.SecretDir != "" { t.TaskEnv[SecretDir] = t.SecretDir } // 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 tasks ids if t.AllocId != "" { t.TaskEnv[AllocID] = t.AllocId } if t.AllocName != "" { t.TaskEnv[AllocName] = t.AllocName } if t.AllocIndex != -1 { t.TaskEnv[AllocIndex] = strconv.Itoa(t.AllocIndex) } if t.TaskName != "" { t.TaskEnv[TaskName] = t.TaskName } if t.JobName != "" { t.TaskEnv[JobName] = t.JobName } // 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 } } // Build the Vault Token if t.InjectVaultToken && t.VaultToken != "" { t.TaskEnv[VaultToken] = t.VaultToken } // 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 }
// ReplaceEnv takes an arg and replaces all occurrences 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 }
// 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 label, port := range t.ports { t.taskEnv[fmt.Sprintf("%s%s", PortPrefix, 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 IP if t.ip != "" { t.taskEnv[TaskIP] = t.ip } // 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 }