Skip to content

Commit

Permalink
feat: extend shell job (#64)
Browse files Browse the repository at this point in the history
  • Loading branch information
rfyiamcool authored Aug 18, 2023
1 parent 87082ee commit 6c23d5c
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 2 deletions.
37 changes: 35 additions & 2 deletions quartz/job.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package quartz

import (
"bytes"
"context"
"fmt"
"io"
"net/http"
"os/exec"
"strings"
"sync"
"sync/atomic"
)

Expand Down Expand Up @@ -41,6 +44,9 @@ const (
type ShellJob struct {
Cmd string
Result string
ExitCode int
Stdout string
Stderr string
JobStatus JobStatus
}

Expand All @@ -63,17 +69,44 @@ func (sh *ShellJob) Key() int {
return HashCode(sh.Description())
}

var (
shellOnce = sync.Once{}
shellPath = "bash"
)

func (sh *ShellJob) getShell() string {
shellOnce.Do(func() {
_, err := exec.LookPath("/bin/bash")
// if not found bash binary, use `sh`.
if err != nil {
shellPath = "sh"
}
})
return shellPath
}

// Execute is called by a Scheduler when the Trigger associated with this job fires.
func (sh *ShellJob) Execute(ctx context.Context) {
out, err := exec.CommandContext(ctx, "sh", "-c", sh.Cmd).Output()
shell := sh.getShell()

var stdout, stderr, result bytes.Buffer
cmd := exec.CommandContext(ctx, shell, "-c", sh.Cmd)
cmd.Stdout = io.MultiWriter(&stdout, &result)
cmd.Stderr = io.MultiWriter(&stderr, &result)

err := cmd.Run()
sh.Stdout = stdout.String()
sh.Stderr = stderr.String()
sh.ExitCode = cmd.ProcessState.ExitCode()

if err != nil {
sh.JobStatus = FAILURE
sh.Result = err.Error()
return
}

sh.JobStatus = OK
sh.Result = string(out)
sh.Result = result.String()
}

// CurlJob represents a cURL command Job, implements the quartz.Job interface.
Expand Down
64 changes: 64 additions & 0 deletions quartz/job_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,3 +199,67 @@ func TestCurlJobDescription(t *testing.T) {
})
}
}

func TestShellJob_Execute(t *testing.T) {
type args struct {
Cmd string
ExitCode int
Result string
Stdout string
Stderr string
}

tests := []struct {
name string
args args
}{
{
name: "test stdout",
args: args{
Cmd: "echo -n ok",
Result: "ok",
ExitCode: 0,
Stdout: "ok",
Stderr: "",
},
},
{
name: "test stderr",
args: args{
Cmd: "echo -n err >&2",
Result: "err",
ExitCode: 0,
Stdout: "",
Stderr: "err",
},
},
{
name: "test combine",
args: args{
Cmd: "echo -n ok && sleep 0.01 && echo -n err >&2",
Result: "okerr",
ExitCode: 0,
Stdout: "ok",
Stderr: "err",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
sh := quartz.NewShellJob(tt.args.Cmd)
sh.Execute(context.TODO())

assertEqual(t, tt.args.ExitCode, sh.ExitCode)
assertEqual(t, tt.args.Result, sh.Result)
assertEqual(t, tt.args.Stderr, sh.Stderr)
assertEqual(t, tt.args.Stdout, sh.Stdout)
})
}

// invalid command
stdoutShell := "invalid_command"
sh := quartz.NewShellJob(stdoutShell)
sh.Execute(context.Background())
assertEqual(t, 127, sh.ExitCode)
// the return value is different under different platforms.
}

0 comments on commit 6c23d5c

Please sign in to comment.