blob: add6502d7da71d8d875c6601241ca93d77e3ad24 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hadoop.fs.s3a;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import com.amazonaws.ClientConfiguration;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.util.AwsHostNameUtils;
import org.assertj.core.api.Assertions;
import org.junit.Test;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.s3a.statistics.impl.EmptyS3AStatisticsContext;
import static org.apache.hadoop.fs.s3a.Constants.AWS_REGION;
import static org.apache.hadoop.fs.s3a.Constants.AWS_S3_CENTRAL_REGION;
import static org.apache.hadoop.fs.s3a.Constants.DEFAULT_ENDPOINT;
import static org.apache.hadoop.fs.s3a.impl.InternalConstants.AWS_REGION_SYSPROP;
import static org.apache.hadoop.test.LambdaTestUtils.intercept;
/**
* Test to check correctness of S3A endpoint regions in
* {@link DefaultS3ClientFactory}.
*/
public class ITestS3AEndpointRegion extends AbstractS3ATestBase {
private static final String AWS_REGION_TEST = "test-region";
private static final String AWS_ENDPOINT_TEST = "test-endpoint";
private static final String AWS_ENDPOINT_TEST_WITH_REGION =
"test-endpoint.some-region.amazonaws.com";
public static final String MARS_NORTH_2 = "mars-north-2";
/**
* Test to verify that setting a region with the config would bypass the
* construction of region from endpoint.
*/
@Test
public void testWithRegionConfig() {
getFileSystem().getConf().set(AWS_REGION, AWS_REGION_TEST);
//Creating an endpoint config with a custom endpoint.
AwsClientBuilder.EndpointConfiguration epr = createEpr(AWS_ENDPOINT_TEST,
getFileSystem().getConf().getTrimmed(AWS_REGION));
//Checking if setting region config bypasses the endpoint region.
Assertions.assertThat(epr.getSigningRegion())
.describedAs("There is a region mismatch")
.isEqualTo(getFileSystem().getConf().get(AWS_REGION));
}
/**
* Test to verify that not setting the region config, would lead to using
* endpoint to construct the region.
*/
@Test
public void testWithoutRegionConfig() {
getFileSystem().getConf().unset(AWS_REGION);
//Creating an endpoint config with a custom endpoint containing a region.
AwsClientBuilder.EndpointConfiguration eprRandom =
createEpr(AWS_ENDPOINT_TEST_WITH_REGION,
getFileSystem().getConf().getTrimmed(AWS_REGION));
String regionFromEndpoint =
AwsHostNameUtils
.parseRegionFromAwsPartitionPattern(AWS_ENDPOINT_TEST_WITH_REGION);
//Checking if not setting region config leads to constructing the region
// from endpoint.
Assertions.assertThat(eprRandom.getSigningRegion())
.describedAs("There is a region mismatch")
.isNotEqualTo(getFileSystem().getConf().get(AWS_REGION))
.isEqualTo(regionFromEndpoint);
}
/**
* Method to create EndpointConfiguration using an endpoint.
*
* @param endpoint the endpoint to be used for EndpointConfiguration creation.
* @return an instance of EndpointConfiguration.
*/
private AwsClientBuilder.EndpointConfiguration createEpr(String endpoint,
String awsRegion) {
return DefaultS3ClientFactory.createEndpointConfiguration(endpoint,
new ClientConfiguration(), awsRegion);
}
@Test
public void testInvalidRegionDefaultEndpoint() throws Throwable {
describe("Create a client with an invalid region and the default endpoint");
Configuration conf = getConfiguration();
// we are making a big assumption about the timetable for AWS
// region rollout.
// if this test ever fails because this region now exists
// -congratulations!
conf.set(AWS_REGION, MARS_NORTH_2);
createMarsNorth2Client(conf);
}
@Test
public void testUnsetRegionDefaultEndpoint() throws Throwable {
describe("Create a client with no region and the default endpoint");
Configuration conf = getConfiguration();
conf.unset(AWS_REGION);
createS3Client(conf, DEFAULT_ENDPOINT, AWS_S3_CENTRAL_REGION);
}
/**
* By setting the system property {@code "aws.region"} we can
* guarantee that the SDK region resolution chain will always succeed
* (and fast).
* Clearly there is no validation of the region during the build process.
*/
@Test
public void testBlankRegionTriggersSDKResolution() throws Throwable {
describe("Create a client with a blank region and the default endpoint."
+ " This will trigger the SDK Resolution chain");
Configuration conf = getConfiguration();
conf.set(AWS_REGION, "");
System.setProperty(AWS_REGION_SYSPROP, MARS_NORTH_2);
try {
createMarsNorth2Client(conf);
} finally {
System.clearProperty(AWS_REGION_SYSPROP);
}
}
/**
* Create an S3 client bonded to an invalid region;
* verify that calling {@code getRegion()} triggers
* a failure.
* @param conf configuration to use in the building.
*/
private void createMarsNorth2Client(Configuration conf) throws Exception {
AmazonS3 client = createS3Client(conf, DEFAULT_ENDPOINT, MARS_NORTH_2);
intercept(IllegalArgumentException.class, MARS_NORTH_2, client::getRegion);
}
/**
* Create an S3 client with the given conf and endpoint.
* The region name must then match that of the expected
* value.
* @param conf configuration to use.
* @param endpoint endpoint.
* @param expectedRegion expected region
* @return the client.
* @throws URISyntaxException parse problems.
* @throws IOException IO problems
*/
@SuppressWarnings("deprecation")
private AmazonS3 createS3Client(Configuration conf,
String endpoint,
String expectedRegion)
throws URISyntaxException, IOException {
DefaultS3ClientFactory factory
= new DefaultS3ClientFactory();
factory.setConf(conf);
S3ClientFactory.S3ClientCreationParameters parameters
= new S3ClientFactory.S3ClientCreationParameters()
.withCredentialSet(new AnonymousAWSCredentialsProvider())
.withPathUri(new URI("s3a://localhost/"))
.withEndpoint(endpoint)
.withMetrics(new EmptyS3AStatisticsContext()
.newStatisticsFromAwsSdk());
AmazonS3 client = factory.createS3Client(
new URI("s3a://localhost/"),
parameters);
Assertions.assertThat(client.getRegionName())
.describedAs("Client region name")
.isEqualTo(expectedRegion);
return client;
}
}