Files
mrvacommander/pkg/agent/agent.go

87 lines
2.1 KiB
Go

package agent
import (
"bufio"
"bytes"
"log/slog"
"mrvacommander/pkg/common"
"mrvacommander/pkg/queue"
"mrvacommander/pkg/storage"
"os"
"os/exec"
"path"
"strconv"
"strings"
)
type RunnerSingle struct {
queue queue.Queue
}
func NewRunnerSingle(numWorkers int, queue queue.Queue) *RunnerSingle {
r := RunnerSingle{queue: queue}
for id := 1; id <= numWorkers; id++ {
go r.worker(id)
}
return &r
}
func (r *RunnerSingle) worker(wid int) {
var job common.AnalyzeJob
for {
job = <-r.queue.Jobs()
slog.Debug("Picking up job", "job", job, "worker", wid)
cwd, err := os.Getwd()
if err != nil {
slog.Error("RunJob: cwd problem: ", "error", err)
continue
}
slog.Debug("Analysis: running", "job", job)
storage.SetStatus(job.QueryPackId, job.ORL, common.StatusQueued)
cmd := exec.Command(path.Join(cwd, "bin", "run-analysis.sh"),
strconv.FormatInt(int64(job.QueryPackId), 10),
job.QueryLanguage, job.ORL.Owner, job.ORL.Repo)
out, err := cmd.CombinedOutput()
if err != nil {
slog.Error("Analysis command failed: exit code: ", "error", err, "job", job)
slog.Error("Analysis command failed: ", "job", job, "output", out)
storage.SetStatus(job.QueryPackId, job.ORL, common.StatusError)
continue
}
slog.Debug("Analysis run finished", "job", job)
// Get the SARIF ouput location
sr := bufio.NewScanner(bytes.NewReader(out))
sr.Split(bufio.ScanLines)
for {
more := sr.Scan()
if !more {
slog.Error("Analysis run failed to report result: ", "output", out)
break
}
fields := strings.Fields(sr.Text())
if len(fields) >= 3 {
if fields[0] == "run-analysis-output" {
slog.Debug("Analysis run successful: ", "job", job, "location", fields[2])
res := common.AnalyzeResult{
RunAnalysisSARIF: fields[2], // Abs. path from run-analysis.sh
RunAnalysisBQRS: "", // FIXME? see note in run-analysis.sh
}
r.queue.Results() <- res
storage.SetStatus(job.QueryPackId, job.ORL, common.StatusSuccess)
storage.SetResult(job.QueryPackId, job.ORL, res)
break
}
}
}
}
}