• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License").
5  * You may not use this file except in compliance with the License.
6  * A copy of the License is located at
7  *
8  *  http://aws.amazon.com/apache2.0
9  *
10  * or in the "license" file accompanying this file. This file is distributed
11  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12  * express or implied. See the License for the specific language governing
13  * permissions and limitations under the License.
14  */
15 
16 package software.amazon.awssdk.services.s3control;
17 
18 import static org.assertj.core.api.Assertions.assertThat;
19 
20 import java.util.Iterator;
21 import java.util.List;
22 import org.junit.BeforeClass;
23 import software.amazon.awssdk.core.ClientType;
24 import software.amazon.awssdk.core.interceptor.Context;
25 import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
26 import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
27 import software.amazon.awssdk.regions.Region;
28 import software.amazon.awssdk.services.s3.S3AsyncClient;
29 import software.amazon.awssdk.services.s3.S3AsyncClientBuilder;
30 import software.amazon.awssdk.services.s3.S3Client;
31 import software.amazon.awssdk.services.s3.S3ClientBuilder;
32 import software.amazon.awssdk.services.s3.model.BucketLocationConstraint;
33 import software.amazon.awssdk.services.s3.model.CreateBucketConfiguration;
34 import software.amazon.awssdk.services.s3.model.CreateBucketRequest;
35 import software.amazon.awssdk.services.s3.model.DeleteBucketRequest;
36 import software.amazon.awssdk.services.s3.model.DeleteObjectRequest;
37 import software.amazon.awssdk.services.s3.model.ListObjectVersionsRequest;
38 import software.amazon.awssdk.services.s3.model.ListObjectVersionsResponse;
39 import software.amazon.awssdk.services.s3.model.ListObjectsRequest;
40 import software.amazon.awssdk.services.s3.model.ListObjectsResponse;
41 import software.amazon.awssdk.services.s3.model.NoSuchBucketException;
42 import software.amazon.awssdk.services.s3.model.S3Exception;
43 import software.amazon.awssdk.services.s3.model.S3Object;
44 import software.amazon.awssdk.services.sts.StsClient;
45 import software.amazon.awssdk.testutils.Waiter;
46 import software.amazon.awssdk.testutils.service.AwsTestBase;
47 
48 /**
49  * Base class for S3 Control integration tests. Loads AWS credentials from a properties
50  * file and creates an S3 client for callers to use.
51  */
52 public class S3ControlIntegrationTestBase extends AwsTestBase {
53 
54     protected static final Region DEFAULT_REGION = Region.US_WEST_2;
55     /**
56      * The S3 client for all tests to use.
57      */
58     protected static S3Client s3;
59 
60     protected static S3AsyncClient s3Async;
61 
62     protected static StsClient sts;
63 
64     protected static String accountId;
65 
66     /**
67      * Loads the AWS account info for the integration tests and creates an S3
68      * client for tests to use.
69      */
70     @BeforeClass
setUp()71     public static void setUp() throws Exception {
72         s3 = s3ClientBuilder().build();
73         s3Async = s3AsyncClientBuilder().build();
74         sts = StsClient.builder()
75                        .region(DEFAULT_REGION)
76                        .credentialsProvider(CREDENTIALS_PROVIDER_CHAIN)
77                        .build();
78         accountId = sts.getCallerIdentity().account();
79     }
80 
s3ClientBuilder()81     protected static S3ClientBuilder s3ClientBuilder() {
82         return S3Client.builder()
83                        .region(DEFAULT_REGION)
84                        .credentialsProvider(CREDENTIALS_PROVIDER_CHAIN)
85                        .overrideConfiguration(o -> o.addExecutionInterceptor(
86                            new UserAgentVerifyingExecutionInterceptor("Apache", ClientType.SYNC)));
87     }
88 
s3AsyncClientBuilder()89     protected static S3AsyncClientBuilder s3AsyncClientBuilder() {
90         return S3AsyncClient.builder()
91                             .region(DEFAULT_REGION)
92                             .credentialsProvider(CREDENTIALS_PROVIDER_CHAIN)
93                             .overrideConfiguration(o -> o.addExecutionInterceptor(
94                                 new UserAgentVerifyingExecutionInterceptor("NettyNio", ClientType.ASYNC)));
95     }
96 
createBucket(String bucketName)97     protected static void createBucket(String bucketName) {
98         createBucket(bucketName, 0);
99     }
100 
createBucket(String bucketName, int retryCount)101     private static void createBucket(String bucketName, int retryCount) {
102         try {
103             s3.createBucket(
104                 CreateBucketRequest.builder()
105                                    .bucket(bucketName)
106                                    .createBucketConfiguration(
107                                        CreateBucketConfiguration.builder()
108                                                                 .locationConstraint(BucketLocationConstraint.US_WEST_2)
109                                                                 .build())
110                                    .build());
111         } catch (S3Exception e) {
112             System.err.println("Error attempting to create bucket: " + bucketName);
113             if (e.awsErrorDetails().errorCode().equals("BucketAlreadyOwnedByYou")) {
114                 System.err.printf("%s bucket already exists, likely leaked by a previous run\n", bucketName);
115             } else if (e.awsErrorDetails().errorCode().equals("TooManyBuckets")) {
116                 System.err.println("Printing all buckets for debug:");
117                 s3.listBuckets().buckets().forEach(System.err::println);
118                 if (retryCount < 2) {
119                     System.err.println("Retrying...");
120                     createBucket(bucketName, retryCount + 1);
121                 } else {
122                     throw e;
123                 }
124             } else {
125                 throw e;
126             }
127         }
128     }
129 
deleteBucketAndAllContents(String bucketName)130     protected static void deleteBucketAndAllContents(String bucketName) {
131         deleteBucketAndAllContents(s3, bucketName);
132     }
133 
134     private static class UserAgentVerifyingExecutionInterceptor implements ExecutionInterceptor {
135 
136         private final String clientName;
137         private final ClientType clientType;
138 
UserAgentVerifyingExecutionInterceptor(String clientName, ClientType clientType)139         public UserAgentVerifyingExecutionInterceptor(String clientName, ClientType clientType) {
140             this.clientName = clientName;
141             this.clientType = clientType;
142         }
143 
144         @Override
beforeTransmission(Context.BeforeTransmission context, ExecutionAttributes executionAttributes)145         public void beforeTransmission(Context.BeforeTransmission context, ExecutionAttributes executionAttributes) {
146             assertThat(context.httpRequest().firstMatchingHeader("User-Agent").get()).containsIgnoringCase("io/" + clientType.name());
147             assertThat(context.httpRequest().firstMatchingHeader("User-Agent").get()).containsIgnoringCase("http/" + clientName);
148         }
149     }
150 
deleteBucketAndAllContents(S3Client s3, String bucketName)151     public static void deleteBucketAndAllContents(S3Client s3, String bucketName) {
152         try {
153             System.out.println("Deleting S3 bucket: " + bucketName);
154             ListObjectsResponse response = Waiter.run(() -> s3.listObjects(r -> r.bucket(bucketName)))
155                                                  .ignoringException(NoSuchBucketException.class)
156                                                  .orFail();
157             List<S3Object> objectListing = response.contents();
158 
159             if (objectListing != null) {
160                 while (true) {
161                     for (Iterator<?> iterator = objectListing.iterator(); iterator.hasNext(); ) {
162                         S3Object objectSummary = (S3Object) iterator.next();
163                         s3.deleteObject(DeleteObjectRequest.builder().bucket(bucketName).key(objectSummary.key()).build());
164                     }
165 
166                     if (response.isTruncated()) {
167                         objectListing = s3.listObjects(ListObjectsRequest.builder()
168                                                                          .bucket(bucketName)
169                                                                          .marker(response.marker())
170                                                                          .build())
171                                           .contents();
172                     } else {
173                         break;
174                     }
175                 }
176             }
177 
178 
179             ListObjectVersionsResponse versions = s3
180                 .listObjectVersions(ListObjectVersionsRequest.builder().bucket(bucketName).build());
181 
182             if (versions.deleteMarkers() != null) {
183                 versions.deleteMarkers().forEach(v -> s3.deleteObject(DeleteObjectRequest.builder()
184                                                                                          .versionId(v.versionId())
185                                                                                          .bucket(bucketName)
186                                                                                          .key(v.key())
187                                                                                          .build()));
188             }
189 
190             if (versions.versions() != null) {
191                 versions.versions().forEach(v -> s3.deleteObject(DeleteObjectRequest.builder()
192                                                                                     .versionId(v.versionId())
193                                                                                     .bucket(bucketName)
194                                                                                     .key(v.key())
195                                                                                     .build()));
196             }
197 
198             s3.deleteBucket(DeleteBucketRequest.builder().bucket(bucketName).build());
199         } catch (Exception e) {
200             System.err.println("Failed to delete bucket: " + bucketName);
201             e.printStackTrace();
202         }
203     }
204 }
205