scron/main.go
kekskurse 7c2131fe24
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/tag/woodpecker Pipeline was successful
feat: send to multiple notification channels if they have the same name
2025-08-26 12:59:30 +02:00

144 lines
3.3 KiB
Go

package main
import (
"bytes"
"os/exec"
"syscall"
"time"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
)
var currentConfig config
func main() {
zerolog.SetGlobalLevel(zerolog.InfoLevel)
log.Info().Msg("Start")
var err error
currentConfig, err = ReadFromFile("config.yml")
if err != nil {
log.Fatal().Err(err).Msg("Cant read config file")
}
log.Debug().Interface("config", currentConfig).Msg("config")
if len(currentConfig.Jobs) == 0 {
log.Warn().Msg("config dont include any jobs")
}
cronTicker, configTicker := createTickers(realTimeProvider{})
// Hauptloop mit select
for {
select {
case t := <-cronTicker:
execucteJobs(t, currentConfig)
case <-configTicker:
log.Debug().Msg("Reload Config")
currentConfig, err = ReadFromFile("config.yml")
if err != nil {
log.Error().Err(err).Msg("cant read config")
}
}
}
}
func execucteJobs(t time.Time, c config) {
for _, job := range c.Jobs {
execute, err := job.MatchCurrentTime(t)
log.Debug().Bool("execution", execute).Time("t", t).Msg("check cron execution")
if err != nil {
log.Error().Err(err).Msg("cant pars time for job")
}
if !execute {
continue
}
go executeJob(t, job, c)
}
}
func executeJob(t time.Time, job jobconfig, c config) {
result, err := executeCommand(job)
log.Info().Str("name", job.Name).Str("command", job.Command).Time("execute-for", t).Int("execCode", result.execCode).Str("output", result.outputString).Err(result.err).Msg("Done execute task")
if err != nil {
log.Err(err).Msg("Error while Execute command")
}
for _, n := range c.Notification {
if n.Name == job.Notification {
sendNotification(result, n)
}
}
}
func sendNotification(result jobResult, notification notificationConfig) error {
title := ""
msg := Message{}
msg.Priority = 10
if result.isSuccess() {
title = "✅ [scron][success] " + result.job.Name
msg.Priority = -1
} else {
title = "❌ [scron][error] " + result.job.Name
}
msg.Message = result.outputString
msg.Title = title
if result.isSuccess() {
if notification.Success.Gotify.URL != "" {
err := SendGotifyNotification(notification.Success.Gotify.URL, msg)
if err != nil {
log.Error().Err(err).Msg("cant send gotify notification")
}
}
if notification.Success.Smtp.Host != "" {
err := SendSMTPNotification(notification.Success.Smtp, title, result.outputString)
if err != nil {
log.Error().Err(err).Msg("cant send smtp notification")
}
}
} else {
if notification.Error.Gotify.URL != "" {
err := SendGotifyNotification(notification.Error.Gotify.URL, msg)
if err != nil {
log.Error().Err(err).Msg("cant send gotify notification")
}
}
if notification.Error.Smtp.Host != "" {
err := SendSMTPNotification(notification.Error.Smtp, title, result.outputString)
if err != nil {
log.Error().Err(err).Msg("cant send smtp notification")
}
}
}
return nil
}
func executeCommand(job jobconfig) (jobResult, error) {
j := jobResult{}
j.job = job
var output bytes.Buffer
cmd := exec.Command("bash", "-c", job.Command)
cmd.Stdout = &output
cmd.Stderr = &output
err := cmd.Run()
j.outputString = output.String()
if err != nil {
if exitErr, ok := err.(*exec.ExitError); ok {
if status, ok := exitErr.Sys().(syscall.WaitStatus); ok {
j.execCode = status.ExitStatus()
}
} else {
j.err = err
return j, err
}
}
return j, nil
}