Files
server/runner/runner.go
T

113 lines
2.5 KiB
Go

package runner
import (
"bytes"
"context"
"fmt"
"os"
"git.ohea.xyz/cursorius/server/config"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/client"
"github.com/docker/docker/pkg/stdcopy"
"github.com/op/go-logging"
)
var log = logging.MustGetLogger("cursorius-server")
type Run struct {
Name string
}
func runJob(job config.Job) {
if job.Folder != nil {
log.Debugf("Job configured with folder \"%v\"", *job.Folder)
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
log.Errorf("Could not create docker clien: %va", err)
return
}
hostname, err := os.Hostname()
if err != nil {
log.Errorf("Could not get hostname: %v", err)
return
}
ctx := context.Background()
resp, err := cli.ContainerCreate(ctx,
&container.Config{
Image: "cursorius:latest",
Cmd: []string{"/launcher.sh"},
Tty: false,
Env: []string{fmt.Sprintf("CURSORIUS_SRC_DIR=%s", *job.Folder)},
},
&container.HostConfig{
VolumesFrom: []string{hostname},
},
nil, nil, "",
)
if err != nil {
log.Errorf("Could not create container: %v", err)
return
}
if err := cli.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{}); err != nil {
log.Errorf("Could not start container: %v", err)
return
}
statusCh, errCh := cli.ContainerWait(ctx, resp.ID, container.WaitConditionNotRunning)
select {
case err := <-errCh:
if err != nil {
log.Errorf("Container returned error: %v", err)
return
}
case retCode := <-statusCh:
log.Debugf("Container finished running with return code: %v", retCode)
}
out, err := cli.ContainerLogs(ctx, resp.ID, types.ContainerLogsOptions{ShowStdout: true, ShowStderr: true})
if err != nil {
log.Errorf("Could not get container logs: %v", err)
return
}
var stdOut bytes.Buffer
var stdErr bytes.Buffer
stdcopy.StdCopy(&stdOut, &stdErr, out)
log.Debugf("%s", stdOut.Bytes())
log.Debugf("%s", stdErr.Bytes())
} else if job.URL != nil {
log.Debugf("Job configured with URL \"%v\"", *job.URL)
}
}
func runnerListen(ch chan Run, jobs map[string]config.Job) {
for {
run := <-ch
log.Debugf("Got Run: %v", run)
job, exists := jobs[run.Name]
if exists {
log.Infof("Launching run for job %v", run.Name)
go runJob(job)
} else {
log.Errorf("No configured job with name %v", run.Name)
}
}
}
func StartRunner(jobs map[string]config.Job) (chan Run, error) {
ch := make(chan Run)
go runnerListen(ch, jobs)
return ch, nil
}