This is an automated email from the ASF dual-hosted git repository.

samueler pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-pekko.git


The following commit(s) were added to refs/heads/main by this push:
     new b7be586e77 Replacing deprecated docker-client with docker-java (#922)
b7be586e77 is described below

commit b7be586e7783f11bdcc970a81dbcb6210d30e638
Author: Samuele Resca <[email protected]>
AuthorDate: Fri Jan 12 16:12:23 2024 +0000

    Replacing deprecated docker-client with docker-java (#922)
    
    * Replacing deprecated docker-client with docker-java.
    
    * Addressing feedback.
    
    * Awaiting for image pull.
    
    ---------
    
    Co-authored-by: Samuele Resca <[email protected]>
---
 .../apache/pekko/io/dns/DockerBindDnsService.scala | 136 +++++++++++++++------
 project/Dependencies.scala                         |  19 ++-
 2 files changed, 104 insertions(+), 51 deletions(-)

diff --git 
a/actor-tests/src/test/scala/org/apache/pekko/io/dns/DockerBindDnsService.scala 
b/actor-tests/src/test/scala/org/apache/pekko/io/dns/DockerBindDnsService.scala
index 6db30a024b..614bee5410 100644
--- 
a/actor-tests/src/test/scala/org/apache/pekko/io/dns/DockerBindDnsService.scala
+++ 
b/actor-tests/src/test/scala/org/apache/pekko/io/dns/DockerBindDnsService.scala
@@ -18,23 +18,43 @@ import scala.util.Try
 import scala.util.control.NonFatal
 
 import com.typesafe.config.Config
-import com.spotify.docker.client.DefaultDockerClient
-import com.spotify.docker.client.DockerClient.{ ListContainersParam, LogsParam 
}
-import com.spotify.docker.client.messages.{ ContainerConfig, HostConfig, 
PortBinding }
+import com.github.dockerjava.core.DockerClientConfig
+import com.github.dockerjava.api.model.HostConfig;
+import com.github.dockerjava.core.DefaultDockerClientConfig
+import com.github.dockerjava.api.model.Frame;
+import com.github.dockerjava.api.async.ResultCallback;
 import org.scalatest.concurrent.Eventually
 
 import org.apache.pekko
 import pekko.testkit.PekkoSpec
 import pekko.util.ccompat.JavaConverters._
+import com.github.dockerjava.api.DockerClient
+import com.github.dockerjava.httpclient5.ApacheDockerHttpClient
+import com.github.dockerjava.api.command.CreateContainerCmd
+import com.github.dockerjava.api.model.PortBinding
+import com.github.dockerjava.api.model.Container
+import com.github.dockerjava.api.model.Volume
+import com.github.dockerjava.core.DockerClientImpl
+import com.github.dockerjava.api.model.Bind
 
 abstract class DockerBindDnsService(config: Config) extends PekkoSpec(config) 
with Eventually {
-  val client = DefaultDockerClient.fromEnv().build()
+
+  val dockerConfig: DockerClientConfig = DefaultDockerClientConfig
+    .createDefaultConfigBuilder()
+    .build();
+
+  val httpClient: ApacheDockerHttpClient = new ApacheDockerHttpClient.Builder()
+    .dockerHost(dockerConfig.getDockerHost())
+    .sslConfig(dockerConfig.getSSLConfig())
+    .build();
+
+  val client: DockerClient = DockerClientImpl.getInstance(dockerConfig, 
httpClient);
 
   val hostPort: Int
 
   var id: Option[String] = None
 
-  def dockerAvailable() = Try(client.ping()).isSuccess
+  def dockerAvailable() = Try(client.pingCmd().exec()).isSuccess
 
   override def atStartup(): Unit = {
     log.info("Running on port port {}", hostPort)
@@ -43,64 +63,100 @@ abstract class DockerBindDnsService(config: Config) 
extends PekkoSpec(config) wi
     // https://github.com/sameersbn/docker-bind/pull/61
     val image = "raboof/bind:9.11.3-20180713-nochown"
     try {
-      client.pull(image)
+      client
+        .pullImageCmd(image)
+        .start()
+        .awaitCompletion()
     } catch {
       case NonFatal(_) =>
         log.warning(s"Failed to pull docker image [$image], is docker 
running?")
         return
     }
 
-    val containerConfig = ContainerConfig
-      .builder()
-      .image(image)
-      .env("NO_CHOWN=true")
-      .cmd("-4") // only listen on ipv4
-      .hostConfig(
-        HostConfig
-          .builder()
-          .portBindings(Map(
-            "53/tcp" -> List(PortBinding.of("", hostPort)).asJava,
-            "53/udp" -> List(PortBinding.of("", hostPort)).asJava).asJava)
-          .binds(HostConfig.Bind
-            .from(new 
java.io.File("actor-tests/src/test/bind/").getAbsolutePath)
-            .to("/data/bind")
-            .build())
-          .build())
-      .build()
-
     val containerName = "pekko-test-dns-" + getClass.getCanonicalName
 
+    val containerCommand: CreateContainerCmd = client
+      .createContainerCmd(image)
+      .withName(containerName)
+      .withEnv("NO_CHOWN=true")
+      .withCmd("-4")
+      .withHostConfig(
+        HostConfig.newHostConfig()
+          .withPortBindings(
+            PortBinding.parse(s"$hostPort:53/tcp"),
+            PortBinding.parse(s"$hostPort:53/udp"))
+          .withBinds(new Bind(new 
java.io.File("actor-tests/src/test/bind/").getAbsolutePath,
+            new Volume("/data/bind"))))
+
     client
-      .listContainers(ListContainersParam.allContainers())
+      .listContainersCmd()
+      .exec()
       .asScala
-      .find(_.names().asScala.exists(_.contains(containerName)))
-      .foreach(c => {
-        if ("running" == c.state()) {
-          client.killContainer(c.id)
+      .find((c: Container) => c.getNames().exists(_.contains(containerName)))
+      .foreach((c: Container) => {
+        if ("running" == c.getState()) {
+          client.killContainerCmd(c.getId()).exec()
         }
-        client.removeContainer(c.id)
+        client.removeContainerCmd(c.getId()).exec()
       })
 
-    val creation = client.createContainer(containerConfig, containerName)
-    if (creation.warnings() != null)
-      creation.warnings() should have(size(0))
-    id = Some(creation.id())
+    val creation = containerCommand.exec()
+    if (creation.getWarnings() != null)
+      creation.getWarnings() should have(size(0))
+    id = Some(creation.getId())
 
-    client.startContainer(creation.id())
+    client.startContainerCmd(creation.getId()).exec()
+    val reader = new StringBuilderLogReader
 
     eventually(timeout(25.seconds)) {
-      client.logs(creation.id(), LogsParam.stderr()).readFully() should 
include("all zones loaded")
+      client
+        .logContainerCmd(creation.getId())
+        .withStdErr(true)
+        .exec(reader)
+
+      reader.toString should include("all zones loaded")
     }
   }
 
   def dumpNameserverLogs(): Unit = {
-    id.foreach(id => log.info("Nameserver std out: {} ", client.logs(id, 
LogsParam.stdout()).readFully()))
-    id.foreach(id => log.info("Nameserver std err: {} ", client.logs(id, 
LogsParam.stderr()).readFully()))
+    id.foreach(id => {
+      val reader = new StringBuilderLogReader
+      client
+        .logContainerCmd(id)
+        .withStdOut(true)
+        .exec(reader)
+        .awaitCompletion()
+
+      log.info("Nameserver std out: {} ", reader.toString())
+    })
+    id.foreach(id => {
+      val reader = new StringBuilderLogReader
+      client
+        .logContainerCmd(id)
+        .withStdErr(true)
+        .exec(reader)
+        .awaitCompletion()
+      log.info("Nameserver std err: {} ", reader.toString())
+    })
   }
 
   override def afterTermination(): Unit = {
     super.afterTermination()
-    id.foreach(client.killContainer)
-    id.foreach(client.removeContainer)
+    id.foreach(id => client.killContainerCmd(id).exec())
+    id.foreach(id => client.removeContainerCmd(id).exec())
+
+    client.close()
   }
 }
+
+class StringBuilderLogReader extends ResultCallback.Adapter[Frame] {
+
+  lazy val builder: StringBuilder = new StringBuilder
+
+  override def onNext(item: Frame): Unit = {
+    builder.append(new String(item.getPayload))
+    super.onNext(item)
+  }
+
+  override def toString(): String = builder.toString()
+}
diff --git a/project/Dependencies.scala b/project/Dependencies.scala
index 381ae9f405..3e6af3fbd0 100644
--- a/project/Dependencies.scala
+++ b/project/Dependencies.scala
@@ -167,9 +167,11 @@ object Dependencies {
       // in-memory filesystem for file related tests
       val jimfs = "com.google.jimfs" % "jimfs" % "1.3.0" % Test
 
-      // docker utils
-      val dockerClient = ("com.spotify" % "docker-client" % "8.16.0" % Test)
-        .exclude("org.bouncycastle", "bcpkix-jdk15on")
+      val dockerClient = Def.setting {
+        Seq(
+          "com.github.docker-java" % "docker-java-core" % "3.3.4" % Test,
+          "com.github.docker-java" % "docker-java-transport-httpclient5" % 
"3.3.4" % Test)
+      }
 
       val jackson = Def.setting {
         Seq(
@@ -250,18 +252,13 @@ object Dependencies {
     TestDependencies.scalatest.value,
     TestDependencies.scalatestJUnit.value,
     TestDependencies.scalatestScalaCheck.value,
-    TestDependencies.bcpkix, // to force TestDependencies.dockerClient to use 
safe version of this lib
     TestDependencies.commonsCodec,
-    TestDependencies.commonsCompress, // to force 
TestDependencies.dockerClient to use safe version of this lib
-    TestDependencies.commonsIo, // to force TestDependencies.dockerClient to 
use safe version of this lib
     TestDependencies.commonsMath,
-    TestDependencies.httpClient, // to force TestDependencies.dockerClient to 
use safe version of this lib
-    TestDependencies.jimfs,
-    TestDependencies.dockerClient,
-    Provided.activation // dockerClient needs javax.activation.DataSource in 
JDK 11+
-  ) ++ {
+    TestDependencies.jimfs) ++ {
     // TestDependencies.dockerClient bring in older versions of libs that have 
CVEs
     TestDependencies.jackson.value
+  } ++ {
+    TestDependencies.dockerClient.value
   }
 
   val actorTestkitTyped = l ++= Seq(


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to