-
Notifications
You must be signed in to change notification settings - Fork 0
/
script.go
104 lines (85 loc) · 1.8 KB
/
script.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
package main
import (
"bytes"
"context"
"fmt"
"os"
"os/exec"
"strings"
)
var (
DefaultScriptType = "post"
DefaultScriptShell = "bash"
)
type Script struct {
Id string
Command string
Disabled bool
// do not print commands stdout and stderr to logs
Quiet bool
// default shell
Shell string
// post or pre; default is 'post'
Type string
}
func (me *Script) Validate() error {
if me.Command == "" {
return fmt.Errorf("command is required")
}
return nil
}
func (me *Script) SetDefaults() {
if me.Type == "" {
me.Type = DefaultScriptType
}
me.Type = strings.ToLower(me.Type)
if me.Shell == "" {
me.Shell = DefaultScriptShell
}
}
func (me *Script) Run() (*ScriptResult, error) {
ret := &ScriptResult{}
ctx := context.Background()
stdin := bytes.NewBufferString(me.Command)
key := fmt.Sprintf("%s/%s", me.Type, me.Id)
log.Tracef("running script %s (id:%s type:%s quiet:%v shell:%s)",
key, me.Id, me.Type, me.Quiet, me.Shell)
if log.IsTrace() {
log.Tracef("command --- begin ---\n%s\n--- end ---\n", me.Command)
}
cmdline := []string{
"/usr/bin/env",
me.Shell,
"-",
}
c := exec.CommandContext(ctx, cmdline[0], cmdline[1:]...)
c.Stdin = stdin
if me.Quiet == false {
c.Stdout = os.Stdout
c.Stderr = os.Stdout
}
c.Env = os.Environ()
err := c.Run()
if err != nil {
if exiterr, ok := err.(*exec.ExitError); ok {
ret.Pid = exiterr.Pid()
ret.ExitCode = exiterr.ExitCode()
}
}
if c.ProcessState != nil {
ret.Pid = c.ProcessState.Pid()
}
if ret.Pid == 0 {
log.Warnf("%s script returned but no pid", key)
}
log.Tracef("%s script ran, exit code %d", key, ret.ExitCode)
return ret, nil
}
type ScriptResult struct {
Pid int
ExitCode int
}
func (me *ScriptResult) String() string {
return fmt.Sprintf("pid:%d exitcode:%d",
me.Pid, me.ExitCode)
}