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 }