Refactor hook

Refactor hook into its own go file.
This commit is contained in:
Felix Niederwanger 2023-04-22 10:23:03 +02:00
parent 919f7b5163
commit a9cda6f310
Signed by: phoenix
GPG key ID: 6E77A590E3F6D71C
3 changed files with 90 additions and 85 deletions

View file

@ -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

View file

@ -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
View 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()
}