feat: add the ability to specify a custom mailto for all cron output
This commit is contained in:
@@ -549,18 +549,18 @@ echo "clock: some-command" >> Procfile
|
||||
popd &>/dev/null
|
||||
```
|
||||
|
||||
### `cron-write`
|
||||
### `cron-get-property`
|
||||
|
||||
- Description: Force triggers writing out cron entries
|
||||
- Description: Return the value for an app's cron property
|
||||
- Invoked by:
|
||||
- Arguments:
|
||||
- Arguments: `$APP $KEY`
|
||||
- Example:
|
||||
|
||||
```shell
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
|
||||
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
|
||||
APP="$1"; PROPERTY="$2"
|
||||
|
||||
# TODO
|
||||
```
|
||||
@@ -583,6 +583,22 @@ DOKKU_SCHEDULER="$1"
|
||||
# TODO
|
||||
```
|
||||
|
||||
### `cron-write`
|
||||
|
||||
- Description: Force triggers writing out cron entries
|
||||
- Invoked by:
|
||||
- Arguments:
|
||||
- Example:
|
||||
|
||||
```shell
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
|
||||
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
|
||||
|
||||
# TODO
|
||||
```
|
||||
|
||||
### `dependencies`
|
||||
|
||||
- Description: Used to install system-level dependencies.
|
||||
|
||||
@@ -46,10 +46,27 @@ When running scheduled cron tasks, there are a few items to be aware of:
|
||||
- Scheduled cron tasks are performed within the app environment available at runtime. If the app image does not exist, the command may fail to execute.
|
||||
- Schedules are performed on the hosting server's timezone, which is typically UTC.
|
||||
- At this time, only the `PATH` and `SHELL` environment variables are specified in the cron template.
|
||||
- A `MAILTO` value can be set via the `cron:set` command.
|
||||
- Each scheduled task is executed within a one-off `run` container, and thus inherit any docker-options specified for `run` containers. Resources are never shared between scheduled tasks.
|
||||
- Scheduled cron tasks are supported on a per-scheduler basis, and are currently only implemented by the `docker-local` scheduler.
|
||||
- Tasks for _all_ apps managed by the `docker-local` scheduler are written to a single crontab file owned by the `dokku` user. The `dokku` user's crontab should be considered reserved for this purpose.
|
||||
|
||||
#### Specifying a MAILTO value
|
||||
|
||||
By default, cron tasks complete and do not perform any reporting. Users can specify a value for `MAILTO` via the global `mailto` cron property by using the `cron:set` command.
|
||||
|
||||
```shell
|
||||
dokku cron:set --global mailto example@example.com
|
||||
```
|
||||
|
||||
All output for individual cron runs will be sent to the specified email.
|
||||
|
||||
Cron emails can be disabled by running the `cron:set` command for the global `mailto` property with no value.
|
||||
|
||||
```shell
|
||||
dokku cron:set --global mailto
|
||||
```
|
||||
|
||||
#### Listing Cron tasks
|
||||
|
||||
Cron tasks for an app can be listed via the `cron:list` command. This command takes an `app` argument.
|
||||
|
||||
1
plugins/20_events/cron-get-property
Symbolic link
1
plugins/20_events/cron-get-property
Symbolic link
@@ -0,0 +1 @@
|
||||
hook
|
||||
@@ -1,5 +1,6 @@
|
||||
SUBCOMMANDS = subcommands/list subcommands/report subcommands/run
|
||||
BUILD = commands subcommands
|
||||
TRIGGERS = triggers/cron-get-property
|
||||
BUILD = commands subcommands triggers
|
||||
PLUGIN_NAME = cron
|
||||
|
||||
include ../../common.mk
|
||||
|
||||
@@ -13,6 +13,18 @@ import (
|
||||
cronparser "github.com/robfig/cron/v3"
|
||||
)
|
||||
|
||||
var (
|
||||
// DefaultProperties is a map of all valid network properties with corresponding default property values
|
||||
DefaultProperties = map[string]string{
|
||||
"mailto": "",
|
||||
}
|
||||
|
||||
// GlobalProperties is a map of all valid global network properties
|
||||
GlobalProperties = map[string]bool{
|
||||
"mailto": true,
|
||||
}
|
||||
)
|
||||
|
||||
type TemplateCommand struct {
|
||||
ID string `json:"id"`
|
||||
App string `json:"app"`
|
||||
|
||||
@@ -13,6 +13,7 @@ func ReportSingleApp(appName string, format string, infoFlag string) error {
|
||||
}
|
||||
|
||||
flags := map[string]common.ReportFunc{
|
||||
"--cron-mailto": reportMailto,
|
||||
"--cron-task-count": reportTasks,
|
||||
}
|
||||
|
||||
@@ -27,6 +28,10 @@ func ReportSingleApp(appName string, format string, infoFlag string) error {
|
||||
return common.ReportSingleApp("cron", appName, infoFlag, infoFlags, flagKeys, format, trimPrefix, uppercaseFirstCharacter)
|
||||
}
|
||||
|
||||
func reportMailto(_ string) string {
|
||||
return common.PropertyGet("cron", "--global", "mailto")
|
||||
}
|
||||
|
||||
func reportTasks(appName string) string {
|
||||
c, _ := FetchCronEntries(appName)
|
||||
return strconv.Itoa(len(c))
|
||||
|
||||
11
plugins/cron/set.go
Normal file
11
plugins/cron/set.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package cron
|
||||
|
||||
import "errors"
|
||||
|
||||
func validateSetValue(appName string, key string, value string) error {
|
||||
if key == "mailto" && appName != "--global" {
|
||||
return errors.New("Property cannot be specified on a per-app basis")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
48
plugins/cron/src/triggers/triggers.go
Normal file
48
plugins/cron/src/triggers/triggers.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/dokku/dokku/plugins/common"
|
||||
"github.com/dokku/dokku/plugins/cron"
|
||||
)
|
||||
|
||||
// main entrypoint to all triggers
|
||||
func main() {
|
||||
parts := strings.Split(os.Args[0], "/")
|
||||
trigger := parts[len(parts)-1]
|
||||
flag.Parse()
|
||||
|
||||
var err error
|
||||
switch trigger {
|
||||
case "cron-get-property":
|
||||
appName := flag.Arg(0)
|
||||
property := flag.Arg(1)
|
||||
err = cron.TriggerCronGetProperty(appName, property)
|
||||
case "install":
|
||||
err = cron.TriggerInstall()
|
||||
case "post-app-clone-setup":
|
||||
oldAppName := flag.Arg(0)
|
||||
newAppName := flag.Arg(1)
|
||||
err = cron.TriggerPostAppCloneSetup(oldAppName, newAppName)
|
||||
case "post-app-rename-setup":
|
||||
oldAppName := flag.Arg(0)
|
||||
newAppName := flag.Arg(1)
|
||||
err = cron.TriggerPostAppRenameSetup(oldAppName, newAppName)
|
||||
case "post-delete":
|
||||
appName := flag.Arg(0)
|
||||
err = cron.TriggerPostDelete(appName)
|
||||
case "report":
|
||||
appName := flag.Arg(0)
|
||||
err = cron.ReportSingleApp(appName, "", "")
|
||||
default:
|
||||
err = fmt.Errorf("Invalid plugin trigger call: %s", trigger)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
common.LogFailWithError(err)
|
||||
}
|
||||
}
|
||||
@@ -112,3 +112,13 @@ func CommandRun(appName string, cronID string, detached bool) error {
|
||||
args := append([]string{scheduler, appName, "0"}, fields...)
|
||||
return common.PlugnTrigger("scheduler-run", args...)
|
||||
}
|
||||
|
||||
// CommandSet set or clear a cron property for an app
|
||||
func CommandSet(appName string, property string, value string) error {
|
||||
if err := validateSetValue(appName, property, value); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
common.CommandPropertySet("cron", appName, property, value, DefaultProperties, GlobalProperties)
|
||||
return common.PlugnTrigger("cron-write")
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
{{ if .Mailto -}}
|
||||
MAILTO={{ .Mailto }}
|
||||
{{ end -}}
|
||||
PATH=/usr/local/bin:/usr/bin:/bin
|
||||
SHELL=/bin/bash
|
||||
|
||||
|
||||
55
plugins/cron/triggers.go
Normal file
55
plugins/cron/triggers.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package cron
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/dokku/dokku/plugins/common"
|
||||
)
|
||||
|
||||
// TriggerCronGetProperty writes the cron key to stdout for a given app container
|
||||
func TriggerCronGetProperty(appName string, key string) error {
|
||||
if key != "mailto" {
|
||||
return errors.New("Invalid cron property specified")
|
||||
}
|
||||
|
||||
fmt.Println(common.PropertyGet("cron", appName, key))
|
||||
return nil
|
||||
}
|
||||
|
||||
// TriggerInstall runs the install step for the cron plugin
|
||||
func TriggerInstall() error {
|
||||
if err := common.PropertySetup("cron"); err != nil {
|
||||
return fmt.Errorf("Unable to install the cron plugin: %s", err.Error())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// TriggerPostAppCloneSetup creates new cron files
|
||||
func TriggerPostAppCloneSetup(oldAppName string, newAppName string) error {
|
||||
err := common.PropertyClone("cron", oldAppName, newAppName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// TriggerPostAppRenameSetup renames cron files
|
||||
func TriggerPostAppRenameSetup(oldAppName string, newAppName string) error {
|
||||
if err := common.PropertyClone("cron", oldAppName, newAppName); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := common.PropertyDestroy("cron", oldAppName); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// TriggerPostDelete destroys the cron property for a given app container
|
||||
func TriggerPostDelete(appName string) error {
|
||||
return common.PropertyDestroy("cron", appName)
|
||||
}
|
||||
@@ -116,8 +116,11 @@ func writeCronEntries() error {
|
||||
return deleteCrontab()
|
||||
}
|
||||
|
||||
mailto, _ := common.PlugnTriggerOutputAsString("cron-get-property", []string{"--global", "mailto"}...)
|
||||
|
||||
data := map[string]interface{}{
|
||||
"Commands": commands,
|
||||
"Mailto": mailto,
|
||||
}
|
||||
|
||||
t, err := getCronTemplate()
|
||||
|
||||
Reference in New Issue
Block a user