Skip to content

Commit 5cf1dc8

Browse files
authored
Merge pull request #530 from mdipirro/scala-429
SCALA-429 Add code for testcontainers-scala article
2 parents 0ca131d + 10b0796 commit 5cf1dc8

File tree

6 files changed

+314
-0
lines changed

6 files changed

+314
-0
lines changed

build.sbt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,12 @@ lazy val scala_libraries_4 = (project in file("scala-libraries-4"))
337337
"com.clever-cloud.pulsar4s" %% "pulsar4s-jackson" % "2.9.0",
338338
"org.testcontainers" % "pulsar" % "1.17.6" % IntegrationTest
339339
),
340+
libraryDependencies ++= Seq(
341+
"software.amazon.awssdk" % "s3" % "2.19.0",
342+
"com.amazonaws" % "aws-java-sdk-s3" % "1.12.368" % IntegrationTest,
343+
"com.dimafeng" %% "testcontainers-scala-scalatest" % "0.40.12" % IntegrationTest,
344+
"com.dimafeng" %% "testcontainers-scala-localstack-v2" % "0.40.12" % IntegrationTest
345+
),
340346
scalacOptions += "-Xasync",
341347
Defaults.itSettings,
342348
IntegrationTest / fork := true
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
version: "3.8"
2+
services:
3+
localstack:
4+
image: localstack/localstack:1.3.0
5+
restart: always
6+
ports:
7+
- "5000:4566"
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package com.baeldung.scala.testcontainers
2+
3+
import com.dimafeng.testcontainers.{DockerComposeContainer, ExposedService}
4+
import com.dimafeng.testcontainers.scalatest.TestContainerForEach
5+
import org.scalatest.flatspec.AnyFlatSpec
6+
import org.scalatest.matchers.should.Matchers
7+
import org.testcontainers.containers.wait.strategy.{
8+
LogMessageWaitStrategy,
9+
Wait
10+
}
11+
import software.amazon.awssdk.auth.credentials.{
12+
AwsBasicCredentials,
13+
StaticCredentialsProvider
14+
}
15+
import software.amazon.awssdk.regions.Region
16+
import software.amazon.awssdk.services.s3.S3Client
17+
import software.amazon.awssdk.services.s3.model.{
18+
CreateBucketRequest,
19+
HeadObjectRequest,
20+
NoSuchKeyException
21+
}
22+
23+
import java.io.File
24+
import java.net.URI
25+
import java.nio.file.Paths
26+
import scala.util.{Random, Try}
27+
28+
class DockerComposeTest
29+
extends AnyFlatSpec
30+
with Matchers
31+
with TestContainerForEach {
32+
33+
private val BucketName = Random.alphanumeric.take(10).mkString.toLowerCase
34+
private val ExposedPort = 5000
35+
36+
override val containerDef: DockerComposeContainer.Def =
37+
DockerComposeContainer.Def(
38+
new File("scala-libraries-4/src/it/resources/docker-compose.yml"),
39+
exposedServices = Seq(
40+
ExposedService(
41+
"localstack",
42+
ExposedPort,
43+
new LogMessageWaitStrategy().withRegEx(".*Ready\\.\n")
44+
)
45+
)
46+
)
47+
48+
"SimpleS3Uploader" should "upload a file in the desired bucket" in {
49+
val region = "us-east-1"
50+
val endpoint = s"http://localhost:$ExposedPort"
51+
52+
val s3 = S3Client
53+
.builder()
54+
.region(Region.of(region))
55+
.endpointOverride(new URI(endpoint))
56+
.credentialsProvider(
57+
StaticCredentialsProvider.create(
58+
AwsBasicCredentials.create("not_used", "not_used")
59+
)
60+
)
61+
.forcePathStyle(true)
62+
.build()
63+
64+
s3.createBucket(CreateBucketRequest.builder().bucket(BucketName).build)
65+
66+
new SimpleS3Uploader(
67+
region = region,
68+
endpoint = new URI(endpoint),
69+
accessKeyId = "not_used",
70+
secretAccessKey = "not_used"
71+
).upload(BucketName, Paths.get("build.sbt"))
72+
73+
Try(
74+
s3.headObject(
75+
HeadObjectRequest.builder().bucket(BucketName).key("build.sbt").build()
76+
)
77+
).fold(
78+
{
79+
case _: NoSuchKeyException => fail("File not found")
80+
case _ => fail
81+
},
82+
_ => succeed
83+
)
84+
}
85+
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package com.baeldung.scala.testcontainers
2+
3+
import com.baeldung.scala.testcontainers.MyLocalStackContainer.LocalStackPort
4+
import com.dimafeng.testcontainers.GenericContainer
5+
import com.dimafeng.testcontainers.scalatest.TestContainerForEach
6+
import org.scalatest.flatspec.AnyFlatSpec
7+
import org.scalatest.matchers.should.Matchers
8+
import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy
9+
import software.amazon.awssdk.auth.credentials.{
10+
AwsBasicCredentials,
11+
StaticCredentialsProvider
12+
}
13+
import software.amazon.awssdk.regions.Region
14+
import software.amazon.awssdk.services.s3.S3Client
15+
import software.amazon.awssdk.services.s3.model.{
16+
CreateBucketRequest,
17+
HeadObjectRequest,
18+
NoSuchKeyException
19+
}
20+
21+
import java.net.URI
22+
import java.nio.file.Paths
23+
import scala.collection.JavaConverters._
24+
import scala.util.{Random, Try}
25+
26+
class MyLocalStackContainer private (
27+
hostPort: Int,
28+
underlying: GenericContainer
29+
) extends GenericContainer(underlying) {
30+
underlying.container.setPortBindings(
31+
List(s"$hostPort:$LocalStackPort").asJava
32+
)
33+
34+
val endpoint = s"http://localhost:$hostPort"
35+
val accessKeyId = "not_used"
36+
val secretAccessKey = "not_used"
37+
}
38+
39+
object MyLocalStackContainer {
40+
private val LocalStackPort = 4566
41+
42+
case class Def(hostPort: Int)
43+
extends GenericContainer.Def[MyLocalStackContainer](
44+
new MyLocalStackContainer(
45+
hostPort,
46+
GenericContainer(
47+
dockerImage = "localstack/localstack:1.3.0",
48+
exposedPorts = Seq(LocalStackPort),
49+
waitStrategy = new LogMessageWaitStrategy().withRegEx(".*Ready\\.\n")
50+
)
51+
)
52+
)
53+
}
54+
55+
class GenericContainerTest
56+
extends AnyFlatSpec
57+
with Matchers
58+
with TestContainerForEach {
59+
60+
private val BucketName = Random.alphanumeric.take(10).mkString.toLowerCase
61+
62+
override val containerDef: MyLocalStackContainer.Def =
63+
MyLocalStackContainer.Def(5000)
64+
65+
"SimpleS3Uploader" should "upload a file in the desired bucket" in {
66+
withContainers { ls =>
67+
val region = "us-east-1"
68+
69+
val s3 = S3Client
70+
.builder()
71+
.region(Region.of(region))
72+
.endpointOverride(new URI(ls.endpoint))
73+
.credentialsProvider(
74+
StaticCredentialsProvider.create(
75+
AwsBasicCredentials.create(ls.accessKeyId, ls.secretAccessKey)
76+
)
77+
)
78+
.forcePathStyle(true)
79+
.build()
80+
81+
s3.createBucket(CreateBucketRequest.builder().bucket(BucketName).build)
82+
83+
new SimpleS3Uploader(
84+
region = region,
85+
endpoint = new URI(ls.endpoint),
86+
accessKeyId = ls.accessKeyId,
87+
secretAccessKey = ls.secretAccessKey
88+
).upload(BucketName, Paths.get("build.sbt"))
89+
90+
Try(
91+
s3.headObject(
92+
HeadObjectRequest
93+
.builder()
94+
.bucket(BucketName)
95+
.key("build.sbt")
96+
.build()
97+
)
98+
).fold(
99+
{
100+
case _: NoSuchKeyException => fail("File not found")
101+
case _ => fail
102+
},
103+
_ => succeed
104+
)
105+
}
106+
}
107+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package com.baeldung.scala.testcontainers
2+
3+
import com.dimafeng.testcontainers.LocalStackV2Container
4+
import com.dimafeng.testcontainers.scalatest.TestContainerForEach
5+
import org.scalatest.flatspec.AnyFlatSpec
6+
import org.scalatest.matchers.should.Matchers
7+
import org.testcontainers.containers.localstack.LocalStackContainer.Service
8+
import software.amazon.awssdk.services.s3.S3Client
9+
import software.amazon.awssdk.services.s3.model.{
10+
CreateBucketRequest,
11+
HeadObjectRequest,
12+
NoSuchKeyException
13+
}
14+
15+
import java.nio.file.Paths
16+
import scala.util.{Random, Try}
17+
18+
class LocalstackModuleTest
19+
extends AnyFlatSpec
20+
with Matchers
21+
with TestContainerForEach {
22+
23+
private val BucketName = Random.alphanumeric.take(10).mkString.toLowerCase
24+
25+
override val containerDef: LocalStackV2Container.Def =
26+
LocalStackV2Container.Def(
27+
tag = "1.3.0",
28+
services = Seq(Service.S3)
29+
)
30+
31+
"SimpleS3Uploader" should "upload a file in the desired bucket" in {
32+
withContainers { ls =>
33+
val s3 = S3Client
34+
.builder()
35+
.region(ls.region)
36+
.endpointOverride(ls.endpointOverride(Service.S3))
37+
.credentialsProvider(ls.staticCredentialsProvider)
38+
.forcePathStyle(true)
39+
.build()
40+
41+
s3.createBucket(CreateBucketRequest.builder().bucket(BucketName).build)
42+
43+
new SimpleS3Uploader(
44+
region = ls.region.toString,
45+
endpoint = ls.endpointOverride(Service.S3),
46+
accessKeyId = ls.container.getAccessKey,
47+
secretAccessKey = ls.container.getSecretKey
48+
).upload(BucketName, Paths.get("build.sbt"))
49+
50+
Try(
51+
s3.headObject(
52+
HeadObjectRequest
53+
.builder()
54+
.bucket(BucketName)
55+
.key("build.sbt")
56+
.build()
57+
)
58+
).fold(
59+
{
60+
case _: NoSuchKeyException => fail("File not found")
61+
case _ => fail
62+
},
63+
_ => succeed
64+
)
65+
}
66+
}
67+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.baeldung.scala.testcontainers
2+
3+
import software.amazon.awssdk.auth.credentials.{
4+
AwsBasicCredentials,
5+
StaticCredentialsProvider
6+
}
7+
import software.amazon.awssdk.regions.Region
8+
import software.amazon.awssdk.services.s3.S3Client
9+
import software.amazon.awssdk.services.s3.model.PutObjectRequest
10+
11+
import java.net.URI
12+
import java.nio.file.Path
13+
14+
class SimpleS3Uploader(
15+
region: String,
16+
endpoint: URI,
17+
accessKeyId: String,
18+
secretAccessKey: String
19+
) {
20+
private lazy val s3 = S3Client
21+
.builder()
22+
.region(Region.of(region))
23+
.endpointOverride(endpoint)
24+
.credentialsProvider(
25+
StaticCredentialsProvider.create(
26+
AwsBasicCredentials.create(accessKeyId, secretAccessKey)
27+
)
28+
)
29+
.forcePathStyle(true)
30+
.build()
31+
32+
def upload(bucket: String, filePath: Path): Unit = {
33+
s3.putObject(
34+
PutObjectRequest
35+
.builder()
36+
.bucket(bucket)
37+
.key(filePath.getFileName.toString)
38+
.build(),
39+
filePath
40+
)
41+
}
42+
}

0 commit comments

Comments
 (0)