kairos-sdk/machine/systemd/unit.go

127 lines
2.5 KiB
Go

package systemd
import (
"fmt"
"os"
"path/filepath"
"strings"
"github.com/kairos-io/kairos-sdk/utils"
)
type ServiceUnit struct {
content string
name, instance string
rootdir string
reload bool
}
const overrideCmdTemplate string = `
[Service]
ExecStart=
ExecStart=%s
`
type ServiceOpts func(*ServiceUnit) error
func WithRoot(n string) ServiceOpts {
return func(su *ServiceUnit) error {
su.rootdir = n
return nil
}
}
func WithName(n string) ServiceOpts {
return func(su *ServiceUnit) error {
su.name = n
return nil
}
}
func WithInstance(n string) ServiceOpts {
return func(su *ServiceUnit) error {
su.instance = n
return nil
}
}
func WithUnitContent(n string) ServiceOpts {
return func(su *ServiceUnit) error {
su.content = n
return nil
}
}
func WithReload(reload bool) ServiceOpts {
return func(su *ServiceUnit) error {
su.reload = reload
return nil
}
}
func NewService(opts ...ServiceOpts) (ServiceUnit, error) {
s := &ServiceUnit{
reload: true, // default to reload to keep the same behavior as before
}
for _, o := range opts {
if err := o(s); err != nil {
return *s, err
}
}
return *s, nil
}
func (s ServiceUnit) WriteUnit() error {
var err error
uname := s.name
if s.instance != "" {
uname = fmt.Sprintf("%s@", s.name)
}
if err = os.WriteFile(filepath.Join(s.rootdir, fmt.Sprintf("/etc/systemd/system/%s.service", uname)), []byte(s.content), 0600); err != nil {
return err
}
if s.reload {
_, err = utils.SH("systemctl daemon-reload")
}
return err
}
func (s ServiceUnit) OverrideCmd(cmd string) error {
svcDir := filepath.Join(s.rootdir, fmt.Sprintf("/etc/systemd/system/%s.service.d/", s.name))
os.MkdirAll(svcDir, 0600) //nolint:errcheck
return os.WriteFile(filepath.Join(svcDir, "override.conf"), []byte(fmt.Sprintf(overrideCmdTemplate, cmd)), 0600)
}
func (s ServiceUnit) Start() error {
return s.systemctl("start", false)
}
func (s ServiceUnit) Restart() error {
return s.systemctl("restart", false)
}
func (s ServiceUnit) Enable() error {
return s.systemctl("enable", false)
}
func (s ServiceUnit) StartBlocking() error {
return s.systemctl("start", true)
}
func (s ServiceUnit) systemctl(action string, blocking bool) error {
uname := s.name
if s.instance != "" {
uname = fmt.Sprintf("%s@%s", s.name, s.instance)
}
args := []string{action}
if !blocking {
args = append(args, "--no-block")
}
args = append(args, uname)
_, err := utils.SH(fmt.Sprintf("systemctl %s", strings.Join(args, " ")))
return err
}