From d34aed9febc5a955a23e75b2ea2388a8abcda642 Mon Sep 17 00:00:00 2001 From: Virgil Date: Fri, 3 Apr 2026 15:34:05 +0000 Subject: [PATCH] feat(ansible): load extensionless include_vars files --- modules.go | 34 +++++++++++++++++++++++++++++----- modules_adv_test.go | 21 +++++++++++++++++++++ 2 files changed, 50 insertions(+), 5 deletions(-) diff --git a/modules.go b/modules.go index 1c82c84..0e49a14 100644 --- a/modules.go +++ b/modules.go @@ -3646,7 +3646,7 @@ func (e *Executor) moduleIncludeVars(args map[string]any) (*TaskResult, error) { name := getStringArg(args, "name", "") filesMatching := getStringArg(args, "files_matching", "") ignoreFiles := normalizeStringList(args["ignore_files"]) - extensions := normalizeIncludeVarsExtensions(normalizeStringList(args["extensions"])) + extensions := normalizeIncludeVarsExtensions(args["extensions"]) hashBehaviour := lower(getStringArg(args, "hash_behaviour", "replace")) depth := getIntArg(args, "depth", 0) @@ -3715,7 +3715,28 @@ func (e *Executor) moduleIncludeVars(args map[string]any) (*TaskResult, error) { return result, nil } -func normalizeIncludeVarsExtensions(values []string) []string { +func normalizeIncludeVarsExtensions(value any) []string { + switch v := value.(type) { + case nil: + return []string{".json", ".yml", ".yaml"} + case string: + return normalizeIncludeVarsExtensionList([]string{v}) + case []string: + return normalizeIncludeVarsExtensionList(v) + case []any: + values := make([]string, 0, len(v)) + for _, item := range v { + if s, ok := item.(string); ok { + values = append(values, s) + } + } + return normalizeIncludeVarsExtensionList(values) + default: + return normalizeIncludeVarsExtensionList([]string{corexSprint(v)}) + } +} + +func normalizeIncludeVarsExtensionList(values []string) []string { if len(values) == 0 { return []string{".json", ".yml", ".yaml"} } @@ -3723,11 +3744,14 @@ func normalizeIncludeVarsExtensions(values []string) []string { extensions := make([]string, 0, len(values)) seen := make(map[string]bool, len(values)) for _, value := range values { - ext := lower(corexTrimSpace(value)) - if ext == "" { + trimmed := corexTrimSpace(value) + ext := lower(trimmed) + if trimmed == "" { + ext = "" + } else if ext == "" { continue } - if !corexHasPrefix(ext, ".") { + if ext != "" && !corexHasPrefix(ext, ".") { ext = "." + ext } if seen[ext] { diff --git a/modules_adv_test.go b/modules_adv_test.go index cf43ee5..5cb73f8 100644 --- a/modules_adv_test.go +++ b/modules_adv_test.go @@ -1396,6 +1396,27 @@ func TestModulesAdv_ModuleIncludeVars_Good_CustomExtensionsFilter(t *testing.T) assert.NotContains(t, result.Msg, joinPath(dir, "01-ignored.yml")) } +func TestModulesAdv_ModuleIncludeVars_Good_LoadExtensionlessFilesWhenRequested(t *testing.T) { + dir := t.TempDir() + require.NoError(t, writeTestFile(joinPath(dir, "vars"), []byte("app_name: demo\n"), 0644)) + require.NoError(t, writeTestFile(joinPath(dir, "ignored.txt"), []byte("ignored_value: true\n"), 0644)) + + e := NewExecutor("/tmp") + + result, err := e.moduleIncludeVars(map[string]any{ + "dir": dir, + "extensions": []any{"", "yml", "yaml", "json"}, + }) + + require.NoError(t, err) + assert.True(t, result.Changed) + assert.Equal(t, "demo", e.vars["app_name"]) + _, hasIgnored := e.vars["ignored_value"] + assert.False(t, hasIgnored) + assert.Contains(t, result.Msg, joinPath(dir, "vars")) + assert.NotContains(t, result.Msg, joinPath(dir, "ignored.txt")) +} + func TestModulesAdv_ModuleIncludeVars_Good_LoadDirectoryWithMerge(t *testing.T) { dir := t.TempDir() require.NoError(t, writeTestFile(joinPath(dir, "01-base.yml"), []byte("app_name: demo\nnested:\n a: 1\n"), 0644))