mirror of
https://github.com/ncarlier/webhookd.git
synced 2025-04-07 17:07:09 +00:00
105 lines
2.5 KiB
Go
105 lines
2.5 KiB
Go
package worker
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"os/exec"
|
|
"path"
|
|
"time"
|
|
|
|
"github.com/ncarlier/webhookd/pkg/logger"
|
|
"github.com/ncarlier/webhookd/pkg/tools"
|
|
)
|
|
|
|
// ChanWriter is a simple writer to a channel of byte.
|
|
type ChanWriter struct {
|
|
ByteChan chan []byte
|
|
}
|
|
|
|
func (c *ChanWriter) Write(p []byte) (int, error) {
|
|
c.ByteChan <- p
|
|
return len(p), nil
|
|
}
|
|
|
|
var (
|
|
workingdir = os.Getenv("APP_WORKING_DIR")
|
|
)
|
|
|
|
func runScript(work *WorkRequest) (string, error) {
|
|
if workingdir == "" {
|
|
workingdir = os.TempDir()
|
|
}
|
|
|
|
logger.Info.Println("Executing script", work.Script, "...")
|
|
binary, err := exec.LookPath(work.Script)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
// Exec script with args...
|
|
cmd := exec.Command(binary, work.Payload)
|
|
// with env variables...
|
|
cmd.Env = append(os.Environ(), work.Args...)
|
|
|
|
// Open the out file for writing
|
|
logFilename := path.Join(workingdir, fmt.Sprintf("%s_%s.txt", tools.ToSnakeCase(work.Name), time.Now().Format("20060102_1504")))
|
|
logFile, err := os.Create(logFilename)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer logFile.Close()
|
|
logger.Debug.Println("Writing output to file: ", logFilename, "...")
|
|
|
|
wLogFile := bufio.NewWriter(logFile)
|
|
|
|
r, w := io.Pipe()
|
|
cmd.Stdout = w
|
|
cmd.Stderr = w
|
|
|
|
// Start the script...
|
|
err = cmd.Start()
|
|
if err != nil {
|
|
return logFilename, err
|
|
}
|
|
|
|
// Write script output to log file and the work message cahnnel.
|
|
go func(reader io.Reader) {
|
|
scanner := bufio.NewScanner(reader)
|
|
for scanner.Scan() {
|
|
if work.Closed {
|
|
logger.Error.Println("Unable to write into the work channel. Work request closed.")
|
|
return
|
|
}
|
|
// writing to the work channel
|
|
line := scanner.Text()
|
|
work.MessageChan <- []byte(line)
|
|
// writing to outfile
|
|
if _, err := wLogFile.WriteString(line + "\n"); err != nil {
|
|
logger.Error.Println("Error while writing into the log file:", logFilename, err)
|
|
}
|
|
if err = wLogFile.Flush(); err != nil {
|
|
logger.Error.Println("Error while flushing the log file:", logFilename, err)
|
|
}
|
|
}
|
|
if err := scanner.Err(); err != nil {
|
|
logger.Error.Println("Error scanning the script stdout: ", logFilename, err)
|
|
}
|
|
}(r)
|
|
|
|
timer := time.AfterFunc(time.Duration(work.Timeout)*time.Second, func() {
|
|
logger.Warning.Printf("Timeout reached (%ds). Killing script: %s\n", work.Timeout, work.Script)
|
|
cmd.Process.Kill()
|
|
})
|
|
err = cmd.Wait()
|
|
if err != nil {
|
|
timer.Stop()
|
|
logger.Info.Println("Script", work.Script, "executed with ERROR.")
|
|
return logFilename, err
|
|
}
|
|
timer.Stop()
|
|
logger.Info.Println("Script", work.Script, "executed with SUCCESS")
|
|
return logFilename, nil
|
|
}
|