goherence/internal/vars/merge.go
2026-09-11 10:17:25 +03:00

58 lines
2.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Package vars реализует единственную ответственность: для заданного
// хоста построить финальный набор переменных, накатывая слои строго
// в порядке приоритета Ansible (упрощённом до того, что реально нужно).
package vars
import "github.com/vladimir/goherence/internal/parser"
// Resolve строит финальные переменные для (хост, роль, play), от самого
// низкого приоритета к самому высокому. Порядок совпадает с комментарием
// в архитектурном документе — намеренно не абстрагирован дальше, чтобы
// последовательность накатывания оставалась видна с первого взгляда.
// facts — собранные internal/facts данные о хосте (os_family и
// т.п.); в реальном Ansible факты имеют высокий приоритет, но ниже
// явных play/role vars и extra-vars — этот порядок здесь и соблюдён.
func Resolve(
host string,
inv *parser.Inventory,
play *parser.Play,
role *parser.Role,
facts map[string]interface{},
extraVars map[string]interface{},
) map[string]interface{} {
result := map[string]interface{}{}
if role != nil {
merge(result, role.Defaults) // 1. role defaults — самый низкий приоритет
}
merge(result, inv.GroupVars("all")) // 2. group_vars/all
for _, g := range inv.GroupChain(host) {
if g == "all" {
continue
}
merge(result, inv.GroupVars(g)) // 3. group_vars/<group>, родители раньше потомков
}
merge(result, inv.HostVars(host)) // 4. host_vars/<host>
merge(result, facts) // 4.5. факты хоста (os_family и т.п.)
if play != nil {
merge(result, play.Vars) // 5. play vars
}
if role != nil {
merge(result, role.Vars) // 6. role vars/main.yml
}
// 7. set_fact / registered vars — накатываются executor'ом во время
// выполнения, а не здесь: Resolve вызывается один раз до старта таска.
merge(result, extraVars) // 8. extra-vars — самый высокий приоритет, всегда последний
return result
}
// merge — намеренно плоская перезапись по ключу (dst[k] = src[k]), БЕЗ
// рекурсивного deep-merge вложенных map. Ровно так себя ведёт и сам
// Ansible по умолчанию (hash_behaviour=replace) — это осознанное решение
// для совместимости ожиданий, а не недосмотр.
func merge(dst, src map[string]interface{}) {
for k, v := range src {
dst[k] = v
}
}