96 lines
2.7 KiB
Go
96 lines
2.7 KiB
Go
package builtin
|
||
|
||
import (
|
||
"context"
|
||
"fmt"
|
||
|
||
"github.com/vladimir/goherence/internal/module"
|
||
"github.com/vladimir/goherence/internal/ssh"
|
||
)
|
||
|
||
// SystemdModule — аналог ansible.builtin.systemd: приводит сервис
|
||
// к желаемому состоянию (started/stopped) и/или включает автозапуск (enabled).
|
||
type SystemdModule struct{}
|
||
|
||
func (m *SystemdModule) Name() string { return "systemd" }
|
||
|
||
func (m *SystemdModule) Run(ctx context.Context, in module.Input, conn *ssh.Conn) (module.Result, error) {
|
||
name, ok := in.Args["name"].(string)
|
||
if !ok {
|
||
return module.Result{}, fmt.Errorf("systemd: аргумент name обязателен")
|
||
}
|
||
state, _ := in.Args["state"].(string)
|
||
enabledArg, hasEnabled := in.Args["enabled"].(bool)
|
||
|
||
changed := false
|
||
var actions []string
|
||
|
||
if state != "" {
|
||
active, err := m.isActive(conn, name)
|
||
if err != nil {
|
||
return module.Result{}, err
|
||
}
|
||
wantActive := state == "started"
|
||
if state == "restarted" {
|
||
actions = append(actions, "systemctl restart "+shArg(name))
|
||
changed = true
|
||
} else if active != wantActive {
|
||
verb := "stop"
|
||
if wantActive {
|
||
verb = "start"
|
||
}
|
||
actions = append(actions, "systemctl "+verb+" "+shArg(name))
|
||
changed = true
|
||
}
|
||
}
|
||
|
||
if hasEnabled {
|
||
enabled, err := m.isEnabled(conn, name)
|
||
if err != nil {
|
||
return module.Result{}, err
|
||
}
|
||
if enabled != enabledArg {
|
||
verb := "disable"
|
||
if enabledArg {
|
||
verb = "enable"
|
||
}
|
||
actions = append(actions, "systemctl "+verb+" "+shArg(name))
|
||
changed = true
|
||
}
|
||
}
|
||
|
||
if !changed {
|
||
return module.Result{SchemaVersion: module.SchemaVersion, Changed: false, Msg: name + ": уже в нужном состоянии"}, nil
|
||
}
|
||
if in.CheckMode {
|
||
return module.Result{SchemaVersion: module.SchemaVersion, Changed: true, Msg: fmt.Sprintf("check mode: %v", actions)}, nil
|
||
}
|
||
|
||
for _, action := range actions {
|
||
res, err := conn.Run(action)
|
||
if err != nil {
|
||
return module.Result{}, err
|
||
}
|
||
if res.ExitCode != 0 {
|
||
return module.Result{SchemaVersion: module.SchemaVersion, Failed: true,
|
||
Msg: fmt.Sprintf("%q завершилась с кодом %d: %s", action, res.ExitCode, res.Stderr)}, nil
|
||
}
|
||
}
|
||
return module.Result{SchemaVersion: module.SchemaVersion, Changed: true, Msg: fmt.Sprintf("%v", actions)}, nil
|
||
}
|
||
|
||
func (m *SystemdModule) isActive(conn *ssh.Conn, name string) (bool, error) {
|
||
res, err := conn.Run("systemctl is-active " + shArg(name))
|
||
if err != nil {
|
||
return false, err
|
||
}
|
||
return res.ExitCode == 0, nil
|
||
}
|
||
|
||
func (m *SystemdModule) isEnabled(conn *ssh.Conn, name string) (bool, error) {
|
||
res, err := conn.Run("systemctl is-enabled " + shArg(name))
|
||
if err != nil {
|
||
return false, err
|
||
}
|
||
return res.ExitCode == 0, nil
|
||
}
|