2016-04-08 21:41:20 +02:00
|
|
|
package tasks
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bufio"
|
2016-05-01 13:24:09 +02:00
|
|
|
"encoding/json"
|
2024-03-03 20:26:28 +01:00
|
|
|
"fmt"
|
2023-08-29 00:51:04 +02:00
|
|
|
"os/exec"
|
|
|
|
"time"
|
2024-03-03 20:26:28 +01:00
|
|
|
|
|
|
|
"github.com/ansible-semaphore/semaphore/api/sockets"
|
2024-04-12 12:32:54 +02:00
|
|
|
"github.com/ansible-semaphore/semaphore/pkg/task_logger"
|
2024-03-03 20:26:28 +01:00
|
|
|
"github.com/ansible-semaphore/semaphore/util"
|
|
|
|
log "github.com/sirupsen/logrus"
|
2016-04-08 21:41:20 +02:00
|
|
|
)
|
|
|
|
|
2024-04-12 12:21:05 +02:00
|
|
|
func (t *TaskRunner) Log(msg string) {
|
|
|
|
t.LogWithTime(time.Now(), msg)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *TaskRunner) Logf(format string, a ...any) {
|
|
|
|
t.LogfWithTime(time.Now(), format, a...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *TaskRunner) LogWithTime(now time.Time, msg string) {
|
2016-04-17 12:41:36 +02:00
|
|
|
for _, user := range t.users {
|
2016-05-01 13:24:09 +02:00
|
|
|
b, err := json.Marshal(&map[string]interface{}{
|
|
|
|
"type": "log",
|
2016-05-08 11:36:17 +02:00
|
|
|
"output": msg,
|
2016-05-17 21:12:54 +02:00
|
|
|
"time": now,
|
2023-08-29 00:51:04 +02:00
|
|
|
"task_id": t.Task.ID,
|
|
|
|
"project_id": t.Task.ProjectID,
|
2016-05-01 13:24:09 +02:00
|
|
|
})
|
|
|
|
|
2018-03-27 22:12:47 +02:00
|
|
|
util.LogPanic(err)
|
2016-05-01 13:24:09 +02:00
|
|
|
sockets.Message(user, b)
|
2016-04-17 12:41:36 +02:00
|
|
|
}
|
2016-04-08 21:41:20 +02:00
|
|
|
|
2022-01-29 19:00:21 +01:00
|
|
|
t.pool.logger <- logRecord{
|
|
|
|
task: t,
|
2021-08-31 00:12:33 +02:00
|
|
|
output: msg,
|
2022-01-29 19:00:21 +01:00
|
|
|
time: now,
|
2021-08-31 00:12:33 +02:00
|
|
|
}
|
2024-06-17 20:37:45 +02:00
|
|
|
|
|
|
|
for _, l := range t.logListeners {
|
|
|
|
l(now, msg)
|
|
|
|
}
|
2016-04-08 21:41:20 +02:00
|
|
|
}
|
|
|
|
|
2024-04-12 12:21:05 +02:00
|
|
|
func (t *TaskRunner) LogfWithTime(now time.Time, format string, a ...any) {
|
|
|
|
t.LogWithTime(now, fmt.Sprintf(format, a...))
|
2023-08-29 00:51:04 +02:00
|
|
|
}
|
|
|
|
|
2024-04-12 12:21:05 +02:00
|
|
|
func (t *TaskRunner) LogCmd(cmd *exec.Cmd) {
|
|
|
|
stderr, _ := cmd.StderrPipe()
|
|
|
|
stdout, _ := cmd.StdoutPipe()
|
|
|
|
|
|
|
|
go t.logPipe(bufio.NewReader(stderr))
|
|
|
|
go t.logPipe(bufio.NewReader(stdout))
|
2024-03-03 20:26:28 +01:00
|
|
|
}
|
|
|
|
|
2024-04-12 12:32:54 +02:00
|
|
|
func (t *TaskRunner) SetStatus(status task_logger.TaskStatus) {
|
2024-04-12 12:21:05 +02:00
|
|
|
if status == t.Task.Status {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
switch t.Task.Status { // check old status
|
2024-04-12 12:32:54 +02:00
|
|
|
case task_logger.TaskConfirmed:
|
|
|
|
if status == task_logger.TaskWaitingConfirmation {
|
2024-04-12 12:21:05 +02:00
|
|
|
return
|
|
|
|
}
|
2024-04-12 12:32:54 +02:00
|
|
|
case task_logger.TaskRunningStatus:
|
|
|
|
if status == task_logger.TaskWaitingStatus {
|
2024-04-12 12:21:05 +02:00
|
|
|
return
|
|
|
|
}
|
2024-04-12 12:32:54 +02:00
|
|
|
case task_logger.TaskStoppingStatus:
|
|
|
|
if status == task_logger.TaskWaitingStatus || status == task_logger.TaskRunningStatus {
|
2024-04-12 12:21:05 +02:00
|
|
|
//panic("stopping TaskRunner cannot be " + status)
|
|
|
|
return
|
|
|
|
}
|
2024-04-12 12:32:54 +02:00
|
|
|
case task_logger.TaskSuccessStatus:
|
|
|
|
case task_logger.TaskFailStatus:
|
|
|
|
case task_logger.TaskStoppedStatus:
|
2024-04-12 12:21:05 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Task.Status = status
|
|
|
|
|
2024-04-12 12:32:54 +02:00
|
|
|
if status == task_logger.TaskRunningStatus {
|
2024-04-12 12:21:05 +02:00
|
|
|
now := time.Now()
|
|
|
|
t.Task.Start = &now
|
|
|
|
}
|
|
|
|
|
|
|
|
t.saveStatus()
|
|
|
|
|
|
|
|
if localJob, ok := t.job.(*LocalJob); ok {
|
|
|
|
localJob.SetStatus(status)
|
|
|
|
}
|
|
|
|
|
2024-04-12 12:32:54 +02:00
|
|
|
if status == task_logger.TaskFailStatus {
|
2024-04-12 12:21:05 +02:00
|
|
|
t.sendMailAlert()
|
|
|
|
}
|
|
|
|
|
|
|
|
if status.IsNotifiable() {
|
|
|
|
t.sendTelegramAlert()
|
|
|
|
t.sendSlackAlert()
|
|
|
|
t.sendRocketChatAlert()
|
|
|
|
t.sendMicrosoftTeamsAlert()
|
2024-09-26 08:28:51 +02:00
|
|
|
t.sendDingTalkAlert()
|
2016-04-08 21:41:20 +02:00
|
|
|
}
|
2024-06-17 20:37:45 +02:00
|
|
|
|
|
|
|
for _, l := range t.statusListeners {
|
|
|
|
l(status)
|
|
|
|
}
|
2017-07-12 04:08:00 +02:00
|
|
|
}
|
|
|
|
|
2024-04-12 12:21:05 +02:00
|
|
|
func (t *TaskRunner) panicOnError(err error, msg string) {
|
|
|
|
if err != nil {
|
|
|
|
t.Log(msg)
|
|
|
|
util.LogPanicWithFields(err, log.Fields{"error": msg})
|
|
|
|
}
|
|
|
|
}
|
2017-07-12 04:08:00 +02:00
|
|
|
|
2024-04-12 12:21:05 +02:00
|
|
|
func (t *TaskRunner) logPipe(reader *bufio.Reader) {
|
2017-07-12 06:24:02 +02:00
|
|
|
line, err := Readln(reader)
|
2024-04-12 12:21:05 +02:00
|
|
|
|
2017-07-12 06:24:02 +02:00
|
|
|
for err == nil {
|
2022-01-30 12:22:18 +01:00
|
|
|
t.Log(line)
|
2017-07-12 06:24:02 +02:00
|
|
|
line, err = Readln(reader)
|
2017-07-12 03:26:55 +02:00
|
|
|
}
|
2017-07-12 04:08:00 +02:00
|
|
|
|
2017-07-12 06:24:02 +02:00
|
|
|
if err != nil && err.Error() != "EOF" {
|
2022-03-13 16:11:29 +01:00
|
|
|
//don't panic on these errors, sometimes it throws not dangerous "read |0: file already closed" error
|
2022-01-29 19:00:21 +01:00
|
|
|
util.LogWarningWithFields(err, log.Fields{"error": "Failed to read TaskRunner output"})
|
2017-07-12 04:08:00 +02:00
|
|
|
}
|
2016-04-08 21:41:20 +02:00
|
|
|
}
|
|
|
|
|
2024-04-12 12:21:05 +02:00
|
|
|
// Readln reads from the pipe
|
|
|
|
func Readln(r *bufio.Reader) (string, error) {
|
|
|
|
var (
|
|
|
|
isPrefix = true
|
|
|
|
err error
|
|
|
|
line, ln []byte
|
|
|
|
)
|
|
|
|
for isPrefix && err == nil {
|
|
|
|
line, isPrefix, err = r.ReadLine()
|
|
|
|
ln = append(ln, line...)
|
2018-03-27 22:12:47 +02:00
|
|
|
}
|
2024-04-12 12:21:05 +02:00
|
|
|
return string(ln), err
|
2018-03-27 22:12:47 +02:00
|
|
|
}
|