Refactor hook
Refactor hook into its own go file.
This commit is contained in:
parent
919f7b5163
commit
a9cda6f310
4
Makefile
4
Makefile
|
@ -1,10 +1,10 @@
|
|||
default: all
|
||||
all: weblug
|
||||
|
||||
weblug: cmd/weblug/weblug.go cmd/weblug/config.go
|
||||
weblug: cmd/weblug/*.go
|
||||
go build -o weblug $^
|
||||
|
||||
static: cmd/weblug/weblug.go cmd/weblug/config.go
|
||||
static: cmd/weblug/*.go
|
||||
CGO_ENABLED=0 go build -ldflags="-w -s" -o weblug $^
|
||||
|
||||
test: weblug
|
||||
|
|
|
@ -3,9 +3,6 @@ package main
|
|||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os/exec"
|
||||
"sync/atomic"
|
||||
"syscall"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
@ -19,18 +16,6 @@ type ConfigSettings struct {
|
|||
BindAddress string `yaml:"bind"` // Bind address for the webserver
|
||||
}
|
||||
|
||||
type Hook struct {
|
||||
Name string `yaml:"name"` // name of the hook
|
||||
Route string `yaml:"route"` // http route
|
||||
Command string `yaml:"command"` // Actual command to execute
|
||||
Background bool `yaml:"background"` // Run in background
|
||||
Concurrency int `yaml:"concurrency"` // Number of allowed concurrent runs
|
||||
concurrentRuns int32 // Number of current concurrent runs
|
||||
UID int `yaml:"uid"` // UID to use when running the command
|
||||
GID int `yaml:"gid"` // GID to use when running the command
|
||||
Output bool `yaml:"output"` // Print program output
|
||||
}
|
||||
|
||||
func (cf *Config) SetDefaults() {
|
||||
cf.Settings.BindAddress = ":2088"
|
||||
}
|
||||
|
@ -68,71 +53,3 @@ func (cf *Config) LoadYAML(filename string) error {
|
|||
}
|
||||
return cf.Check()
|
||||
}
|
||||
|
||||
// Tries to lock a spot. Returns false, if the max. number of concurrent runs has been reached
|
||||
func (hook *Hook) TryLock() bool {
|
||||
res := int(atomic.AddInt32(&hook.concurrentRuns, 1))
|
||||
if res > hook.Concurrency {
|
||||
atomic.AddInt32(&hook.concurrentRuns, -1)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (hook *Hook) Unlock() {
|
||||
atomic.AddInt32(&hook.concurrentRuns, -1)
|
||||
}
|
||||
|
||||
// Split a command into program arguments, obey quotation mark escapes
|
||||
func cmdSplit(command string) []string {
|
||||
null := rune(0)
|
||||
esc := null // Escape character or \0 if not escaped currently
|
||||
ret := make([]string, 0)
|
||||
buf := "" // Current command
|
||||
|
||||
for _, char := range command {
|
||||
if esc != null {
|
||||
if char == esc {
|
||||
esc = null
|
||||
} else {
|
||||
buf += string(char)
|
||||
}
|
||||
} else {
|
||||
// Check for quotation marks
|
||||
if char == '\'' || char == '"' {
|
||||
esc = char
|
||||
} else if char == ' ' {
|
||||
ret = append(ret, buf)
|
||||
buf = ""
|
||||
} else {
|
||||
buf += string(char)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Remaining characters
|
||||
if buf != "" {
|
||||
ret = append(ret, buf)
|
||||
buf = ""
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// Run executes the given command and return it's return code. It also respects the given concurrency number and will block until resources are free
|
||||
func (hook *Hook) Run() error {
|
||||
split := cmdSplit(hook.Command)
|
||||
args := make([]string, 0)
|
||||
if len(split) > 1 {
|
||||
args = split[1:]
|
||||
}
|
||||
cmd := exec.Command(split[0], args...)
|
||||
if hook.UID > 0 || hook.GID > 0 {
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{}
|
||||
cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uint32(hook.UID), Gid: uint32(hook.GID)}
|
||||
}
|
||||
if hook.Output {
|
||||
buf, ret := cmd.Output()
|
||||
fmt.Println(string(buf))
|
||||
return ret
|
||||
}
|
||||
return cmd.Run()
|
||||
}
|
||||
|
|
88
cmd/weblug/hook.go
Normal file
88
cmd/weblug/hook.go
Normal file
|
@ -0,0 +1,88 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"sync/atomic"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
type Hook struct {
|
||||
Name string `yaml:"name"` // name of the hook
|
||||
Route string `yaml:"route"` // http route
|
||||
Command string `yaml:"command"` // Actual command to execute
|
||||
Background bool `yaml:"background"` // Run in background
|
||||
Concurrency int `yaml:"concurrency"` // Number of allowed concurrent runs
|
||||
concurrentRuns int32 // Number of current concurrent runs
|
||||
UID int `yaml:"uid"` // UID to use when running the command
|
||||
GID int `yaml:"gid"` // GID to use when running the command
|
||||
Output bool `yaml:"output"` // Print program output
|
||||
}
|
||||
|
||||
// Tries to lock a spot. Returns false, if the max. number of concurrent runs has been reached
|
||||
func (hook *Hook) TryLock() bool {
|
||||
res := int(atomic.AddInt32(&hook.concurrentRuns, 1))
|
||||
if res > hook.Concurrency {
|
||||
atomic.AddInt32(&hook.concurrentRuns, -1)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (hook *Hook) Unlock() {
|
||||
atomic.AddInt32(&hook.concurrentRuns, -1)
|
||||
}
|
||||
|
||||
// Split a command into program arguments, obey quotation mark escapes
|
||||
func cmdSplit(command string) []string {
|
||||
null := rune(0)
|
||||
esc := null // Escape character or \0 if not escaped currently
|
||||
ret := make([]string, 0)
|
||||
buf := "" // Current command
|
||||
|
||||
for _, char := range command {
|
||||
if esc != null {
|
||||
if char == esc {
|
||||
esc = null
|
||||
} else {
|
||||
buf += string(char)
|
||||
}
|
||||
} else {
|
||||
// Check for quotation marks
|
||||
if char == '\'' || char == '"' {
|
||||
esc = char
|
||||
} else if char == ' ' {
|
||||
ret = append(ret, buf)
|
||||
buf = ""
|
||||
} else {
|
||||
buf += string(char)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Remaining characters
|
||||
if buf != "" {
|
||||
ret = append(ret, buf)
|
||||
buf = ""
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// Run executes the given command and return it's return code. It also respects the given concurrency number and will block until resources are free
|
||||
func (hook *Hook) Run() error {
|
||||
split := cmdSplit(hook.Command)
|
||||
args := make([]string, 0)
|
||||
if len(split) > 1 {
|
||||
args = split[1:]
|
||||
}
|
||||
cmd := exec.Command(split[0], args...)
|
||||
if hook.UID > 0 || hook.GID > 0 {
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{}
|
||||
cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uint32(hook.UID), Gid: uint32(hook.GID)}
|
||||
}
|
||||
if hook.Output {
|
||||
buf, ret := cmd.Output()
|
||||
fmt.Println(string(buf))
|
||||
return ret
|
||||
}
|
||||
return cmd.Run()
|
||||
}
|
Loading…
Reference in a new issue