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 }