Select Git revision
directories-go-utilities.mk
-
Volker Schukai authoredVolker Schukai authored
runnable-shell.go 2.52 KiB
package jobqueue
import (
"context"
"fmt"
"os"
"os/exec"
"strings"
)
func NewShellRunnableFromMap(data map[string]interface{}) (*ShellRunnable, error) {
scriptPath, _ := data["scriptpath"].(string)
script, _ := data["script"].(string)
if scriptPath != "" && script != "" {
return nil, fmt.Errorf("%w: ScriptPath and Script are mutually exclusive", ErrInvalidData)
}
if scriptPath == "" && script == "" {
return nil, fmt.Errorf("%w: ScriptPath or Script is required", ErrInvalidData)
}
return &ShellRunnable{
ScriptPath: scriptPath,
Script: script,
}, nil
}
// ShellResult is a result of a shell script
type ShellResult struct {
Output string
Error string
ExitCode int
}
type ShellRunnable struct {
ScriptPath string
Script string
}
func (s *ShellRunnable) Run(ctx context.Context) (RunResult[ShellResult], error) {
scriptPath := s.ScriptPath
if s.Script != "" {
// write to temp
tmp, err := os.CreateTemp("", "script-*.sh")
if err != nil {
return RunResult[ShellResult]{
Status: ResultStatusFailed,
Data: ShellResult{
Output: "",
ExitCode: DefaultErrorExitCode,
Error: fmt.Errorf("%w: %v", ErrFailedToCreateTempFile, err).Error(),
},
}, err
}
scriptPath = tmp.Name()
defer os.Remove(scriptPath)
_, err = tmp.WriteString(s.Script)
defer tmp.Close()
if err != nil {
return RunResult[ShellResult]{
Status: ResultStatusFailed,
Data: ShellResult{
Output: "",
ExitCode: DefaultErrorExitCode,
Error: fmt.Errorf("%w: %v", ErrFailedToWriteTempFile, err).Error(),
},
}, err
}
}
// #nosec
cmd := exec.CommandContext(ctx, "sh", scriptPath)
output, err := cmd.Output()
var stderr []byte
if err != nil {
stderr = err.(*exec.ExitError).Stderr
}
exitCode := SuccessExitCode
if err != nil {
if exitError, ok := err.(*exec.ExitError); ok {
exitCode = exitError.ExitCode()
}
return RunResult[ShellResult]{
Status: ResultStatusFailed,
Data: ShellResult{
Output: string(output),
ExitCode: exitCode,
Error: string(stderr),
},
}, err
}
return RunResult[ShellResult]{
Status: ResultStatusSuccess,
Data: ShellResult{
Output: strings.TrimSpace(string(output)),
ExitCode: exitCode,
Error: string(stderr),
},
}, nil
}
func (s *ShellRunnable) GetType() string {
return "shell"
}
func (c *ShellRunnable) GetPersistence() RunnableImport {
data := JSONMap{
"script_path": c.ScriptPath,
"script": c.Script,
}
return RunnableImport{
Type: c.GetType(),
Data: data,
}
}