Skip to content

Commit 64a54dd

Browse files
hughsimpsonc-solo
andauthored
Cross-compile with scala 3 (#146)
* bump scalatest * actualy commit the changes 🤦 * toDockerContainer() always adds a HostConfig -- how did this test pass before??? * kafka container needs hostname to match advertised listeners * Manually trigger for github actions Co-authored-by: C.Solovev <[email protected]>
1 parent 5742a42 commit 64a54dd

31 files changed

+174
-78
lines changed

.github/workflows/ci.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: CI
22
on:
3-
push:
3+
[ push, workflow_dispatch ]
44
jobs:
55
test:
66
runs-on: ubuntu-latest

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ class MyMongoSpec extends FlatSpec with Matchers with DockerMongodbService {
202202
class AllAtOnceSpec extends FlatSpec with Matchers with BeforeAndAfterAll with GivenWhenThen with ScalaFutures
203203
with DockerElasticsearchService with DockerCassandraService with DockerNeo4jService with DockerMongodbService {
204204

205-
implicit val pc = PatienceConfig(Span(20, Seconds), Span(1, Second))
205+
implicit val pc: PatienceConfig = PatienceConfig(Span(20, Seconds), Span(1, Second))
206206

207207
"all containers" should "be ready at the same time" in {
208208
dockerContainers.map(_.image).foreach(println)

build.sbt

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
lazy val commonSettings = Seq(
22
organization := "com.whisk",
33
version := "0.9.9",
4-
scalaVersion := "2.13.5",
5-
crossScalaVersions := Seq("2.13.5", "2.12.8", "2.11.12"),
4+
scalaVersion := "2.13.6",
5+
crossScalaVersions := Seq("2.13.6", "2.12.15", "2.11.12", "3.0.2"),
66
scalacOptions ++= Seq("-feature", "-deprecation"),
77
Test / fork := true,
88
licenses += ("MIT", url("http://opensource.org/licenses/MIT")),
@@ -36,7 +36,14 @@ lazy val root =
3636
.in(file("."))
3737
.settings(commonSettings: _*)
3838
.settings(publish := {}, publishLocal := {}, packagedArtifacts := Map.empty)
39-
.aggregate(core, testkitSpotifyImpl, testkitSpotifyShadedImpl, testkitDockerJavaImpl, config, scalatest, specs2, samples)
39+
.aggregate(core,
40+
testkitSpotifyImpl,
41+
testkitSpotifyShadedImpl,
42+
testkitDockerJavaImpl,
43+
config,
44+
scalatest,
45+
specs2,
46+
samples)
4047

4148
lazy val core =
4249
project
@@ -58,12 +65,13 @@ lazy val testkitSpotifyShadedImpl =
5865
project
5966
.in(file("impl/spotify"))
6067
.settings(commonSettings: _*)
61-
.settings(name := "docker-testkit-impl-spotify-shaded",
62-
libraryDependencies ++=
63-
Seq("com.spotify" % "docker-client" % "8.11.5" classifier "shaded",
64-
"com.google.code.findbugs" % "jsr305" % "3.0.1"),
65-
target := baseDirectory.value / "target-shaded"
66-
)
68+
.settings(
69+
name := "docker-testkit-impl-spotify-shaded",
70+
libraryDependencies ++=
71+
Seq("com.spotify" % "docker-client" % "8.11.5" classifier "shaded",
72+
"com.google.code.findbugs" % "jsr305" % "3.0.1"),
73+
target := baseDirectory.value / "target-shaded"
74+
)
6775
.dependsOn(core)
6876

6977
lazy val testkitDockerJavaImpl =
@@ -90,9 +98,12 @@ lazy val scalatest =
9098
.settings(
9199
name := "docker-testkit-scalatest",
92100
libraryDependencies ++=
93-
Seq("org.scalatest" %% "scalatest" % "3.0.8",
94-
"ch.qos.logback" % "logback-classic" % "1.2.1" % "test",
95-
"org.postgresql" % "postgresql" % "9.4.1210" % "test")
101+
Seq(
102+
"org.scalatest" %% "scalatest" % "3.2.9",
103+
"ch.qos.logback" % "logback-classic" % "1.2.1" % "test",
104+
"org.postgresql" % "postgresql" % "9.4.1210" % "test",
105+
"javax.activation" % "activation" % "1.1.1" % "test"
106+
)
96107
)
97108
.dependsOn(core, testkitSpotifyShadedImpl % "test", testkitDockerJavaImpl % "test", samples % "test")
98109

@@ -102,9 +113,13 @@ lazy val specs2 =
102113
.settings(
103114
name := "docker-testkit-specs2",
104115
libraryDependencies ++=
105-
Seq("org.specs2" %% "specs2-core" % "4.5.1",
106-
"ch.qos.logback" % "logback-classic" % "1.2.1" % "test",
107-
"org.postgresql" % "postgresql" % "9.4.1210" % "test")
116+
Seq(
117+
"org.specs2" %% "specs2-core" % (if (scalaVersion.value.startsWith("2.1")) "4.5.1"
118+
else "5.0.0-RC-11"),
119+
"ch.qos.logback" % "logback-classic" % "1.2.1" % "test",
120+
"org.postgresql" % "postgresql" % "9.4.1210" % "test",
121+
"javax.activation" % "activation" % "1.1.1" % "test"
122+
)
108123
)
109124
.dependsOn(core, samples % "test", testkitDockerJavaImpl % "test")
110125

@@ -114,9 +129,6 @@ lazy val config =
114129
.settings(
115130
name := "docker-testkit-config",
116131
libraryDependencies ++=
117-
Seq(
118-
"com.iheart" %% "ficus" % "1.4.7",
119-
"org.scalatest" %% "scalatest" % "3.0.8" % "test"
120-
)
132+
Seq("com.typesafe" % "config" % "1.4.1", "org.scalatest" %% "scalatest" % "3.2.9" % "test")
121133
)
122134
.dependsOn(core, testkitDockerJavaImpl)
Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,69 @@
11
package com.whisk.docker.config
22

3-
import com.typesafe.config.ConfigFactory
4-
import com.whisk.docker.DockerContainer
3+
import scala.collection.JavaConverters._
4+
5+
import com.typesafe.config.{Config, ConfigFactory}
6+
import com.whisk.docker.{DockerContainer, VolumeMapping}
57
import com.whisk.docker.config.DockerTypesafeConfig._
68
import com.whisk.docker.impl.dockerjava.DockerKitDockerJava
7-
import net.ceedubs.ficus.Ficus._
8-
import net.ceedubs.ficus.readers.ArbitraryTypeReader._
99

1010
trait DockerKitConfig extends DockerKitDockerJava {
1111
def dockerConfig = ConfigFactory.load()
1212

13+
implicit class RichConfig(c: Config) {
14+
def getOpt[T](fn: (Config, String) => T, path: String): Option[T] =
15+
if (c.hasPath(path)) Some(fn(c, path)) else None
16+
}
17+
18+
private def toPortMapping(c: Config): DockerConfigPortMap = DockerConfigPortMap(
19+
c.getInt("internal"),
20+
c.getOpt(_ getInt _, "external")
21+
)
22+
private def toPortMappings(c: Config): Map[String, DockerConfigPortMap] =
23+
c.entrySet()
24+
.asScala
25+
.map { e =>
26+
val k = e.getKey.split('.').head
27+
k -> toPortMapping(c.getConfig(k))
28+
}
29+
.toMap
30+
private def toReadyCheckerLooped(c: Config): DockerConfigReadyCheckerLooped =
31+
DockerConfigReadyCheckerLooped(c.getInt("attempts"), c.getInt("delay"))
32+
private def toReadyResponse(c: Config): DockerConfigHttpResponseReady =
33+
DockerConfigHttpResponseReady(
34+
c.getInt("port"),
35+
c.getOpt(_ getString _, "path") getOrElse "/",
36+
c.getOpt(_ getString _, "host"),
37+
c.getOpt(_ getInt _, "code").getOrElse(200),
38+
c.getOpt(_ getInt _, "within"),
39+
c.getOpt((c, s) => toReadyCheckerLooped(c.getConfig(s)), "looped")
40+
)
41+
private def toReadyChecker(c: Config): DockerConfigReadyChecker = DockerConfigReadyChecker(
42+
c.getOpt(_ getString _, "log-line"),
43+
c.getOpt((c, s) => toReadyResponse(c.getConfig(s)), "http-response-code")
44+
)
45+
private def toVolumeMaps(c: Config): VolumeMapping =
46+
VolumeMapping(c.getString("host"),
47+
c.getString("container"),
48+
c.getOpt(_ getBoolean _, "rw").getOrElse(false))
49+
private def toDockerConfig(c: Config): DockerConfig = DockerConfig(
50+
c.getString("image-name"),
51+
c.getOpt(_ getString _, "container-name"),
52+
c.getOpt((c, s) => c.getStringList(s).asScala.toSeq, "command"),
53+
c.getOpt((c, s) => c.getStringList(s).asScala.toSeq, "entrypoint"),
54+
c.getOpt((c, s) => c.getStringList(s).asScala.toSeq, "environmental-variables")
55+
.getOrElse(Nil),
56+
c.getOpt((c, s) => toPortMappings(c.getConfig(s)), "port-maps"),
57+
c.getOpt((c, s) => toReadyChecker(c.getConfig(s)), "ready-checker"),
58+
c.getOpt((c, s) => c.getConfigList(s).asScala.toSeq.map(toVolumeMaps), "volume-maps")
59+
.getOrElse(Nil),
60+
c.getOpt(_ getLong _, "memory"),
61+
c.getOpt(_ getLong _, "memory-reservation")
62+
)
1363
def configureDockerContainer(configurationName: String): DockerContainer = {
14-
dockerConfig.as[DockerConfig](configurationName).toDockerContainer()
64+
val config =
65+
if (configurationName == "." || configurationName == "") dockerConfig
66+
else dockerConfig.getConfig(configurationName)
67+
toDockerConfig(config).toDockerContainer()
1568
}
1669
}

config/src/test/scala/com/whisk/docker/config/test/DockerConfigSpec.scala

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@ package com.whisk.docker.config.test
22

33
import com.whisk.docker.{DockerContainer, DockerReadyChecker, HostConfig, VolumeMapping}
44
import com.whisk.docker.config.DockerKitConfig
5-
import org.scalatest._
65

76
import scala.concurrent.duration._
7+
import org.scalatest.flatspec.AnyFlatSpec
8+
import org.scalatest.matchers.should.Matchers
89

9-
class DockerConfigSpec extends FlatSpec with Matchers with DockerKitConfig {
10+
class DockerConfigSpec extends AnyFlatSpec with Matchers with DockerKitConfig {
1011

1112
"Config-based configurations" should "produce same containers as code-based ones" in {
1213
val volumes = Seq(
@@ -26,11 +27,9 @@ class DockerConfigSpec extends FlatSpec with Matchers with DockerKitConfig {
2627
.withPorts((5432, None))
2728
.withEnv(s"POSTGRES_USER=nph", s"POSTGRES_PASSWORD=suitup")
2829
.withReadyChecker(
29-
DockerReadyChecker.LogLineContains("database system is ready to accept connections")
30-
)
30+
DockerReadyChecker.LogLineContains("database system is ready to accept connections"))
3131
.withHostConfig(HostConfig(None, None, None))
3232

33-
3433
configureDockerContainer("docker.postgres") shouldBe postgresExpected
3534

3635
val mongodbExpected = DockerContainer("mongo:3.0.6")

core/src/main/scala/com/whisk/docker/DockerContainerManager.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class DockerContainerManager(containers: Seq[DockerContainer], executor: DockerC
1111
implicit ec: ExecutionContext) {
1212

1313
private lazy val log = LoggerFactory.getLogger(this.getClass)
14-
private implicit val dockerExecutor = executor
14+
private implicit val dockerExecutor: DockerCommandExecutor = executor
1515

1616
private val dockerStatesMap: Map[DockerContainer, DockerContainerState] =
1717
containers.map(c => c -> new DockerContainerState(c)).toMap

core/src/main/scala/com/whisk/docker/DockerContainerState.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class DockerContainerState(spec: DockerContainer) {
5050
spec.logLineReceiver.foreach {
5151
case LogLineReceiver(withErr, f) => docker.withLogStreamLines(s, withErr)(f)
5252
}
53-
runReadyCheck
53+
runReadyCheck()
5454
this
5555
}
5656
}
@@ -79,13 +79,13 @@ class DockerContainerState(spec: DockerContainer) {
7979
id.flatMap(docker.inspectContainer)
8080

8181
def getName()(implicit docker: DockerCommandExecutor, ec: ExecutionContext): Future[String] =
82-
getRunningContainer.flatMap {
82+
getRunningContainer().flatMap {
8383
case Some(res) => Future.successful(res.name)
8484
case None => Future.failed(new RuntimeException(s"Container ${spec.image} is not running"))
8585
}
8686

8787
def getIpAddresses()(implicit docker: DockerCommandExecutor,
88-
ec: ExecutionContext): Future[Seq[String]] = getRunningContainer.flatMap {
88+
ec: ExecutionContext): Future[Seq[String]] = getRunningContainer().flatMap {
8989
case Some(res) => Future.successful(res.ipAddresses)
9090
case None => Future.failed(new RuntimeException(s"Container ${spec.image} is not running"))
9191
}

core/src/main/scala/com/whisk/docker/DockerKit.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ trait DockerKit {
2525
ExecutionContext.fromExecutor(
2626
Executors.newFixedThreadPool(Math.max(1, dockerContainers.length * 2)))
2727
}
28-
implicit lazy val dockerExecutor = dockerFactory.createExecutor()
28+
implicit lazy val dockerExecutor: DockerCommandExecutor = dockerFactory.createExecutor()
2929

3030
lazy val containerManager = new DockerContainerManager(dockerContainers, dockerExecutor)
3131

impl/docker-java/src/main/scala/com/whisk/docker/impl/dockerjava/DockerJavaExecutor.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ import java.util.concurrent.TimeUnit
44

55
import com.github.dockerjava.api.DockerClient
66
import com.github.dockerjava.api.exception.NotFoundException
7-
import com.github.dockerjava.api.model.{PortBinding => _, ContainerPort => _, _}
7+
import com.github.dockerjava.api.model.{ContainerPort => _, PortBinding => _, _}
88
import com.github.dockerjava.core.command.{LogContainerResultCallback, PullImageResultCallback}
99
import com.google.common.io.Closeables
1010
import com.whisk.docker._
11-
1211
import scala.collection.JavaConverters._
1312
import scala.concurrent.duration.FiniteDuration
1413
import scala.concurrent.{ExecutionContext, Future, Promise}
14+
import scala.reflect.ClassTag
1515

1616
class DockerJavaExecutor(override val host: String, client: DockerClient)
1717
extends DockerCommandExecutor {
@@ -175,7 +175,7 @@ class DockerJavaExecutor(override val host: String, client: DockerClient)
175175
.listImagesCmd()
176176
.exec()
177177
.asScala
178-
.flatMap(img => Option(img.getRepoTags).getOrElse(Array()))
178+
.flatMap(img => Option(img.getRepoTags).getOrElse(Array.empty(ClassTag(classOf[String]))))
179179
.toSet)
180180
}
181181

project/plugins.sbt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@ addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.10")
33
addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.1.2")
44

55
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.5")
6+
7+
addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.9.18-1")

0 commit comments

Comments
 (0)