first version
This commit is contained in:
182
appmodules.go
Normal file
182
appmodules.go
Normal file
@@ -0,0 +1,182 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type AppModule struct {
|
||||
Name string
|
||||
Folder string
|
||||
CheckS string
|
||||
}
|
||||
|
||||
type AppModuleConfig struct {
|
||||
Name string `yaml:"name"`
|
||||
CheckUrl *string `yaml:"check-url"`
|
||||
}
|
||||
|
||||
type Script struct {
|
||||
Name string
|
||||
AbsPath string
|
||||
Runner ScriptRunner
|
||||
}
|
||||
|
||||
func (s *Script) Run() (string, error) {
|
||||
args := runnerArgs(s.Runner.Runner, s.AbsPath)
|
||||
if len(args) == 0 {
|
||||
return "", errors.New("runner command is empty")
|
||||
}
|
||||
|
||||
cmd := exec.Command(args[0], args[1:]...)
|
||||
output, err := cmd.CombinedOutput()
|
||||
return string(output), err
|
||||
}
|
||||
|
||||
func runnerArgs(template string, scriptPath string) []string {
|
||||
fields := strings.Fields(template)
|
||||
for i, field := range fields {
|
||||
fields[i] = strings.ReplaceAll(field, "%v", scriptPath)
|
||||
}
|
||||
return fields
|
||||
}
|
||||
|
||||
func (m *AppModule) HasScript(name string, subfolder *string) (bool, *Script) {
|
||||
folder := m.Folder
|
||||
if subfolder != nil {
|
||||
folder = filepath.Join(folder, *subfolder)
|
||||
}
|
||||
|
||||
for _, r := range runners {
|
||||
ext := r.Extension
|
||||
if ext != "" && !strings.HasPrefix(ext, ".") {
|
||||
ext = "." + ext
|
||||
}
|
||||
|
||||
scriptPath := filepath.Join(folder, name+ext)
|
||||
if fileExists(scriptPath) {
|
||||
abs, err := filepath.Abs(scriptPath)
|
||||
if err != nil {
|
||||
return false, nil
|
||||
}
|
||||
return true, &Script{Name: name, AbsPath: abs, Runner: r}
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
func (m *AppModule) Check() (bool, string, error) {
|
||||
if strings.HasPrefix(m.CheckS, "URL ") {
|
||||
check := strings.Split(m.CheckS, " ")[1:]
|
||||
if len(check) < 1 || len(check) > 3 {
|
||||
return false, "", errors.New("check url is bad")
|
||||
}
|
||||
checkUrl := check[0]
|
||||
code := ""
|
||||
if len(check) > 1 {
|
||||
code = check[1]
|
||||
}
|
||||
body := ""
|
||||
if len(check) > 2 {
|
||||
dBody, err := url.QueryUnescape(check[2])
|
||||
if err != nil {
|
||||
return false, "", errors.New("check body decode failed")
|
||||
}
|
||||
body = dBody
|
||||
}
|
||||
|
||||
cCode, cBody, err := fetch(checkUrl, defaultFetchTimeout)
|
||||
if err != nil {
|
||||
return false, "", err
|
||||
}
|
||||
if code != "" && strconv.Itoa(cCode) != code {
|
||||
return false, "", fmt.Errorf("code is different: expected %s, got %d", code, cCode)
|
||||
}
|
||||
if body != "" && body != cBody {
|
||||
return false, "", errors.New("body is different")
|
||||
}
|
||||
|
||||
return true, "", nil
|
||||
|
||||
} else {
|
||||
exists, script := m.HasScript("check", nil)
|
||||
if exists && script != nil {
|
||||
output, err := script.Run()
|
||||
if err != nil {
|
||||
return false, output, err
|
||||
} else {
|
||||
return true, output, nil
|
||||
}
|
||||
} else {
|
||||
return false, "", errors.New("check script not found")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *AppModule) Start() (string, error) {
|
||||
exists, script := m.HasScript("start", nil)
|
||||
if exists && script != nil {
|
||||
return script.Run()
|
||||
} else {
|
||||
return "", errors.New("start script not found")
|
||||
}
|
||||
}
|
||||
|
||||
func (m *AppModule) Stop() (string, error) {
|
||||
exists, script := m.HasScript("stop", nil)
|
||||
if exists && script != nil {
|
||||
return script.Run()
|
||||
} else {
|
||||
return "", errors.New("stop script not found")
|
||||
}
|
||||
}
|
||||
|
||||
func (m *AppModule) Restart() (string, error) {
|
||||
exists, script := m.HasScript("restart", nil)
|
||||
if exists && script != nil {
|
||||
return script.Run()
|
||||
} else {
|
||||
stopOutput, err := m.Stop()
|
||||
if err != nil {
|
||||
return stopOutput, err
|
||||
}
|
||||
startOutput, err := m.Start()
|
||||
return joinOutput(stopOutput, startOutput), err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (m *AppModule) Fix() (string, error) {
|
||||
exists, script := m.HasScript("fix", nil)
|
||||
|
||||
if exists && script != nil {
|
||||
return script.Run()
|
||||
} else {
|
||||
return m.Restart()
|
||||
}
|
||||
}
|
||||
|
||||
func (m *AppModule) Run(scriptN string) (string, error) {
|
||||
var sub = "run"
|
||||
exists, script := m.HasScript(scriptN, &sub)
|
||||
|
||||
if exists && script != nil {
|
||||
return script.Run()
|
||||
} else {
|
||||
return "", errors.New("run script not found")
|
||||
}
|
||||
}
|
||||
|
||||
type Application struct {
|
||||
Name string
|
||||
Folder string
|
||||
AppModules []AppModule
|
||||
}
|
||||
|
||||
type AppConfig struct {
|
||||
Name string `yaml:"name"`
|
||||
}
|
||||
Reference in New Issue
Block a user