mirror of
https://github.com/kemko/nomad.git
synced 2026-01-06 10:25:42 +03:00
Render consul templates using task env only (#6055)
When rendering a task consul template, ensure that only task environment
variables are used.
Currently, `consul-template` always falls back to host process
environment variables when key isn't a task env var[1]. Thus, we add
an empty entry for each host process env-var not found in task env-vars.
[1] bfa5d0e133/template/funcs.go (L61-L75)
This commit is contained in:
@@ -508,8 +508,12 @@ func templateRunner(config *TaskTemplateManagerConfig) (
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Set Nomad's environment variables
|
||||
runner.Env = config.EnvBuilder.Build().All()
|
||||
// Set Nomad's environment variables.
|
||||
// consul-template falls back to the host process environment if a
|
||||
// variable isn't explicitly set in the configuration, so we need
|
||||
// to mask the environment out to ensure only the task env vars are
|
||||
// available.
|
||||
runner.Env = maskProcessEnv(config.EnvBuilder.Build().All())
|
||||
|
||||
// Build the lookup
|
||||
idMap := runner.TemplateConfigMapping()
|
||||
@@ -525,6 +529,20 @@ func templateRunner(config *TaskTemplateManagerConfig) (
|
||||
return runner, lookup, nil
|
||||
}
|
||||
|
||||
// maskProcessEnv masks away any environment variable not found in task env.
|
||||
// It manipulates the parameter directly and returns it without copying.
|
||||
func maskProcessEnv(env map[string]string) map[string]string {
|
||||
procEnvs := os.Environ()
|
||||
for _, e := range procEnvs {
|
||||
ekv := strings.SplitN(e, "=", 2)
|
||||
if _, ok := env[ekv[0]]; !ok {
|
||||
env[ekv[0]] = ""
|
||||
}
|
||||
}
|
||||
|
||||
return env
|
||||
}
|
||||
|
||||
// parseTemplateConfigs converts the tasks templates in the config into
|
||||
// consul-templates
|
||||
func parseTemplateConfigs(config *TaskTemplateManagerConfig) (map[ctconf.TemplateConfig]*structs.Template, error) {
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"github.com/hashicorp/nomad/client/config"
|
||||
"github.com/hashicorp/nomad/client/taskenv"
|
||||
"github.com/hashicorp/nomad/helper"
|
||||
"github.com/hashicorp/nomad/helper/uuid"
|
||||
"github.com/hashicorp/nomad/nomad/mock"
|
||||
"github.com/hashicorp/nomad/nomad/structs"
|
||||
sconfig "github.com/hashicorp/nomad/nomad/structs/config"
|
||||
@@ -1022,6 +1023,52 @@ func TestTaskTemplateManager_Signal_Error(t *testing.T) {
|
||||
require.Contains(harness.mockHooks.KillEvent.DisplayMessage, "failed to send signals")
|
||||
}
|
||||
|
||||
// TestTaskTemplateManager_FiltersProcessEnvVars asserts that we only render
|
||||
// environment variables found in task env-vars and not read the nomad host
|
||||
// process environment variables. nomad host process environment variables
|
||||
// are to be treated the same as not found environment variables.
|
||||
func TestTaskTemplateManager_FiltersEnvVars(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
defer os.Setenv("NOMAD_TASK_NAME", os.Getenv("NOMAD_TASK_NAME"))
|
||||
os.Setenv("NOMAD_TASK_NAME", "should be overridden by task")
|
||||
|
||||
testenv := "TESTENV_" + strings.ReplaceAll(uuid.Generate(), "-", "")
|
||||
os.Setenv(testenv, "MY_TEST_VALUE")
|
||||
defer os.Unsetenv(testenv)
|
||||
|
||||
// Make a template that will render immediately
|
||||
content := `Hello Nomad Task: {{env "NOMAD_TASK_NAME"}}
|
||||
TEST_ENV: {{ env "` + testenv + `" }}
|
||||
TEST_ENV_NOT_FOUND: {{env "` + testenv + `_NOTFOUND" }}`
|
||||
expected := fmt.Sprintf("Hello Nomad Task: %s\nTEST_ENV: \nTEST_ENV_NOT_FOUND: ", TestTaskName)
|
||||
|
||||
file := "my.tmpl"
|
||||
template := &structs.Template{
|
||||
EmbeddedTmpl: content,
|
||||
DestPath: file,
|
||||
ChangeMode: structs.TemplateChangeModeNoop,
|
||||
}
|
||||
|
||||
harness := newTestHarness(t, []*structs.Template{template}, false, false)
|
||||
harness.start(t)
|
||||
defer harness.stop()
|
||||
|
||||
// Wait for the unblock
|
||||
select {
|
||||
case <-harness.mockHooks.UnblockCh:
|
||||
case <-time.After(time.Duration(5*testutil.TestMultiplier()) * time.Second):
|
||||
require.Fail(t, "Task unblock should have been called")
|
||||
}
|
||||
|
||||
// Check the file is there
|
||||
path := filepath.Join(harness.taskDir, file)
|
||||
raw, err := ioutil.ReadFile(path)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, expected, string(raw))
|
||||
}
|
||||
|
||||
// TestTaskTemplateManager_Env asserts templates with the env flag set are read
|
||||
// into the task's environment.
|
||||
func TestTaskTemplateManager_Env(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user