This repository has been archived by the owner on May 1, 2024. It is now read-only.
forked from skx/overseer
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathmain.go
217 lines (184 loc) · 3.96 KB
/
main.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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
//
// This is the sendmail bridge, which should be built like so:
//
// go build .
//
// Once built launch it as follows:
//
// $ ./sendmail-bridge [email protected]
//
// When a test fails an email will sent via sendmail
//
// Steve
// --
//
package main
import (
"bytes"
"flag"
"fmt"
"io/ioutil"
"os"
"os/exec"
"text/template"
"github.com/cmaster11/overseer/test"
"github.com/go-redis/redis"
)
// The redis handle
var r *redis.Client
// Template is our text/template which is used to generate the email
// notification to the user.
var Template = `From: {{.From}}
To: {{.To}}
Subject: The {{.Type}} test failed against {{.Target}}
The {{.Type}} test failed against {{.Target}}.
The complete test was:
{{.Input}}
The failure was:
{{.Failure}}
`
type EmailBridge struct {
// The email we notify
Email string
}
//
// Given a JSON string decode it and post it via email if it describes
// a test-failure.
//
func (bridge *EmailBridge) Process(msg []byte) {
testResult, err := test.ResultFromJSON(msg)
if err != nil {
panic(err)
}
//
// If the test passed then we don't care.
//
if testResult.Error == nil {
return
}
//
// Here is a temporary structure we'll use to popular our email
// template.
//
type TemplateParms struct {
To string
From string
Target string
Type string
Input string
Failure string
}
//
// Populate it appropriately.
//
var x TemplateParms
x.To = bridge.Email
x.From = bridge.Email
x.Type = testResult.Type
x.Target = testResult.Target
x.Input = testResult.Input
x.Failure = *testResult.Error
//
// Render our template into a buffer.
//
src := string(Template)
t := template.Must(template.New("tmpl").Parse(src))
buf := &bytes.Buffer{}
err = t.Execute(buf, x)
if err != nil {
fmt.Printf("Failed to compile email-template %s\n", err.Error())
return
}
//
// Prepare to run sendmail, with a pipe we can write our message to.
//
sendmail := exec.Command("/usr/sbin/sendmail", "-f", bridge.Email, bridge.Email)
stdin, err := sendmail.StdinPipe()
if err != nil {
fmt.Printf("Error sending email: %s\n", err.Error())
return
}
//
// Get the output pipe.
//
stdout, err := sendmail.StdoutPipe()
if err != nil {
fmt.Printf("Error sending email: %s\n", err.Error())
return
}
//
// Run the command, and pipe in the rendered template-result
//
sendmail.Start()
_, err = stdin.Write(buf.Bytes())
if err != nil {
fmt.Printf("Failed to write to sendmail pipe: %s\n", err.Error())
}
stdin.Close()
//
// Read the output of Sendmail.
//
_, err = ioutil.ReadAll(stdout)
if err != nil {
fmt.Printf("Error reading mail output: %s\n", err.Error())
return
}
err = sendmail.Wait()
if err != nil {
fmt.Printf("Waiting for process to terminate failed: %s\n", err.Error())
}
}
//
// Entry Point
//
func main() {
//
// Parse our flags
//
redisHost := flag.String("redis-host", "127.0.0.1:6379", "Specify the address of the redis queue.")
redisPass := flag.String("redis-pass", "", "Specify the password of the redis queue.")
var email = flag.String("email", "", "The email address to notify")
flag.Parse()
//
// Sanity-check.
//
if *email == "" {
fmt.Printf("Usage: email-bridge [email protected] [-redis-host=127.0.0.1:6379] [-redis-pass=foo]\n")
os.Exit(1)
}
//
// Create the redis client
//
r = redis.NewClient(&redis.Options{
Addr: *redisHost,
Password: *redisPass,
DB: 0, // use default DB
})
//
// And run a ping, just to make sure it worked.
//
_, err := r.Ping().Result()
if err != nil {
fmt.Printf("Redis connection failed: %s\n", err.Error())
os.Exit(1)
}
bridge := EmailBridge{
Email: *email,
}
for {
//
// Get test-results
//
msg, _ := r.BLPop(0, "overseer.results").Result()
//
// If they were non-empty, process them.
//
// msg[0] will be "overseer.results"
//
// msg[1] will be the value removed from the list.
//
if len(msg) >= 1 {
bridge.Process([]byte(msg[1]))
}
}
}