-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Keycloak container with AdminClient
Signed-off-by: Yurii Shynbuiev <[email protected]>
- Loading branch information
1 parent
77b3588
commit 397aa95
Showing
11 changed files
with
379 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
39 changes: 39 additions & 0 deletions
39
shared-test/src/main/scala/io/iohk/atala/sharedtest/containers/KeycloakContainerCustom.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package io.iohk.atala.sharedtest.containers | ||
|
||
import com.dimafeng.testcontainers.SingleContainer | ||
import dasniko.testcontainers.keycloak.ExtendableKeycloakContainer | ||
import KeycloakTestContainer.keycloakContainer | ||
import org.testcontainers.utility.DockerImageName | ||
import zio.{TaskLayer, ZIO, ZLayer} | ||
|
||
final class KeycloakContainerCustom( | ||
dockerImageNameOverride: DockerImageName, | ||
isOnGithubRunner: Boolean = false | ||
) extends SingleContainer[ExtendableKeycloakContainer[_]] { | ||
|
||
private val keycloakContainer: ExtendableKeycloakContainer[_] = new ExtendableKeycloakContainer( | ||
dockerImageNameOverride.toString | ||
) { | ||
override def getHost: String = { | ||
if (isOnGithubRunner) super.getContainerId.take(12) | ||
else super.getHost | ||
} | ||
// override def getMappedPort(originalPort: Int): Integer = { | ||
// if (isOnGithubRunner) 8300 | ||
// else super.getMappedPort(originalPort) | ||
// } | ||
} | ||
|
||
override val container: ExtendableKeycloakContainer[_] = keycloakContainer | ||
} | ||
|
||
object KeycloakContainerCustom { | ||
val layer: TaskLayer[KeycloakContainerCustom] = | ||
ZLayer.scoped { | ||
ZIO | ||
.acquireRelease(ZIO.attemptBlockingIO { | ||
keycloakContainer() | ||
})(container => ZIO.attemptBlockingIO(container.stop()).orDie) | ||
.tap(container => ZIO.attemptBlocking(container.start())) | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
shared-test/src/main/scala/io/iohk/atala/sharedtest/containers/KeycloakTestContainer.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package io.iohk.atala.sharedtest.containers | ||
|
||
import org.testcontainers.containers.output.OutputFrame | ||
import org.testcontainers.utility.DockerImageName | ||
|
||
object KeycloakTestContainer { | ||
def keycloakContainer( | ||
imageName: String = "quay.io/keycloak/keycloak:22.0.4", | ||
): KeycloakContainerCustom = { | ||
val isOnGithubRunner = sys.env.contains("GITHUB_NETWORK") | ||
val container = | ||
new KeycloakContainerCustom( | ||
dockerImageNameOverride = DockerImageName.parse(imageName), | ||
isOnGithubRunner = isOnGithubRunner | ||
) | ||
|
||
sys.env.get("GITHUB_NETWORK").map { network => | ||
container.container.withNetworkMode(network) | ||
} | ||
|
||
container | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
...est/src/main/scala/io/iohk/atala/sharedtest/containers/KeycloakTestContainerSupport.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package io.iohk.atala.sharedtest.containers | ||
import org.keycloak.admin.client.Keycloak | ||
import zio.* | ||
|
||
type KeycloakAdminClient = Keycloak | ||
|
||
trait KeycloakTestContainerSupport { | ||
protected val keycloakContainerLayer: TaskLayer[KeycloakContainerCustom] = | ||
KeycloakContainerCustom.layer | ||
|
||
protected val keycloakAdminClientLayer: URLayer[KeycloakContainerCustom, KeycloakAdminClient] = | ||
ZLayer.fromZIO(ZIO.service[KeycloakContainerCustom].map(_.container.getKeycloakAdminClient)) | ||
} |
51 changes: 51 additions & 0 deletions
51
...d-test/src/main/scala/io/iohk/atala/sharedtest/containers/PostgreSQLContainerCustom.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package io.iohk.atala.sharedtest.containers | ||
|
||
import com.dimafeng.testcontainers.{JdbcDatabaseContainer, PostgreSQLContainer} | ||
import org.testcontainers.utility.DockerImageName | ||
|
||
class PostgreSQLContainerCustom( | ||
dockerImageNameOverride: Option[DockerImageName] = None, | ||
databaseName: Option[String] = None, | ||
pgUsername: Option[String] = None, | ||
pgPassword: Option[String] = None, | ||
mountPostgresDataToTmpfs: Boolean = false, | ||
urlParams: Map[String, String] = Map.empty, | ||
commonJdbcParams: JdbcDatabaseContainer.CommonParams = JdbcDatabaseContainer.CommonParams() | ||
) extends PostgreSQLContainer( | ||
dockerImageNameOverride, | ||
databaseName, | ||
pgUsername, | ||
pgPassword, | ||
mountPostgresDataToTmpfs, | ||
urlParams, | ||
commonJdbcParams | ||
) { | ||
|
||
override def jdbcUrl: String = { | ||
/* This is such a hack! | ||
* | ||
* We are running PostgreSQL test containers inside a bridged (user-derfined) | ||
* network. Testcontainers expects to be able to connect to the _host_ and | ||
* map ports on the host. However we are running _inside_ a docker container. | ||
* So now the mapping to _localhost:randomport_ -> spawned postgres:5432 is | ||
* available from _outside_, but not form the docker container actually | ||
* spawning the others. | ||
* | ||
* We also can't refer to them by name, because docker somehow fails to | ||
* resolve names sometimes once a container has joined a network but didn't | ||
* get a name assigned when joining :shurg:. | ||
* | ||
* We can however refer to containers by their containerId, or more | ||
* precisely by their _short_ (first 12 char) Id. | ||
* | ||
* So we overwrite the jdbcUrl, and change the way it's constructed in test | ||
* containers. | ||
* | ||
* This is a mess :( | ||
*/ | ||
val origUrl = super.jdbcUrl | ||
val idx = origUrl.indexOf('?') | ||
val params = if (idx >= 0) origUrl.substring(idx) else "" | ||
s"jdbc:postgresql://${containerId.take(12)}:5432/${super.databaseName}${params}" | ||
} | ||
} |
39 changes: 39 additions & 0 deletions
39
shared-test/src/main/scala/io/iohk/atala/sharedtest/containers/PostgresLayer.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package io.iohk.atala.sharedtest.containers | ||
|
||
import com.dimafeng.testcontainers.PostgreSQLContainer | ||
import doobie.util.transactor.Transactor | ||
import io.iohk.atala.shared.db.ContextAwareTask | ||
import io.iohk.atala.shared.db.DbConfig | ||
import io.iohk.atala.shared.db.TransactorLayer | ||
import io.iohk.atala.shared.test.containers.PostgresTestContainer.postgresContainer | ||
import zio.* | ||
|
||
object PostgresLayer { | ||
|
||
def postgresLayer( | ||
imageName: Option[String] = Some("postgres:13"), | ||
verbose: Boolean = false | ||
): TaskLayer[PostgreSQLContainer] = | ||
ZLayer.scoped { | ||
ZIO | ||
.acquireRelease(ZIO.attemptBlockingIO { | ||
postgresContainer(imageName, verbose) | ||
})(container => ZIO.attemptBlockingIO(container.stop()).orDie) | ||
// Start the container outside the aquireRelease as this might fail | ||
// to ensure contianer.stop() is added to the finalizer | ||
.tap(container => ZIO.attemptBlocking(container.start())) | ||
} | ||
|
||
private def dbConfig(container: PostgreSQLContainer): DbConfig = { | ||
DbConfig( | ||
username = container.username, | ||
password = container.password, | ||
jdbcUrl = container.jdbcUrl | ||
) | ||
} | ||
|
||
lazy val dbConfigLayer: ZLayer[PostgreSQLContainer, Nothing, DbConfig] = | ||
ZLayer.fromZIO { ZIO.serviceWith[PostgreSQLContainer](dbConfig) } | ||
|
||
def transactor: ZLayer[DbConfig, Throwable, Transactor[ContextAwareTask]] = TransactorLayer.contextAwareTask | ||
} |
27 changes: 27 additions & 0 deletions
27
shared-test/src/main/scala/io/iohk/atala/sharedtest/containers/PostgresTestContainer.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package io.iohk.atala.sharedtest.containers | ||
|
||
import com.dimafeng.testcontainers.PostgreSQLContainer | ||
import org.testcontainers.containers.output.OutputFrame | ||
import org.testcontainers.utility.DockerImageName | ||
|
||
object PostgresTestContainer { | ||
def postgresContainer( | ||
imageName: Option[String] = Some("postgres:13"), | ||
verbose: Boolean = false | ||
): PostgreSQLContainer = { | ||
val container = | ||
if (sys.env.contains("GITHUB_NETWORK")) | ||
new PostgreSQLContainerCustom(dockerImageNameOverride = imageName.map(DockerImageName.parse)) | ||
else | ||
new PostgreSQLContainer(dockerImageNameOverride = imageName.map(DockerImageName.parse)) | ||
sys.env.get("GITHUB_NETWORK").map { network => | ||
container.container.withNetworkMode(network) | ||
} | ||
if (verbose) { | ||
container.container | ||
.withLogConsumer((t: OutputFrame) => println(t.getUtf8String)) | ||
.withCommand("postgres", "-c", "log_statement=all", "-c", "log_destination=stderr") | ||
} | ||
container | ||
} | ||
} |
64 changes: 64 additions & 0 deletions
64
...est/src/main/scala/io/iohk/atala/sharedtest/containers/PostgresTestContainerSupport.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package io.iohk.atala.sharedtest.containers | ||
|
||
import com.dimafeng.testcontainers.PostgreSQLContainer | ||
import doobie.util.transactor.Transactor | ||
import io.iohk.atala.shared.db.ContextAwareTask | ||
import io.iohk.atala.shared.db.TransactorLayer | ||
import zio.* | ||
|
||
trait PostgresTestContainerSupport { | ||
|
||
protected val pgContainerLayer: TaskLayer[PostgreSQLContainer] = PostgresLayer.postgresLayer() | ||
|
||
protected val contextAwareTransactorLayer: TaskLayer[Transactor[ContextAwareTask]] = { | ||
import doobie.* | ||
import doobie.implicits.* | ||
import zio.interop.catz.* | ||
|
||
val appUser = "test-application-user" | ||
val appPassword = "password" | ||
|
||
val createAppUser = (xa: Transactor[Task]) => | ||
doobie.free.connection.createStatement | ||
.map { stm => | ||
stm.execute(s"""CREATE USER "$appUser" WITH PASSWORD '$appPassword';""") | ||
stm.execute( | ||
s"""ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO "$appUser";""" | ||
) | ||
stm | ||
} | ||
.transact(xa) | ||
.unit | ||
|
||
val superUserTransactor = ZLayer.makeSome[PostgreSQLContainer, Transactor[Task]]( | ||
TransactorLayer.task, | ||
PostgresLayer.dbConfigLayer, | ||
) | ||
|
||
val appUserTransactor = ZLayer.makeSome[PostgreSQLContainer, Transactor[ContextAwareTask]]( | ||
TransactorLayer.contextAwareTask, | ||
PostgresLayer.dbConfigLayer.map(conf => | ||
ZEnvironment( | ||
conf.get.copy( | ||
username = appUser, | ||
password = appPassword | ||
) | ||
) | ||
), | ||
) | ||
|
||
val initializedTransactor = ZLayer.fromZIO { | ||
for { | ||
_ <- ZIO | ||
.serviceWithZIO[Transactor[Task]](createAppUser) | ||
.provideSomeLayer(superUserTransactor) | ||
} yield appUserTransactor | ||
}.flatten | ||
|
||
pgContainerLayer >>> initializedTransactor | ||
} | ||
|
||
protected val systemTransactorLayer: TaskLayer[Transactor[Task]] = { | ||
pgContainerLayer >>> PostgresLayer.dbConfigLayer >>> TransactorLayer.task | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
shared-test/src/main/scala/io/iohk/atala/sharedtest/containers/VaultContainerCustom.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package io.iohk.atala.sharedtest.containers | ||
|
||
import com.dimafeng.testcontainers.{SingleContainer, VaultContainer} | ||
import org.testcontainers.vault.{VaultContainer => JavaVaultContainer} | ||
import org.testcontainers.utility.DockerImageName | ||
|
||
/** See PostgreSQLContainerCustom for explanation */ | ||
class VaultContainerCustom( | ||
dockerImageNameOverride: DockerImageName, | ||
vaultToken: Option[String] = None, | ||
secrets: Option[VaultContainer.Secrets] = None, | ||
isOnGithubRunner: Boolean = false | ||
) extends SingleContainer[JavaVaultContainer[_]] { | ||
|
||
private val vaultContainer: JavaVaultContainer[_] = new JavaVaultContainer(dockerImageNameOverride) { | ||
override def getHost: String = { | ||
if (isOnGithubRunner) super.getContainerId().take(12) | ||
else super.getHost() | ||
} | ||
override def getMappedPort(originalPort: Int): Integer = { | ||
if (isOnGithubRunner) 8200 | ||
else super.getMappedPort(originalPort) | ||
} | ||
} | ||
|
||
if (vaultToken.isDefined) vaultContainer.withVaultToken(vaultToken.get) | ||
secrets.foreach { x => | ||
vaultContainer.withSecretInVault(x.path, x.firstSecret, x.secrets: _*) | ||
} | ||
|
||
override val container: JavaVaultContainer[_] = vaultContainer | ||
} |
Oops, something went wrong.