|
@@ -0,0 +1,170 @@
|
|
|
+/*
|
|
|
+ * 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));
|
|
|
+ expectUnknownStore(() -> 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();
|
|
|
+ }
|
|
|
+}
|