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

58 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 external
import (
"context"
"encoding/json"
"fmt"
"github.com/vladimir/goherence/internal/module"
"github.com/vladimir/goherence/internal/ssh"
)
// Module — обёртка над внешним (сторонним) модулем: реализует тот же
// интерфейс module.Module, что и builtin-модули, но вместо чистого Go-кода
// доставляет и запускает на хосте subprocess, обмениваясь с ним JSON
// по stdin/stdout. Executor не отличает Module от builtin — он получает
// его из того же Registry, резолвя по имени.
type Module struct {
Manifest Manifest
BinPath map[string]string // arch ("linux/amd64") → путь к локальному бинарнику
}
func (m *Module) Name() string { return m.Manifest.Name }
func (m *Module) Run(ctx context.Context, in module.Input, conn *ssh.Conn) (module.Result, error) {
if m.Manifest.SchemaVersion != module.SchemaVersion {
return module.Result{}, fmt.Errorf(
"модуль %s: schema_version %d не совпадает с ожидаемой %d — "+
"обнови модуль или goherence", m.Manifest.Name, m.Manifest.SchemaVersion, module.SchemaVersion)
}
remoteBin, err := ensureDeployed(conn, m)
if err != nil {
return module.Result{}, err
}
inputJSON, err := json.Marshal(in)
if err != nil {
return module.Result{}, fmt.Errorf("сериализация input для %s: %w", m.Manifest.Name, err)
}
res, err := conn.RunWithInput(remoteBin, inputJSON)
if err != nil {
return module.Result{}, fmt.Errorf("запуск внешнего модуля %s: %w", m.Manifest.Name, err)
}
if res.ExitCode != 0 {
return module.Result{}, fmt.Errorf(
"внешний модуль %s завершился с кодом %d, stderr: %s",
m.Manifest.Name, res.ExitCode, res.Stderr)
}
var out module.Result
if err := json.Unmarshal([]byte(res.Stdout), &out); err != nil {
return module.Result{}, fmt.Errorf(
"внешний модуль %s вернул невалидный JSON: %w (stdout: %s)",
m.Manifest.Name, err, res.Stdout)
}
return out, nil
}