package builtin import ( "bytes" "context" "fmt" "os" "github.com/vladimir/goherence/internal/module" "github.com/vladimir/goherence/internal/ssh" tmpl "github.com/vladimir/goherence/internal/template" ) // TemplateModule — аналог ansible.builtin.template: рендерит файл шаблона // (text/template + sprig, см. internal/template) с текущими переменными // таска и приводит удалённый файл к результату — идемпотентно, как copy. type TemplateModule struct { // Vars — переменные, с которыми рендерится шаблон. Заполняется // executor'ом перед вызовом Run (сам Module не знает про vars.Resolve, // чтобы не тянуть в module-пакет зависимость на parser/vars). Vars map[string]interface{} } func (m *TemplateModule) Name() string { return "template" } func (m *TemplateModule) Run(ctx context.Context, in module.Input, conn *ssh.Conn) (module.Result, error) { src, ok := in.Args["src"].(string) if !ok { return module.Result{}, fmt.Errorf("template: аргумент src обязателен") } dest, ok := in.Args["dest"].(string) if !ok { return module.Result{}, fmt.Errorf("template: аргумент dest обязателен") } mode, _ := in.Args["mode"].(string) if mode == "" { mode = "0644" } raw, err := os.ReadFile(src) if err != nil { return module.Result{}, fmt.Errorf("template: чтение шаблона %s: %w", src, err) } rendered, err := tmpl.Render(src, string(raw), m.Vars) if err != nil { return module.Result{}, fmt.Errorf("template: рендер %s: %w", src, err) } current, err := conn.ReadFile(dest) same := err == nil && bytes.Equal(current, []byte(rendered)) if same { return module.Result{SchemaVersion: module.SchemaVersion, Changed: false, Msg: "уже в нужном состоянии"}, nil } if in.CheckMode { return module.Result{SchemaVersion: module.SchemaVersion, Changed: true, Msg: "check mode: файл был бы изменён: " + dest}, nil } if err := conn.WriteFile(dest, []byte(rendered), mode); err != nil { return module.Result{}, fmt.Errorf("template: запись %s: %w", dest, err) } return module.Result{ SchemaVersion: module.SchemaVersion, Changed: true, Msg: "шаблон отрендерен и записан: " + dest, }, nil }