Skip to content

Commit de470e5

Browse files
committed
Add DefaultAwsSigner to MRAP test
1 parent 8c073b9 commit de470e5

File tree

2 files changed

+134
-148
lines changed

2 files changed

+134
-148
lines changed

services/s3/e2eTest/src/MutliRegionAccessPointTest.kt

Lines changed: 134 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,90 +4,190 @@
44
*/
55
package aws.sdk.kotlin.e2etest
66

7-
import aws.sdk.kotlin.e2etest.S3TestUtils.createMultiRegionAccessPoint
87
import aws.sdk.kotlin.e2etest.S3TestUtils.deleteBucketAndAllContents
9-
import aws.sdk.kotlin.e2etest.S3TestUtils.deleteMultiRegionAccessPoint
108
import aws.sdk.kotlin.e2etest.S3TestUtils.getAccountId
119
import aws.sdk.kotlin.e2etest.S3TestUtils.getBucketWithPrefix
12-
import aws.sdk.kotlin.e2etest.S3TestUtils.getMultiRegionAccessPointArn
13-
import aws.sdk.kotlin.e2etest.S3TestUtils.multiRegionAccessPointWasCreated
1410
import aws.sdk.kotlin.services.s3.S3Client
1511
import aws.sdk.kotlin.services.s3.deleteObject
1612
import aws.sdk.kotlin.services.s3.putObject
1713
import aws.sdk.kotlin.services.s3.withConfig
1814
import aws.sdk.kotlin.services.s3control.S3ControlClient
15+
import aws.sdk.kotlin.services.s3control.createMultiRegionAccessPoint
16+
import aws.sdk.kotlin.services.s3control.deleteMultiRegionAccessPoint
17+
import aws.sdk.kotlin.services.s3control.describeMultiRegionAccessPointOperation
18+
import aws.sdk.kotlin.services.s3control.getMultiRegionAccessPoint
19+
import aws.sdk.kotlin.services.s3control.model.Region
20+
import aws.smithy.kotlin.runtime.auth.awssigning.AwsSigner
21+
import aws.smithy.kotlin.runtime.auth.awssigning.DefaultAwsSigner
1922
import aws.smithy.kotlin.runtime.auth.awssigning.crt.CrtAwsSigner
2023
import aws.smithy.kotlin.runtime.http.auth.SigV4AsymmetricAuthScheme
24+
import kotlinx.coroutines.delay
2125
import kotlinx.coroutines.runBlocking
26+
import kotlinx.coroutines.withTimeout
2227
import org.junit.jupiter.api.AfterAll
2328
import org.junit.jupiter.api.BeforeAll
2429
import org.junit.jupiter.api.TestInstance
25-
import kotlin.test.Test
30+
import org.junit.jupiter.params.ParameterizedTest
31+
import org.junit.jupiter.params.provider.Arguments
32+
import org.junit.jupiter.params.provider.MethodSource
33+
import java.util.stream.Stream
34+
import kotlin.time.Duration
35+
import kotlin.time.Duration.Companion.minutes
36+
import kotlin.time.Duration.Companion.seconds
2637

2738
private const val MRAP_BUCKET_PREFIX = "s3-mrap-test-bucket-"
39+
private const val MULTI_REGION_ACCESS_POINT_NAME = "aws-sdk-for-kotlin-test-multi-region-access-point"
40+
private const val TEST_OBJECT_KEY = "test.txt"
2841

2942
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
3043
class MutliRegionAccessPointTest {
31-
private val s3West = S3Client { region = "us-west-2" }
32-
private val s3East = s3West.withConfig { region = "us-east-2" }
33-
private val s3SigV4a = s3West.withConfig { authSchemes = listOf(SigV4AsymmetricAuthScheme(CrtAwsSigner)) }
34-
private val s3Control = S3ControlClient { region = "us-west-2" }
35-
36-
private val multiRegionAccessPoint = "aws-sdk-for-kotlin-test-multi-region-access-point"
37-
private val objectKey = "test.txt"
44+
private lateinit var s3West: S3Client
45+
private lateinit var s3East: S3Client
46+
private lateinit var s3Control: S3ControlClient
3847

3948
private lateinit var accountId: String
4049
private lateinit var multiRegionAccessPointArn: String
4150
private lateinit var usWestBucket: String
4251
private lateinit var usEastBucket: String
4352

4453
@BeforeAll
45-
private fun setUp(): Unit = runBlocking {
54+
fun setup(): Unit = runBlocking {
55+
s3West = S3Client { region = "us-west-2" }
56+
s3East = S3Client { region = "us-east-2" }
57+
s3Control = S3ControlClient { region = "us-west-2" }
58+
4659
accountId = getAccountId()
4760
usWestBucket = getBucketWithPrefix(s3West, MRAP_BUCKET_PREFIX, "us-west-2", accountId)
4861
usEastBucket = getBucketWithPrefix(s3East, MRAP_BUCKET_PREFIX, "us-east-2", accountId)
4962

50-
createMultiRegionAccessPoint(
51-
s3Control,
52-
multiRegionAccessPoint,
53-
usWestBucket,
54-
usEastBucket,
63+
multiRegionAccessPointArn = s3Control.createMultiRegionAccessPoint(
64+
MULTI_REGION_ACCESS_POINT_NAME,
5565
accountId,
66+
listOf(usWestBucket, usEastBucket)
5667
)
57-
58-
multiRegionAccessPointArn =
59-
getMultiRegionAccessPointArn(
60-
s3Control,
61-
multiRegionAccessPoint,
62-
accountId,
63-
)
6468
}
6569

6670
@AfterAll
67-
private fun cleanUp(): Unit = runBlocking {
68-
if (multiRegionAccessPointWasCreated(s3Control, multiRegionAccessPoint, accountId)) {
69-
deleteMultiRegionAccessPoint(s3Control, multiRegionAccessPoint, accountId)
70-
}
71+
fun cleanup(): Unit = runBlocking {
72+
s3Control.deleteMultiRegionAccessPoint(MULTI_REGION_ACCESS_POINT_NAME, accountId)
7173

7274
deleteBucketAndAllContents(s3West, usWestBucket)
7375
deleteBucketAndAllContents(s3East, usEastBucket)
7476

7577
s3West.close()
7678
s3East.close()
77-
s3SigV4a.close()
7879
s3Control.close()
7980
}
8081

81-
@Test
82-
fun testMultiRegionAccessPointOperation(): Unit = runBlocking {
82+
@ParameterizedTest
83+
@MethodSource("signerProvider")
84+
fun testMultiRegionAccessPointOperation(signer: AwsSigner): Unit = runBlocking {
85+
println("Testing multi-region access point operations with $signer")
86+
87+
val s3SigV4a = s3West.withConfig {
88+
authSchemes = listOf(SigV4AsymmetricAuthScheme(signer))
89+
}
90+
8391
s3SigV4a.putObject {
8492
bucket = multiRegionAccessPointArn
85-
key = objectKey
93+
key = TEST_OBJECT_KEY
8694
}
8795

8896
s3SigV4a.deleteObject {
8997
bucket = multiRegionAccessPointArn
90-
key = objectKey
98+
key = TEST_OBJECT_KEY
9199
}
92100
}
101+
102+
fun signerProvider(): Stream<Arguments> = Stream.of(
103+
Arguments.of(DefaultAwsSigner),
104+
Arguments.of(CrtAwsSigner),
105+
)
106+
}
107+
108+
/**
109+
* Create a multi-region access point named [name] in account [accountId] with [buckets] buckets.
110+
* @return the ARN of the multi-region access point that was created
111+
*/
112+
private suspend fun S3ControlClient.createMultiRegionAccessPoint(
113+
name: String,
114+
accountId: String,
115+
buckets: List<String>,
116+
): String {
117+
println("Creating multi-region access point: $name")
118+
119+
val requestTokenArn = checkNotNull(createMultiRegionAccessPoint {
120+
this.accountId = accountId
121+
details {
122+
this.name = name
123+
this.regions = buckets.map { Region { bucket = it } }
124+
}
125+
}.requestTokenArn) { "createMultiRegionAccessPoint requestTokenArn was unexpectedly null" }
126+
127+
waitUntilOperationCompletes("createMultiRegionAccessPoint", accountId, requestTokenArn, 10.minutes)
128+
129+
return getMultiRegionAccessPointArn(name, accountId)
93130
}
131+
132+
private suspend fun S3ControlClient.getMultiRegionAccessPointArn(
133+
name: String,
134+
accountId: String
135+
): String {
136+
return getMultiRegionAccessPoint {
137+
this.name = name
138+
this.accountId = accountId
139+
}.accessPoint?.alias?.let {
140+
"arn:aws:s3::$accountId:accesspoint/$it"
141+
} ?: throw IllegalStateException("Failed to get ARN for multi-region access point $name")
142+
}
143+
144+
private suspend fun S3ControlClient.deleteMultiRegionAccessPoint(
145+
name: String,
146+
accountId: String
147+
) {
148+
println("Deleting multi-region access point $name")
149+
150+
val requestTokenArn = checkNotNull(deleteMultiRegionAccessPoint {
151+
this.accountId = accountId
152+
details {
153+
this.name = name
154+
}
155+
}.requestTokenArn) { "deleteMultiRegionAccessPoint requestTokenArn was unexpectedly null" }
156+
157+
waitUntilOperationCompletes("deleteMultiRegionAccessPoint", accountId, requestTokenArn, 5.minutes)
158+
}
159+
160+
/**
161+
* Continuously poll the status of [requestTokenArn] until its status is "SUCCEEDED" or [timeout] duration has passed.
162+
*/
163+
private suspend fun S3ControlClient.waitUntilOperationCompletes(
164+
operation: String,
165+
accountId: String,
166+
requestTokenArn: String,
167+
timeout: Duration,
168+
) = withTimeout(timeout) {
169+
var status: String? = null
170+
171+
while (true) {
172+
val latestStatus = describeMultiRegionAccessPointOperation {
173+
this.accountId = accountId
174+
this.requestTokenArn = requestTokenArn
175+
}.asyncOperation?.requestStatus
176+
177+
when (latestStatus) {
178+
"SUCCEEDED" -> {
179+
println("$operation operation succeeded.")
180+
return@withTimeout
181+
}
182+
"FAILED" -> throw IllegalStateException("$operation operation failed")
183+
else -> {
184+
if (status == null || latestStatus != status) {
185+
println("Waiting for $operation to complete. Status: $latestStatus ")
186+
status = latestStatus
187+
}
188+
}
189+
}
190+
191+
delay(10.seconds) // Avoid constant status checks
192+
}
193+
}

services/s3/e2eTest/src/S3TestUtils.kt

Lines changed: 0 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -209,120 +209,6 @@ object S3TestUtils {
209209
return checkNotNull(accountId) { "Unable to get AWS account ID" }
210210
}
211211

212-
internal suspend fun createMultiRegionAccessPoint(
213-
s3ControlClient: S3ControlClient,
214-
multiRegionAccessPointName: String,
215-
regionOneBucket: String,
216-
regionTwoBucket: String,
217-
testAccountId: String,
218-
) {
219-
println("Creating multi region access point: $multiRegionAccessPointName")
220-
221-
val createRequestToken = s3ControlClient.createMultiRegionAccessPoint {
222-
accountId = testAccountId
223-
details {
224-
name = multiRegionAccessPointName
225-
regions = listOf(
226-
Region { bucket = regionOneBucket },
227-
Region { bucket = regionTwoBucket },
228-
)
229-
}
230-
}
231-
232-
waitUntilMultiRegionAccessPointOperationCompletes(
233-
s3ControlClient,
234-
checkNotNull(createRequestToken.requestTokenArn) { "Unable to get request token ARN" },
235-
10.minutes,
236-
testAccountId,
237-
"createMultiRegionAccessPoint",
238-
)
239-
}
240-
241-
internal suspend fun getMultiRegionAccessPointArn(
242-
s3ControlClient: S3ControlClient,
243-
multiRegionAccessPointName: String,
244-
testAccountId: String,
245-
): String {
246-
println("Getting multi region access point arn for: $multiRegionAccessPointName")
247-
248-
s3ControlClient.getMultiRegionAccessPoint {
249-
accountId = testAccountId
250-
name = multiRegionAccessPointName
251-
}.accessPoint?.alias?.let { alias ->
252-
return "arn:aws:s3::$testAccountId:accesspoint/$alias"
253-
}
254-
throw Exception("Unable to get multi region access point arn")
255-
}
256-
257-
internal suspend fun deleteMultiRegionAccessPoint(
258-
s3ControlClient: S3ControlClient,
259-
multiRegionAccessPointName: String,
260-
testAccountId: String,
261-
) {
262-
println("Deleting multi region access point: $multiRegionAccessPointName")
263-
264-
val deleteRequestToken = s3ControlClient.deleteMultiRegionAccessPoint {
265-
accountId = testAccountId
266-
details {
267-
name = multiRegionAccessPointName
268-
}
269-
}
270-
271-
waitUntilMultiRegionAccessPointOperationCompletes(
272-
s3ControlClient,
273-
checkNotNull(deleteRequestToken.requestTokenArn) { "Unable to get request token ARN" },
274-
5.minutes,
275-
testAccountId,
276-
"deleteMultiRegionAccessPoint",
277-
)
278-
}
279-
280-
private suspend fun waitUntilMultiRegionAccessPointOperationCompletes(
281-
s3ControlClient: S3ControlClient,
282-
request: String,
283-
timeoutAfter: Duration,
284-
testAccountId: String,
285-
operation: String,
286-
) {
287-
withTimeout(timeoutAfter) {
288-
var status: String? = null
289-
while (true) {
290-
val latestStatus = s3ControlClient.describeMultiRegionAccessPointOperation {
291-
accountId = testAccountId
292-
requestTokenArn = request
293-
}.asyncOperation?.requestStatus
294-
295-
when (latestStatus) {
296-
"SUCCEEDED" -> {
297-
println("$operation operation succeeded.")
298-
return@withTimeout
299-
}
300-
"FAILED" -> throw IllegalStateException("$operation operation failed")
301-
else -> {
302-
if (status == null || latestStatus != status) {
303-
println("Waiting on $operation operation. Status: $latestStatus ")
304-
status = latestStatus
305-
}
306-
}
307-
}
308-
309-
delay(10.seconds) // Avoid constant status checks
310-
}
311-
}
312-
}
313-
314-
internal suspend fun multiRegionAccessPointWasCreated(
315-
s3Control: S3ControlClient,
316-
multiRegionAccessPointName: String,
317-
testAccountId: String,
318-
): Boolean {
319-
println("Checking if multi region access point was created: $multiRegionAccessPointName")
320-
321-
return s3Control.listMultiRegionAccessPoints {
322-
accountId = testAccountId
323-
}.accessPoints?.any { it.name == multiRegionAccessPointName } ?: false
324-
}
325-
326212
internal suspend fun deleteMultiPartUploads(client: S3Client, bucketName: String) {
327213
client.listMultipartUploads {
328214
bucket = bucketName

0 commit comments

Comments
 (0)