This is an automated email from the ASF dual-hosted git repository.
jshao pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git
The following commit(s) were added to refs/heads/main by this push:
new 9f416c789 [#4890] improvement(IT): Add the Integration Tests for
`getFileLocation` interface (#4920)
9f416c789 is described below
commit 9f416c7899f788b30e0bbae314e70866ca2c0f35
Author: xloya <[email protected]>
AuthorDate: Fri Sep 13 12:32:25 2024 +0800
[#4890] improvement(IT): Add the Integration Tests for `getFileLocation`
interface (#4920)
### What changes were proposed in this pull request?
Add the integration Tests for `getFileLocation` interface and fix some
issues.
### Why are the changes needed?
Fix: #4890
### How was this patch tested?
Add some ITs.
---
.../hadoop/integration/test/HadoopCatalogIT.java | 82 ++++++++++++++++++-
.../gravitino/listener/FilesetEventDispatcher.java | 6 +-
.../server/web/rest/FilesetOperations.java | 7 +-
.../server/web/rest/TestFilesetOperations.java | 93 +++++++++++++++++++---
4 files changed, 174 insertions(+), 14 deletions(-)
diff --git
a/catalogs/catalog-hadoop/src/test/java/org/apache/gravitino/catalog/hadoop/integration/test/HadoopCatalogIT.java
b/catalogs/catalog-hadoop/src/test/java/org/apache/gravitino/catalog/hadoop/integration/test/HadoopCatalogIT.java
index 5a49e4033..aa4284eee 100644
---
a/catalogs/catalog-hadoop/src/test/java/org/apache/gravitino/catalog/hadoop/integration/test/HadoopCatalogIT.java
+++
b/catalogs/catalog-hadoop/src/test/java/org/apache/gravitino/catalog/hadoop/integration/test/HadoopCatalogIT.java
@@ -24,12 +24,17 @@ import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
+import java.util.HashMap;
import java.util.Map;
import org.apache.gravitino.Catalog;
import org.apache.gravitino.CatalogChange;
import org.apache.gravitino.NameIdentifier;
import org.apache.gravitino.Namespace;
import org.apache.gravitino.Schema;
+import org.apache.gravitino.audit.CallerContext;
+import org.apache.gravitino.audit.FilesetAuditConstants;
+import org.apache.gravitino.audit.FilesetDataOperation;
+import org.apache.gravitino.audit.InternalClientType;
import org.apache.gravitino.client.GravitinoMetalake;
import org.apache.gravitino.exceptions.FilesetAlreadyExistsException;
import org.apache.gravitino.exceptions.IllegalNameIdentifierException;
@@ -71,7 +76,6 @@ public class HadoopCatalogIT extends AbstractIT {
@BeforeAll
public static void setup() throws IOException {
containerSuite.startHiveContainer();
-
Configuration conf = new Configuration();
conf.set("fs.defaultFS", defaultBaseLocation());
hdfs = FileSystem.get(conf);
@@ -609,6 +613,82 @@ public class HadoopCatalogIT extends AbstractIT {
Assertions.assertFalse(metalake.catalogExists(catalogName), "catalog
should not be exists");
}
+ @Test
+ public void testGetFileLocation() {
+ String filesetName = GravitinoITUtils.genRandomName("fileset");
+ NameIdentifier filesetIdent = NameIdentifier.of(schemaName, filesetName);
+
Assertions.assertFalse(catalog.asFilesetCatalog().filesetExists(filesetIdent));
+ Fileset expectedFileset =
+ catalog
+ .asFilesetCatalog()
+ .createFileset(
+ filesetIdent,
+ "fileset comment",
+ Fileset.Type.MANAGED,
+ generateLocation(filesetName),
+ Maps.newHashMap());
+
Assertions.assertTrue(catalog.asFilesetCatalog().filesetExists(filesetIdent));
+ // test without caller context
+ try {
+ String actualFileLocation =
+ catalog.asFilesetCatalog().getFileLocation(filesetIdent,
"/test1.par");
+
+ Assertions.assertEquals(expectedFileset.storageLocation() +
"/test1.par", actualFileLocation);
+ } finally {
+ CallerContext.CallerContextHolder.remove();
+ }
+
+ // test with caller context
+ try {
+ Map<String, String> context = new HashMap<>();
+ context.put(
+ FilesetAuditConstants.HTTP_HEADER_INTERNAL_CLIENT_TYPE,
+ InternalClientType.HADOOP_GVFS.name());
+ context.put(
+ FilesetAuditConstants.HTTP_HEADER_FILESET_DATA_OPERATION,
+ FilesetDataOperation.CREATE.name());
+ CallerContext callerContext =
CallerContext.builder().withContext(context).build();
+ CallerContext.CallerContextHolder.set(callerContext);
+
+ String actualFileLocation =
+ catalog.asFilesetCatalog().getFileLocation(filesetIdent,
"/test2.par");
+
+ Assertions.assertEquals(expectedFileset.storageLocation() +
"/test2.par", actualFileLocation);
+ } finally {
+ CallerContext.CallerContextHolder.remove();
+ }
+ }
+
+ @Test
+ public void testGetFileLocationWithInvalidAuditHeaders() {
+ try {
+ String filesetName = GravitinoITUtils.genRandomName("fileset");
+ NameIdentifier filesetIdent = NameIdentifier.of(schemaName, filesetName);
+
+ Map<String, String> context = new HashMap<>();
+ // this is an invalid internal client type.
+ context.put(FilesetAuditConstants.HTTP_HEADER_INTERNAL_CLIENT_TYPE,
"test");
+ CallerContext callerContext =
CallerContext.builder().withContext(context).build();
+ CallerContext.CallerContextHolder.set(callerContext);
+
+ Assertions.assertThrows(
+ IllegalArgumentException.class,
+ () -> catalog.asFilesetCatalog().getFileLocation(filesetIdent,
"/test.par"));
+ } finally {
+ CallerContext.CallerContextHolder.remove();
+ }
+ }
+
+ private static String generateLocation(String filesetName) {
+ return String.format(
+ "hdfs://%s:%d/user/hadoop/%s/%s/%s",
+ containerSuite.getHiveContainer().getContainerIpAddress(),
+ HiveContainer.HDFS_DEFAULTFS_PORT,
+ catalogName,
+ schemaName,
+ filesetName);
+ }
+
private Fileset createFileset(
String filesetName,
String comment,
diff --git
a/core/src/main/java/org/apache/gravitino/listener/FilesetEventDispatcher.java
b/core/src/main/java/org/apache/gravitino/listener/FilesetEventDispatcher.java
index fd8e6c370..7b1d2f070 100644
---
a/core/src/main/java/org/apache/gravitino/listener/FilesetEventDispatcher.java
+++
b/core/src/main/java/org/apache/gravitino/listener/FilesetEventDispatcher.java
@@ -149,9 +149,11 @@ public class FilesetEventDispatcher implements
FilesetDispatcher {
try {
String actualFileLocation = dispatcher.getFileLocation(ident, subPath);
// get the audit info from the thread local context
- CallerContext callerContext = CallerContext.CallerContextHolder.get();
ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
- builder.putAll(callerContext.context());
+ CallerContext callerContext = CallerContext.CallerContextHolder.get();
+ if (callerContext != null && callerContext.context() != null) {
+ builder.putAll(callerContext.context());
+ }
eventBus.dispatchEvent(
new GetFileLocationEvent(
PrincipalUtils.getCurrentUserName(),
diff --git
a/server/src/main/java/org/apache/gravitino/server/web/rest/FilesetOperations.java
b/server/src/main/java/org/apache/gravitino/server/web/rest/FilesetOperations.java
index f7838d0ae..8dc22e022 100644
---
a/server/src/main/java/org/apache/gravitino/server/web/rest/FilesetOperations.java
+++
b/server/src/main/java/org/apache/gravitino/server/web/rest/FilesetOperations.java
@@ -52,6 +52,7 @@ import org.apache.gravitino.file.FilesetChange;
import org.apache.gravitino.lock.LockType;
import org.apache.gravitino.lock.TreeLockUtils;
import org.apache.gravitino.metrics.MetricNames;
+import org.apache.gravitino.rest.RESTUtils;
import org.apache.gravitino.server.web.Utils;
import org.apache.gravitino.utils.NameIdentifierUtil;
import org.apache.gravitino.utils.NamespaceUtil;
@@ -268,7 +269,7 @@ public class FilesetOperations {
catalog,
schema,
fileset,
- subPath);
+ RESTUtils.decodeString(subPath));
try {
return Utils.doAs(
httpRequest,
@@ -283,7 +284,9 @@ public class FilesetOperations {
}
String actualFileLocation =
TreeLockUtils.doWithTreeLock(
- ident, LockType.READ, () ->
dispatcher.getFileLocation(ident, subPath));
+ ident,
+ LockType.READ,
+ () -> dispatcher.getFileLocation(ident,
RESTUtils.decodeString(subPath)));
return Utils.ok(new FileLocationResponse(actualFileLocation));
});
} catch (Exception e) {
diff --git
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestFilesetOperations.java
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestFilesetOperations.java
index c1badd3fb..4b5e1f864 100644
---
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestFilesetOperations.java
+++
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestFilesetOperations.java
@@ -28,6 +28,7 @@ import static org.mockito.Mockito.when;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
import java.io.IOException;
import java.time.Instant;
import java.util.Map;
@@ -41,6 +42,10 @@ import org.apache.gravitino.Audit;
import org.apache.gravitino.Config;
import org.apache.gravitino.GravitinoEnv;
import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.audit.CallerContext;
+import org.apache.gravitino.audit.FilesetAuditConstants;
+import org.apache.gravitino.audit.FilesetDataOperation;
+import org.apache.gravitino.audit.InternalClientType;
import org.apache.gravitino.catalog.FilesetDispatcher;
import org.apache.gravitino.catalog.FilesetOperationDispatcher;
import org.apache.gravitino.dto.file.FilesetDTO;
@@ -68,6 +73,7 @@ import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
+import org.mockito.stubbing.Answer;
public class TestFilesetOperations extends JerseyTest {
private static class MockServletRequestFactory extends
ServletRequestFactoryBase {
@@ -435,12 +441,13 @@ public class TestFilesetOperations extends JerseyTest {
@Test
public void testGetFileLocation() {
- String actualPath = "mock location/path1";
-
- when(dispatcher.getFileLocation(any(), any())).thenReturn(actualPath);
+ // Test encoded subPath
+ NameIdentifier fullIdentifier = NameIdentifier.of(metalake, catalog,
schema, "fileset1");
+ String subPath = "/test/1";
+ when(dispatcher.getFileLocation(fullIdentifier,
subPath)).thenReturn(subPath);
Response resp =
target(filesetPath(metalake, catalog, schema) + "fileset1/location")
- .queryParam("sub_path", RESTUtils.encodeString("test/1"))
+ .queryParam("sub_path", RESTUtils.encodeString(subPath))
.request(MediaType.APPLICATION_JSON_TYPE)
.accept("application/vnd.gravitino.v1+json")
.get();
@@ -449,13 +456,15 @@ public class TestFilesetOperations extends JerseyTest {
FileLocationResponse contextResponse =
resp.readEntity(FileLocationResponse.class);
Assertions.assertEquals(0, contextResponse.getCode());
- Assertions.assertEquals(actualPath, contextResponse.getFileLocation());
+ Assertions.assertEquals(subPath, contextResponse.getFileLocation());
// Test throw NoSuchFilesetException
- doThrow(new NoSuchFilesetException("no
found")).when(dispatcher).getFileLocation(any(), any());
+ doThrow(new NoSuchFilesetException("no found"))
+ .when(dispatcher)
+ .getFileLocation(fullIdentifier, subPath);
Response resp1 =
target(filesetPath(metalake, catalog, schema) + "fileset1/location")
- .queryParam("sub_path", RESTUtils.encodeString("test/1"))
+ .queryParam("sub_path", RESTUtils.encodeString(subPath))
.request(MediaType.APPLICATION_JSON_TYPE)
.accept("application/vnd.gravitino.v1+json")
.get();
@@ -466,10 +475,12 @@ public class TestFilesetOperations extends JerseyTest {
Assertions.assertEquals(NoSuchFilesetException.class.getSimpleName(),
errorResp.getType());
// Test throw RuntimeException
- doThrow(new RuntimeException("internal
error")).when(dispatcher).getFileLocation(any(), any());
+ doThrow(new RuntimeException("internal error"))
+ .when(dispatcher)
+ .getFileLocation(fullIdentifier, subPath);
Response resp2 =
target(filesetPath(metalake, catalog, schema) + "fileset1/location")
- .queryParam("sub_path", RESTUtils.encodeString("test/1"))
+ .queryParam("sub_path", RESTUtils.encodeString(subPath))
.request(MediaType.APPLICATION_JSON_TYPE)
.accept("application/vnd.gravitino.v1+json")
.get();
@@ -479,6 +490,70 @@ public class TestFilesetOperations extends JerseyTest {
ErrorResponse errorResp2 = resp2.readEntity(ErrorResponse.class);
Assertions.assertEquals(ErrorConstants.INTERNAL_ERROR_CODE,
errorResp2.getCode());
Assertions.assertEquals(RuntimeException.class.getSimpleName(),
errorResp2.getType());
+
+ // Test not encoded subPath
+ NameIdentifier fullIdentifier1 = NameIdentifier.of(metalake, catalog,
schema, "fileset2");
+ String subPath1 = "/test/2";
+ when(dispatcher.getFileLocation(fullIdentifier1,
subPath1)).thenReturn(subPath1);
+ Response resp3 =
+ target(filesetPath(metalake, catalog, schema) + "fileset2/location")
+ .queryParam("sub_path", subPath1)
+ .request(MediaType.APPLICATION_JSON_TYPE)
+ .accept("application/vnd.gravitino.v1+json")
+ .get();
+ Assertions.assertEquals(Response.Status.OK.getStatusCode(),
resp3.getStatus());
+
+ FileLocationResponse contextResponse1 =
resp3.readEntity(FileLocationResponse.class);
+ Assertions.assertEquals(0, contextResponse1.getCode());
+
+ Assertions.assertEquals(subPath1, contextResponse1.getFileLocation());
+
+ // Test header to caller context
+ try {
+ Map<String, String> callerContextMap = Maps.newHashMap();
+ NameIdentifier fullIdentifier2 = NameIdentifier.of(metalake, catalog,
schema, "fileset3");
+ String subPath2 = "/test/3";
+ when(dispatcher.getFileLocation(fullIdentifier2, subPath2))
+ .thenAnswer(
+ (Answer<String>)
+ invocation -> {
+ try {
+ CallerContext context =
CallerContext.CallerContextHolder.get();
+ callerContextMap.putAll(context.context());
+ return subPath2;
+ } finally {
+ CallerContext.CallerContextHolder.remove();
+ }
+ });
+ Response resp4 =
+ target(filesetPath(metalake, catalog, schema) + "fileset3/location")
+ .queryParam("sub_path", RESTUtils.encodeString(subPath2))
+ .request(MediaType.APPLICATION_JSON_TYPE)
+ .header(
+ FilesetAuditConstants.HTTP_HEADER_INTERNAL_CLIENT_TYPE,
+ InternalClientType.HADOOP_GVFS.name())
+ .header(
+ FilesetAuditConstants.HTTP_HEADER_FILESET_DATA_OPERATION,
+ FilesetDataOperation.CREATE.name())
+ .accept("application/vnd.gravitino.v1+json")
+ .get();
+ Assertions.assertEquals(Response.Status.OK.getStatusCode(),
resp3.getStatus());
+
+ FileLocationResponse contextResponse2 =
resp4.readEntity(FileLocationResponse.class);
+ Assertions.assertEquals(0, contextResponse2.getCode());
+
+ Assertions.assertEquals(subPath2, contextResponse2.getFileLocation());
+
+ Assertions.assertFalse(callerContextMap.isEmpty());
+ Assertions.assertEquals(
+ InternalClientType.HADOOP_GVFS.name(),
+
callerContextMap.get(FilesetAuditConstants.HTTP_HEADER_INTERNAL_CLIENT_TYPE));
+ Assertions.assertEquals(
+ FilesetDataOperation.CREATE.name(),
+
callerContextMap.get(FilesetAuditConstants.HTTP_HEADER_FILESET_DATA_OPERATION));
+ } finally {
+ CallerContext.CallerContextHolder.remove();
+ }
}
private void assertUpdateFileset(FilesetUpdatesRequest req, Fileset
updatedFileset) {