2017-02-22 09:46:42 +01:00
|
|
|
package tasks
|
|
|
|
|
|
|
|
import (
|
2017-03-07 09:35:14 +01:00
|
|
|
"bytes"
|
2022-02-12 13:15:15 +01:00
|
|
|
"github.com/ansible-semaphore/semaphore/db"
|
2022-04-19 14:32:03 +02:00
|
|
|
"github.com/ansible-semaphore/semaphore/util"
|
2017-03-07 09:35:14 +01:00
|
|
|
"html/template"
|
2017-03-22 08:22:09 +01:00
|
|
|
"net/http"
|
2017-02-22 09:46:42 +01:00
|
|
|
"strconv"
|
2021-10-26 18:54:19 +02:00
|
|
|
"strings"
|
2017-02-22 09:46:42 +01:00
|
|
|
)
|
|
|
|
|
2022-10-02 19:10:56 +02:00
|
|
|
const emailTemplate = "Subject: Task '{{ .Name }}' failed\r\n" +
|
|
|
|
"From: {{ .From }}\r\n" +
|
|
|
|
"\r\n" +
|
|
|
|
"Task {{ .TaskID }} with template '{{ .Name }}' has failed!`\n" +
|
|
|
|
"Task Log: {{ .TaskURL }}"
|
2017-03-07 09:35:14 +01:00
|
|
|
|
2022-02-03 08:05:13 +01:00
|
|
|
const telegramTemplate = `{"chat_id": "{{ .ChatID }}","parse_mode":"HTML","text":"<code>{{ .Name }}</code>\n#{{ .TaskID }} <b>{{ .TaskResult }}</b> <code>{{ .TaskVersion }}</code> {{ .TaskDescription }}\nby {{ .Author }}\n{{ .TaskURL }}"}`
|
2017-03-22 08:22:09 +01:00
|
|
|
|
2022-04-19 14:32:03 +02:00
|
|
|
const slackTemplate = `{ "attachments": [ { "title": "Task: {{ .Name }}", "title_link": "{{ .TaskURL }}", "text": "execution ID #{{ .TaskID }}, status: {{ .TaskResult }}!", "color": "{{ .Color }}", "mrkdwn_in": ["text"], "fields": [ { "title": "Author", "value": "{{ .Author }}", "short": true }] } ]}`
|
2022-04-11 10:29:48 +02:00
|
|
|
|
2018-03-27 22:12:47 +02:00
|
|
|
// Alert represents an alert that will be templated and sent to the appropriate service
|
2017-03-07 09:35:14 +01:00
|
|
|
type Alert struct {
|
2021-10-26 18:54:19 +02:00
|
|
|
TaskID string
|
2022-02-03 08:05:13 +01:00
|
|
|
Name string
|
2021-10-26 18:54:19 +02:00
|
|
|
TaskURL string
|
|
|
|
ChatID string
|
|
|
|
TaskResult string
|
|
|
|
TaskDescription string
|
|
|
|
TaskVersion string
|
|
|
|
Author string
|
2022-04-19 14:32:03 +02:00
|
|
|
Color string
|
2022-10-02 19:10:56 +02:00
|
|
|
From string
|
2017-03-07 09:35:14 +01:00
|
|
|
}
|
|
|
|
|
2022-01-29 19:00:21 +01:00
|
|
|
func (t *TaskRunner) sendMailAlert() {
|
2018-03-27 22:12:47 +02:00
|
|
|
if !util.Config.EmailAlert || !t.alert {
|
2017-03-13 03:30:48 +01:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
mailHost := util.Config.EmailHost + ":" + util.Config.EmailPort
|
|
|
|
|
|
|
|
var mailBuffer bytes.Buffer
|
2017-04-18 16:36:09 +02:00
|
|
|
alert := Alert{
|
2022-10-02 19:10:56 +02:00
|
|
|
TaskID: strconv.Itoa(t.task.ID),
|
|
|
|
Name: t.template.Name,
|
|
|
|
TaskURL: util.Config.WebHost + "/project/" + strconv.Itoa(t.template.ProjectID) +
|
|
|
|
"/templates/" + strconv.Itoa(t.template.ID) +
|
|
|
|
"?t=" + strconv.Itoa(t.task.ID),
|
|
|
|
From: util.Config.EmailSender,
|
2017-04-18 16:36:09 +02:00
|
|
|
}
|
2017-03-13 03:30:48 +01:00
|
|
|
tpl := template.New("mail body template")
|
|
|
|
tpl, err := tpl.Parse(emailTemplate)
|
2018-03-27 22:12:47 +02:00
|
|
|
util.LogError(err)
|
2017-03-13 03:30:48 +01:00
|
|
|
|
2018-03-27 22:12:47 +02:00
|
|
|
t.panicOnError(tpl.Execute(&mailBuffer, alert), "Can't generate alert template!")
|
2017-02-22 09:46:42 +01:00
|
|
|
|
2017-03-13 03:30:48 +01:00
|
|
|
for _, user := range t.users {
|
2022-01-29 19:00:21 +01:00
|
|
|
userObj, err := t.pool.store.GetUser(user)
|
2017-03-13 03:30:48 +01:00
|
|
|
|
2018-03-27 22:12:47 +02:00
|
|
|
if !userObj.Alert {
|
2017-03-13 03:30:48 +01:00
|
|
|
return
|
|
|
|
}
|
2021-10-26 18:54:19 +02:00
|
|
|
t.panicOnError(err, "Can't find user Email!")
|
2017-03-13 03:30:48 +01:00
|
|
|
|
2022-01-30 12:22:18 +01:00
|
|
|
t.Log("Sending email to " + userObj.Email + " from " + util.Config.EmailSender)
|
2022-10-02 19:10:56 +02:00
|
|
|
|
2021-09-22 05:43:19 +02:00
|
|
|
if util.Config.EmailSecure {
|
2022-10-02 19:10:56 +02:00
|
|
|
err = util.SendSecureMail(util.Config.EmailHost, util.Config.EmailPort,
|
|
|
|
util.Config.EmailSender, util.Config.EmailUsername, util.Config.EmailPassword,
|
|
|
|
userObj.Email, mailBuffer)
|
2021-09-22 05:43:19 +02:00
|
|
|
} else {
|
|
|
|
err = util.SendMail(mailHost, util.Config.EmailSender, userObj.Email, mailBuffer)
|
|
|
|
}
|
2022-10-02 19:10:56 +02:00
|
|
|
|
2018-03-27 22:12:47 +02:00
|
|
|
t.panicOnError(err, "Can't send email!")
|
2017-03-13 03:30:48 +01:00
|
|
|
}
|
2017-02-22 09:46:42 +01:00
|
|
|
}
|
2017-03-22 08:22:09 +01:00
|
|
|
|
2022-01-29 19:00:21 +01:00
|
|
|
func (t *TaskRunner) sendTelegramAlert() {
|
2018-03-27 22:12:47 +02:00
|
|
|
if !util.Config.TelegramAlert || !t.alert {
|
2017-03-22 08:22:09 +01:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-02-12 13:15:15 +01:00
|
|
|
if t.template.SuppressSuccessAlerts && t.task.Status == db.TaskSuccessStatus {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-03-27 22:12:47 +02:00
|
|
|
chatID := util.Config.TelegramChat
|
2022-02-03 19:35:32 +01:00
|
|
|
if t.alertChat != nil && *t.alertChat != "" {
|
|
|
|
chatID = *t.alertChat
|
2017-05-03 06:27:58 +02:00
|
|
|
}
|
|
|
|
|
2017-03-22 08:22:09 +01:00
|
|
|
var telegramBuffer bytes.Buffer
|
2021-10-26 18:54:19 +02:00
|
|
|
|
|
|
|
var version string
|
|
|
|
if t.task.Version != nil {
|
|
|
|
version = *t.task.Version
|
|
|
|
} else if t.task.BuildTaskID != nil {
|
|
|
|
version = "build " + strconv.Itoa(*t.task.BuildTaskID)
|
|
|
|
} else {
|
|
|
|
version = ""
|
|
|
|
}
|
|
|
|
|
|
|
|
var message string
|
|
|
|
if t.task.Message != "" {
|
|
|
|
message = "- " + t.task.Message
|
|
|
|
}
|
|
|
|
|
|
|
|
var author string
|
|
|
|
if t.task.UserID != nil {
|
2022-01-29 19:00:21 +01:00
|
|
|
user, err := t.pool.store.GetUser(*t.task.UserID)
|
2021-10-26 18:54:19 +02:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
author = user.Name
|
|
|
|
}
|
|
|
|
|
2017-04-18 16:36:09 +02:00
|
|
|
alert := Alert{
|
2021-10-26 18:54:19 +02:00
|
|
|
TaskID: strconv.Itoa(t.task.ID),
|
2022-02-03 08:05:13 +01:00
|
|
|
Name: t.template.Name,
|
2021-10-26 18:54:19 +02:00
|
|
|
TaskURL: util.Config.WebHost + "/project/" + strconv.Itoa(t.template.ProjectID) + "/templates/" + strconv.Itoa(t.template.ID) + "?t=" + strconv.Itoa(t.task.ID),
|
|
|
|
ChatID: chatID,
|
2022-02-12 13:15:15 +01:00
|
|
|
TaskResult: strings.ToUpper(string(t.task.Status)),
|
2021-10-26 18:54:19 +02:00
|
|
|
TaskVersion: version,
|
|
|
|
TaskDescription: message,
|
|
|
|
Author: author,
|
2017-04-18 16:36:09 +02:00
|
|
|
}
|
2021-08-31 14:03:52 +02:00
|
|
|
|
2017-03-22 08:22:09 +01:00
|
|
|
tpl := template.New("telegram body template")
|
2021-10-26 18:54:19 +02:00
|
|
|
|
2017-03-22 08:22:09 +01:00
|
|
|
tpl, err := tpl.Parse(telegramTemplate)
|
2021-10-26 18:54:19 +02:00
|
|
|
if err != nil {
|
2022-01-30 12:22:18 +01:00
|
|
|
t.Log("Can't parse telegram template!")
|
2021-10-26 18:54:19 +02:00
|
|
|
panic(err)
|
|
|
|
}
|
2017-03-22 08:22:09 +01:00
|
|
|
|
2021-10-26 18:54:19 +02:00
|
|
|
err = tpl.Execute(&telegramBuffer, alert)
|
|
|
|
if err != nil {
|
2022-01-30 12:22:18 +01:00
|
|
|
t.Log("Can't generate alert template!")
|
2021-10-26 18:54:19 +02:00
|
|
|
panic(err)
|
|
|
|
}
|
2017-03-22 08:22:09 +01:00
|
|
|
|
2017-03-24 08:50:26 +01:00
|
|
|
resp, err := http.Post("https://api.telegram.org/bot"+util.Config.TelegramToken+"/sendMessage", "application/json", &telegramBuffer)
|
2017-03-22 08:22:09 +01:00
|
|
|
|
2021-10-26 18:54:19 +02:00
|
|
|
if err != nil {
|
2022-10-02 19:10:56 +02:00
|
|
|
t.Log("Can't send telegram alert! Error: " + err.Error())
|
2021-10-26 18:54:19 +02:00
|
|
|
} else if resp.StatusCode != 200 {
|
2022-10-02 19:10:56 +02:00
|
|
|
t.Log("Can't send telegram alert! Response code: " + strconv.Itoa(resp.StatusCode))
|
2017-03-24 08:50:26 +01:00
|
|
|
}
|
2017-03-22 08:22:09 +01:00
|
|
|
}
|
2022-04-11 10:29:48 +02:00
|
|
|
|
|
|
|
func (t *TaskRunner) sendSlackAlert() {
|
|
|
|
if !util.Config.SlackAlert || !t.alert {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if t.template.SuppressSuccessAlerts && t.task.Status == db.TaskSuccessStatus {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
slackUrl := util.Config.SlackUrl
|
|
|
|
|
|
|
|
var slackBuffer bytes.Buffer
|
|
|
|
|
|
|
|
var version string
|
|
|
|
if t.task.Version != nil {
|
|
|
|
version = *t.task.Version
|
|
|
|
} else if t.task.BuildTaskID != nil {
|
|
|
|
version = "build " + strconv.Itoa(*t.task.BuildTaskID)
|
|
|
|
} else {
|
|
|
|
version = ""
|
|
|
|
}
|
|
|
|
|
|
|
|
var message string
|
|
|
|
if t.task.Message != "" {
|
|
|
|
message = "- " + t.task.Message
|
|
|
|
}
|
|
|
|
|
|
|
|
var author string
|
|
|
|
if t.task.UserID != nil {
|
|
|
|
user, err := t.pool.store.GetUser(*t.task.UserID)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
author = user.Name
|
|
|
|
}
|
|
|
|
|
|
|
|
var color string
|
|
|
|
if t.task.Status == db.TaskSuccessStatus {
|
|
|
|
color = "good"
|
2022-04-19 14:32:03 +02:00
|
|
|
} else if t.task.Status == db.TaskFailStatus {
|
2022-04-11 10:29:48 +02:00
|
|
|
color = "bad"
|
2022-04-19 14:32:03 +02:00
|
|
|
} else if t.task.Status == db.TaskRunningStatus {
|
|
|
|
color = "#333CFF"
|
|
|
|
} else if t.task.Status == db.TaskWaitingStatus {
|
|
|
|
color = "#FFFC33"
|
|
|
|
} else if t.task.Status == db.TaskStoppingStatus {
|
|
|
|
color = "#BEBEBE"
|
|
|
|
} else if t.task.Status == db.TaskStoppedStatus {
|
|
|
|
color = "#5B5B5B"
|
2022-04-11 10:29:48 +02:00
|
|
|
}
|
|
|
|
alert := Alert{
|
|
|
|
TaskID: strconv.Itoa(t.task.ID),
|
|
|
|
Name: t.template.Name,
|
|
|
|
TaskURL: util.Config.WebHost + "/project/" + strconv.Itoa(t.template.ProjectID) + "/templates/" + strconv.Itoa(t.template.ID) + "?t=" + strconv.Itoa(t.task.ID),
|
|
|
|
TaskResult: strings.ToUpper(string(t.task.Status)),
|
|
|
|
TaskVersion: version,
|
|
|
|
TaskDescription: message,
|
|
|
|
Author: author,
|
2022-04-19 14:32:03 +02:00
|
|
|
Color: color,
|
2022-04-11 10:29:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
tpl := template.New("slack body template")
|
|
|
|
|
|
|
|
tpl, err := tpl.Parse(slackTemplate)
|
|
|
|
if err != nil {
|
|
|
|
t.Log("Can't parse slack template!")
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = tpl.Execute(&slackBuffer, alert)
|
|
|
|
if err != nil {
|
|
|
|
t.Log("Can't generate alert template!")
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
resp, err := http.Post(slackUrl, "application/json", &slackBuffer)
|
|
|
|
|
|
|
|
if err != nil {
|
2022-10-02 19:10:56 +02:00
|
|
|
t.Log("Can't send slack alert! Error: " + err.Error())
|
2022-04-11 10:29:48 +02:00
|
|
|
} else if resp.StatusCode != 200 {
|
2022-10-02 19:10:56 +02:00
|
|
|
t.Log("Can't send slack alert! Response code: " + strconv.Itoa(resp.StatusCode))
|
2022-04-11 10:29:48 +02:00
|
|
|
}
|
|
|
|
}
|