blob: 8c215d79ea680151e8f042fbd69e132bfe88932d [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.net.URI;
import java.util.UUID;
import java.util.concurrent.Callable;
import org.junit.Test;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.test.LambdaTestUtils;
import static org.apache.hadoop.fs.contract.ContractTestUtils.dataset;
import static org.apache.hadoop.fs.contract.ContractTestUtils.writeDataset;
import static org.apache.hadoop.fs.s3a.Constants.FS_S3A;
import static org.apache.hadoop.fs.s3a.Constants.S3A_BUCKET_PROBE;
import static org.apache.hadoop.fs.s3a.Constants.S3GUARD_METASTORE_NULL;
import static org.apache.hadoop.fs.s3a.Constants.S3_METADATA_STORE_IMPL;
import static org.apache.hadoop.test.LambdaTestUtils.intercept;
/**
* Class to test bucket existence APIs.
*/
public class ITestS3ABucketExistence extends AbstractS3ATestBase {
private FileSystem fs;
private final String randomBucket =
"random-bucket-" + UUID.randomUUID().toString();
private final URI uri = URI.create(FS_S3A + "://" + randomBucket + "/");
@SuppressWarnings("deprecation")
@Test
public void testNoBucketProbing() throws Exception {
describe("Disable init-time probes and expect FS operations to fail");
Configuration conf = createConfigurationWithProbe(0);
// metastores can bypass S3 checks, so disable S3Guard, always
conf.set(S3_METADATA_STORE_IMPL, S3GUARD_METASTORE_NULL);
fs = FileSystem.get(uri, conf);
Path root = new Path(uri);
expectUnknownStore(
() -> fs.getFileStatus(root));
expectUnknownStore(
() -> fs.listStatus(root));
Path src = new Path(root, "testfile");
Path dest = new Path(root, "dst");
expectUnknownStore(
() -> fs.getFileStatus(src));
// the exception must not be caught and marked down to an FNFE
expectUnknownStore(() -> fs.exists(src));
// now that isFile() only does a HEAD, it will get a 404 without
// the no-such-bucket error.
assertFalse("isFile(" + src + ")"
+ " was expected to complete by returning false",
fs.isFile(src));
expectUnknownStore(() -> fs.isDirectory(src));
expectUnknownStore(() -> fs.mkdirs(src));
expectUnknownStore(() -> fs.delete(src));
expectUnknownStore(() -> fs.rename(src, dest));
byte[] data = dataset(1024, 'a', 'z');
expectUnknownStore(
() -> writeDataset(fs, src, data, data.length, 1024 * 1024, true));
}
/**
* Expect an operation to raise an UnknownStoreException.
* @param eval closure
* @param <T> return type of closure
* @throws Exception anything else raised.
*/
public static <T> void expectUnknownStore(
Callable<T> eval)
throws Exception {
intercept(UnknownStoreException.class, eval);
}
/**
* Expect an operation to raise an UnknownStoreException.
* @param eval closure
* @throws Exception anything else raised.
*/
public static void expectUnknownStore(
LambdaTestUtils.VoidCallable eval)
throws Exception {
intercept(UnknownStoreException.class, eval);
}
/**
* Create a new configuration with the given bucket probe;
* we also disable FS caching.
* @param probe value to use as the bucket probe.
* @return a configuration.
*/
private Configuration createConfigurationWithProbe(final int probe) {
Configuration conf = new Configuration(getFileSystem().getConf());
S3ATestUtils.disableFilesystemCaching(conf);
conf.setInt(S3A_BUCKET_PROBE, probe);
return conf;
}
@Test
public void testBucketProbingV1() throws Exception {
describe("Test the V1 bucket probe");
Configuration configuration = createConfigurationWithProbe(1);
expectUnknownStore(
() -> FileSystem.get(uri, configuration));
}
@Test
public void testBucketProbingV2() throws Exception {
describe("Test the V2 bucket probe");
Configuration configuration = createConfigurationWithProbe(2);
expectUnknownStore(
() -> FileSystem.get(uri, configuration));
/*
* Bucket probing should also be done when value of
* S3A_BUCKET_PROBE is greater than 2.
*/
configuration.setInt(S3A_BUCKET_PROBE, 3);
expectUnknownStore(
() -> FileSystem.get(uri, configuration));
}
@Test
public void testBucketProbingParameterValidation() throws Exception {
describe("Test bucket probe parameter %s validation", S3A_BUCKET_PROBE);
Configuration configuration = createConfigurationWithProbe(-1);
intercept(IllegalArgumentException.class,
"Value of " + S3A_BUCKET_PROBE + " should be >= 0",
"Should throw IllegalArgumentException",
() -> FileSystem.get(uri, configuration));
}
@Override
protected Configuration getConfiguration() {
Configuration configuration = super.getConfiguration();
S3ATestUtils.disableFilesystemCaching(configuration);
return configuration;
}
@Override
public void teardown() throws Exception {
IOUtils.cleanupWithLogger(getLogger(), fs);
super.teardown();
}
}