Raja's Exocortex

Requirement

Dkron needs a free mechanism to send email alerts when a job fails. Dkron Pro has an email processor plugin that can do this. If a generic command processor plugin exists, then it will be more flexible and can be used to send email/chat/etc.

Plugin name: dkron plugin-processor-cmd

Pseudo Code

  1. Run an external command
  2. Pass DKRON job details as environment variables
  3. Invoke cmd + args
  4. Send job output (stdout + stderr) to cmd Stdin
  5. Use exec.CommandContext() timer for cmd execution timeout
  6. Config params -
    1. cmd, args as array
    2. timeout in seconds
    3. forward
  7. Capture ouput of cmd and log it in DKRON DB

Relevant Code Examples

SENDING STDIN TO CMD

package main

import "os/exec"
import "strings"

func main() {
    cmd := exec.Command("kinit", username)
    cmd.Stdin = strings.NewReader(password)
    err := cmd.Run()
}

SETTING ENVIRONMENTAL VARIABLES

package main

import (
    "log"
    "os"
    "os/exec"
)

func main() {
    cmd := exec.Command("prog")
    cmd.Env = append(os.Environ(),
        "FOO=duplicate_value", // ignored
        "FOO=actual_value",    // this value is used
    )
    if err := cmd.Run(); err != nil {
        log.Fatal(err)
    }
}

EXEC WITH CONTEXT FOR TIMEOUT

package main

import (
    "context"
    "os/exec"
    "time"
)

func main() {
    ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
    defer cancel()

    if err := exec.CommandContext(ctx, "sleep", "5").Run(); err != nil {
        // This will fail after 100 milliseconds. The 5 second sleep
        // will be interrupted.
    }
}

Random Example

package main

import (
    "fmt"
    "io"
    "log"
    "os/exec"
)

func main() {
    cmd := exec.Command("cat")
    stdin, err := cmd.StdinPipe()
    if err != nil {
        log.Fatal(err)
    }

    go func() {
        defer stdin.Close()
        io.WriteString(stdin, "values written to stdin are passed to cmd's standard input")
    }()

    out, err := cmd.CombinedOutput()
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("%s\n", out)
}