Sfoglia il codice sorgente

HDDS-521. Implement DeleteBucket REST endpoint. Contributed by Bharat Viswanadham.

Márton Elek 6 anni fa
parent
commit
d7c7f68c26

+ 31 - 4
hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/bucket/DeleteBucket.java

@@ -15,6 +15,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.hadoop.ozone.s3.bucket;
 
 import javax.ws.rs.DELETE;
@@ -22,9 +23,15 @@ import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
 import java.io.IOException;
 
+import org.apache.commons.lang3.RandomStringUtils;
 import org.apache.hadoop.ozone.s3.EndpointBase;
+import org.apache.hadoop.ozone.s3.exception.OS3Exception;
+import org.apache.hadoop.ozone.s3.exception.S3ErrorTable;
+import org.apache.hadoop.ozone.web.utils.OzoneUtils;
+import org.apache.http.HttpStatus;
 
 /**
  * Delete a bucket.
@@ -34,11 +41,31 @@ public class DeleteBucket extends EndpointBase {
 
   @DELETE
   @Produces(MediaType.APPLICATION_XML)
-  public void put(
-      @PathParam("volume") String volumeName,
-      @PathParam("bucket") String bucketName) throws IOException {
+  public Response delete(@PathParam("volume") String volumeName,
+                         @PathParam("bucket") String bucketName)
+      throws IOException, OS3Exception {
+
+    setRequestId(OzoneUtils.getRequestID());
+
+    try {
+      getVolume(volumeName).deleteBucket(bucketName);
+    } catch (IOException ex) {
+      if (ex.getMessage().contains("BUCKET_NOT_EMPTY")) {
+        OS3Exception os3Exception = S3ErrorTable.newError(S3ErrorTable
+            .BUCKET_NOT_EMPTY, getRequestId(), S3ErrorTable.Resource.BUCKET);
+        throw os3Exception;
+      } else if (ex.getMessage().contains("BUCKET_NOT_FOUND")) {
+        OS3Exception os3Exception = S3ErrorTable.newError(S3ErrorTable
+            .NO_SUCH_BUCKET, getRequestId(), S3ErrorTable.Resource.BUCKET);
+        throw os3Exception;
+      } else {
+        throw ex;
+      }
+    }
 
-    getVolume(volumeName).deleteBucket(bucketName);
+    return Response.ok().status(HttpStatus.SC_NO_CONTENT).header(
+        "x-amz-request-id", getRequestId()).header("x-amz-id-2",
+        RandomStringUtils.randomAlphanumeric(8, 16)).build();
 
   }
 }

+ 5 - 0
hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/exception/S3ErrorTable.java

@@ -19,6 +19,7 @@ package org.apache.hadoop.ozone.s3.exception;
 
 
 import static java.net.HttpURLConnection.HTTP_BAD_REQUEST;
+import static java.net.HttpURLConnection.HTTP_CONFLICT;
 import static java.net.HttpURLConnection.HTTP_NOT_FOUND;
 
 /**
@@ -37,6 +38,10 @@ public final class S3ErrorTable {
   public static final OS3Exception NO_SUCH_BUCKET = new OS3Exception(
       "NoSuchBucket", "The specified bucket does not exist", HTTP_NOT_FOUND);
 
+  public static final OS3Exception BUCKET_NOT_EMPTY = new OS3Exception(
+      "BucketNotEmpty", "The bucket you tried to delete is not empty.",
+      HTTP_CONFLICT);
+
 
   /**
    * Create a new instance of Error.

+ 21 - 2
hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/client/OzoneVolumeStub.java

@@ -35,6 +35,7 @@ import org.apache.hadoop.ozone.OzoneAcl;
 public class OzoneVolumeStub extends OzoneVolume {
 
   private Map<String, OzoneBucketStub> buckets = new HashMap<>();
+  private Map<String, Boolean> bucketEmptyStatus = new HashMap<>();
 
   public OzoneVolumeStub(String name, String admin, String owner,
       long quotaInBytes,
@@ -60,12 +61,18 @@ public class OzoneVolumeStub extends OzoneVolume {
         bucketArgs.getStorageType(),
         bucketArgs.getVersioning(),
         System.currentTimeMillis()));
+    bucketEmptyStatus.put(bucketName, true);
 
   }
 
   @Override
   public OzoneBucket getBucket(String bucketName) throws IOException {
-    return buckets.get(bucketName);
+    if (buckets.containsKey(bucketName)) {
+      return buckets.get(bucketName);
+    } else {
+      throw new IOException("BUCKET_NOT_FOUND");
+    }
+
   }
 
   @Override
@@ -90,6 +97,18 @@ public class OzoneVolumeStub extends OzoneVolume {
 
   @Override
   public void deleteBucket(String bucketName) throws IOException {
-    buckets.remove(bucketName);
+    if (buckets.containsKey(bucketName)) {
+      if (bucketEmptyStatus.get(bucketName)) {
+        buckets.remove(bucketName);
+      } else {
+        throw new IOException("BUCKET_NOT_EMPTY");
+      }
+    } else {
+      throw new IOException("BUCKET_NOT_FOUND");
+    }
+  }
+
+  public void setBucketEmptyStatus(String bucketName, boolean status) {
+    bucketEmptyStatus.put(bucketName, status);
   }
 }

+ 109 - 0
hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/bucket/TestDeleteBucket.java

@@ -0,0 +1,109 @@
+/*
+ * 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.ozone.s3.bucket;
+
+import org.apache.hadoop.ozone.client.ObjectStore;
+import org.apache.hadoop.ozone.client.OzoneClientStub;
+import org.apache.hadoop.ozone.client.OzoneVolume;
+import org.apache.hadoop.ozone.client.OzoneVolumeStub;
+import org.apache.hadoop.ozone.s3.exception.OS3Exception;
+import org.apache.hadoop.ozone.s3.exception.S3ErrorTable;
+import org.apache.http.HttpStatus;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.ws.rs.core.Response;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+/**
+ * This class tests delete bucket functionality.
+ */
+public class TestDeleteBucket {
+  private String volumeName = "myVolume";
+  private String bucketName = "myBucket";
+  private OzoneClientStub clientStub;
+  private ObjectStore objectStoreStub;
+  private OzoneVolume volumeStub;
+  private DeleteBucket deleteBucket;
+
+  @Before
+  public void setup() throws Exception {
+
+    //Create client stub and object store stub.
+    clientStub = new OzoneClientStub();
+    objectStoreStub = clientStub.getObjectStore();
+
+    // Create volume and bucket
+    objectStoreStub.createVolume(volumeName);
+
+    volumeStub = objectStoreStub.getVolume(volumeName);
+    volumeStub.createBucket(bucketName);
+
+    // Create HeadBucket and setClient to OzoneClientStub
+    deleteBucket = new DeleteBucket();
+    deleteBucket.setClient(clientStub);
+
+
+  }
+
+  @Test
+  public void testDeleteBucket() throws Exception {
+    Response response = deleteBucket.delete(volumeName, bucketName);
+    assertEquals(response.getStatus(), HttpStatus.SC_NO_CONTENT);
+    assertEquals(deleteBucket.getRequestId(), response.getHeaderString(
+        "x-amz-request-id"));
+  }
+
+  @Test
+  public void testDeleteWithNoSuchBucket() throws Exception {
+    try {
+      deleteBucket.delete(volumeName, "unknownbucket");
+    } catch (OS3Exception ex) {
+      assertEquals(S3ErrorTable.NO_SUCH_BUCKET.getCode(), ex.getCode());
+      assertEquals(S3ErrorTable.NO_SUCH_BUCKET.getErrorMessage(),
+          ex.getErrorMessage());
+      assertEquals(deleteBucket.getRequestId(), ex.getRequestId());
+      return;
+    }
+    fail("testDeleteWithNoSuchBucket failed");
+  }
+
+
+  @Test
+  public void testDeleteWithBucketNotEmpty() throws Exception {
+    try {
+      String bucket = "nonemptybucket";
+      volumeStub.createBucket(bucket);
+      OzoneVolumeStub stub  = (OzoneVolumeStub) volumeStub;
+      stub.setBucketEmptyStatus(bucket, false);
+      deleteBucket.delete(volumeName, bucket);
+    } catch (OS3Exception ex) {
+      assertEquals(S3ErrorTable.BUCKET_NOT_EMPTY.getCode(), ex.getCode());
+      assertEquals(S3ErrorTable.BUCKET_NOT_EMPTY.getErrorMessage(),
+          ex.getErrorMessage());
+      assertEquals(deleteBucket.getRequestId(), ex.getRequestId());
+      return;
+    }
+    fail("testDeleteWithBucketNotEmpty failed");
+  }
+}

+ 2 - 2
hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/bucket/TestHeadBucket.java

@@ -83,13 +83,13 @@ public class TestHeadBucket {
             ((OS3Exception) ex).getCode());
         assertEquals(S3ErrorTable.NO_SUCH_BUCKET.getErrorMessage(), (
             (OS3Exception) ex).getErrorMessage());
-        assertEquals(S3ErrorTable.NO_SUCH_BUCKET.getResource(), (
-            (OS3Exception) ex).getResource());
         assertEquals(headBucket.getRequestId(), (
             (OS3Exception) ex).getRequestId());
       } else {
         fail("testHeadFail failed");
       }
+      return;
     }
+    fail("testHeadFail failed");
   }
 }