feat(ansible): recurse include_vars directories
This commit is contained in:
parent
efa2ac3ea1
commit
bfa9a8d0ba
2 changed files with 94 additions and 15 deletions
65
modules.go
65
modules.go
|
|
@ -2115,6 +2115,7 @@ func (e *Executor) moduleIncludeVars(args map[string]any) (*TaskResult, error) {
|
|||
dir := getStringArg(args, "dir", "")
|
||||
name := getStringArg(args, "name", "")
|
||||
hashBehaviour := lower(getStringArg(args, "hash_behaviour", "replace"))
|
||||
depth := getIntArg(args, "depth", 0)
|
||||
|
||||
if file == "" && dir == "" {
|
||||
return &TaskResult{Changed: false}, nil
|
||||
|
|
@ -2147,24 +2148,11 @@ func (e *Executor) moduleIncludeVars(args map[string]any) (*TaskResult, error) {
|
|||
|
||||
if dir != "" {
|
||||
dir = e.resolveLocalPath(dir)
|
||||
entries, err := os.ReadDir(dir)
|
||||
files, err := collectIncludeVarsFiles(dir, depth)
|
||||
if err != nil {
|
||||
return nil, coreerr.E("Executor.moduleIncludeVars", "read vars dir", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var files []string
|
||||
for _, entry := range entries {
|
||||
if entry.IsDir() {
|
||||
continue
|
||||
}
|
||||
|
||||
ext := lower(filepath.Ext(entry.Name()))
|
||||
if ext == ".yml" || ext == ".yaml" {
|
||||
files = append(files, joinPath(dir, entry.Name()))
|
||||
}
|
||||
}
|
||||
sort.Strings(files)
|
||||
|
||||
for _, path := range files {
|
||||
sources = append(sources, path)
|
||||
if err := loadFile(path); err != nil {
|
||||
|
|
@ -2187,6 +2175,53 @@ func (e *Executor) moduleIncludeVars(args map[string]any) (*TaskResult, error) {
|
|||
return &TaskResult{Changed: true, Msg: msg}, nil
|
||||
}
|
||||
|
||||
func collectIncludeVarsFiles(dir string, depth int) ([]string, error) {
|
||||
info, err := os.Stat(dir)
|
||||
if err != nil {
|
||||
return nil, coreerr.E("Executor.moduleIncludeVars", "read vars dir", err)
|
||||
}
|
||||
if !info.IsDir() {
|
||||
return nil, coreerr.E("Executor.moduleIncludeVars", "read vars dir: not a directory", nil)
|
||||
}
|
||||
|
||||
type dirEntry struct {
|
||||
path string
|
||||
depth int
|
||||
}
|
||||
|
||||
var files []string
|
||||
stack := []dirEntry{{path: dir, depth: 0}}
|
||||
for len(stack) > 0 {
|
||||
current := stack[len(stack)-1]
|
||||
stack = stack[:len(stack)-1]
|
||||
|
||||
entries, err := os.ReadDir(current.path)
|
||||
if err != nil {
|
||||
return nil, coreerr.E("Executor.moduleIncludeVars", "read vars dir", err)
|
||||
}
|
||||
|
||||
for i := len(entries) - 1; i >= 0; i-- {
|
||||
entry := entries[i]
|
||||
fullPath := joinPath(current.path, entry.Name())
|
||||
|
||||
if entry.IsDir() {
|
||||
if depth == 0 || current.depth < depth {
|
||||
stack = append(stack, dirEntry{path: fullPath, depth: current.depth + 1})
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
ext := lower(filepath.Ext(entry.Name()))
|
||||
if ext == ".yml" || ext == ".yaml" {
|
||||
files = append(files, fullPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sort.Strings(files)
|
||||
return files, nil
|
||||
}
|
||||
|
||||
func mergeVars(dst, src map[string]any, mergeMaps bool) {
|
||||
if dst == nil || src == nil {
|
||||
return
|
||||
|
|
|
|||
|
|
@ -954,6 +954,50 @@ func TestModulesAdv_ModuleIncludeVars_Good_ResolvesRelativePathsAgainstBasePath(
|
|||
assert.Equal(t, 8080, e.vars["app_port"])
|
||||
}
|
||||
|
||||
func TestModulesAdv_ModuleIncludeVars_Good_RecursesIntoNestedDirectories(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
require.NoError(t, writeTestFile(joinPath(dir, "01-root.yml"), []byte("root_value: root\n"), 0644))
|
||||
require.NoError(t, writeTestFile(joinPath(dir, "nested", "02-child.yaml"), []byte("child_value: child\n"), 0644))
|
||||
require.NoError(t, writeTestFile(joinPath(dir, "nested", "deep", "03-grandchild.yml"), []byte("grandchild_value: grandchild\n"), 0644))
|
||||
|
||||
e := NewExecutor("/tmp")
|
||||
|
||||
result, err := e.moduleIncludeVars(map[string]any{
|
||||
"dir": dir,
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.True(t, result.Changed)
|
||||
assert.Equal(t, "root", e.vars["root_value"])
|
||||
assert.Equal(t, "child", e.vars["child_value"])
|
||||
assert.Equal(t, "grandchild", e.vars["grandchild_value"])
|
||||
assert.Contains(t, result.Msg, joinPath(dir, "01-root.yml"))
|
||||
assert.Contains(t, result.Msg, joinPath(dir, "nested", "02-child.yaml"))
|
||||
assert.Contains(t, result.Msg, joinPath(dir, "nested", "deep", "03-grandchild.yml"))
|
||||
}
|
||||
|
||||
func TestModulesAdv_ModuleIncludeVars_Good_RespectsDepthLimit(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
require.NoError(t, writeTestFile(joinPath(dir, "01-root.yml"), []byte("root_value: root\n"), 0644))
|
||||
require.NoError(t, writeTestFile(joinPath(dir, "nested", "02-child.yaml"), []byte("child_value: child\n"), 0644))
|
||||
require.NoError(t, writeTestFile(joinPath(dir, "nested", "deep", "03-grandchild.yml"), []byte("grandchild_value: grandchild\n"), 0644))
|
||||
|
||||
e := NewExecutor("/tmp")
|
||||
|
||||
result, err := e.moduleIncludeVars(map[string]any{
|
||||
"dir": dir,
|
||||
"depth": 1,
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.True(t, result.Changed)
|
||||
assert.Equal(t, "root", e.vars["root_value"])
|
||||
assert.Equal(t, "child", e.vars["child_value"])
|
||||
_, hasGrandchild := e.vars["grandchild_value"]
|
||||
assert.False(t, hasGrandchild)
|
||||
assert.NotContains(t, result.Msg, joinPath(dir, "nested", "deep", "03-grandchild.yml"))
|
||||
}
|
||||
|
||||
// --- sysctl module ---
|
||||
|
||||
func TestModulesAdv_ModuleSysctl_Good_ReloadsAfterPersisting(t *testing.T) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue