This is an automated email from the ASF dual-hosted git repository.
jtuglu1 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/druid.git
The following commit(s) were added to refs/heads/master by this push:
new 8308a662874 perf: Streamline s3 backend (#19394)
8308a662874 is described below
commit 8308a662874667b49e227a3422742922a08889e3
Author: jtuglu1 <[email protected]>
AuthorDate: Mon May 18 18:57:43 2026 -0700
perf: Streamline s3 backend (#19394)
S3 achieve strong read-after-write consistency in 2020. The current s3
backend architecture assumes a prior consistency model and therefore does some
redundant calls which are both slow and costly.
---
.../druid/storage/s3/S3DataSegmentMover.java | 125 +++++++++------------
.../druid/storage/s3/S3DataSegmentPuller.java | 23 +---
.../java/org/apache/druid/storage/s3/S3Utils.java | 18 +--
.../storage/s3/ServerSideEncryptingAmazonS3.java | 12 ++
.../druid/storage/s3/S3DataSegmentMoverTest.java | 52 +++++++++
.../druid/storage/s3/S3DataSegmentPullerTest.java | 9 --
.../druid/storage/s3/S3DataSegmentPusherTest.java | 50 +--------
.../apache/druid/storage/s3/S3TaskLogsTest.java | 19 ++--
8 files changed, 136 insertions(+), 172 deletions(-)
diff --git
a/extensions-core/s3-extensions/src/main/java/org/apache/druid/storage/s3/S3DataSegmentMover.java
b/extensions-core/s3-extensions/src/main/java/org/apache/druid/storage/s3/S3DataSegmentMover.java
index cd6675c5b42..fe266cd72d1 100644
---
a/extensions-core/s3-extensions/src/main/java/org/apache/druid/storage/s3/S3DataSegmentMover.java
+++
b/extensions-core/s3-extensions/src/main/java/org/apache/druid/storage/s3/S3DataSegmentMover.java
@@ -24,8 +24,6 @@ import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.inject.Inject;
-import org.apache.druid.java.util.common.IOE;
-import org.apache.druid.java.util.common.ISE;
import org.apache.druid.java.util.common.MapUtils;
import org.apache.druid.java.util.common.RetryUtils;
import org.apache.druid.java.util.common.StringUtils;
@@ -35,13 +33,13 @@ import org.apache.druid.segment.loading.DataSegmentPusher;
import org.apache.druid.segment.loading.SegmentLoadingException;
import org.apache.druid.timeline.DataSegment;
import software.amazon.awssdk.services.s3.model.CopyObjectRequest;
+import software.amazon.awssdk.services.s3.model.HeadObjectResponse;
import software.amazon.awssdk.services.s3.model.ListObjectsV2Request;
import software.amazon.awssdk.services.s3.model.ListObjectsV2Response;
-import software.amazon.awssdk.services.s3.model.ObjectStorageClass;
import software.amazon.awssdk.services.s3.model.S3Exception;
import software.amazon.awssdk.services.s3.model.S3Object;
+import software.amazon.awssdk.services.s3.model.StorageClass;
-import java.io.IOException;
import java.nio.file.Paths;
import java.util.Map;
@@ -163,10 +161,10 @@ public class S3DataSegmentMover implements
DataSegmentMover
targetS3Path
);
try {
- selfCheckingMove(s3Bucket, targetS3Bucket, s3Path, targetS3Path,
copyMsg);
+ moveObject(s3Bucket, targetS3Bucket, s3Path, targetS3Path,
copyMsg);
return null;
}
- catch (S3Exception | IOException | SegmentLoadingException e) {
+ catch (S3Exception | SegmentLoadingException e) {
log.info(e, "Error while trying to move " + copyMsg);
throw e;
}
@@ -185,90 +183,75 @@ public class S3DataSegmentMover implements
DataSegmentMover
}
/**
- * Copies an object and after that checks that the object is present at the
target location, via a separate API call.
- * If it is not, an exception is thrown, and the object is not deleted at
the old location. This "paranoic" check
- * is added after it was observed that S3 may report a successful move, and
the object is not found at the target
- * location.
+ * Copies an S3 object to a target location and deletes the source.
+ * S3 has been strongly consistent since December 2020, so no post-copy
existence check is needed.
*/
- private void selfCheckingMove(
+ private void moveObject(
String s3Bucket,
String targetS3Bucket,
String s3Path,
String targetS3Path,
String copyMsg
- ) throws IOException, SegmentLoadingException
+ ) throws SegmentLoadingException
{
if (s3Bucket.equals(targetS3Bucket) && s3Path.equals(targetS3Path)) {
log.info("No need to move file[s3://%s/%s] onto itself", s3Bucket,
s3Path);
return;
}
final ServerSideEncryptingAmazonS3 s3Client = this.s3ClientSupplier.get();
- if (s3Client.doesObjectExist(s3Bucket, s3Path)) {
- ListObjectsV2Request request = ListObjectsV2Request.builder()
- .bucket(s3Bucket)
- .prefix(s3Path)
- .maxKeys(1)
- .build();
- final ListObjectsV2Response listResult = s3Client.listObjectsV2(request);
- // Using contents().size() instead of keyCount as, in some cases
- // it is observed that even though the contents returns some data
- // keyCount is still zero.
- if (listResult.contents().size() == 0) {
- // should never happen
- throw new ISE("Unable to list object [s3://%s/%s]", s3Bucket, s3Path);
- }
- final S3Object objectSummary = listResult.contents().get(0);
- if (objectSummary.storageClass() != null &&
- objectSummary.storageClass().equals(ObjectStorageClass.GLACIER)) {
- throw S3Exception.builder()
- .message(StringUtils.format(
- "Cannot move file[s3://%s/%s] of storage class glacier,
skipping.",
- s3Bucket,
- s3Path
- ))
- .build();
- } else {
- log.info("Moving file %s", copyMsg);
- CopyObjectRequest.Builder copyRequestBuilder =
CopyObjectRequest.builder()
- .sourceBucket(s3Bucket)
- .sourceKey(s3Path)
- .destinationBucket(targetS3Bucket)
- .destinationKey(targetS3Path);
- if (!config.getDisableAcl()) {
- final String headerValue = S3Utils.grantFullControlHeaderValue(
- S3Utils.grantFullControlToBucketOwner(s3Client, targetS3Bucket)
+ final HeadObjectResponse sourceMetadata;
+ try {
+ sourceMetadata = s3Client.getObjectMetadata(s3Bucket, s3Path);
+ }
+ catch (S3Exception e) {
+ if (e.statusCode() == 404) {
+ // Source is gone; succeed silently if it already landed at the target.
+ if (s3Client.doesObjectExist(targetS3Bucket, targetS3Path)) {
+ log.info(
+ "Not moving file [s3://%s/%s], already present in target
location [s3://%s/%s]",
+ s3Bucket,
+ s3Path,
+ targetS3Bucket,
+ targetS3Path
);
- if (headerValue != null) {
- copyRequestBuilder.grantFullControl(headerValue);
- }
- }
- s3Client.copyObject(copyRequestBuilder);
- if (!s3Client.doesObjectExist(targetS3Bucket, targetS3Path)) {
- throw new IOE(
- "After copy was reported as successful the file doesn't exist in
the target location [%s]",
+ } else {
+ throw new SegmentLoadingException(
+ "Unable to move file %s, not present in either source or target
location",
copyMsg
);
}
- deleteWithRetriesSilent(s3Bucket, s3Path);
- log.debug("Finished moving file %s", copyMsg);
+ return;
}
- } else {
- // ensure object exists in target location
- if (s3Client.doesObjectExist(targetS3Bucket, targetS3Path)) {
- log.info(
- "Not moving file [s3://%s/%s], already present in target location
[s3://%s/%s]",
- s3Bucket,
- s3Path,
- targetS3Bucket,
- targetS3Path
- );
- } else {
- throw new SegmentLoadingException(
- "Unable to move file %s, not present in either source or target
location",
- copyMsg
- );
+ throw e;
+ }
+ final StorageClass sc = sourceMetadata.storageClass();
+ if (StorageClass.GLACIER.equals(sc) ||
StorageClass.DEEP_ARCHIVE.equals(sc)) {
+ throw S3Exception.builder()
+ .message(StringUtils.format(
+ "Cannot move file[s3://%s/%s] of storage class [%s], skipping.",
+ s3Bucket,
+ s3Path,
+ sc
+ ))
+ .build();
+ }
+ log.info("Moving file %s", copyMsg);
+ CopyObjectRequest.Builder copyRequestBuilder = CopyObjectRequest.builder()
+ .sourceBucket(s3Bucket)
+ .sourceKey(s3Path)
+ .destinationBucket(targetS3Bucket)
+ .destinationKey(targetS3Path);
+ if (!config.getDisableAcl()) {
+ final String headerValue = S3Utils.grantFullControlHeaderValue(
+ s3Client.getBucketOwnerGrant(targetS3Bucket)
+ );
+ if (headerValue != null) {
+ copyRequestBuilder.grantFullControl(headerValue);
}
}
+ s3Client.copyObject(copyRequestBuilder);
+ deleteWithRetriesSilent(s3Bucket, s3Path);
+ log.debug("Finished moving file %s", copyMsg);
}
private void deleteWithRetriesSilent(final String s3Bucket, final String
s3Path)
diff --git
a/extensions-core/s3-extensions/src/main/java/org/apache/druid/storage/s3/S3DataSegmentPuller.java
b/extensions-core/s3-extensions/src/main/java/org/apache/druid/storage/s3/S3DataSegmentPuller.java
index 797bb7fcb1c..d133256c49b 100644
---
a/extensions-core/s3-extensions/src/main/java/org/apache/druid/storage/s3/S3DataSegmentPuller.java
+++
b/extensions-core/s3-extensions/src/main/java/org/apache/druid/storage/s3/S3DataSegmentPuller.java
@@ -87,9 +87,6 @@ public class S3DataSegmentPuller implements URIDataPuller
FileUtils.mkdirp(outDir);
if (CompressionUtils.isZip(s3Coords.getPath())) {
- if (!isObjectInBucket(s3Coords)) {
- throw new SegmentLoadingException("IndexFile[%s] does not exist.",
s3Coords);
- }
final URI uri = s3Coords.toUri(S3StorageDruidModule.SCHEME);
final ByteSource byteSource = getByteSource(uri);
final FileUtils.FileCopyResult result = CompressionUtils.unzip(
@@ -101,9 +98,6 @@ public class S3DataSegmentPuller implements URIDataPuller
log.info("Loaded %d bytes from [%s] to [%s]", result.size(),
s3Coords.toString(), outDir.getAbsolutePath());
return result;
} else if (CompressionUtils.isGz(s3Coords.getPath())) {
- if (!isObjectInBucket(s3Coords)) {
- throw new SegmentLoadingException("IndexFile[%s] does not exist.",
s3Coords);
- }
final URI uri = s3Coords.toUri(S3StorageDruidModule.SCHEME);
final ByteSource byteSource = getByteSource(uri);
final String fname = Files.getNameWithoutExtension(uri.getPath());
@@ -235,6 +229,9 @@ public class S3DataSegmentPuller implements URIDataPuller
};
}
catch (SdkException e) {
+ if (e instanceof S3Exception && ((S3Exception) e).statusCode() ==
404) {
+ throw new IOE(e, "IndexFile[s3://%s/%s] does not exist",
coords.getBucket(), coords.getPath());
+ }
throw new IOE(e, "Could not load S3 URI [%s]", uri);
}
}
@@ -318,18 +315,4 @@ public class S3DataSegmentPuller implements URIDataPuller
}
}
- private boolean isObjectInBucket(final CloudObjectLocation coords) throws
SegmentLoadingException
- {
- try {
- return S3Utils.retryS3Operation(
- () -> S3Utils.isObjectInBucketIgnoringPermission(s3Client,
coords.getBucket(), coords.getPath())
- );
- }
- catch (S3Exception | IOException e) {
- throw new SegmentLoadingException(e, "S3 fail! Key[%s]", coords);
- }
- catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
}
diff --git
a/extensions-core/s3-extensions/src/main/java/org/apache/druid/storage/s3/S3Utils.java
b/extensions-core/s3-extensions/src/main/java/org/apache/druid/storage/s3/S3Utils.java
index 0feeb655fdf..2cac95a200b 100644
---
a/extensions-core/s3-extensions/src/main/java/org/apache/druid/storage/s3/S3Utils.java
+++
b/extensions-core/s3-extensions/src/main/java/org/apache/druid/storage/s3/S3Utils.java
@@ -43,11 +43,9 @@ import software.amazon.awssdk.services.s3.model.Grant;
import software.amazon.awssdk.services.s3.model.Grantee;
import software.amazon.awssdk.services.s3.model.HeadObjectResponse;
import software.amazon.awssdk.services.s3.model.ObjectIdentifier;
-import software.amazon.awssdk.services.s3.model.Permission;
import software.amazon.awssdk.services.s3.model.S3Error;
import software.amazon.awssdk.services.s3.model.S3Exception;
import software.amazon.awssdk.services.s3.model.S3Object;
-import software.amazon.awssdk.services.s3.model.Type;
import javax.annotation.Nullable;
import java.io.File;
@@ -240,20 +238,6 @@ public class S3Utils
) + "/";
}
- static Grant grantFullControlToBucketOwner(ServerSideEncryptingAmazonS3
s3Client, String bucket)
- {
- final String ownerId = s3Client.getBucketAcl(bucket).owner().id();
- return Grant
- .builder()
- .grantee(Grantee
- .builder()
- .type(Type.CANONICAL_USER)
- .id(ownerId)
- .build())
- .permission(Permission.FULL_CONTROL)
- .build();
- }
-
/**
* Builds the header value for {@code x-amz-grant-full-control}.
*
@@ -427,7 +411,7 @@ public class S3Utils
)
{
log.info("Pushing [%s] to bucket[%s] and key[%s].", file, bucket, key);
- service.upload(bucket, key, file, disableAcl ? null :
S3Utils.grantFullControlToBucketOwner(service, bucket));
+ service.upload(bucket, key, file, disableAcl ? null :
service.getBucketOwnerGrant(bucket));
}
/**
diff --git
a/extensions-core/s3-extensions/src/main/java/org/apache/druid/storage/s3/ServerSideEncryptingAmazonS3.java
b/extensions-core/s3-extensions/src/main/java/org/apache/druid/storage/s3/ServerSideEncryptingAmazonS3.java
index d59124ecba2..b8b76d0cf5a 100644
---
a/extensions-core/s3-extensions/src/main/java/org/apache/druid/storage/s3/ServerSideEncryptingAmazonS3.java
+++
b/extensions-core/s3-extensions/src/main/java/org/apache/druid/storage/s3/ServerSideEncryptingAmazonS3.java
@@ -40,13 +40,16 @@ import
software.amazon.awssdk.services.s3.model.GetBucketAclResponse;
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
import software.amazon.awssdk.services.s3.model.GetObjectResponse;
import software.amazon.awssdk.services.s3.model.Grant;
+import software.amazon.awssdk.services.s3.model.Grantee;
import software.amazon.awssdk.services.s3.model.HeadObjectRequest;
import software.amazon.awssdk.services.s3.model.HeadObjectResponse;
import software.amazon.awssdk.services.s3.model.ListObjectsV2Request;
import software.amazon.awssdk.services.s3.model.ListObjectsV2Response;
+import software.amazon.awssdk.services.s3.model.Permission;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.PutObjectResponse;
import software.amazon.awssdk.services.s3.model.S3Exception;
+import software.amazon.awssdk.services.s3.model.Type;
import software.amazon.awssdk.services.s3.model.UploadPartRequest;
import software.amazon.awssdk.services.s3.model.UploadPartResponse;
import software.amazon.awssdk.transfer.s3.S3TransferManager;
@@ -139,6 +142,15 @@ public class ServerSideEncryptingAmazonS3
return s3Client.getBucketAcl(builder -> builder.bucket(bucket));
}
+ public Grant getBucketOwnerGrant(String bucket)
+ {
+ final String ownerId = getBucketAcl(bucket).owner().id();
+ return Grant.builder()
+
.grantee(Grantee.builder().type(Type.CANONICAL_USER).id(ownerId).build())
+ .permission(Permission.FULL_CONTROL)
+ .build();
+ }
+
public HeadObjectResponse getObjectMetadata(String bucket, String key)
{
HeadObjectRequest.Builder requestBuilder = HeadObjectRequest.builder()
diff --git
a/extensions-core/s3-extensions/src/test/java/org/apache/druid/storage/s3/S3DataSegmentMoverTest.java
b/extensions-core/s3-extensions/src/test/java/org/apache/druid/storage/s3/S3DataSegmentMoverTest.java
index c504fbe7e04..4a9e8b4b9b1 100644
---
a/extensions-core/s3-extensions/src/test/java/org/apache/druid/storage/s3/S3DataSegmentMoverTest.java
+++
b/extensions-core/s3-extensions/src/test/java/org/apache/druid/storage/s3/S3DataSegmentMoverTest.java
@@ -38,6 +38,7 @@ import
software.amazon.awssdk.services.s3.model.CopyObjectResponse;
import software.amazon.awssdk.services.s3.model.GetBucketAclResponse;
import software.amazon.awssdk.services.s3.model.Grant;
import software.amazon.awssdk.services.s3.model.Grantee;
+import software.amazon.awssdk.services.s3.model.HeadObjectResponse;
import software.amazon.awssdk.services.s3.model.ListObjectsV2Request;
import software.amazon.awssdk.services.s3.model.ListObjectsV2Response;
import software.amazon.awssdk.services.s3.model.Owner;
@@ -130,6 +131,45 @@ public class S3DataSegmentMoverTest
Assert.assertFalse(mockS3Client.didMove());
}
+ @Test
+ public void testMoveNoopWhenHeadReturnsGeneric404() throws Exception
+ {
+ final MockAmazonS3Client mockS3Client = new MockAmazonS3Client()
+ {
+ @Override
+ public HeadObjectResponse getObjectMetadata(String bucketName, String
key)
+ {
+ if (doesObjectExist(bucketName, key)) {
+ return
HeadObjectResponse.builder().storageClass(StorageClass.STANDARD).build();
+ }
+ throw (S3Exception) S3Exception.builder().statusCode(404).build();
+ }
+ };
+ final S3DataSegmentMover mover = new S3DataSegmentMover(
+ Suppliers.ofInstance(mockS3Client),
+ new S3DataSegmentPusherConfig()
+ );
+
+ mockS3Client.putObject(
+ "archive",
+
"targetBaseKey/test/2013-01-01T00:00:00.000Z_2013-01-02T00:00:00.000Z/1/0/index.zip"
+ );
+
+ final DataSegment movedSegment = mover.move(
+ SOURCE_SEGMENT,
+ ImmutableMap.of("baseKey", "targetBaseKey", "bucket", "archive")
+ );
+
+ final Map<String, Object> targetLoadSpec = movedSegment.getLoadSpec();
+
+ Assert.assertEquals(
+
"targetBaseKey/test/2013-01-01T00:00:00.000Z_2013-01-02T00:00:00.000Z/1/0/index.zip",
+ MapUtils.getString(targetLoadSpec, "key")
+ );
+ Assert.assertEquals("archive", MapUtils.getString(targetLoadSpec,
"bucket"));
+ Assert.assertFalse(mockS3Client.didMove());
+ }
+
@Test(expected = SegmentLoadingException.class)
public void testMoveException() throws Exception
{
@@ -250,6 +290,18 @@ public class S3DataSegmentMoverTest
return (objects != null && objects.contains(objectKey));
}
+ @Override
+ public HeadObjectResponse getObjectMetadata(String bucketName, String key)
+ {
+ if (doesObjectExist(bucketName, key)) {
+ return
HeadObjectResponse.builder().storageClass(StorageClass.STANDARD).build();
+ }
+ throw (S3Exception) S3Exception.builder()
+
.awsErrorDetails(AwsErrorDetails.builder().errorCode("NoSuchKey").build())
+ .statusCode(404)
+ .build();
+ }
+
@Override
public ListObjectsV2Response listObjectsV2(ListObjectsV2Request
listObjectsV2Request)
{
diff --git
a/extensions-core/s3-extensions/src/test/java/org/apache/druid/storage/s3/S3DataSegmentPullerTest.java
b/extensions-core/s3-extensions/src/test/java/org/apache/druid/storage/s3/S3DataSegmentPullerTest.java
index bc1b9f6ad76..289c60219af 100644
---
a/extensions-core/s3-extensions/src/test/java/org/apache/druid/storage/s3/S3DataSegmentPullerTest.java
+++
b/extensions-core/s3-extensions/src/test/java/org/apache/druid/storage/s3/S3DataSegmentPullerTest.java
@@ -101,9 +101,6 @@ public class S3DataSegmentPullerTest
final File tmpDir = temporaryFolder.newFolder("gzTestDir");
- EasyMock.expect(s3Client.doesObjectExist(EasyMock.eq(bucket),
EasyMock.eq(key)))
- .andReturn(true)
- .once();
EasyMock.expect(s3Client.getObject(EasyMock.eq(bucket), EasyMock.eq(key)))
.andAnswer(() -> new ResponseInputStream<>(
GetObjectResponse.builder().lastModified(Instant.ofEpochMilli(0)).build(),
@@ -152,9 +149,6 @@ public class S3DataSegmentPullerTest
.build())
.statusCode(404)
.build();
- EasyMock.expect(s3Client.doesObjectExist(EasyMock.eq(bucket),
EasyMock.eq(key)))
- .andReturn(true)
- .once();
EasyMock.expect(s3Client.getObject(EasyMock.eq(bucket), EasyMock.eq(key)))
.andThrow(exception)
.once();
@@ -201,9 +195,6 @@ public class S3DataSegmentPullerTest
.build())
.statusCode(503)
.build();
- EasyMock.expect(s3Client.doesObjectExist(EasyMock.eq(bucket),
EasyMock.eq(key)))
- .andReturn(true)
- .once();
EasyMock.expect(s3Client.getObject(EasyMock.eq(bucket), EasyMock.eq(key)))
.andThrow(exception)
.once();
diff --git
a/extensions-core/s3-extensions/src/test/java/org/apache/druid/storage/s3/S3DataSegmentPusherTest.java
b/extensions-core/s3-extensions/src/test/java/org/apache/druid/storage/s3/S3DataSegmentPusherTest.java
index 036df9446fa..6bde494d900 100644
---
a/extensions-core/s3-extensions/src/test/java/org/apache/druid/storage/s3/S3DataSegmentPusherTest.java
+++
b/extensions-core/s3-extensions/src/test/java/org/apache/druid/storage/s3/S3DataSegmentPusherTest.java
@@ -33,10 +33,8 @@ import org.junit.Test;
import org.junit.internal.matchers.ThrowableMessageMatcher;
import org.junit.rules.TemporaryFolder;
import software.amazon.awssdk.awscore.exception.AwsErrorDetails;
-import software.amazon.awssdk.services.s3.model.GetBucketAclResponse;
import software.amazon.awssdk.services.s3.model.Grant;
import software.amazon.awssdk.services.s3.model.Grantee;
-import software.amazon.awssdk.services.s3.model.Owner;
import software.amazon.awssdk.services.s3.model.Permission;
import software.amazon.awssdk.services.s3.model.S3Exception;
import software.amazon.awssdk.services.s3.model.Type;
@@ -96,23 +94,11 @@ public class S3DataSegmentPusherTest
{
ServerSideEncryptingAmazonS3 s3Client =
EasyMock.createStrictMock(ServerSideEncryptingAmazonS3.class);
- Owner owner = Owner.builder()
- .id("ownerId")
- .displayName("owner")
- .build();
- Grantee grantee = Grantee.builder()
- .id(owner.id())
- .type(Type.CANONICAL_USER)
- .build();
Grant grant = Grant.builder()
- .grantee(grantee)
+
.grantee(Grantee.builder().id("ownerId").type(Type.CANONICAL_USER).build())
.permission(Permission.FULL_CONTROL)
.build();
- final GetBucketAclResponse aclResponse = GetBucketAclResponse.builder()
- .owner(owner)
- .grants(grant)
- .build();
-
EasyMock.expect(s3Client.getBucketAcl(EasyMock.eq("bucket"))).andReturn(aclResponse).once();
+
EasyMock.expect(s3Client.getBucketOwnerGrant(EasyMock.eq("bucket"))).andReturn(grant).once();
s3Client.upload(EasyMock.anyString(), EasyMock.anyString(),
EasyMock.anyObject(File.class), EasyMock.anyObject(Grant.class));
EasyMock.expectLastCall().once();
@@ -136,23 +122,11 @@ public class S3DataSegmentPusherTest
{
ServerSideEncryptingAmazonS3 s3Client =
EasyMock.createStrictMock(ServerSideEncryptingAmazonS3.class);
- Owner owner = Owner.builder()
- .id("ownerId")
- .displayName("owner")
- .build();
- Grantee grantee = Grantee.builder()
- .id(owner.id())
- .type(Type.CANONICAL_USER)
- .build();
Grant grant = Grant.builder()
- .grantee(grantee)
+
.grantee(Grantee.builder().id("ownerId").type(Type.CANONICAL_USER).build())
.permission(Permission.FULL_CONTROL)
.build();
- final GetBucketAclResponse aclResponse = GetBucketAclResponse.builder()
- .owner(owner)
- .grants(grant)
- .build();
-
EasyMock.expect(s3Client.getBucketAcl(EasyMock.eq("bucket"))).andReturn(aclResponse).once();
+
EasyMock.expect(s3Client.getBucketOwnerGrant(EasyMock.eq("bucket"))).andReturn(grant).once();
s3Client.upload(EasyMock.anyString(), EasyMock.anyString(),
EasyMock.anyObject(File.class), EasyMock.anyObject(Grant.class));
EasyMock.expectLastCall().once();
@@ -174,23 +148,11 @@ public class S3DataSegmentPusherTest
.statusCode(400)
.build();
- Owner owner = Owner.builder()
- .id("ownerId")
- .displayName("owner")
- .build();
- Grantee grantee = Grantee.builder()
- .id(owner.id())
- .type(Type.CANONICAL_USER)
- .build();
Grant grant = Grant.builder()
- .grantee(grantee)
+
.grantee(Grantee.builder().id("ownerId").type(Type.CANONICAL_USER).build())
.permission(Permission.FULL_CONTROL)
.build();
- final GetBucketAclResponse aclResponse = GetBucketAclResponse.builder()
- .owner(owner)
- .grants(grant)
- .build();
-
EasyMock.expect(s3Client.getBucketAcl(EasyMock.eq("bucket"))).andReturn(aclResponse).once();
+
EasyMock.expect(s3Client.getBucketOwnerGrant(EasyMock.eq("bucket"))).andReturn(grant).once();
s3Client.upload(EasyMock.anyString(), EasyMock.anyString(),
EasyMock.anyObject(File.class), EasyMock.anyObject(Grant.class));
EasyMock.expectLastCall().andThrow(e).once();
diff --git
a/extensions-core/s3-extensions/src/test/java/org/apache/druid/storage/s3/S3TaskLogsTest.java
b/extensions-core/s3-extensions/src/test/java/org/apache/druid/storage/s3/S3TaskLogsTest.java
index f82f587f1ae..2516b62ba4c 100644
---
a/extensions-core/s3-extensions/src/test/java/org/apache/druid/storage/s3/S3TaskLogsTest.java
+++
b/extensions-core/s3-extensions/src/test/java/org/apache/druid/storage/s3/S3TaskLogsTest.java
@@ -39,16 +39,16 @@ import org.junit.runner.RunWith;
import software.amazon.awssdk.core.ResponseInputStream;
import software.amazon.awssdk.core.exception.SdkClientException;
import software.amazon.awssdk.services.s3.model.DeleteObjectsRequest;
-import software.amazon.awssdk.services.s3.model.GetBucketAclResponse;
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
import software.amazon.awssdk.services.s3.model.GetObjectResponse;
import software.amazon.awssdk.services.s3.model.Grant;
+import software.amazon.awssdk.services.s3.model.Grantee;
import software.amazon.awssdk.services.s3.model.HeadObjectResponse;
import software.amazon.awssdk.services.s3.model.ObjectIdentifier;
-import software.amazon.awssdk.services.s3.model.Owner;
import software.amazon.awssdk.services.s3.model.Permission;
import software.amazon.awssdk.services.s3.model.S3Exception;
import software.amazon.awssdk.services.s3.model.S3Object;
+import software.amazon.awssdk.services.s3.model.Type;
import javax.annotation.Nonnull;
import java.io.BufferedReader;
@@ -633,22 +633,19 @@ public class S3TaskLogsTest extends EasyMockSupport
private List<Grant> testPushInternal(boolean disableAcl, String ownerId,
String ownerDisplayName) throws Exception
{
List<Grant> capturedGrants = new ArrayList<>();
- Owner owner = Owner.builder()
- .id(ownerId)
- .displayName(ownerDisplayName)
- .build();
if (disableAcl) {
// When ACL is disabled, upload is called with null grant
s3Client.upload(EasyMock.anyString(), EasyMock.anyString(),
EasyMock.anyObject(File.class), EasyMock.isNull(Grant.class));
EasyMock.expectLastCall().once();
} else {
- // When ACL is enabled, getBucketAcl is called and a grant is created
- GetBucketAclResponse aclResponse = GetBucketAclResponse.builder()
- .owner(owner)
+ // When ACL is enabled, getBucketOwnerGrant is called and a grant is
created
+ Grant ownerGrant = Grant.builder()
+
.grantee(Grantee.builder().type(Type.CANONICAL_USER).id(ownerId).build())
+ .permission(Permission.FULL_CONTROL)
.build();
- EasyMock.expect(s3Client.getBucketAcl(TEST_BUCKET))
- .andReturn(aclResponse)
+ EasyMock.expect(s3Client.getBucketOwnerGrant(TEST_BUCKET))
+ .andReturn(ownerGrant)
.once();
Capture<Grant> grantCapture = Capture.newInstance(CaptureType.FIRST);
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]