goherence/internal/module/builtin/template.go
2026-09-11 10:17:25 +03:00

68 lines
2.4 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 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
}