mirror of
https://github.com/kemko/nomad.git
synced 2026-01-05 09:55:44 +03:00
Functional consul template env file support
This commit is contained in:
@@ -336,6 +336,7 @@ type Template struct {
|
||||
Perms *string `mapstructure:"perms"`
|
||||
LeftDelim *string `mapstructure:"left_delimiter"`
|
||||
RightDelim *string `mapstructure:"right_delimiter"`
|
||||
Envvars *bool `mapstructure:"env"`
|
||||
}
|
||||
|
||||
func (tmpl *Template) Canonicalize() {
|
||||
@@ -373,6 +374,9 @@ func (tmpl *Template) Canonicalize() {
|
||||
if tmpl.RightDelim == nil {
|
||||
tmpl.RightDelim = helper.StringToPtr("}}")
|
||||
}
|
||||
if tmpl.Envvars == nil {
|
||||
tmpl.Envvars = helper.BoolToPtr(false)
|
||||
}
|
||||
}
|
||||
|
||||
type Vault struct {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package driver
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/md5"
|
||||
"errors"
|
||||
@@ -8,6 +10,7 @@ import (
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/nomad/client/allocdir"
|
||||
@@ -314,6 +317,26 @@ func GetTaskEnv(taskDir *allocdir.TaskDir, node *structs.Node,
|
||||
SetEnvvars(task.Env).
|
||||
SetTaskName(task.Name)
|
||||
|
||||
// Set env vars from env files
|
||||
for _, tmpl := range task.Templates {
|
||||
if !tmpl.Envvars {
|
||||
continue
|
||||
}
|
||||
f, err := os.Open(filepath.Join(taskDir.Dir, tmpl.DestPath))
|
||||
if err != nil {
|
||||
//FIXME GetTaskEnv may be called before env files are written
|
||||
log.Printf("[DEBUG] driver: XXX FIXME Templates not rendered yet, skipping")
|
||||
continue
|
||||
}
|
||||
defer f.Close()
|
||||
vars, err := parseEnvFile(f)
|
||||
if err != nil {
|
||||
//TODO soft or hard fail?!
|
||||
return nil, err
|
||||
}
|
||||
env.AppendEnvvars(vars)
|
||||
}
|
||||
|
||||
// Vary paths by filesystem isolation used
|
||||
drv, err := NewDriver(task.Driver, NewEmptyDriverContext())
|
||||
if err != nil {
|
||||
@@ -355,6 +378,41 @@ func GetTaskEnv(taskDir *allocdir.TaskDir, node *structs.Node,
|
||||
return env.Build(), nil
|
||||
}
|
||||
|
||||
// parseEnvFile and return a map of the environment variables suitable for
|
||||
// TaskEnvironment.AppendEnvvars or an error.
|
||||
//
|
||||
// See nomad/structs#Template.Envvars comment for format.
|
||||
func parseEnvFile(r io.Reader) (map[string]string, error) {
|
||||
vars := make(map[string]string, 50)
|
||||
lines := 0
|
||||
scanner := bufio.NewScanner(r)
|
||||
for scanner.Scan() {
|
||||
lines++
|
||||
buf := scanner.Bytes()
|
||||
if len(buf) == 0 {
|
||||
// Skip empty lines
|
||||
continue
|
||||
}
|
||||
if buf[0] == '#' {
|
||||
// Skip lines starting with a #
|
||||
continue
|
||||
}
|
||||
n := bytes.IndexByte(buf, '=')
|
||||
if n == -1 {
|
||||
return nil, fmt.Errorf("error on line %d: no '=' sign: %q", lines, string(buf))
|
||||
}
|
||||
if len(buf) > n {
|
||||
vars[string(buf[0:n])] = string(buf[n+1 : len(buf)])
|
||||
} else {
|
||||
vars[string(buf[0:n])] = ""
|
||||
}
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return vars, nil
|
||||
}
|
||||
|
||||
func mapMergeStrInt(maps ...map[string]int) map[string]int {
|
||||
out := map[string]int{}
|
||||
for _, in := range maps {
|
||||
|
||||
@@ -1339,6 +1339,12 @@ func (r *TaskRunner) killTask(killingEvent *structs.TaskEvent) {
|
||||
|
||||
// startTask creates the driver, task dir, and starts the task.
|
||||
func (r *TaskRunner) startTask() error {
|
||||
// Env vars may have been updated prior to task starting, so update the
|
||||
// env vars before starting the task
|
||||
if err := r.setTaskEnv(); err != nil {
|
||||
return fmt.Errorf("failed updating environment before starting task: %v", err)
|
||||
}
|
||||
|
||||
// Create a driver
|
||||
drv, err := r.createDriver()
|
||||
if err != nil {
|
||||
|
||||
@@ -680,6 +680,7 @@ func ApiTaskToStructsTask(apiTask *api.Task, structsTask *structs.Task) {
|
||||
Perms: *template.Perms,
|
||||
LeftDelim: *template.LeftDelim,
|
||||
RightDelim: *template.RightDelim,
|
||||
Envvars: *template.Envvars,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -861,6 +861,7 @@ func parseTemplates(result *[]*api.Template, list *ast.ObjectList) error {
|
||||
"right_delimiter",
|
||||
"source",
|
||||
"splay",
|
||||
"env",
|
||||
}
|
||||
if err := checkHCLKeys(o.Val, valid); err != nil {
|
||||
return err
|
||||
|
||||
@@ -2943,6 +2943,18 @@ type Template struct {
|
||||
// delimiter is utilized when parsing the template.
|
||||
LeftDelim string
|
||||
RightDelim string
|
||||
|
||||
// Envvars enables exposing the template as environment variables
|
||||
// instead of as a file. The template must be of the form:
|
||||
//
|
||||
// VAR_NAME_1={{ key service/my-key }}
|
||||
// VAR_NAME_2=raw string and {{ env "attr.kernel.name" }}
|
||||
//
|
||||
// Lines will be split on the initial "=" with the first part being the
|
||||
// key name and the second part the value.
|
||||
// Empty lines and lines starting with # will be ignored, but to avoid
|
||||
// escaping issues #s within lines will not be treated as comments.
|
||||
Envvars bool
|
||||
}
|
||||
|
||||
// DefaultTemplate returns a default template.
|
||||
|
||||
Reference in New Issue
Block a user