From 6ebb73d67429f9b0fd00d590d306b55681838eda Mon Sep 17 00:00:00 2001 From: EzequielPostan Date: Wed, 3 Jul 2024 16:59:58 -0300 Subject: [PATCH] ATL-7315: Replace docker library for tests This commit replaces the old docker-it-scala library with test-containers library, fixing the incompatibility issues with docker server 26.1.3 --- .github/workflows/unit-tests.yml | 2 +- build.sbt | 15 ++- .../prism/node/AtalaWithPostgresSpec.scala | 4 +- .../repositories/DockerPostgresService.scala | 101 ++++-------------- .../repositories/PostgresRepositorySpec.scala | 4 +- 5 files changed, 34 insertions(+), 92 deletions(-) diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 10dad4d82..769405043 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -16,7 +16,7 @@ env: jobs: build-and-test: name: "Unit tests" - runs-on: self-hosted + runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 diff --git a/build.sbt b/build.sbt index c627031b9..9394038e6 100644 --- a/build.sbt +++ b/build.sbt @@ -25,8 +25,6 @@ lazy val versions = new { val circe = "0.14.1" val circeOptics = "0.14.1" val diffx = "0.7.0" - val dockerClient = "8.16.0" - val dockerTestkit = "0.9.9" val doobie = "1.0.0-RC2" val enumeratum = "1.7.0" val enumeratumDoobie = "1.7.1" @@ -50,6 +48,7 @@ lazy val versions = new { val typesafeConfig = "1.4.2" val fs2 = "3.8.0" val scalaUri = "4.0.0" + val testContainers = "0.41.4" } lazy val Dependencies = new { @@ -105,12 +104,6 @@ lazy val Dependencies = new { "com.ironcorelabs" %% "cats-scalatest" % versions.catsScalatest % Test val diffx = "com.softwaremill.diffx" %% "diffx-scalatest-must" % versions.diffx % Test - val dockerClient = - "com.spotify" % "docker-client" % versions.dockerClient % Test - val dockerTestkitScalatest = - "com.whisk" %% "docker-testkit-scalatest" % versions.dockerTestkit % Test - val dockerTestkitSpotify = - "com.whisk" %% "docker-testkit-impl-spotify" % versions.dockerTestkit % Test val doobieScalatest = "org.tpolecat" %% "doobie-scalatest" % versions.doobie % Test val mockito = "org.mockito" %% "mockito-scala" % versions.mockito % Test @@ -121,12 +114,16 @@ lazy val Dependencies = new { "org.scalatest" %% "scalatest-wordspec" % versions.scalatest % Test val scalatestplus = "org.scalatestplus" %% "scalacheck-1-15" % versions.scalatestplus % Test + val testContainersScalaTest = + "com.dimafeng" %% "testcontainers-scala-scalatest" % versions.testContainers % Test + val testContainersPSQL = + "com.dimafeng" %% "testcontainers-scala-postgresql" % versions.testContainers % Test val bouncyDependencies = Seq(bouncyBcpkix, bouncyBcprov) val circeDependencies = Seq(circeCore, circeGeneric, circeGenericExtras, circeParser, circeOptics) val dockerDependencies = - Seq(dockerClient, dockerTestkitScalatest, dockerTestkitSpotify) + Seq(testContainersScalaTest, testContainersPSQL) val doobieDependencies = Seq(doobieCore, doobiePostgresCirce, doobieHikari, doobieScalatest) val enumeratumDependencies = diff --git a/src/test/scala/io/iohk/atala/prism/node/AtalaWithPostgresSpec.scala b/src/test/scala/io/iohk/atala/prism/node/AtalaWithPostgresSpec.scala index 0aef3a36a..3e752dabf 100644 --- a/src/test/scala/io/iohk/atala/prism/node/AtalaWithPostgresSpec.scala +++ b/src/test/scala/io/iohk/atala/prism/node/AtalaWithPostgresSpec.scala @@ -1,10 +1,11 @@ package io.iohk.atala.prism.node import cats.effect.IO +import com.dimafeng.testcontainers.ContainerDef import doobie.util.transactor.Transactor import io.iohk.atala.prism.node.logging.TraceId import io.iohk.atala.prism.node.logging.TraceId.IOWithTraceIdContext -import io.iohk.atala.prism.node.repositories.PostgresRepositorySpec +import io.iohk.atala.prism.node.repositories.{DockerPostgresService, PostgresRepositorySpec} import org.scalatest.concurrent.ScalaFutures import scala.concurrent.ExecutionContext @@ -17,4 +18,5 @@ class AtalaWithPostgresSpec extends PostgresRepositorySpec[IO] with ScalaFutures val dbLiftedToTraceIdIO: Transactor[IOWithTraceIdContext] = db.mapK(TraceId.liftToIOWithTraceId) + override val containerDef: ContainerDef = DockerPostgresService.containerDef } diff --git a/src/test/scala/io/iohk/atala/prism/node/repositories/DockerPostgresService.scala b/src/test/scala/io/iohk/atala/prism/node/repositories/DockerPostgresService.scala index 955c785e5..2b3d01834 100644 --- a/src/test/scala/io/iohk/atala/prism/node/repositories/DockerPostgresService.scala +++ b/src/test/scala/io/iohk/atala/prism/node/repositories/DockerPostgresService.scala @@ -1,47 +1,23 @@ package io.iohk.atala.prism.node.repositories -import com.spotify.docker.client.DefaultDockerClient -import com.whisk.docker._ -import com.whisk.docker.impl.spotify.SpotifyDockerFactory -import org.scalatest.concurrent.ScalaFutures._ -import org.scalatest.matchers.must.Matchers._ +import com.dimafeng.testcontainers.PostgreSQLContainer +import org.testcontainers.utility.DockerImageName -import java.sql.DriverManager -import scala.concurrent.{ExecutionContext, Future} +object DockerPostgresService { -object DockerPostgresService extends DockerKit { + private val postgresImage = "postgres:16" + private val postgresUsername = "postgres" + private val postgresPassword = "postgres" + private val databaseName = "db" - import scala.concurrent.duration._ - - override val PullImagesTimeout = 120.minutes - override val StartContainersTimeout = 120.seconds - override val StopContainersTimeout = 120.seconds - - override implicit val dockerFactory: DockerFactory = new SpotifyDockerFactory( - DefaultDockerClient.fromEnv().build() + val containerDef: PostgreSQLContainer.Def = PostgreSQLContainer.Def( + dockerImageName = DockerImageName.parse(postgresImage), + databaseName = databaseName, + username = postgresUsername, + password = postgresPassword ) - val PostgresImage = "postgres:13" - val PostgresUsername = "postgres" - val PostgresPassword = "postgres" - val DatabaseName = "db" - - val postgresContainer = DockerContainer(PostgresImage) - .withCommand("-N 1000") - .withPorts((PostgresAdvertisedPort, Some(PostgresExposedPort))) - .withEnv( - s"POSTGRES_USER=$PostgresUsername", - s"POSTGRES_PASSWORD=$PostgresPassword" - ) - .withReadyChecker( - new PostgresReadyChecker().looped(15, 1.second) - ) - - override val dockerContainers: List[DockerContainer] = - postgresContainer :: super.dockerContainers - - def PostgresAdvertisedPort = 5432 - def PostgresExposedPort = 44444 + lazy private val postgresContainer = containerDef.start() private var isRunning = false @@ -52,59 +28,24 @@ object DockerPostgresService extends DockerKit { override def run(): Unit = { println("Stopping Docker container with Postgres") - stopAllQuietly() + postgresContainer.stop() println("Stopped Docker container with Postgres") } }) println("Starting Docker container with Postgres") - startAllOrFail() - isContainerReady(postgresContainer).futureValue mustEqual true + postgresContainer isRunning = true println("Started Docker container with Postgres") } - val hostname = postgresContainer.hostname.getOrElse("localhost") + val host = postgresContainer.host + val port = postgresContainer.mappedPort(5432) PostgresConfig( - s"$hostname:$PostgresExposedPort", - DatabaseName, - PostgresUsername, - PostgresPassword + s"$host:$port", + postgresContainer.databaseName, + postgresContainer.username, + postgresContainer.password ) } - - class PostgresReadyChecker extends DockerReadyChecker { - - override def apply( - container: DockerContainerState - )(implicit - dockerExecutor: DockerCommandExecutor, - ec: ExecutionContext - ): Future[Boolean] = { - - container - .getPorts()(dockerExecutor, ec) - .map { _ => - try { - Class.forName("org.postgresql.Driver") - val url = - s"jdbc:postgresql://${dockerExecutor.host}:$PostgresExposedPort/" - Option( - DriverManager - .getConnection(url, PostgresUsername, PostgresPassword) - ) - .foreach { conn => - // NOTE: For some reason the result is always false - conn.createStatement().execute(s"CREATE DATABASE $DatabaseName") - conn.close() - } - - true - } catch { - case _: Throwable => - false - } - }(ec) - } - } } diff --git a/src/test/scala/io/iohk/atala/prism/node/repositories/PostgresRepositorySpec.scala b/src/test/scala/io/iohk/atala/prism/node/repositories/PostgresRepositorySpec.scala index d42ab1e71..45724a007 100644 --- a/src/test/scala/io/iohk/atala/prism/node/repositories/PostgresRepositorySpec.scala +++ b/src/test/scala/io/iohk/atala/prism/node/repositories/PostgresRepositorySpec.scala @@ -2,6 +2,7 @@ package io.iohk.atala.prism.node.repositories import cats.effect.unsafe.implicits.global import cats.effect.IO +import com.dimafeng.testcontainers.scalatest.TestContainerForAll import org.scalatest.matchers.must.Matchers import org.scalatest.wordspec.AnyWordSpec import org.scalatest.{BeforeAndAfterAll, BeforeAndAfterEach} @@ -43,7 +44,8 @@ abstract class PostgresRepositorySpec[F[_]] extends AnyWordSpec with Matchers with BeforeAndAfterAll - with BeforeAndAfterEach { + with BeforeAndAfterEach + with TestContainerForAll { val POSTGRES_HOST_ENVNAME = "POSTGRES_TEST_HOST" val POSTGRES_DB_ENVNAME = "POSTGRES_TEST_DB"