From b04e68fdbff4d6f774c1e2515a94848e1fcd8520 Mon Sep 17 00:00:00 2001 From: Virgil Date: Thu, 2 Apr 2026 14:38:23 +0000 Subject: [PATCH] feat(ansible): template play vars_files paths --- executor.go | 17 ++++++++++++++++- executor_test.go | 31 +++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/executor.go b/executor.go index 36581a2..b4815d4 100644 --- a/executor.go +++ b/executor.go @@ -479,9 +479,24 @@ func (e *Executor) loadPlayVarsFiles(play *Play) error { return nil } + // Vars file paths may reference play or executor variables, so render them + // against a temporary merged scope before reading from disk. + savedVars := e.vars + renderVars := make(map[string]any, len(savedVars)+len(play.Vars)) + for k, v := range savedVars { + renderVars[k] = v + } + for k, v := range play.Vars { + renderVars[k] = v + } + e.vars = renderVars + defer func() { + e.vars = savedVars + }() + merged := make(map[string]any) for _, file := range files { - resolved := e.resolveLocalPath(file) + resolved := e.resolveLocalPath(e.templateString(file, "", nil)) data, err := coreio.Local.Read(resolved) if err != nil { return coreerr.E("Executor.loadPlayVarsFiles", "read vars file", err) diff --git a/executor_test.go b/executor_test.go index 1d92063..882cd14 100644 --- a/executor_test.go +++ b/executor_test.go @@ -399,6 +399,37 @@ app_name: demo assert.Equal(t, "8080 demo prod", e.results["localhost"]["vars_result"].Msg) } +func TestExecutor_Run_Good_VarsFilesSupportTemplatedPaths(t *testing.T) { + dir := t.TempDir() + + require.NoError(t, writeTestFile(joinPath(dir, "vars", "prod.yml"), []byte(`--- +app_name: templated +`), 0644)) + + playbookPath := joinPath(dir, "playbook.yml") + require.NoError(t, writeTestFile(playbookPath, []byte(`--- +- name: Vars files templated path + hosts: localhost + gather_facts: false + vars: + environment: prod + vars_files: + - vars/{{ environment }}.yml + tasks: + - name: Show templated var + debug: + msg: "{{ app_name }}" + register: vars_result +`), 0644)) + + e := NewExecutor(dir) + require.NoError(t, e.Run(context.Background(), playbookPath)) + + require.NotNil(t, e.results["localhost"]) + require.NotNil(t, e.results["localhost"]["vars_result"]) + assert.Equal(t, "templated", e.results["localhost"]["vars_result"].Msg) +} + func TestExecutor_RunTaskOnHosts_Good_WithFileUsesFileContents(t *testing.T) { dir := t.TempDir() require.NoError(t, writeTestFile(joinPath(dir, "fragments", "hello.txt"), []byte("hello from file"), 0644))