This makes it easier to parse output in a machine-readable format - such as when interacting with cron tasks via jq for writing tests.
79 lines
2.0 KiB
Go
79 lines
2.0 KiB
Go
package cron
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"strings"
|
|
|
|
appjson "github.com/dokku/dokku/plugins/app-json"
|
|
"github.com/dokku/dokku/plugins/common"
|
|
|
|
"github.com/multiformats/go-base36"
|
|
cronparser "github.com/robfig/cron/v3"
|
|
)
|
|
|
|
type TemplateCommand struct {
|
|
ID string `json:"id"`
|
|
App string `json:"app"`
|
|
Command string `json:"command"`
|
|
Schedule string `json:"schedule"`
|
|
AltCommand string `json:"-"`
|
|
LogFile string `json:"-"`
|
|
}
|
|
|
|
func (t TemplateCommand) CronCommand() string {
|
|
if t.AltCommand != "" {
|
|
if t.LogFile != "" {
|
|
return fmt.Sprintf("%s &>> %s", t.AltCommand, t.LogFile)
|
|
}
|
|
return t.AltCommand
|
|
}
|
|
|
|
return fmt.Sprintf("dokku run --cron-id %s %s %s", t.ID, t.App, t.Command)
|
|
}
|
|
|
|
func FetchCronEntries(appName string) ([]TemplateCommand, error) {
|
|
commands := []TemplateCommand{}
|
|
appjsonPath := appjson.GetAppjsonPath(appName)
|
|
if !common.FileExists(appjsonPath) {
|
|
return commands, nil
|
|
}
|
|
|
|
b, err := ioutil.ReadFile(appjsonPath)
|
|
if err != nil {
|
|
return commands, fmt.Errorf("Cannot read app.json file for %s: %v", appName, err)
|
|
}
|
|
|
|
if strings.TrimSpace(string(b)) == "" {
|
|
return commands, nil
|
|
}
|
|
|
|
var appJSON appjson.AppJSON
|
|
if err = json.Unmarshal(b, &appJSON); err != nil {
|
|
return commands, fmt.Errorf("Cannot parse app.json for %s: %v", appName, err)
|
|
}
|
|
|
|
for _, c := range appJSON.Cron {
|
|
parser := cronparser.NewParser(cronparser.Minute | cronparser.Hour | cronparser.Dom | cronparser.Month | cronparser.Dow | cronparser.Descriptor)
|
|
_, err := parser.Parse(c.Schedule)
|
|
if err != nil {
|
|
return commands, err
|
|
}
|
|
|
|
commands = append(commands, TemplateCommand{
|
|
App: appName,
|
|
Command: c.Command,
|
|
Schedule: c.Schedule,
|
|
ID: GenerateCommandID(appName, c),
|
|
})
|
|
}
|
|
|
|
return commands, nil
|
|
}
|
|
|
|
// GenerateCommandID creates a unique ID for a given app/command/schedule combination
|
|
func GenerateCommandID(appName string, c appjson.CronCommand) string {
|
|
return base36.EncodeToStringLc([]byte(appName + "===" + c.Command + "===" + c.Schedule))
|
|
}
|