mail, context

This commit is contained in:
Sebastian Frank 2021-08-11 11:46:05 +02:00
parent f5e83ef690
commit da1322b7cb
Signed by: apairon
GPG Key ID: A0E05A8199CE3F57
4 changed files with 149 additions and 33 deletions

View File

@ -1,3 +1,6 @@
mail:
host: localhost:25
directories:
- path: /tmp/foo
recursive: false
@ -5,7 +8,9 @@ directories:
pollingInterval: 60
regex: "/[^\\.][^/]+.xml$"
actions:
- type: http
- id: postXML
description: POST xml
type: http
method: post
url: http://localhost:8080/api/v1/_/renz_einfo/xml
header:
@ -13,12 +18,32 @@ directories:
ContentType: application/xml
# content: PLAIN IS FILECONTENT
onError:
- type: move
- id: moveXMLError
description: MOVE xml to error dir
type: move
to: /tmp/error/{{ filename }}
- id: mailXMLError
description: eInfo Import ERROR on POST xml
type: mail
to: sebastian@webmakers.de
subject: "{{ action.Description }}"
body: |
path: {{ path }}
event: {{ event }}
http status: {{ context.postXML.response.Status }}
http response body
------------------
{{ context.postXML.response.Body }}
from: noreply@webmakers.de
stop: true
onSuccess:
- type: delete
- id: deleteXML
description: DELETE xml after POST
type: delete
- path: /tmp/foo
recursive: false

2
go.mod
View File

@ -3,7 +3,7 @@ module gitbase.de/apairon/fstrigger
go 1.16
require (
github.com/davecgh/go-spew v1.1.1
github.com/domodwyer/mailyak/v3 v3.3.3
github.com/flosch/pongo2/v4 v4.0.2
github.com/rjeczalik/notify v0.9.2
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b

4
go.sum
View File

@ -1,5 +1,5 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/domodwyer/mailyak/v3 v3.3.3 h1:E9cjqDUiwY1QSE5G2CbWHM7EJV5FybKPHnGovc2iaA8=
github.com/domodwyer/mailyak/v3 v3.3.3/go.mod h1:lOm/u9CyCVWHeaAmHIdF4RiKVxKUT/H5XX10lIKAL6c=
github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw=
github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=

145
main.go
View File

@ -13,13 +13,16 @@ import (
"sync"
"time"
"github.com/domodwyer/mailyak/v3"
"github.com/flosch/pongo2/v4"
"github.com/rjeczalik/notify"
"gopkg.in/yaml.v3"
)
type ActionConfig struct {
Type string
Id string
Type string
Description string
// http
Method *string
@ -30,6 +33,12 @@ type ActionConfig struct {
// move
To *string
// mail
// To *string
Subject *string
Body *string
From *string
Stop bool
OnSuccess []ActionConfig `yaml:"onSuccess"`
OnError []ActionConfig `yaml:"onError"`
@ -45,10 +54,17 @@ type DirectoryConfig struct {
Actions []ActionConfig
}
type MailConfig struct {
Host *string
}
type Config struct {
Mail MailConfig
Directories []DirectoryConfig
}
var conf = Config{}
var wg sync.WaitGroup
type pollInfo struct {
@ -68,6 +84,8 @@ func (p pollInfo) Sys() interface{} {
return nil
}
type actionCtx map[string]map[string]interface{}
func startWatcher(directory *DirectoryConfig) {
c := make(chan notify.EventInfo, 1000)
monitoredEvents := []notify.Event{}
@ -140,10 +158,14 @@ func startWatcher(directory *DirectoryConfig) {
if eventInfo != nil {
p := eventInfo.Path()
log.Printf("path: %s; event: %s\n", p, eventInfo.Event().String())
eventStr := eventInfo.Event().String()
if eventInfo.Event() == 0 {
eventStr = "POLLING"
}
log.Printf("path: %s; event: %s\n", p, eventStr)
if directory._regex == nil || directory._regex.MatchString(p) {
for _, action := range directory.Actions {
contin, _ := runAction(&action, eventInfo)
contin, _ := runAction(&action, eventInfo, nil)
if !contin {
break
}
@ -180,41 +202,46 @@ func startWatcher(directory *DirectoryConfig) {
}
func runAction(action *ActionConfig, eventInfo notify.EventInfo) (contin bool, err error) {
func runAction(action *ActionConfig, eventInfo notify.EventInfo, ctx actionCtx) (contin bool, err error) {
if ctx == nil {
ctx = make(actionCtx)
}
add2Ctx(action, ctx, "action", action)
contin = !action.Stop
log.Printf("path: %s; action: %s; stop: %v\n", eventInfo.Path(), action.Type, !contin)
log.Printf("path: %s; action: %s; stop: %v\n", eventInfo.Path(), action.Id, !contin)
switch action.Type {
case "http":
err = actionHttp(action, eventInfo)
err = actionHttp(action, eventInfo, ctx)
case "move":
err = actionMove(action, eventInfo)
err = actionMove(action, eventInfo, ctx)
case "delete":
err = actionDelete(action, eventInfo)
err = actionDelete(action, eventInfo, ctx)
case "log":
err = actionLog(action, eventInfo)
err = actionLog(action, eventInfo, ctx)
case "mail":
err = actionMail(action, eventInfo, ctx)
default:
err = fmt.Errorf("action type %s unknown", action.Type)
}
if err != nil {
log.Printf("path: %s; action: %s; error %s", eventInfo.Path(), action.Type, err)
add2Ctx(action, ctx, "error", err.Error())
log.Printf("path: %s; action: %s; error %s", eventInfo.Path(), action.Id, err)
for _, aE := range action.OnError {
_c, errE := runAction(&aE, eventInfo)
_c, _ := runAction(&aE, eventInfo, ctx)
contin = contin && _c
if errE != nil {
log.Printf("path: %s; action: %s; onError %s, error %s", eventInfo.Path(), action.Type, aE.Type, errE)
}
if !contin {
break
}
}
} else {
for _, aS := range action.OnSuccess {
_c, errS := runAction(&aS, eventInfo)
_c, errS := runAction(&aS, eventInfo, ctx)
contin = contin && _c
if errS != nil {
log.Printf("path: %s; action: %s; onSuccess %s, error %s", eventInfo.Path(), action.Type, aS.Type, errS)
err = errS
}
if !contin {
@ -226,10 +253,19 @@ func runAction(action *ActionConfig, eventInfo notify.EventInfo) (contin bool, e
return contin, err
}
func actionHttp(action *ActionConfig, eventInfo notify.EventInfo) error {
func add2Ctx(action *ActionConfig, ctx actionCtx, key string, val interface{}) {
if action.Id != "" {
if ctx[action.Id] == nil {
ctx[action.Id] = make(map[string]interface{})
}
ctx[action.Id][key] = val
}
}
func actionHttp(action *ActionConfig, eventInfo notify.EventInfo, ctx actionCtx) error {
method := "POST"
if action.Method != nil {
m, err := tpl2String(*action.Method, action, eventInfo)
m, err := tpl2String(*action.Method, action, eventInfo, ctx)
if err != nil {
return err
}
@ -238,7 +274,7 @@ func actionHttp(action *ActionConfig, eventInfo notify.EventInfo) error {
if action.URL == nil {
return fmt.Errorf("missing url in http action")
}
url, err := tpl2String(*action.URL, action, eventInfo)
url, err := tpl2String(*action.URL, action, eventInfo, ctx)
if err != nil {
return err
}
@ -253,7 +289,7 @@ func actionHttp(action *ActionConfig, eventInfo notify.EventInfo) error {
}
postData = bytes.NewBuffer(postBytes)
} else {
p, err := tpl2String(*action.Content, action, eventInfo)
p, err := tpl2String(*action.Content, action, eventInfo, ctx)
if err != nil {
return err
}
@ -281,6 +317,12 @@ func actionHttp(action *ActionConfig, eventInfo notify.EventInfo) error {
fmt.Println(string(body))
defer resp.Body.Close()
add2Ctx(action, ctx, "response", map[string]interface{}{
"Status": resp.Status,
"StatusCode": resp.StatusCode,
"Body": string(body),
})
if resp.StatusCode >= 400 {
return fmt.Errorf("response status %s", resp.Status)
}
@ -288,12 +330,12 @@ func actionHttp(action *ActionConfig, eventInfo notify.EventInfo) error {
return nil
}
func actionMove(action *ActionConfig, eventInfo notify.EventInfo) error {
func actionMove(action *ActionConfig, eventInfo notify.EventInfo, ctx actionCtx) error {
if action.To == nil {
return fmt.Errorf("missing to: as destination for move action")
}
to, err := tpl2String(*action.To, action, eventInfo)
to, err := tpl2String(*action.To, action, eventInfo, ctx)
if err != nil {
return err
}
@ -302,11 +344,11 @@ func actionMove(action *ActionConfig, eventInfo notify.EventInfo) error {
return err
}
func actionDelete(action *ActionConfig, eventInfo notify.EventInfo) error {
func actionDelete(action *ActionConfig, eventInfo notify.EventInfo, ctx actionCtx) error {
return os.Remove(eventInfo.Path())
}
func actionLog(action *ActionConfig, eventInfo notify.EventInfo) error {
func actionLog(action *ActionConfig, eventInfo notify.EventInfo, ctx actionCtx) error {
var logstr string
if action.Content != nil {
logstr = *action.Content
@ -317,7 +359,55 @@ func actionLog(action *ActionConfig, eventInfo notify.EventInfo) error {
return nil
}
func tpl2String(tpl string, action *ActionConfig, eventInfo notify.EventInfo) (string, error) {
func actionMail(action *ActionConfig, eventInfo notify.EventInfo, ctx actionCtx) error {
if conf.Mail.Host == nil {
return fmt.Errorf("missing host in mail: config")
}
if action.To == nil {
return fmt.Errorf("missing to: as recipient mail address")
}
if action.Subject == nil {
return fmt.Errorf("missing subject: action")
}
if action.Body == nil {
return fmt.Errorf("missing body: action")
}
if action.From == nil {
return fmt.Errorf("missing from: in action")
}
mail := mailyak.New(*conf.Mail.Host, nil)
to, err := tpl2String(*action.To, action, eventInfo, ctx)
if err != nil {
return err
}
mail.To(to)
from, err := tpl2String(*action.From, action, eventInfo, ctx)
if err != nil {
return err
}
mail.From(from)
mail.FromName("fstrigger")
subject, err := tpl2String(*action.Subject, action, eventInfo, ctx)
if err != nil {
return err
}
mail.Subject(subject)
body, err := tpl2String(*action.Body, action, eventInfo, ctx)
if err != nil {
return err
}
mail.Plain().Set(body)
return mail.Send()
}
func tpl2String(tpl string, action *ActionConfig, eventInfo notify.EventInfo, ctx actionCtx) (string, error) {
_tpl, err := pongo2.FromString(tpl)
if err != nil {
return "", err
@ -328,13 +418,14 @@ func tpl2String(tpl string, action *ActionConfig, eventInfo notify.EventInfo) (s
"path": p,
"dirname": filepath.Dir(p),
"filename": filepath.Base(p),
"event": eventInfo.Event().String(),
"action": action,
"context": ctx,
})
}
func main() {
conf := Config{}
confDat, err := ioutil.ReadFile("./config.yml")
if err != nil {
log.Fatalf("error %v", err)