Skip to content

Commit

Permalink
HDDS-11833. Return NotImplemented for S3 put-object-acl request. (apa…
Browse files Browse the repository at this point in the history
  • Loading branch information
ivandika3 authored Dec 5, 2024
1 parent e8ad7ad commit fc63710
Show file tree
Hide file tree
Showing 18 changed files with 164 additions and 85 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ private CompleteMultipartUploadRequest.Part uploadPart(String uploadID,
ByteArrayInputStream body =
new ByteArrayInputStream(content.getBytes(UTF_8));
Response response = REST.put(BUCKET, KEY, content.length(),
partNumber, uploadID, null, body);
partNumber, uploadID, null, null, body);
assertEquals(200, response.getStatus());
assertNotNull(response.getHeaderString(OzoneConsts.ETAG));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.services.s3.model.S3ObjectInputStream;
import com.amazonaws.services.s3.model.S3ObjectSummary;
import com.amazonaws.services.s3.model.SetObjectAclRequest;
import com.amazonaws.services.s3.model.Tag;
import com.amazonaws.services.s3.model.UploadPartRequest;
import com.amazonaws.services.s3.model.UploadPartResult;
Expand Down Expand Up @@ -375,6 +376,50 @@ public void testPutObjectEmpty() {
assertEquals("d41d8cd98f00b204e9800998ecf8427e", putObjectResult.getETag());
}

@Test
public void testPutObjectACL() throws Exception {
final String bucketName = getBucketName();
final String keyName = getKeyName();
final String content = "bar";
final byte[] contentBytes = content.getBytes(StandardCharsets.UTF_8);
s3Client.createBucket(bucketName);

InputStream is = new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8));

PutObjectResult putObjectResult = s3Client.putObject(bucketName, keyName, is, new ObjectMetadata());
String originalObjectETag = putObjectResult.getETag();
assertTrue(s3Client.doesObjectExist(bucketName, keyName));

AccessControlList aclList = new AccessControlList();
Owner owner = new Owner("owner", "owner");
aclList.withOwner(owner);
Grantee grantee = new CanonicalGrantee("testGrantee");
aclList.grantPermission(grantee, Permission.Read);

SetObjectAclRequest setObjectAclRequest = new SetObjectAclRequest(bucketName, keyName, aclList);

AmazonServiceException ase = assertThrows(AmazonServiceException.class,
() -> s3Client.setObjectAcl(setObjectAclRequest));
assertEquals("NotImplemented", ase.getErrorCode());
assertEquals(501, ase.getStatusCode());
assertEquals(ErrorType.Service, ase.getErrorType());

// Ensure that the object content remains unchanged
ObjectMetadata updatedObjectMetadata = s3Client.getObjectMetadata(bucketName, keyName);
assertEquals(originalObjectETag, updatedObjectMetadata.getETag());
S3Object updatedObject = s3Client.getObject(bucketName, keyName);

try (S3ObjectInputStream s3is = updatedObject.getObjectContent();
ByteArrayOutputStream bos = new ByteArrayOutputStream(contentBytes.length)) {
byte[] readBuf = new byte[1024];
int readLen = 0;
while ((readLen = s3is.read(readBuf)) > 0) {
bos.write(readBuf, 0, readLen);
}
assertEquals(content, bos.toString("UTF-8"));
}
}

@Test
public void testGetObject() throws Exception {
final String bucketName = getBucketName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ public enum S3GAction implements AuditAction {
REVOKE_SECRET,
GET_OBJECT_TAGGING,
PUT_OBJECT_TAGGING,
DELETE_OBJECT_TAGGING;
DELETE_OBJECT_TAGGING,
PUT_OBJECT_ACL;

@Override
public String getAction() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@
import static org.apache.hadoop.ozone.s3.exception.S3ErrorTable.ENTITY_TOO_SMALL;
import static org.apache.hadoop.ozone.s3.exception.S3ErrorTable.INVALID_ARGUMENT;
import static org.apache.hadoop.ozone.s3.exception.S3ErrorTable.INVALID_REQUEST;
import static org.apache.hadoop.ozone.s3.exception.S3ErrorTable.NOT_IMPLEMENTED;
import static org.apache.hadoop.ozone.s3.exception.S3ErrorTable.NO_SUCH_UPLOAD;
import static org.apache.hadoop.ozone.s3.exception.S3ErrorTable.PRECOND_FAILED;
import static org.apache.hadoop.ozone.s3.exception.S3ErrorTable.newError;
Expand Down Expand Up @@ -222,6 +223,7 @@ public Response put(
@QueryParam("partNumber") int partNumber,
@QueryParam("uploadId") @DefaultValue("") String uploadID,
@QueryParam("tagging") String taggingMarker,
@QueryParam("acl") String aclMarker,
final InputStream body) throws IOException, OS3Exception {
long startNanos = Time.monotonicNowNanos();
S3GAction s3GAction = S3GAction.CREATE_KEY;
Expand All @@ -231,6 +233,10 @@ public Response put(
String copyHeader = null, storageType = null;
DigestInputStream digestInputStream = null;
try {
if (aclMarker != null) {
s3GAction = S3GAction.PUT_OBJECT_ACL;
throw newError(NOT_IMPLEMENTED, keyPath);
}
OzoneVolume volume = getVolume();
if (taggingMarker != null) {
s3GAction = S3GAction.PUT_OBJECT_TAGGING;
Expand Down Expand Up @@ -369,7 +375,9 @@ public Response put(
} catch (Exception ex) {
auditSuccess = false;
auditWriteFailure(s3GAction, ex);
if (taggingMarker != null) {
if (aclMarker != null) {
getMetrics().updatePutObjectAclFailureStats(startNanos);
} else if (taggingMarker != null) {
getMetrics().updatePutObjectTaggingFailureStats(startNanos);
} else if (copyHeader != null) {
getMetrics().updateCopyObjectFailureStats(startNanos);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ public final class S3GatewayMetrics implements Closeable, MetricsSource {
private @Metric MutableCounterLong putObjectTaggingFailure;
private @Metric MutableCounterLong deleteObjectTaggingSuccess;
private @Metric MutableCounterLong deleteObjectTaggingFailure;
private @Metric MutableCounterLong putObjectAclSuccess;
private @Metric MutableCounterLong putObjectAclFailure;

// S3 Gateway Latency Metrics
// BucketEndpoint
Expand Down Expand Up @@ -270,6 +272,14 @@ public final class S3GatewayMetrics implements Closeable, MetricsSource {
@Metric(about = "Latency for failing to delete object tagging of a key in nanoseconds")
private PerformanceMetrics deleteObjectTaggingFailureLatencyNs;

@Metric(about = "Latency for successfully setting an S3 object ACL " +
"in nanoseconds")
private PerformanceMetrics putObjectAclSuccessLatencyNs;

@Metric(about = "Latency for failing to set an S3 object ACL " +
"in nanoseconds")
private PerformanceMetrics putObjectAclFailureLatencyNs;

private final Map<String, PerformanceMetrics> performanceMetrics;

/**
Expand Down Expand Up @@ -411,6 +421,8 @@ public void getMetrics(MetricsCollector collector, boolean all) {
deleteObjectTaggingSuccessLatencyNs.snapshot(recordBuilder, true);
deleteObjectTaggingFailure.snapshot(recordBuilder, true);
deleteObjectTaggingFailureLatencyNs.snapshot(recordBuilder, true);
putObjectAclSuccess.snapshot(recordBuilder, true);
putObjectAclFailure.snapshot(recordBuilder, true);
}

// INC and UPDATE
Expand Down Expand Up @@ -662,6 +674,16 @@ public void updateDeleteObjectTaggingFailureStats(long startNanos) {
this.deleteObjectTaggingFailureLatencyNs.add(Time.monotonicNowNanos() - startNanos);
}

public void updatePutObjectAclSuccessStats(long startNanos) {
this.putObjectAclSuccess.incr();
this.putObjectAclSuccessLatencyNs.add(Time.monotonicNowNanos() - startNanos);
}

public void updatePutObjectAclFailureStats(long startNanos) {
this.putObjectAclFailure.incr();
this.putObjectAclFailureLatencyNs.add(Time.monotonicNowNanos() - startNanos);
}

// GET
public long getListS3BucketsSuccess() {
return listS3BucketsSuccess.value();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,17 +77,17 @@ public static void setUp() throws Exception {
ByteArrayInputStream body =
new ByteArrayInputStream(content.getBytes(UTF_8));
response = REST.put(OzoneConsts.S3_BUCKET, OzoneConsts.KEY,
content.length(), 1, uploadID, null, body);
content.length(), 1, uploadID, null, null, body);

assertNotNull(response.getHeaderString(OzoneConsts.ETAG));

response = REST.put(OzoneConsts.S3_BUCKET, OzoneConsts.KEY,
content.length(), 2, uploadID, null, body);
content.length(), 2, uploadID, null, null, body);

assertNotNull(response.getHeaderString(OzoneConsts.ETAG));

response = REST.put(OzoneConsts.S3_BUCKET, OzoneConsts.KEY,
content.length(), 3, uploadID, null, body);
content.length(), 3, uploadID, null, null, body);

assertNotNull(response.getHeaderString(OzoneConsts.ETAG));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ private Part uploadPart(String key, String uploadID, int partNumber, String
ByteArrayInputStream body =
new ByteArrayInputStream(content.getBytes(UTF_8));
Response response = REST.put(OzoneConsts.S3_BUCKET, key, content.length(),
partNumber, uploadID, null, body);
partNumber, uploadID, null, null, body);
assertEquals(200, response.getStatus());
assertNotNull(response.getHeaderString(OzoneConsts.ETAG));
Part part = new Part();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ private Part uploadPart(String key, String uploadID, int partNumber, String
ByteArrayInputStream body =
new ByteArrayInputStream(content.getBytes(UTF_8));
Response response = REST.put(OzoneConsts.S3_BUCKET, key, content.length(),
partNumber, uploadID, null, body);
partNumber, uploadID, null, null, body);
assertEquals(200, response.getStatus());
assertNotNull(response.getHeaderString(OzoneConsts.ETAG));
Part part = new Part();
Expand Down Expand Up @@ -375,7 +375,7 @@ private Part uploadPartWithCopy(String key, String uploadID, int partNumber,

ByteArrayInputStream body = new ByteArrayInputStream("".getBytes(UTF_8));
Response response = REST.put(OzoneConsts.S3_BUCKET, key, 0, partNumber,
uploadID, null, body);
uploadID, null, null, body);
assertEquals(200, response.getStatus());

CopyPartResult result = (CopyPartResult) response.getEntity();
Expand All @@ -402,7 +402,7 @@ public void testUploadWithRangeCopyContentLength()
OzoneConsts.S3_BUCKET + "/" + EXISTING_KEY);
additionalHeaders.put(COPY_SOURCE_HEADER_RANGE, "bytes=0-3");
setHeaders(additionalHeaders);
REST.put(OzoneConsts.S3_BUCKET, KEY, 0, 1, uploadID, null, body);
REST.put(OzoneConsts.S3_BUCKET, KEY, 0, 1, uploadID, null, null, body);
OzoneMultipartUploadPartListParts parts =
CLIENT.getObjectStore().getS3Bucket(OzoneConsts.S3_BUCKET)
.listParts(KEY, uploadID, 0, 100);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,11 @@ public void init() throws OS3Exception, IOException {

ByteArrayInputStream body = new ByteArrayInputStream(CONTENT.getBytes(UTF_8));
rest.put(BUCKET_NAME, KEY_NAME, CONTENT.length(),
1, null, null, body);
1, null, null, null, body);
// Create a key with object tags
when(headers.getHeaderString(TAG_HEADER)).thenReturn("tag1=value1&tag2=value2");
rest.put(BUCKET_NAME, KEY_WITH_TAG, CONTENT.length(),
1, null, null, body);
1, null, null, null, body);

context = mock(ContainerRequestContext.class);
when(context.getUriInfo()).thenReturn(mock(UriInfo.class));
Expand Down
Loading

0 comments on commit fc63710

Please sign in to comment.