-
Notifications
You must be signed in to change notification settings - Fork 12
/
run.go
113 lines (101 loc) · 2.51 KB
/
run.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package spicy
import (
"bytes"
"errors"
"fmt"
log "github.com/sirupsen/logrus"
"io"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"
)
type Runner interface {
Run(r io.Reader, args []string) (io.Reader, error)
}
type ExecRunner struct {
command string
}
func NewRunner(cmd string) ExecRunner {
return ExecRunner{command: cmd}
}
func (e ExecRunner) Run(r io.Reader, args []string) (io.Reader, error) {
log.Infof("About to run %s %s\n", e.command, strings.Join(args, " "))
cmd := exec.Command(e.command, args...)
var out bytes.Buffer
var errout bytes.Buffer
cmd.Stdin = r
cmd.Stdout = &out
cmd.Stderr = &errout
err := cmd.Run()
log.Debug("stdout: ", out.String())
if err != nil {
return nil, errors.New(fmt.Sprintf("Error running '%s': %s", e.command, errout.String()))
}
return &out, nil
}
type OutputFileRunner struct {
runner Runner
expectedOutputFile string
}
func NewOutputFileRunner(r Runner, outputFile string) OutputFileRunner {
return OutputFileRunner{runner: r, expectedOutputFile: outputFile}
}
func (e OutputFileRunner) Run(r io.Reader, args []string) (io.Reader, error) {
_, err := e.runner.Run(r, args)
if err != nil {
return nil, err
}
return os.Open(e.expectedOutputFile)
}
type MappedFileRunner struct {
runner Runner
inputFileArgs map[string]io.Reader
outputFileArg string
}
func NewMappedFileRunner(r Runner, inputFileArgs map[string]io.Reader, outputFileArg string) MappedFileRunner {
return MappedFileRunner{runner: r, inputFileArgs: inputFileArgs, outputFileArg: outputFileArg}
}
func writeTempFile(r io.Reader, prefix string) (string, error) {
tmpfile, err := ioutil.TempFile("", prefix)
if err != nil {
return "", err
}
path, err := filepath.Abs(tmpfile.Name())
if err != nil {
return "", err
}
log.Debugf("Writing file for prefix %s to %s", prefix, path)
_, err = io.Copy(tmpfile, r)
if err != nil {
return "", err
}
if err := tmpfile.Close(); err != nil {
return "", err
}
return path, nil
}
func (e MappedFileRunner) Run(r io.Reader, args []string) (io.Reader, error) {
var newArgs []string = make([]string, len(args))
for i, arg := range args {
if _, ok := e.inputFileArgs[arg]; ok {
tempFile, err := writeTempFile(e.inputFileArgs[arg], arg)
if err != nil {
return nil, err
}
newArgs[i] = tempFile
} else {
newArgs[i] = args[i]
}
}
_, err := e.runner.Run(r, newArgs)
if err != nil {
return nil, err
}
b, err := ioutil.ReadFile(e.outputFileArg)
if err != nil {
return nil, err
}
return bytes.NewBuffer(b), nil
}