summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Odersky <jakob@odersky.com>2017-03-18 01:58:01 -0400
committerJakob Odersky <jakob@odersky.com>2017-03-18 01:58:01 -0400
commitdff97b40df39e5eb391e1fc30ca47180384f1747 (patch)
tree76d1a4d3af4c8a0b8b316a151d40493e8f22957b
parent3f00b87a022e92e3bf341d40d05d81b5538e4974 (diff)
downloadcrashbox-ci-nocake.tar.gz
crashbox-ci-nocake.tar.bz2
crashbox-ci-nocake.zip
Refactor trait-based dependencies to constructor parametersnocake
-rw-r--r--crashbox-server/src/main/scala/io/crashbox/ci/BuildDef.scala8
-rw-r--r--crashbox-server/src/main/scala/io/crashbox/ci/Core.scala2
-rw-r--r--crashbox-server/src/main/scala/io/crashbox/ci/DockerExecutor.scala (renamed from crashbox-server/src/main/scala/io/crashbox/ci/Executors.scala)11
-rw-r--r--crashbox-server/src/main/scala/io/crashbox/ci/Git.scala21
-rw-r--r--crashbox-server/src/main/scala/io/crashbox/ci/HttpApi.scala9
-rw-r--r--crashbox-server/src/main/scala/io/crashbox/ci/Main.scala24
-rw-r--r--crashbox-server/src/main/scala/io/crashbox/ci/Parser.scala (renamed from crashbox-server/src/main/scala/io/crashbox/ci/Parsers.scala)9
-rw-r--r--crashbox-server/src/main/scala/io/crashbox/ci/Scheduler.scala (renamed from crashbox-server/src/main/scala/io/crashbox/ci/Schedulers.scala)38
-rw-r--r--crashbox-server/src/main/scala/io/crashbox/ci/Source.scala19
-rw-r--r--crashbox-server/src/main/scala/io/crashbox/ci/Storage.scala6
-rw-r--r--crashbox-server/src/main/scala/io/crashbox/ci/package.scala9
11 files changed, 91 insertions, 65 deletions
diff --git a/crashbox-server/src/main/scala/io/crashbox/ci/BuildDef.scala b/crashbox-server/src/main/scala/io/crashbox/ci/BuildDef.scala
new file mode 100644
index 0000000..898c222
--- /dev/null
+++ b/crashbox-server/src/main/scala/io/crashbox/ci/BuildDef.scala
@@ -0,0 +1,8 @@
+package io.crashbox.ci
+
+case class BuildDef(
+ image: String,
+ script: String
+)
+
+case class ParseError(message: String)
diff --git a/crashbox-server/src/main/scala/io/crashbox/ci/Core.scala b/crashbox-server/src/main/scala/io/crashbox/ci/Core.scala
index 39a1aec..cb1db5c 100644
--- a/crashbox-server/src/main/scala/io/crashbox/ci/Core.scala
+++ b/crashbox-server/src/main/scala/io/crashbox/ci/Core.scala
@@ -8,7 +8,7 @@ import akka.event.LoggingAdapter
import akka.stream.ActorMaterializer
import com.typesafe.config.Config
-trait Core {
+class Core {
implicit val system: ActorSystem = ActorSystem("crashbox")
implicit val materializer = ActorMaterializer()
diff --git a/crashbox-server/src/main/scala/io/crashbox/ci/Executors.scala b/crashbox-server/src/main/scala/io/crashbox/ci/DockerExecutor.scala
index 045bf89..b5405c7 100644
--- a/crashbox-server/src/main/scala/io/crashbox/ci/Executors.scala
+++ b/crashbox-server/src/main/scala/io/crashbox/ci/DockerExecutor.scala
@@ -16,7 +16,12 @@ import com.spotify.docker.client.exceptions.ContainerNotFoundException
import com.spotify.docker.client.messages.{ContainerConfig, HostConfig}
import com.spotify.docker.client.messages.HostConfig.Bind
-trait Executors { core: Core =>
+case class ExecutionId(containerId: String) {
+ override def toString = containerId
+}
+
+class DockerExecutor(implicit core: Core) {
+ import core._
val dockerClient =
DefaultDockerClient.builder().uri("unix:///run/docker.sock").build()
@@ -29,10 +34,6 @@ trait Executors { core: Core =>
def containerWorkDirectory = "/home/crashbox"
def containerKillTimeout = 10.seconds
- case class ExecutionId(containerId: String) {
- override def toString = containerId
- }
-
def startExecution(
image: String,
script: String,
diff --git a/crashbox-server/src/main/scala/io/crashbox/ci/Git.scala b/crashbox-server/src/main/scala/io/crashbox/ci/Git.scala
new file mode 100644
index 0000000..db39891
--- /dev/null
+++ b/crashbox-server/src/main/scala/io/crashbox/ci/Git.scala
@@ -0,0 +1,21 @@
+package io.crashbox.ci
+
+import java.io.File
+import java.net.URL
+
+import scala.concurrent.Future
+
+import org.eclipse.jgit.api.{Git => JGit}
+
+object Git {
+
+ def fetchSource(from: URL, to: File)(implicit core: Core): Future[File] = {
+ import core._
+ Future {
+ log.debug(s"Cloning git repo from $from to $to")
+ JGit.cloneRepository.setURI(from.toURI.toString).setDirectory(to).call()
+ to
+ }(blockingDispatcher)
+ }
+
+}
diff --git a/crashbox-server/src/main/scala/io/crashbox/ci/HttpApi.scala b/crashbox-server/src/main/scala/io/crashbox/ci/HttpApi.scala
index c9e62c3..cbdbbf1 100644
--- a/crashbox-server/src/main/scala/io/crashbox/ci/HttpApi.scala
+++ b/crashbox-server/src/main/scala/io/crashbox/ci/HttpApi.scala
@@ -14,7 +14,8 @@ import akka.stream.scaladsl.{Source => Src}
import akka.stream.scaladsl.StreamConverters
import spray.json._
-trait HttpApi { self: Core with Schedulers with Storage =>
+class HttpApi(scheduler: Scheduler, storage: Storage)(implicit core: Core) {
+ import core._
val endpoint = "api"
@@ -46,21 +47,21 @@ trait HttpApi { self: Core with Schedulers with Storage =>
path("submit") {
post {
entity(as[Request]) { req =>
- val scheduled = scheduleBuild(req.url).map(_.toString())
+ val scheduled = scheduler.scheduleBuild(req.url).map(_.toString())
complete(scheduled)
}
}
} ~
path(Segment / "cancel") { buildId =>
post {
- cancelBuild(UUID.fromString(buildId))
+ scheduler.cancelBuild(UUID.fromString(buildId))
complete(204 -> None)
}
} ~
path(Segment / "logs") { buildId =>
get {
val src = StreamConverters
- .fromInputStream(() => readLog(UUID.fromString(buildId), 0))
+ .fromInputStream(() => storage.readLog(UUID.fromString(buildId), 0))
.map { bs =>
bs.utf8String
}
diff --git a/crashbox-server/src/main/scala/io/crashbox/ci/Main.scala b/crashbox-server/src/main/scala/io/crashbox/ci/Main.scala
index 55971b1..ae9499d 100644
--- a/crashbox-server/src/main/scala/io/crashbox/ci/Main.scala
+++ b/crashbox-server/src/main/scala/io/crashbox/ci/Main.scala
@@ -6,22 +6,24 @@ import akka.http.scaladsl.Http
import scala.concurrent._
import scala.concurrent.duration._
-object Main
- extends Core
- with Schedulers
- with Storage
- with Executors
- with Parsers
- with Source
- with HttpApi {
+object Main {
+
+ implicit val core = new Core()
+ import core._
+
+ val storage = new Storage()
+ val executor = new DockerExecutor
+ val scheduler = new Scheduler(executor, storage)
+ val api = new HttpApi(scheduler, storage)
+
def main(args: Array[String]): Unit = {
- reapDeadBuilds()
- Await.result(setupDatabase(), 10.seconds)
+ executor.reapDeadBuilds()
+ Await.result(storage.setupDatabase(), 10.seconds)
val host = config.getString("crashbox.host")
val port = config.getInt("crashbox.port")
- Http(system).bindAndHandle(httpApi, host, port) onComplete {
+ Http(system).bindAndHandle(api.httpApi, host, port) onComplete {
case Success(_) =>
log.info(s"Listening on $host:$port")
case Failure(ex) =>
diff --git a/crashbox-server/src/main/scala/io/crashbox/ci/Parsers.scala b/crashbox-server/src/main/scala/io/crashbox/ci/Parser.scala
index 020521c..a8b4f19 100644
--- a/crashbox-server/src/main/scala/io/crashbox/ci/Parsers.scala
+++ b/crashbox-server/src/main/scala/io/crashbox/ci/Parser.scala
@@ -5,17 +5,10 @@ import java.nio.file.Files
import scala.collection.JavaConverters._
-trait Parsers {
+object Parser {
def defaultImage = "crashbox/default"
- case class BuildDef(
- image: String,
- script: String
- )
-
- case class ParseError(message: String)
-
def parseBuild(workdir: File): Either[BuildDef, ParseError] = {
val file = new File(workdir, ".crashbox.txt")
if (!file.exists()) {
diff --git a/crashbox-server/src/main/scala/io/crashbox/ci/Schedulers.scala b/crashbox-server/src/main/scala/io/crashbox/ci/Scheduler.scala
index 0beec31..f263a9c 100644
--- a/crashbox-server/src/main/scala/io/crashbox/ci/Schedulers.scala
+++ b/crashbox-server/src/main/scala/io/crashbox/ci/Scheduler.scala
@@ -12,22 +12,18 @@ import scala.util.{Failure, Success}
import akka.actor.{Actor, ActorLogging, ActorRef, Props, Terminated}
import akka.util.Timeout
-trait Schedulers {
- self: Core with Source with Executors with Parsers with Storage =>
+class Scheduler(
+ val executor: DockerExecutor,
+ storage: Storage
+)(implicit core: Core) {
+ import Scheduler._
+ import core._
+ import executor._
+ import storage._
private def newTempDir: File =
Files.createTempDirectory("crashbox-run").toFile()
- sealed trait BuildState
- case class Cloning(url: URL) extends BuildState
- case class Parsing(dir: File) extends BuildState
- case class Starting(dir: File, buildDef: BuildDef) extends BuildState
- case class Running(id: ExecutionId) extends BuildState
-
- sealed trait EndBuildState extends BuildState
- case class Finished(status: Int) extends EndBuildState
- case class Failed(message: String) extends EndBuildState
-
class BuildManager(
buildId: BuildId,
url: URL
@@ -55,7 +51,7 @@ trait Schedulers {
case state @ Cloning(url) =>
log.debug("Update build state: cloning")
updateBuildState(buildId, state)
- fetchSource(url, newTempDir) onComplete {
+ Git.fetchSource(url, newTempDir) onComplete {
case Success(dir) =>
self ! Parsing(dir)
case Failure(err) =>
@@ -66,7 +62,7 @@ trait Schedulers {
log.debug("Update build state: parsing")
updateBuildState(buildId, state)
buildDir = Some(src)
- parseBuild(src) match {
+ Parser.parseBuild(src) match {
case Left(buildDef) =>
self ! Starting(src, buildDef)
case Right(err) =>
@@ -160,3 +156,17 @@ trait Schedulers {
}
}
+
+object Scheduler {
+
+ sealed trait BuildState
+ case class Cloning(url: URL) extends BuildState
+ case class Parsing(dir: File) extends BuildState
+ case class Starting(dir: File, buildDef: BuildDef) extends BuildState
+ case class Running(id: ExecutionId) extends BuildState
+
+ sealed trait EndBuildState extends BuildState
+ case class Finished(status: Int) extends EndBuildState
+ case class Failed(message: String) extends EndBuildState
+
+}
diff --git a/crashbox-server/src/main/scala/io/crashbox/ci/Source.scala b/crashbox-server/src/main/scala/io/crashbox/ci/Source.scala
deleted file mode 100644
index dffb5ea..0000000
--- a/crashbox-server/src/main/scala/io/crashbox/ci/Source.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-package io.crashbox.ci
-
-import java.io.File
-import java.net.URL
-
-import scala.concurrent.Future
-
-import org.eclipse.jgit.api.Git
-
-trait Source { self: Core =>
-
- def fetchSource(from: URL, to: File): Future[File] =
- Future {
- log.debug(s"Cloning git repo from $from to $to")
- Git.cloneRepository.setURI(from.toURI.toString).setDirectory(to).call()
- to
- }(blockingDispatcher)
-
-}
diff --git a/crashbox-server/src/main/scala/io/crashbox/ci/Storage.scala b/crashbox-server/src/main/scala/io/crashbox/ci/Storage.scala
index 0f095eb..bb995ef 100644
--- a/crashbox-server/src/main/scala/io/crashbox/ci/Storage.scala
+++ b/crashbox-server/src/main/scala/io/crashbox/ci/Storage.scala
@@ -12,9 +12,9 @@ import scala.concurrent.Future
import java.util.UUID
import slick.jdbc.H2Profile.api._
-trait Storage { self: Core with Parsers with Schedulers =>
-
- type BuildId = UUID
+class Storage(implicit core: Core) {
+ import core._
+ import Scheduler._
case class Build(
id: BuildId,
diff --git a/crashbox-server/src/main/scala/io/crashbox/ci/package.scala b/crashbox-server/src/main/scala/io/crashbox/ci/package.scala
new file mode 100644
index 0000000..183f9b5
--- /dev/null
+++ b/crashbox-server/src/main/scala/io/crashbox/ci/package.scala
@@ -0,0 +1,9 @@
+package io.crashbox
+
+import java.util.UUID
+
+package object ci {
+
+ type BuildId = UUID
+
+}