Skip to content

Commit 0bdff0e

Browse files
authored
Update multi-region access point test to not create new resources if there are exsiting ones (#2758)
1 parent df70a4c commit 0bdff0e

File tree

1 file changed

+71
-108
lines changed

1 file changed

+71
-108
lines changed

services/s3control/src/it/java/software.amazon.awssdk.services.s3control/S3MrapIntegrationTest.java

+71-108
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
import static org.assertj.core.api.Assertions.assertThat;
1818
import static org.junit.Assert.assertEquals;
19-
import static software.amazon.awssdk.testutils.service.S3BucketUtils.temporaryBucketName;
2019
import static software.amazon.awssdk.utils.FunctionalUtils.invokeSafely;
2120
import static software.amazon.awssdk.utils.StringUtils.isEmpty;
2221

@@ -27,7 +26,6 @@
2726
import java.util.Collections;
2827
import java.util.List;
2928
import java.util.Optional;
30-
import org.junit.AfterClass;
3129
import org.junit.BeforeClass;
3230
import org.junit.Test;
3331
import software.amazon.awssdk.auth.signer.S3SignerExecutionAttribute;
@@ -38,7 +36,10 @@
3836
import software.amazon.awssdk.core.interceptor.Context;
3937
import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
4038
import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
39+
import software.amazon.awssdk.core.retry.backoff.FixedDelayBackoffStrategy;
4140
import software.amazon.awssdk.core.sync.RequestBody;
41+
import software.amazon.awssdk.core.waiters.Waiter;
42+
import software.amazon.awssdk.core.waiters.WaiterAcceptor;
4243
import software.amazon.awssdk.http.HttpExecuteRequest;
4344
import software.amazon.awssdk.http.HttpExecuteResponse;
4445
import software.amazon.awssdk.http.SdkHttpMethod;
@@ -48,68 +49,90 @@
4849
import software.amazon.awssdk.services.s3.S3Client;
4950
import software.amazon.awssdk.services.s3.S3Configuration;
5051
import software.amazon.awssdk.services.s3.model.Bucket;
52+
import software.amazon.awssdk.services.s3.model.BucketAlreadyOwnedByYouException;
5153
import software.amazon.awssdk.services.s3.model.NoSuchKeyException;
5254
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
5355
import software.amazon.awssdk.services.s3.model.UploadPartRequest;
5456
import software.amazon.awssdk.services.s3.presigner.S3Presigner;
5557
import software.amazon.awssdk.services.s3.presigner.model.PresignedGetObjectRequest;
56-
import software.amazon.awssdk.services.s3control.model.AsyncOperation;
58+
import software.amazon.awssdk.services.s3control.model.BucketAlreadyExistsException;
5759
import software.amazon.awssdk.services.s3control.model.CreateMultiRegionAccessPointInput;
5860
import software.amazon.awssdk.services.s3control.model.CreateMultiRegionAccessPointResponse;
59-
import software.amazon.awssdk.services.s3control.model.DeleteMultiRegionAccessPointResponse;
60-
import software.amazon.awssdk.services.s3control.model.DescribeMultiRegionAccessPointOperationResponse;
6161
import software.amazon.awssdk.services.s3control.model.GetMultiRegionAccessPointResponse;
6262
import software.amazon.awssdk.services.s3control.model.ListMultiRegionAccessPointsResponse;
63-
import software.amazon.awssdk.services.s3control.model.MultiRegionAccessPointReport;
6463
import software.amazon.awssdk.services.s3control.model.MultiRegionAccessPointStatus;
64+
import software.amazon.awssdk.services.sts.StsClient;
6565
import software.amazon.awssdk.utils.IoUtils;
66+
import software.amazon.awssdk.utils.Logger;
6667
import software.amazon.awssdk.utils.StringInputStream;
6768

6869
public class S3MrapIntegrationTest extends S3ControlIntegrationTestBase {
70+
private static final Logger log = Logger.loggerFor(S3MrapIntegrationTest.class);
6971

7072
private static final String CHUNKED_PAYLOAD_SIGNING = "STREAMING-AWS4-ECDSA-P256-SHA256-PAYLOAD";
7173
private static final String UNSIGNED_PAYLOAD = "UNSIGNED-PAYLOAD";
7274

7375
private static final Region REGION = Region.US_WEST_2;
74-
private static final String BUCKET = temporaryBucketName(S3MrapIntegrationTest.class);
75-
private static final String MRAP_NAME = "javaintegtest" + System.currentTimeMillis();
76+
private static String bucket;
77+
private static String mrapName;
7678
private static final String KEY = "aws-java-sdk-small-test-object";
7779
private static final String CONTENT = "A short string for a small test object";
7880

79-
private static final int RETRY_TIMES = 20;
80-
private static final int RETRY_DELAY_IN_MS = 15 * 1000;
81+
private static final int RETRY_TIMES = 10;
82+
private static final int RETRY_DELAY_IN_SECONDS = 30;
8183

8284
private static S3ControlClient s3control;
8385
private static CaptureRequestInterceptor captureInterceptor;
8486
private static String mrapAlias;
87+
private static StsClient stsClient;
88+
private static S3Client s3Client;
8589

8690
@BeforeClass
87-
public static void setupFixture() throws Exception {
91+
public static void setupFixture() {
8892
captureInterceptor = new CaptureRequestInterceptor();
89-
createBucket(BUCKET);
9093

9194
s3control = S3ControlClient.builder()
9295
.region(REGION)
9396
.credentialsProvider(CREDENTIALS_PROVIDER_CHAIN)
9497
.build();
9598

96-
String resourceTokenArn = createMrap(MRAP_NAME);
97-
waitForResourceCreation(resourceTokenArn);
99+
s3Client = S3Client.builder()
100+
.region(REGION)
101+
.credentialsProvider(CREDENTIALS_PROVIDER_CHAIN)
102+
.build();
103+
104+
stsClient = StsClient.builder()
105+
.credentialsProvider(CREDENTIALS_PROVIDER_CHAIN)
106+
.region(REGION)
107+
.build();
108+
String accountId = getAccountId();
109+
bucket = "do-not-delete-s3mraptest-" + accountId;
110+
mrapName = "javaintegtest" + accountId;
111+
log.info(() -> "bucket " + bucket);
112+
createBucketIfNotExist(bucket);
113+
createMrapIfNotExist(mrapName);
114+
98115
mrapAlias = getMrapAliasAndVerify();
99116
}
100117

101-
@AfterClass
102-
public static void tearDown() throws Exception {
103-
String resourceTokenArn = deleteMrap(MRAP_NAME);
104-
waitForResourceDeletion(resourceTokenArn);
105-
deleteBucketAndAllContents(BUCKET);
118+
private static void createBucketIfNotExist(String bucket) {
119+
try {
120+
s3Client.createBucket(b -> b.bucket(bucket));
121+
s3Client.waiter().waitUntilBucketExists(b -> b.bucket(bucket));
122+
} catch (BucketAlreadyOwnedByYouException | BucketAlreadyExistsException e) {
123+
// ignore
124+
}
125+
}
126+
127+
private static String getAccountId() {
128+
return stsClient.getCallerIdentity().account();
106129
}
107130

108131
public static String getMrapAliasAndVerify() {
109-
GetMultiRegionAccessPointResponse mrap = s3control.getMultiRegionAccessPoint(r -> r.accountId(accountId).name(MRAP_NAME));
132+
GetMultiRegionAccessPointResponse mrap = s3control.getMultiRegionAccessPoint(r -> r.accountId(accountId).name(mrapName));
110133
assertThat(mrap.accessPoint()).isNotNull();
111-
assertThat(mrap.accessPoint().name()).isEqualTo(MRAP_NAME);
112-
System.out.println("Alias: " + mrap.accessPoint().alias());
134+
assertThat(mrap.accessPoint().name()).isEqualTo(mrapName);
135+
log.info(() -> "Alias: " + mrap.accessPoint().alias());
113136
return mrap.accessPoint().alias();
114137
}
115138

@@ -136,7 +159,7 @@ public void signingWorkflow(List<ExecutionInterceptor> interceptors, String payl
136159

137160
private void listAndVerify(S3Client s3) {
138161
List<Bucket> buckets = s3.listBuckets().buckets();
139-
assertThat(buckets.stream().map(Bucket::name)).contains(BUCKET);
162+
assertThat(buckets.stream().map(Bucket::name)).contains(bucket);
140163
verifySigv4SignedRequest(captureInterceptor.request());
141164
}
142165

@@ -224,96 +247,36 @@ private S3Presigner s3Presigner() {
224247
.build();
225248
}
226249

227-
private static String createMrap(String mrapName) {
250+
private static void createMrapIfNotExist(String mrapName) {
228251
software.amazon.awssdk.services.s3control.model.Region mrapRegion =
229-
software.amazon.awssdk.services.s3control.model.Region.builder().bucket(BUCKET).build();
230-
231-
CreateMultiRegionAccessPointInput details = CreateMultiRegionAccessPointInput.builder()
232-
.name(mrapName)
233-
.regions(mrapRegion)
234-
.build();
235-
System.out.println("Creating MRAP: " + mrapName);
236-
CreateMultiRegionAccessPointResponse response = s3control.createMultiRegionAccessPoint(r -> r.accountId(accountId)
237-
.details(details));
238-
return response.requestTokenARN();
239-
}
240-
241-
private static String deleteMrap(String mrapName) {
242-
System.out.println("Deleting MRAP: " + mrapName + " with alias " + mrapAlias);
243-
DeleteMultiRegionAccessPointResponse response =
244-
s3control.deleteMultiRegionAccessPoint(r -> r.accountId(accountId).details(d -> d.name(mrapName)));
245-
246-
return response.requestTokenARN();
247-
}
248-
249-
private static void waitForResourceCreation(String resourceTokenArn) throws InterruptedException, IllegalStateException {
250-
int retryCounter = 0;
251-
MultiRegionAccessPointStatus status = null;
252-
253-
System.out.println("Polling status every " + RETRY_DELAY_IN_MS / 1000 + " s.");
254-
255-
while (retryCounter++ < RETRY_TIMES && !MultiRegionAccessPointStatus.READY.equals(status)) {
256-
Thread.sleep(RETRY_DELAY_IN_MS);
257-
258-
System.out.println("Async operation request status: " + getRequestStatus(resourceTokenArn));
259-
260-
Optional<MultiRegionAccessPointReport> testReport = getMrapReport(MRAP_NAME);
261-
if (testReport.isPresent()) {
262-
status = testReport.get().status();
263-
}
264-
System.out.println("MRAP status: " + status);
252+
software.amazon.awssdk.services.s3control.model.Region.builder().bucket(bucket).build();
253+
254+
255+
if (s3control.listMultiRegionAccessPoints(r -> r.accountId(accountId))
256+
.accessPoints().stream().noneMatch(a -> a.name().equals(S3MrapIntegrationTest.mrapName))) {
257+
CreateMultiRegionAccessPointInput details = CreateMultiRegionAccessPointInput.builder()
258+
.name(mrapName)
259+
.regions(mrapRegion)
260+
.build();
261+
log.info(() -> "Creating MRAP: " + mrapName);
262+
CreateMultiRegionAccessPointResponse response = s3control.createMultiRegionAccessPoint(r -> r.accountId(accountId)
263+
.details(details));
264+
waitForResourceCreation(mrapName);
265265
}
266-
267-
if (!MultiRegionAccessPointStatus.READY.equals(status)) {
268-
throw new IllegalStateException("MRAP isn't in ready state, aborting");
269-
}
270-
System.out.println("Created MRAP in " + retryCounter * RETRY_DELAY_IN_MS / 1000 + " s.");
271-
}
272-
273-
private static void waitForResourceDeletion(String resourceTokenArn) throws InterruptedException, IllegalStateException {
274-
int retryCounter = 0;
275-
boolean deleted = false;
276-
277-
System.out.println("Polling status every " + RETRY_DELAY_IN_MS / 1000 + " s.");
278-
279-
while (retryCounter++ < RETRY_TIMES && !deleted) {
280-
Thread.sleep(RETRY_DELAY_IN_MS);
281-
282-
System.out.println("Async operation request status: " + getRequestStatus(resourceTokenArn));
283-
284-
Optional<MultiRegionAccessPointReport> testReport = getMrapReport(MRAP_NAME);
285-
MultiRegionAccessPointStatus status = null;
286-
if (testReport.isPresent()) {
287-
status = testReport.get().status();
288-
} else {
289-
deleted = true;
290-
}
291-
System.out.println("MRAP status: " + status);
292-
}
293-
294-
if (!deleted) {
295-
throw new IllegalStateException("Something went wrong with deleting MRAP " + MRAP_NAME);
296-
}
297-
System.out.println("Deleted MRAP in " + retryCounter * RETRY_DELAY_IN_MS / 1000 + " s.");
298266
}
299267

300-
private static String getRequestStatus(String resourceTokenArn) {
301-
DescribeMultiRegionAccessPointOperationResponse response =
302-
s3control.describeMultiRegionAccessPointOperation(r -> r.accountId(accountId).requestTokenARN(resourceTokenArn));
303-
AsyncOperation operationDetails = response.asyncOperation();
304-
return operationDetails.requestStatus();
305-
}
268+
private static void waitForResourceCreation(String mrapName) throws IllegalStateException {
306269

307-
private static Optional<MultiRegionAccessPointReport> getMrapReport(String name) {
308-
List<MultiRegionAccessPointReport> mrapReports = getMrapReportList();
309-
return mrapReports.stream()
310-
.filter(mrap -> mrap.name().equals(name))
311-
.findFirst();
312-
}
270+
Waiter<ListMultiRegionAccessPointsResponse> waiter =
271+
Waiter.builder(ListMultiRegionAccessPointsResponse.class)
272+
.addAcceptor(WaiterAcceptor.successOnResponseAcceptor(r ->
273+
r.accessPoints().stream().findFirst().filter(mrap -> mrap.name().equals(mrapName) && mrap.status().equals(MultiRegionAccessPointStatus.READY)).isPresent()
274+
))
275+
.addAcceptor(WaiterAcceptor.retryOnResponseAcceptor(i -> true))
276+
.overrideConfiguration(b -> b.maxAttempts(RETRY_TIMES).backoffStrategy(FixedDelayBackoffStrategy.create(Duration.ofSeconds(RETRY_DELAY_IN_SECONDS))))
277+
.build();
313278

314-
private static List<MultiRegionAccessPointReport> getMrapReportList() {
315-
ListMultiRegionAccessPointsResponse listResponse = s3control.listMultiRegionAccessPoints(r -> r.accountId(accountId));
316-
return listResponse.accessPoints();
279+
waiter.run(() -> s3control.listMultiRegionAccessPoints(r -> r.accountId(accountId)));
317280
}
318281

319282
private String applyPresignedUrl(PresignedRequest presignedRequest, String content) {
@@ -328,7 +291,7 @@ private String applyPresignedUrl(PresignedRequest presignedRequest, String conte
328291
.map(stream -> invokeSafely(() -> IoUtils.toUtf8String(stream)))
329292
.orElseThrow(() -> new IOException("No input stream"));
330293
} catch (IOException e) {
331-
e.printStackTrace();
294+
log.error(() -> "Error occurred ", e);
332295
}
333296
return null;
334297
}

0 commit comments

Comments
 (0)