106 lines
1.6 KiB
Go
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
|
||
|
}
|