This is an automated email from the ASF dual-hosted git repository.

chungen0126 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git


The following commit(s) were added to refs/heads/master by this push:
     new db63057eaf2 HDDS-16635. Remove redundant InfoBucket RPC from S3 
GetBucketLifecycleConfiguration (#11355)
db63057eaf2 is described below

commit db63057eaf2944e3da48c4d3da1172a9b72e39e7
Author: KUAN-HAO HUANG <[email protected]>
AuthorDate: Wed Sep 30 14:40:34 2026 +0800

    HDDS-16635. Remove redundant InfoBucket RPC from S3 
GetBucketLifecycleConfiguration (#11355)
---
 .../ozone/s3/endpoint/BucketLifecycleHandler.java  |  3 +-
 .../endpoint/TestS3LifecycleConfigurationGet.java  | 90 ++++++++++++++++++++++
 2 files changed, 91 insertions(+), 2 deletions(-)

diff --git 
a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/BucketLifecycleHandler.java
 
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/BucketLifecycleHandler.java
index ae6efe0f107..c305fe99c95 100644
--- 
a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/BucketLifecycleHandler.java
+++ 
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/BucketLifecycleHandler.java
@@ -172,8 +172,7 @@ public Response 
getBucketLifecycleConfiguration(S3RequestContext context, String
   protected OzoneLifecycleConfiguration getLifecycleConfiguration(
       S3RequestContext context, String bucketName) throws IOException, 
OS3Exception {
     try {
-      OzoneBucket ozoneBucket = context.getVolume().getBucket(bucketName);
-      return ozoneBucket.getLifecycleConfiguration();
+      return 
getClientProtocol().getLifecycleConfiguration(context.getVolume().getName(), 
bucketName);
     } catch (OMException ex) {
       if (ex.getResult() == 
OMException.ResultCodes.LIFECYCLE_CONFIGURATION_NOT_FOUND) {
         throw S3ErrorTable.newError(
diff --git 
a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestS3LifecycleConfigurationGet.java
 
b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestS3LifecycleConfigurationGet.java
index 8e4d0eb88ad..58834271512 100644
--- 
a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestS3LifecycleConfigurationGet.java
+++ 
b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestS3LifecycleConfigurationGet.java
@@ -19,22 +19,43 @@
 
 import static java.net.HttpURLConnection.HTTP_NOT_FOUND;
 import static java.net.HttpURLConnection.HTTP_OK;
+import static 
org.apache.hadoop.ozone.s3.endpoint.EndpointTestUtils.assertErrorResponse;
+import static org.apache.hadoop.ozone.s3.exception.S3ErrorTable.ACCESS_DENIED;
 import static 
org.apache.hadoop.ozone.s3.exception.S3ErrorTable.NO_SUCH_LIFECYCLE_CONFIGURATION;
+import static 
org.apache.hadoop.ozone.s3.util.S3Consts.EXPECTED_BUCKET_OWNER_HEADER;
+import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.Response;
+import org.apache.hadoop.hdds.conf.OzoneConfiguration;
 import org.apache.hadoop.ozone.client.ObjectStore;
+import org.apache.hadoop.ozone.client.OzoneBucket;
 import org.apache.hadoop.ozone.client.OzoneClient;
 import org.apache.hadoop.ozone.client.OzoneClientStub;
+import org.apache.hadoop.ozone.client.OzoneLifecycleConfiguration;
+import org.apache.hadoop.ozone.client.OzoneVolume;
+import org.apache.hadoop.ozone.client.protocol.ClientProtocol;
+import org.apache.hadoop.ozone.om.exceptions.OMException;
+import org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes;
 import org.apache.hadoop.ozone.s3.exception.OS3Exception;
+import org.apache.hadoop.ozone.s3.exception.S3ErrorTable;
 import org.apache.hadoop.ozone.s3.util.S3Consts;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
 
 /**
  * Testing for GetBucketLifecycleConfiguration.
@@ -143,6 +164,75 @@ public void testGetLifecycleWithDateBasedExpiration() 
throws Exception {
     assertNull(rule.getExpiration().getDays());
   }
 
+  @ParameterizedTest
+  @CsvSource({", 0", "'', 0", "owner, 1"})
+  public void testGetLifecycleOnlyLooksUpBucketForOwner(String expectedOwner, 
int bucketLookups) throws Exception {
+    ClientProtocol proxy = mock(ClientProtocol.class);
+    HttpHeaders headers = mock(HttpHeaders.class);
+    
when(headers.getHeaderString(EXPECTED_BUCKET_OWNER_HEADER)).thenReturn(expectedOwner);
+    BucketEndpoint endpoint = newEndpoint(proxy, headers);
+    when(proxy.getLifecycleConfiguration("volume1", "bucket1"))
+        .thenReturn(new OzoneLifecycleConfiguration("volume1", "bucket1", 0, 
Collections.emptyList()));
+
+    try (Response response = endpoint.get("bucket1")) {
+      assertThat(response.getStatus()).isEqualTo(HTTP_OK);
+      assertThat(((S3LifecycleConfiguration) 
response.getEntity()).getRules()).isEmpty();
+    }
+
+    verify(proxy, times(bucketLookups)).getBucketDetails("volume1", "bucket1");
+    verify(proxy).getLifecycleConfiguration("volume1", "bucket1");
+  }
+
+  @Test
+  public void 
testGetLifecycleRejectsIncorrectOwnerBeforeReadingConfiguration() throws 
Exception {
+    ClientProtocol proxy = mock(ClientProtocol.class);
+    HttpHeaders headers = mock(HttpHeaders.class);
+    
when(headers.getHeaderString(EXPECTED_BUCKET_OWNER_HEADER)).thenReturn("other-owner");
+    BucketEndpoint endpoint = newEndpoint(proxy, headers);
+
+    assertErrorResponse(ACCESS_DENIED, () -> endpoint.get("bucket1"));
+
+    verify(proxy).getBucketDetails("volume1", "bucket1");
+    verify(proxy, never()).getLifecycleConfiguration("volume1", "bucket1");
+  }
+
+  @ParameterizedTest
+  @CsvSource({
+      "LIFECYCLE_CONFIGURATION_NOT_FOUND, NO_SUCH_LIFECYCLE_CONFIGURATION",
+      "BUCKET_NOT_FOUND, NO_SUCH_BUCKET",
+      "VOLUME_NOT_FOUND, NO_SUCH_BUCKET",
+      "PERMISSION_DENIED, ACCESS_DENIED"
+  })
+  public void testGetLifecycleProtocolErrors(ResultCodes resultCode, 
S3ErrorTable expectedError) throws Exception {
+    ClientProtocol proxy = mock(ClientProtocol.class);
+    BucketEndpoint endpoint = newEndpoint(proxy, mock(HttpHeaders.class));
+    when(proxy.getLifecycleConfiguration("volume1", "bucket1"))
+        .thenThrow(new OMException("Lifecycle lookup failed", resultCode));
+
+    assertErrorResponse(expectedError, () -> endpoint.get("bucket1"));
+
+    verify(proxy, never()).getBucketDetails("volume1", "bucket1");
+    verify(proxy).getLifecycleConfiguration("volume1", "bucket1");
+  }
+
+  private BucketEndpoint newEndpoint(ClientProtocol proxy, HttpHeaders 
headers) throws Exception {
+    OzoneConfiguration conf = new OzoneConfiguration();
+    OzoneVolume volume = OzoneVolume.newBuilder(conf, proxy)
+        .setName("volume1").setAcls(Collections.emptyList()).build();
+    OzoneBucket bucket = OzoneBucket.newBuilder(conf, proxy)
+        .setVolumeName("volume1").setName("bucket1").setOwner("owner").build();
+    when(proxy.getBucketDetails("volume1", "bucket1")).thenReturn(bucket);
+    ObjectStore objectStore = mock(ObjectStore.class);
+    when(objectStore.getS3Volume()).thenReturn(volume);
+    when(objectStore.getClientProxy()).thenReturn(proxy);
+    OzoneClient client = mock(OzoneClient.class);
+    when(client.getObjectStore()).thenReturn(objectStore);
+    when(client.getProxy()).thenReturn(proxy);
+    BucketEndpoint endpoint = 
EndpointBuilder.newBucketEndpointBuilder().setClient(client).setHeaders(headers).build();
+    endpoint.queryParamsForTest().set(S3Consts.QueryParams.LIFECYCLE, "");
+    return endpoint;
+  }
+
   private static InputStream getBody() {
     String xml = ("<LifecycleConfiguration xmlns=\"http://s3.amazonaws"; +
         ".com/doc/2006-03-01/\">" +


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to