Skip to content

Commit b6da28f

Browse files
HADOOP-19635. ABFS: Marker creation failure should not be propagated (#7825)
Contributed by Anmol Asrani
1 parent 38ec09b commit b6da28f

File tree

2 files changed

+45
-3
lines changed

2 files changed

+45
-3
lines changed

hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsBlobClient.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ public AbfsRestOperation createPath(final String path,
532532
*
533533
* @throws AzureBlobFileSystemException if an error occurs during the operation.
534534
*/
535-
protected AbfsRestOperation createMarkerAtPath(final String path,
535+
public AbfsRestOperation createMarkerAtPath(final String path,
536536
final String eTag,
537537
final ContextEncryptionAdapter contextEncryptionAdapter,
538538
final TracingContext tracingContext) throws AzureBlobFileSystemException {
@@ -1241,8 +1241,16 @@ public AbfsRestOperation getPathStatus(final String path,
12411241
if (op.getResult().getStatusCode() == HTTP_NOT_FOUND
12421242
&& isImplicitCheckRequired && isNonEmptyDirectory(path, tracingContext)) {
12431243
// Implicit path found.
1244-
// Create a marker blob at this path.
1245-
this.createMarkerAtPath(path, null, contextEncryptionAdapter, tracingContext);
1244+
// Create a marker blob at this path. Marker creation might fail due to permission issues, so we swallow exception in case of failure.
1245+
try {
1246+
this.createMarkerAtPath(path, null, contextEncryptionAdapter,
1247+
tracingContext);
1248+
} catch (AbfsRestOperationException exception) {
1249+
LOG.debug("Marker creation failed for path {} during getPathStatus. StatusCode: {}, ErrorCode: {}",
1250+
path,
1251+
exception.getStatusCode(),
1252+
exception.getErrorCode());
1253+
}
12461254
AbfsRestOperation successOp = getSuccessOp(
12471255
AbfsRestOperationType.GetPathStatus, HTTP_METHOD_HEAD,
12481256
url, requestHeaders);

hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/ITestAzureBlobFileSystemOauth.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
import org.junit.Assume;
2626
import org.junit.Test;
27+
import org.mockito.Mockito;
2728
import org.slf4j.Logger;
2829
import org.slf4j.LoggerFactory;
2930

@@ -35,6 +36,8 @@
3536
import org.apache.hadoop.fs.azurebfs.constants.TestConfigurationKeys;
3637
import org.apache.hadoop.fs.azurebfs.contracts.exceptions.AbfsRestOperationException;
3738
import org.apache.hadoop.fs.azurebfs.contracts.services.AzureServiceErrorCode;
39+
import org.apache.hadoop.fs.azurebfs.security.ContextEncryptionAdapter;
40+
import org.apache.hadoop.fs.azurebfs.services.AbfsBlobClient;
3841
import org.apache.hadoop.fs.azurebfs.services.AuthType;
3942
import org.apache.hadoop.fs.azurebfs.utils.TracingContext;
4043
import org.apache.hadoop.io.IOUtils;
@@ -47,6 +50,7 @@
4750
import static org.apache.hadoop.fs.azurebfs.constants.TestConfigurationKeys.FS_AZURE_BLOB_DATA_READER_CLIENT_SECRET;
4851
import static org.apache.hadoop.fs.contract.ContractTestUtils.assertPathDoesNotExist;
4952
import static org.apache.hadoop.fs.contract.ContractTestUtils.assertPathExists;
53+
import static org.assertj.core.api.AssertionsForClassTypes.assertThatCode;
5054

5155
/**
5256
* Test Azure Oauth with Blob Data contributor role and Blob Data Reader role.
@@ -167,6 +171,36 @@ public void testBlobDataReader() throws Exception {
167171

168172
}
169173

174+
/*
175+
* GetPathStatus with Blob Data Reader role should not throw an exception when marker creation fails due to permission issues.
176+
* */
177+
@Test
178+
public void testGetPathStatusWithReader() throws Exception {
179+
String clientId = this.getConfiguration().get(FS_AZURE_BLOB_DATA_READER_CLIENT_ID);
180+
Assume.assumeTrue("Reader client id not provided", clientId != null);
181+
String secret = this.getConfiguration().get(FS_AZURE_BLOB_DATA_READER_CLIENT_SECRET);
182+
Assume.assumeTrue("Reader client secret not provided", secret != null);
183+
184+
Path existedFolderPath = path(EXISTED_FOLDER_PATH);
185+
createAzCopyFolder(existedFolderPath);
186+
final AzureBlobFileSystem fs = Mockito.spy(getBlobReader());
187+
188+
// Use abfsStore in this test to verify the ERROR code in AbfsRestOperationException
189+
AzureBlobFileSystemStore abfsStore = Mockito.spy(fs.getAbfsStore());
190+
Mockito.doReturn(abfsStore).when(fs).getAbfsStore();
191+
AbfsBlobClient abfsClient = Mockito.spy(abfsStore.getClientHandler().getBlobClient());
192+
Mockito.doReturn(abfsClient).when(abfsStore).getClient();
193+
TracingContext tracingContext = getTestTracingContext(fs, true);
194+
195+
// GETPATHSTATUS marker creation fail should not be propagated to the caller.
196+
assertThatCode(() -> abfsStore.getPathStatus(existedFolderPath, tracingContext))
197+
.as("Expected getPathStatus to complete without throwing an exception")
198+
.doesNotThrowAnyException();
199+
Mockito.verify(abfsClient, Mockito.times(1)).createMarkerAtPath(Mockito.anyString(), Mockito.nullable(String.class),
200+
Mockito.nullable(ContextEncryptionAdapter.class),
201+
Mockito.nullable(TracingContext.class));
202+
}
203+
170204
private void prepareFiles(Path existedFilePath, Path existedFolderPath) throws IOException {
171205
// create test files/folders to verify access control diff between
172206
// Blob data contributor and Blob data reader

0 commit comments

Comments
 (0)