Skip to content

Commit 4a3e4dd

Browse files
committed
feat: add support for envfiles
1 parent d6c9e7e commit 4a3e4dd

File tree

8 files changed

+147
-12
lines changed

8 files changed

+147
-12
lines changed

build.sbt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,13 +213,14 @@ val `docker-controller-scala-root` = (project in file("."))
213213
`docker-controller-scala-core`,
214214
`docker-controller-scala-scalatest`,
215215
`docker-controller-scala-mysql`,
216-
`docker-controller-scala-redis`,
217216
`docker-controller-scala-dynamodb-local`,
218217
`docker-controller-scala-minio`,
219218
`docker-controller-scala-zookeeper`,
220219
`docker-controller-scala-kafka`,
221220
`docker-controller-scala-elasticsearch`,
222-
`docker-controller-scala-localstack`
221+
`docker-controller-scala-localstack`,
222+
`docker-controller-scala-redis`,
223+
`docker-controller-scala-elasticmq`
223224
)
224225

225226
// --- Custom commands

docker-controller-scala-core/src/main/scala/com/github/j5ik2o/dockerController/DockerComposeController.scala

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,27 @@ import com.github.dockerjava.api.DockerClient
44
import com.github.dockerjava.api.command.CreateContainerCmd
55
import com.github.dockerjava.api.model.HostConfig.newHostConfig
66
import com.github.dockerjava.api.model.{ AccessMode, Bind, SELContext, Volume }
7+
import org.apache.commons.io.FileUtils
78
import org.seasar.util.io.ResourceUtil
89

910
import java.io.File
10-
import java.nio.file.Files
11+
import java.nio.file.StandardCopyOption
1112
import scala.concurrent.duration.{ DurationInt, FiniteDuration }
1213

1314
object DockerComposeController {
1415

1516
def apply(dockerClient: DockerClient, outputFrameInterval: FiniteDuration = 500.millis)(
1617
dockerComposeWorkingDir: File,
1718
ymlResourceName: String,
19+
environmentNames: Seq[String],
1820
context: Map[String, AnyRef]
1921
): DockerController =
20-
new DockerComposeController(dockerClient, outputFrameInterval)(dockerComposeWorkingDir, ymlResourceName, context)
22+
new DockerComposeController(dockerClient, outputFrameInterval)(
23+
dockerComposeWorkingDir,
24+
ymlResourceName,
25+
environmentNames,
26+
context
27+
)
2128
}
2229

2330
private[dockerController] class DockerComposeController(
@@ -26,17 +33,35 @@ private[dockerController] class DockerComposeController(
2633
)(
2734
val dockerComposeWorkingDir: File,
2835
val ymlResourceName: String,
36+
val environmentResourceNames: Seq[String],
2937
val context: Map[String, AnyRef]
3038
) extends DockerControllerImpl(dockerClient, outputFrameInterval)("docker/compose", Some("1.24.1")) {
3139

3240
override protected def newCreateContainerCmd(): CreateContainerCmd = {
41+
val id = Base58.randomString(16)
42+
if (!dockerComposeWorkingDir.exists()) dockerComposeWorkingDir.mkdir()
3343
val ymlFile = if (ymlResourceName.endsWith(".ftl")) {
34-
if (!dockerComposeWorkingDir.exists()) dockerComposeWorkingDir.mkdir()
35-
val file = Files.createTempFile(dockerComposeWorkingDir.toPath, "docker-compose-", ".yml").toFile
36-
DockerComposeYmlGen.generate(ymlResourceName, context, file)
44+
val file = new File(dockerComposeWorkingDir, s"docker-compose-$id.yml")
45+
DockerComposeFileGen.generate(ymlResourceName, context + ("id" -> id), file)
3746
file
38-
} else
39-
ResourceUtil.getResourceAsFile(ymlResourceName)
47+
} else {
48+
val srcFile = ResourceUtil.getResourceAsFile(ymlResourceName)
49+
val destFile = new File(dockerComposeWorkingDir, srcFile.getName)
50+
FileUtils.copyFile(srcFile, destFile, StandardCopyOption.REPLACE_EXISTING)
51+
destFile
52+
}
53+
54+
environmentResourceNames.foreach { environmentResourceName =>
55+
if (environmentResourceName.endsWith(".ftl")) {
56+
val Array(base, ext, _) = environmentResourceName.split("\\.")
57+
val file = new File(dockerComposeWorkingDir, s"$base-$id.$ext")
58+
DockerComposeFileGen.generate(environmentResourceName, context, file)
59+
} else {
60+
val srcFile = ResourceUtil.getResourceAsFile(environmentResourceName)
61+
val destFile = new File(dockerComposeWorkingDir, srcFile.getName)
62+
FileUtils.copyFile(srcFile, destFile, StandardCopyOption.REPLACE_EXISTING)
63+
}
64+
}
4065

4166
val baseDir = ymlFile.getParentFile
4267
val bind = new Bind(baseDir.getPath, new Volume(baseDir.getPath), AccessMode.ro, SELContext.none)
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import java.io.{ File, FileWriter }
77
import java.util.Locale
88
import scala.jdk.CollectionConverters._
99

10-
object DockerComposeYmlGen {
10+
object DockerComposeFileGen {
1111

1212
final val FreemarkerVersion = Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS
1313

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
version: '3'
2+
services:
3+
nginx:
4+
image: bithavoc/hello-world-env
5+
ports:
6+
- ${hostPort}:3000
7+
env_file:
8+
- ./settings-${id}.env
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
MESSAGE=${message}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package com.github.j5ik2o.dockerController
2+
3+
import com.github.dockerjava.api.DockerClient
4+
import com.github.dockerjava.core.{ DockerClientConfig, DockerClientImpl }
5+
import com.github.dockerjava.httpclient5.ApacheDockerHttpClient
6+
import org.apache.commons.io.IOUtils
7+
import org.scalatest.freespec.AnyFreeSpec
8+
import org.scalatest.{ BeforeAndAfter, BeforeAndAfterAll }
9+
import org.seasar.util.io.ResourceUtil
10+
import org.slf4j.{ Logger, LoggerFactory }
11+
12+
import java.io.{ File, InputStream }
13+
import java.net.{ HttpURLConnection, URL }
14+
import java.time.Instant
15+
import scala.concurrent.duration.Duration
16+
import scala.jdk.CollectionConverters._
17+
18+
class DockerComposeController2Spec extends AnyFreeSpec with BeforeAndAfter with BeforeAndAfterAll {
19+
val logger: Logger = LoggerFactory.getLogger(getClass)
20+
21+
val dockerClientConfig: DockerClientConfig = DockerClientConfigUtil.buildConfigAwareOfDockerMachine()
22+
23+
val dockerClient: DockerClient = {
24+
val httpClient: ApacheDockerHttpClient = new ApacheDockerHttpClient.Builder()
25+
.dockerHost(dockerClientConfig.getDockerHost).sslConfig(dockerClientConfig.getSSLConfig).build()
26+
DockerClientImpl.getInstance(dockerClientConfig, httpClient)
27+
}
28+
29+
val host: String = DockerClientConfigUtil.dockerHost(dockerClientConfig)
30+
31+
val hostPort: Int = RandomPortUtil.temporaryServerPort()
32+
33+
val url = new URL(s"http://$host:$hostPort")
34+
35+
def wget: Unit = {
36+
var connection: HttpURLConnection = null
37+
var in: InputStream = null
38+
try {
39+
connection = url.openConnection().asInstanceOf[HttpURLConnection]
40+
connection.setRequestMethod("GET")
41+
connection.connect()
42+
val responseCode = connection.getResponseCode
43+
assert(responseCode == HttpURLConnection.HTTP_OK)
44+
in = connection.getInputStream
45+
val lines = IOUtils.readLines(in, "UTF-8").asScala.mkString("\n")
46+
println(lines)
47+
} catch {
48+
case ex: Throwable =>
49+
ex.printStackTrace()
50+
} finally {
51+
if (in != null)
52+
in.close()
53+
if (connection != null)
54+
connection.disconnect()
55+
}
56+
}
57+
58+
var dockerController: DockerController = _
59+
60+
override protected def beforeAll(): Unit = {
61+
val buildDir: File = ResourceUtil.getBuildDir(getClass)
62+
val dockerComposeWorkingDir: File = new File(buildDir, "docker-compose")
63+
dockerController = DockerComposeController(dockerClient)(
64+
dockerComposeWorkingDir,
65+
"docker-compose-3.yml.ftl",
66+
Seq("settings.env.ftl"),
67+
Map("hostPort" -> hostPort.toString, "message" -> Instant.now().toString)
68+
)
69+
dockerController.pullImageIfNotExists()
70+
dockerController.createContainer()
71+
}
72+
73+
override protected def afterAll(): Unit = {
74+
dockerController.removeContainer()
75+
dockerClient.close()
76+
}
77+
78+
before {
79+
dockerController.startContainer()
80+
dockerController.awaitCondition(Duration.Inf)(
81+
_.toString.contains("Listening on port 3000")
82+
)
83+
Thread.sleep(1000)
84+
}
85+
86+
after {
87+
dockerController.stopContainer()
88+
}
89+
90+
"DockerComposeController" - {
91+
"run-1" in {
92+
wget
93+
}
94+
"run-2" in {
95+
wget
96+
}
97+
98+
}
99+
}

docker-controller-scala-core/src/test/scala/com/github/j5ik2o/dockerController/DockerComposeControllerSpec.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ class DockerComposeControllerSpec extends AnyFreeSpec with BeforeAndAfter with B
6262
dockerController = DockerComposeController(dockerClient)(
6363
dockerComposeWorkingDir,
6464
"docker-compose-2.yml.ftl",
65+
Seq.empty,
6566
Map("nginxHostPort" -> hostPort.toString)
6667
)
6768
dockerController.pullImageIfNotExists()
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ import org.scalatest.freespec.AnyFreeSpec
44

55
import java.nio.file.{ Files, Paths }
66

7-
class DockerComposeYmlGenSpec extends AnyFreeSpec {
7+
class DockerComposeFileGenSpec extends AnyFreeSpec {
88
"DockerComposeYmlGenSpec" - {
99
"generate" in {
1010
val tmpFile = Files.createTempFile(Paths.get("/tmp"), "docker-compose-", ".yml")
1111

12-
DockerComposeYmlGen.generate(
12+
DockerComposeFileGen.generate(
1313
"docker-compose-2.yml.ftl",
1414
Map("nginxHostPort" -> Integer.valueOf(8080)),
1515
tmpFile.toFile

0 commit comments

Comments
 (0)