inits/cmd/dkl-system-init/user-service.go
2018-07-06 19:07:37 +11:00

106 lines
1.6 KiB
Go

package main
import (
"bufio"
"bytes"
"io"
"os"
"path/filepath"
"regexp"
"strings"
"time"
yaml "gopkg.in/yaml.v2"
"novit.nc/direktil/pkg/log"
)
var (
reYamlStart = regexp.MustCompile("^#\\s+---\\s*$")
)
type UserService struct {
Restart int
Needs []string
Provides []string
}
func loadUserServices() {
retry:
files, err := filepath.Glob("/etc/direktil/services/*")
if err != nil {
initLog.Taint(log.Error, "failed to load user services: ", err)
time.Sleep(10 * time.Second)
goto retry
}
for _, path := range files {
path := path
go func() {
for {
if err := loadUserService(path); err != nil {
initLog.Taintf(log.Error, "failed to load %s: %v", path, err)
time.Sleep(10 * time.Second)
continue
}
break
}
}()
}
}
func loadUserService(path string) error {
f, err := os.Open(path)
if err != nil {
return err
}
defer f.Close()
r := bufio.NewReader(f)
yamlBuf := &bytes.Buffer{}
inYaml := false
for {
line, err := r.ReadString('\n')
if err == io.EOF {
break
} else if err != nil {
return err
}
if inYaml {
if !strings.HasPrefix(line, "# ") {
break
}
yamlBuf.WriteString(line[2:])
} else if reYamlStart.MatchString(line) {
inYaml = true
}
}
spec := &UserService{}
if inYaml {
if err := yaml.Unmarshal(yamlBuf.Bytes(), &spec); err != nil {
return err
}
}
svc := &CommandService{
Name: filepath.Base(path),
Restart: time.Duration(spec.Restart) * time.Second,
Needs: spec.Needs,
Provides: spec.Provides,
Command: []string{path},
}
initLog.Taintf(log.OK, "user service: %s", path)
services.Register(svc)
return nil
}