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

55 lines
2.2 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 (
"context"
"fmt"
"github.com/vladimir/goherence/internal/module"
"github.com/vladimir/goherence/internal/ssh"
)
// ShellModule — единственный по-настоящему императивный builtin-модуль.
// Его использование намеренно ограничивается линтером (internal/lint) —
// сам модуль здесь просто честно исполняет команду, никакой магии.
type ShellModule struct{}
func (m *ShellModule) Name() string { return "shell" }
func (m *ShellModule) Run(ctx context.Context, in module.Input, conn *ssh.Conn) (module.Result, error) {
cmd, ok := in.Args["cmd"].(string)
if !ok {
return module.Result{}, fmt.Errorf("shell: аргумент cmd обязателен и должен быть строкой")
}
if in.CheckMode {
return module.Result{
SchemaVersion: module.SchemaVersion,
Changed: true, // shell не умеет предсказывать идемпотентность — check-mode всегда "would change"
Msg: "check mode: команда не выполнена: " + cmd,
}, nil
}
res, err := conn.Run(cmd)
if err != nil {
return module.Result{}, err
}
return module.Result{
SchemaVersion: module.SchemaVersion,
Changed: true, // shell не имеет понятия состояния — считается изменяющим всегда
Failed: res.ExitCode != 0,
Msg: res.Stdout,
Diff: map[string]string{
"stderr": res.Stderr,
"exit_code": fmt.Sprintf("%d", res.ExitCode),
},
}, nil
}
// CommandModule — то же самое, что shell, но семантически "без shell-обвязки"
// (в реальном Ansible command не проходит через /bin/sh, что важно для
// экранирования). Для первой версии реализация идентична shell —
// разница добавляется отдельно, когда понадобится exec без shell-интерпретации.
type CommandModule struct{ ShellModule }
func (m *CommandModule) Name() string { return "command" }