Skip to content

Cross-compile with scala 3 #146

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Dec 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: CI
on:
push:
[ push, workflow_dispatch ]
jobs:
test:
runs-on: ubuntu-latest
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ class MyMongoSpec extends FlatSpec with Matchers with DockerMongodbService {
class AllAtOnceSpec extends FlatSpec with Matchers with BeforeAndAfterAll with GivenWhenThen with ScalaFutures
with DockerElasticsearchService with DockerCassandraService with DockerNeo4jService with DockerMongodbService {

implicit val pc = PatienceConfig(Span(20, Seconds), Span(1, Second))
implicit val pc: PatienceConfig = PatienceConfig(Span(20, Seconds), Span(1, Second))

"all containers" should "be ready at the same time" in {
dockerContainers.map(_.image).foreach(println)
Expand Down
50 changes: 31 additions & 19 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
lazy val commonSettings = Seq(
organization := "com.whisk",
version := "0.9.9",
scalaVersion := "2.13.5",
crossScalaVersions := Seq("2.13.5", "2.12.8", "2.11.12"),
scalaVersion := "2.13.6",
crossScalaVersions := Seq("2.13.6", "2.12.15", "2.11.12", "3.0.2"),
scalacOptions ++= Seq("-feature", "-deprecation"),
Test / fork := true,
licenses += ("MIT", url("http://opensource.org/licenses/MIT")),
Expand Down Expand Up @@ -36,7 +36,14 @@ lazy val root =
.in(file("."))
.settings(commonSettings: _*)
.settings(publish := {}, publishLocal := {}, packagedArtifacts := Map.empty)
.aggregate(core, testkitSpotifyImpl, testkitSpotifyShadedImpl, testkitDockerJavaImpl, config, scalatest, specs2, samples)
.aggregate(core,
testkitSpotifyImpl,
testkitSpotifyShadedImpl,
testkitDockerJavaImpl,
config,
scalatest,
specs2,
samples)

lazy val core =
project
Expand All @@ -58,12 +65,13 @@ lazy val testkitSpotifyShadedImpl =
project
.in(file("impl/spotify"))
.settings(commonSettings: _*)
.settings(name := "docker-testkit-impl-spotify-shaded",
libraryDependencies ++=
Seq("com.spotify" % "docker-client" % "8.11.5" classifier "shaded",
"com.google.code.findbugs" % "jsr305" % "3.0.1"),
target := baseDirectory.value / "target-shaded"
)
.settings(
name := "docker-testkit-impl-spotify-shaded",
libraryDependencies ++=
Seq("com.spotify" % "docker-client" % "8.11.5" classifier "shaded",
"com.google.code.findbugs" % "jsr305" % "3.0.1"),
target := baseDirectory.value / "target-shaded"
)
.dependsOn(core)

lazy val testkitDockerJavaImpl =
Expand All @@ -90,9 +98,12 @@ lazy val scalatest =
.settings(
name := "docker-testkit-scalatest",
libraryDependencies ++=
Seq("org.scalatest" %% "scalatest" % "3.0.8",
"ch.qos.logback" % "logback-classic" % "1.2.1" % "test",
"org.postgresql" % "postgresql" % "9.4.1210" % "test")
Seq(
"org.scalatest" %% "scalatest" % "3.2.9",
"ch.qos.logback" % "logback-classic" % "1.2.1" % "test",
"org.postgresql" % "postgresql" % "9.4.1210" % "test",
"javax.activation" % "activation" % "1.1.1" % "test"
)
)
.dependsOn(core, testkitSpotifyShadedImpl % "test", testkitDockerJavaImpl % "test", samples % "test")

Expand All @@ -102,9 +113,13 @@ lazy val specs2 =
.settings(
name := "docker-testkit-specs2",
libraryDependencies ++=
Seq("org.specs2" %% "specs2-core" % "4.5.1",
"ch.qos.logback" % "logback-classic" % "1.2.1" % "test",
"org.postgresql" % "postgresql" % "9.4.1210" % "test")
Seq(
"org.specs2" %% "specs2-core" % (if (scalaVersion.value.startsWith("2.1")) "4.5.1"
else "5.0.0-RC-11"),
"ch.qos.logback" % "logback-classic" % "1.2.1" % "test",
"org.postgresql" % "postgresql" % "9.4.1210" % "test",
"javax.activation" % "activation" % "1.1.1" % "test"
)
)
.dependsOn(core, samples % "test", testkitDockerJavaImpl % "test")

Expand All @@ -114,9 +129,6 @@ lazy val config =
.settings(
name := "docker-testkit-config",
libraryDependencies ++=
Seq(
"com.iheart" %% "ficus" % "1.4.7",
"org.scalatest" %% "scalatest" % "3.0.8" % "test"
)
Seq("com.typesafe" % "config" % "1.4.1", "org.scalatest" %% "scalatest" % "3.2.9" % "test")
)
.dependsOn(core, testkitDockerJavaImpl)
Original file line number Diff line number Diff line change
@@ -1,16 +1,69 @@
package com.whisk.docker.config

import com.typesafe.config.ConfigFactory
import com.whisk.docker.DockerContainer
import scala.collection.JavaConverters._

import com.typesafe.config.{Config, ConfigFactory}
import com.whisk.docker.{DockerContainer, VolumeMapping}
import com.whisk.docker.config.DockerTypesafeConfig._
import com.whisk.docker.impl.dockerjava.DockerKitDockerJava
import net.ceedubs.ficus.Ficus._
import net.ceedubs.ficus.readers.ArbitraryTypeReader._

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

implicit class RichConfig(c: Config) {
def getOpt[T](fn: (Config, String) => T, path: String): Option[T] =
if (c.hasPath(path)) Some(fn(c, path)) else None
}

private def toPortMapping(c: Config): DockerConfigPortMap = DockerConfigPortMap(
c.getInt("internal"),
c.getOpt(_ getInt _, "external")
)
private def toPortMappings(c: Config): Map[String, DockerConfigPortMap] =
c.entrySet()
.asScala
.map { e =>
val k = e.getKey.split('.').head
k -> toPortMapping(c.getConfig(k))
}
.toMap
private def toReadyCheckerLooped(c: Config): DockerConfigReadyCheckerLooped =
DockerConfigReadyCheckerLooped(c.getInt("attempts"), c.getInt("delay"))
private def toReadyResponse(c: Config): DockerConfigHttpResponseReady =
DockerConfigHttpResponseReady(
c.getInt("port"),
c.getOpt(_ getString _, "path") getOrElse "/",
c.getOpt(_ getString _, "host"),
c.getOpt(_ getInt _, "code").getOrElse(200),
c.getOpt(_ getInt _, "within"),
c.getOpt((c, s) => toReadyCheckerLooped(c.getConfig(s)), "looped")
)
private def toReadyChecker(c: Config): DockerConfigReadyChecker = DockerConfigReadyChecker(
c.getOpt(_ getString _, "log-line"),
c.getOpt((c, s) => toReadyResponse(c.getConfig(s)), "http-response-code")
)
private def toVolumeMaps(c: Config): VolumeMapping =
VolumeMapping(c.getString("host"),
c.getString("container"),
c.getOpt(_ getBoolean _, "rw").getOrElse(false))
private def toDockerConfig(c: Config): DockerConfig = DockerConfig(
c.getString("image-name"),
c.getOpt(_ getString _, "container-name"),
c.getOpt((c, s) => c.getStringList(s).asScala.toSeq, "command"),
c.getOpt((c, s) => c.getStringList(s).asScala.toSeq, "entrypoint"),
c.getOpt((c, s) => c.getStringList(s).asScala.toSeq, "environmental-variables")
.getOrElse(Nil),
c.getOpt((c, s) => toPortMappings(c.getConfig(s)), "port-maps"),
c.getOpt((c, s) => toReadyChecker(c.getConfig(s)), "ready-checker"),
c.getOpt((c, s) => c.getConfigList(s).asScala.toSeq.map(toVolumeMaps), "volume-maps")
.getOrElse(Nil),
c.getOpt(_ getLong _, "memory"),
c.getOpt(_ getLong _, "memory-reservation")
)
def configureDockerContainer(configurationName: String): DockerContainer = {
dockerConfig.as[DockerConfig](configurationName).toDockerContainer()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updating ficus to work with scala 3 is much harder, because of all the functionality that needs to be implemented using the new macro system. Maybe one day, but for now just writing this all out by hand

val config =
if (configurationName == "." || configurationName == "") dockerConfig
else dockerConfig.getConfig(configurationName)
toDockerConfig(config).toDockerContainer()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ package com.whisk.docker.config.test

import com.whisk.docker.{DockerContainer, DockerReadyChecker, HostConfig, VolumeMapping}
import com.whisk.docker.config.DockerKitConfig
import org.scalatest._

import scala.concurrent.duration._
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers

class DockerConfigSpec extends FlatSpec with Matchers with DockerKitConfig {
class DockerConfigSpec extends AnyFlatSpec with Matchers with DockerKitConfig {

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


configureDockerContainer("docker.postgres") shouldBe postgresExpected

val mongodbExpected = DockerContainer("mongo:3.0.6")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class DockerContainerManager(containers: Seq[DockerContainer], executor: DockerC
implicit ec: ExecutionContext) {

private lazy val log = LoggerFactory.getLogger(this.getClass)
private implicit val dockerExecutor = executor
private implicit val dockerExecutor: DockerCommandExecutor = executor

private val dockerStatesMap: Map[DockerContainer, DockerContainerState] =
containers.map(c => c -> new DockerContainerState(c)).toMap
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class DockerContainerState(spec: DockerContainer) {
spec.logLineReceiver.foreach {
case LogLineReceiver(withErr, f) => docker.withLogStreamLines(s, withErr)(f)
}
runReadyCheck
runReadyCheck()
this
}
}
Expand Down Expand Up @@ -79,13 +79,13 @@ class DockerContainerState(spec: DockerContainer) {
id.flatMap(docker.inspectContainer)

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

def getIpAddresses()(implicit docker: DockerCommandExecutor,
ec: ExecutionContext): Future[Seq[String]] = getRunningContainer.flatMap {
ec: ExecutionContext): Future[Seq[String]] = getRunningContainer().flatMap {
case Some(res) => Future.successful(res.ipAddresses)
case None => Future.failed(new RuntimeException(s"Container ${spec.image} is not running"))
}
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/com/whisk/docker/DockerKit.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ trait DockerKit {
ExecutionContext.fromExecutor(
Executors.newFixedThreadPool(Math.max(1, dockerContainers.length * 2)))
}
implicit lazy val dockerExecutor = dockerFactory.createExecutor()
implicit lazy val dockerExecutor: DockerCommandExecutor = dockerFactory.createExecutor()

lazy val containerManager = new DockerContainerManager(dockerContainers, dockerExecutor)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import java.util.concurrent.TimeUnit

import com.github.dockerjava.api.DockerClient
import com.github.dockerjava.api.exception.NotFoundException
import com.github.dockerjava.api.model.{PortBinding => _, ContainerPort => _, _}
import com.github.dockerjava.api.model.{ContainerPort => _, PortBinding => _, _}
import com.github.dockerjava.core.command.{LogContainerResultCallback, PullImageResultCallback}
import com.google.common.io.Closeables
import com.whisk.docker._

import scala.collection.JavaConverters._
import scala.concurrent.duration.FiniteDuration
import scala.concurrent.{ExecutionContext, Future, Promise}
import scala.reflect.ClassTag

class DockerJavaExecutor(override val host: String, client: DockerClient)
extends DockerCommandExecutor {
Expand Down Expand Up @@ -175,7 +175,7 @@ class DockerJavaExecutor(override val host: String, client: DockerClient)
.listImagesCmd()
.exec()
.asScala
.flatMap(img => Option(img.getRepoTags).getOrElse(Array()))
.flatMap(img => Option(img.getRepoTags).getOrElse(Array.empty(ClassTag(classOf[String]))))
.toSet)
}

Expand Down
2 changes: 2 additions & 0 deletions project/plugins.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.10")
addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.1.2")

addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.5")

addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.9.18-1")
7 changes: 4 additions & 3 deletions scalatest/src/test/scala/com/whisk/docker/AllAtOnceSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ package com.whisk.docker

import com.whisk.docker.impl.spotify.DockerKitSpotify
import org.scalatest.time.{Second, Seconds, Span}
import org.scalatest.{FlatSpec, Matchers}
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers

class AllAtOnceSpec
extends FlatSpec
extends AnyFlatSpec
with Matchers
with DockerKitSpotify
with DockerElasticsearchService
Expand All @@ -14,7 +15,7 @@ class AllAtOnceSpec
with DockerMongodbService
with PingContainerKit {

implicit val pc = PatienceConfig(Span(20, Seconds), Span(1, Second))
implicit val pc: PatienceConfig = PatienceConfig(Span(20, Seconds), Span(1, Second))

"all containers" should "be ready at the same time" in {
dockerContainers.map(_.image).foreach(println)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@ import com.github.dockerjava.netty.NettyDockerCmdExecFactory
import com.whisk.docker.impl.dockerjava.{Docker, DockerJavaExecutorFactory}
import com.whisk.docker.scalatest.DockerTestKit
import org.scalatest.time.{Second, Seconds, Span}
import org.scalatest.{FlatSpec, Matchers}
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers

class CassandraServiceSpec
extends FlatSpec
extends AnyFlatSpec
with Matchers
with DockerCassandraService
with DockerTestKit {

implicit val pc = PatienceConfig(Span(20, Seconds), Span(1, Second))
implicit val pc: PatienceConfig = PatienceConfig(Span(20, Seconds), Span(1, Second))

override implicit val dockerFactory: DockerFactory = new DockerJavaExecutorFactory(
new Docker(DefaultDockerClientConfig.createDefaultConfigBuilder().build(),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package com.whisk.docker

import com.whisk.docker.impl.spotify.DockerKitSpotify
import org.scalatest.{FlatSpec, Matchers}
import org.slf4j.LoggerFactory

import scala.concurrent.Await
import scala.concurrent.duration._
import scala.language.postfixOps
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers

class DependencyGraphReadyCheckSpec extends FlatSpec with Matchers with DockerKitSpotify {
class DependencyGraphReadyCheckSpec extends AnyFlatSpec with Matchers with DockerKitSpotify {

override val StartContainersTimeout = 45 seconds

Expand All @@ -24,6 +25,7 @@ class DependencyGraphReadyCheckSpec extends FlatSpec with Matchers with DockerKi
"KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181",
"KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://kafka:9092")
.withLinks(ContainerLink(zookeeperContainer, "zookeeper"))
.withHostname("kafka")
.withReadyChecker(DockerReadyChecker.LogLineContains("[Kafka Server 1], started"))

val schemaRegistryContainer = DockerContainer("confluentinc/cp-schema-registry:3.1.2",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ import time._
import impl.dockerjava._
import impl.spotify._
import scalatest.DockerTestKit
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers

abstract class DockerContainerLinkingSpec extends FlatSpec with Matchers with DockerTestKit {
abstract class DockerContainerLinkingSpec extends AnyFlatSpec with Matchers with DockerTestKit {

lazy val cmdExecutor = implicitly[DockerCommandExecutor]
implicit val pc = PatienceConfig(Span(20, Seconds), Span(1, Second))
implicit val pc: PatienceConfig = PatienceConfig(Span(20, Seconds), Span(1, Second))

val pingName = "ping"
val pongName = "pong"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ package com.whisk.docker
import com.whisk.docker.DockerContainerManager._
import com.whisk.docker.impl.dockerjava._
import org.scalatest._
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpecLike

class DockerContainerManagerSpec extends WordSpecLike with Matchers {
class DockerContainerManagerSpec extends AnyWordSpecLike with Matchers {

"The DockerContainerManager" should {
"a list of containers with dependencies" should {
Expand Down
Loading