Functional consul template env file support

This commit is contained in:
Michael Schurter
2017-05-12 17:07:54 -07:00
parent 052cb28c30
commit 7dac668adf
6 changed files with 82 additions and 0 deletions

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -680,6 +680,7 @@ func ApiTaskToStructsTask(apiTask *api.Task, structsTask *structs.Task) {
Perms: *template.Perms,
LeftDelim: *template.LeftDelim,
RightDelim: *template.RightDelim,
Envvars: *template.Envvars,
}
}
}

View File

@@ -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

View File

@@ -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.