Add export apis back and new apis should be called exportAsync (#18552)

* Add export apis back and new apis should be called exportAsync

* ui: use exportAsync endpoint for export assets

* fix build failure

---------

Co-authored-by: Sachin Chaurasiya <sachinchaurasiyachotey87@gmail.com>
Co-authored-by: sonikashah <sonikashah94@gmail.com>
This commit is contained in:
Sriharsha Chintalapani 2024-11-08 10:35:02 -08:00 committed by GitHub
parent 2f39b76c33
commit 7f5f47f618
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 214 additions and 26 deletions

View File

@ -382,8 +382,7 @@ public abstract class EntityResource<T extends EntityInterface, K extends Entity
return response.toResponse();
}
public Response exportCsvInternal(SecurityContext securityContext, String name)
throws IOException {
public Response exportCsvInternalAsync(SecurityContext securityContext, String name) {
OperationContext operationContext =
new OperationContext(entityType, MetadataOperation.VIEW_ALL);
authorizer.authorize(securityContext, operationContext, getResourceContextByName(name));
@ -405,6 +404,13 @@ public abstract class EntityResource<T extends EntityInterface, K extends Entity
return Response.accepted().entity(response).type(MediaType.APPLICATION_JSON).build();
}
public String exportCsvInternal(SecurityContext securityContext, String name) throws IOException {
OperationContext operationContext =
new OperationContext(entityType, MetadataOperation.VIEW_ALL);
authorizer.authorize(securityContext, operationContext, getResourceContextByName(name));
return repository.exportToCsv(name, securityContext.getUserPrincipal().getName());
}
protected CsvImportResult importCsvInternal(
SecurityContext securityContext, String name, String csv, boolean dryRun) throws IOException {
OperationContext operationContext =

View File

@ -423,7 +423,7 @@ public class DatabaseResource extends EntityResource<Database, DatabaseRepositor
}
@GET
@Path("/name/{name}/export")
@Path("/name/{name}/exportAsync")
@Produces(MediaType.APPLICATION_JSON)
@Valid
@Operation(
@ -438,7 +438,31 @@ public class DatabaseResource extends EntityResource<Database, DatabaseRepositor
mediaType = "application/json",
schema = @Schema(implementation = CSVExportResponse.class)))
})
public Response exportCsv(
public Response exportCsvAsync(
@Context SecurityContext securityContext,
@Parameter(description = "Name of the Database", schema = @Schema(type = "string"))
@PathParam("name")
String name) {
return exportCsvInternalAsync(securityContext, name);
}
@GET
@Path("/name/{name}/export")
@Produces(MediaType.TEXT_PLAIN)
@Valid
@Operation(
operationId = "exportDatabase",
summary = "Export database in CSV format",
responses = {
@ApiResponse(
responseCode = "200",
description = "Exported csv with database schemas",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = String.class)))
})
public String exportCsv(
@Context SecurityContext securityContext,
@Parameter(description = "Name of the Database", schema = @Schema(type = "string"))
@PathParam("name")

View File

@ -395,7 +395,7 @@ public class DatabaseSchemaResource
}
@GET
@Path("/name/{name}/export")
@Path("/name/{name}/exportAsync")
@Produces(MediaType.APPLICATION_JSON)
@Valid
@Operation(
@ -410,7 +410,31 @@ public class DatabaseSchemaResource
mediaType = "application/json",
schema = @Schema(implementation = CSVExportResponse.class)))
})
public Response exportCsv(
public Response exportCsvAsync(
@Context SecurityContext securityContext,
@Parameter(description = "Name of the Database schema", schema = @Schema(type = "string"))
@PathParam("name")
String name) {
return exportCsvInternalAsync(securityContext, name);
}
@GET
@Path("/name/{name}/export")
@Produces(MediaType.TEXT_PLAIN)
@Valid
@Operation(
operationId = "exportDatabaseSchema",
summary = "Export database schema in CSV format",
responses = {
@ApiResponse(
responseCode = "200",
description = "Exported csv with tables from the database schema",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = String.class)))
})
public String exportCsv(
@Context SecurityContext securityContext,
@Parameter(description = "Name of the Database schema", schema = @Schema(type = "string"))
@PathParam("name")

View File

@ -452,6 +452,30 @@ public class TableResource extends EntityResource<Table, TableRepository> {
return patchInternal(uriInfo, securityContext, fqn, patch);
}
@GET
@Path("/name/{name}/exportAsync")
@Produces(MediaType.TEXT_PLAIN)
@Valid
@Operation(
operationId = "exportTable",
summary = "Export table in CSV format",
responses = {
@ApiResponse(
responseCode = "200",
description = "Exported csv with columns from the table",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = String.class)))
})
public Response exportCsvAsync(
@Context SecurityContext securityContext,
@Parameter(description = "Name of the table", schema = @Schema(type = "string"))
@PathParam("name")
String name) {
return exportCsvInternalAsync(securityContext, name);
}
@GET
@Path("/name/{name}/export")
@Produces(MediaType.TEXT_PLAIN)
@ -468,7 +492,7 @@ public class TableResource extends EntityResource<Table, TableRepository> {
mediaType = "application/json",
schema = @Schema(implementation = String.class)))
})
public Response exportCsv(
public String exportCsv(
@Context SecurityContext securityContext,
@Parameter(description = "Name of the table", schema = @Schema(type = "string"))
@PathParam("name")

View File

@ -492,12 +492,32 @@ public class GlossaryResource extends EntityResource<Glossary, GlossaryRepositor
@Path("/documentation/csv")
@Valid
@Operation(operationId = "getCsvDocumentation", summary = "Get CSV documentation")
public String getCsvDocumentation(
public String getCsvDocumentation(@Context SecurityContext securityContext) {
return JsonUtils.pojoToJson(GlossaryCsv.DOCUMENTATION);
}
@GET
@Path("/name/{name}/exportAsync")
@Produces(MediaType.TEXT_PLAIN)
@Valid
@Operation(
operationId = "exportGlossary",
summary = "Export glossary in CSV format",
responses = {
@ApiResponse(
responseCode = "200",
description = "Exported csv with glossary terms",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = CSVExportResponse.class)))
})
public Response exportCsvAsync(
@Context SecurityContext securityContext,
@Parameter(description = "Name of the glossary", schema = @Schema(type = "string"))
@PathParam("name")
String name) {
return JsonUtils.pojoToJson(GlossaryCsv.DOCUMENTATION);
return exportCsvInternalAsync(securityContext, name);
}
@GET
@ -514,9 +534,9 @@ public class GlossaryResource extends EntityResource<Glossary, GlossaryRepositor
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = CSVExportResponse.class)))
schema = @Schema(implementation = String.class)))
})
public Response exportCsv(
public String exportCsv(
@Context SecurityContext securityContext,
@Parameter(description = "Name of the glossary", schema = @Schema(type = "string"))
@PathParam("name")

View File

@ -64,6 +64,7 @@ import org.openmetadata.service.resources.Collection;
import org.openmetadata.service.resources.services.ServiceEntityResource;
import org.openmetadata.service.security.Authorizer;
import org.openmetadata.service.security.policyevaluator.OperationContext;
import org.openmetadata.service.util.CSVExportResponse;
import org.openmetadata.service.util.JsonUtils;
import org.openmetadata.service.util.ResultList;
@ -456,7 +457,7 @@ public class DatabaseServiceResource
mediaType = "application/json",
schema = @Schema(implementation = String.class)))
})
public Response exportCsv(
public String exportCsv(
@Context SecurityContext securityContext,
@Parameter(description = "Name of the Database Service", schema = @Schema(type = "string"))
@PathParam("name")
@ -465,6 +466,30 @@ public class DatabaseServiceResource
return exportCsvInternal(securityContext, name);
}
@GET
@Path("/name/{name}/exportAsync")
@Produces(MediaType.APPLICATION_JSON)
@Valid
@Operation(
operationId = "exportDatabaseService",
summary = "Export database service in CSV format",
responses = {
@ApiResponse(
responseCode = "200",
description = "Exported csv with database schemas",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = CSVExportResponse.class)))
})
public Response exportCsvAsync(
@Context SecurityContext securityContext,
@Parameter(description = "Name of the Database", schema = @Schema(type = "string"))
@PathParam("name")
String name) {
return exportCsvInternalAsync(securityContext, name);
}
@PUT
@Path("/name/{name}/import")
@Consumes(MediaType.TEXT_PLAIN)

View File

@ -594,7 +594,7 @@ public class TeamResource extends EntityResource<Team, TeamRepository> {
}
@GET
@Path("/name/{name}/export")
@Path("/name/{name}/exportAsync")
@Produces(MediaType.TEXT_PLAIN)
@Valid
@Operation(
@ -609,8 +609,29 @@ public class TeamResource extends EntityResource<Team, TeamRepository> {
mediaType = "application/json",
schema = @Schema(implementation = CSVExportResponse.class)))
})
public Response exportCsv(
public Response exportCsvAsync(
@Context SecurityContext securityContext, @PathParam("name") String name) throws IOException {
return exportCsvInternalAsync(securityContext, name);
}
@GET
@Path("/name/{name}/export")
@Produces(MediaType.TEXT_PLAIN)
@Valid
@Operation(
operationId = "exportTeams",
summary = "Export teams in CSV format",
responses = {
@ApiResponse(
responseCode = "200",
description = "Exported csv with teams information",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = String.class)))
})
public String exportCsv(@Context SecurityContext securityContext, @PathParam("name") String name)
throws IOException {
return exportCsvInternal(securityContext, name);
}

View File

@ -1392,8 +1392,8 @@ public class UserResource extends EntityResource<User, UserRepository> {
}
@GET
@Path("/export")
@Produces(MediaType.TEXT_PLAIN)
@Path("/exportAsync")
@Produces(MediaType.APPLICATION_JSON)
@Valid
@Operation(
operationId = "exportUsers",
@ -1407,7 +1407,34 @@ public class UserResource extends EntityResource<User, UserRepository> {
mediaType = "application/json",
schema = @Schema(implementation = CSVExportResponse.class)))
})
public Response exportUsersCsv(
public Response exportUsersCsvAsync(
@Context SecurityContext securityContext,
@Parameter(
description = "Name of the team to under which the users are imported to",
required = true,
schema = @Schema(type = "string"))
@QueryParam("team")
String team) {
return exportCsvInternalAsync(securityContext, team);
}
@GET
@Path("/export")
@Produces(MediaType.TEXT_PLAIN)
@Valid
@Operation(
operationId = "exportUsers",
summary = "Export users in a team in CSV format",
responses = {
@ApiResponse(
responseCode = "200",
description = "Exported csv with user information",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = String.class)))
})
public String exportUsersCsv(
@Context SecurityContext securityContext,
@Parameter(
description = "Name of the team to under which the users are imported to",

View File

@ -3972,6 +3972,11 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
return TestUtils.putCsv(target, csv, CsvImportResult.class, Status.OK, ADMIN_AUTH_HEADERS);
}
protected String exportCsv(String entityName) throws HttpResponseException {
WebTarget target = getResourceByName(entityName + "/export");
return TestUtils.get(target, String.class, ADMIN_AUTH_HEADERS);
}
private String receiveCsvViaSocketIO(String entityName) throws Exception {
UUID userId = getAdminUserId();
String uri = String.format("http://localhost:%d", APP.getLocalPort());
@ -4052,7 +4057,7 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
}
protected String initiateExport(String entityName) throws IOException {
WebTarget target = getResourceByName(entityName + "/export");
WebTarget target = getResourceByName(entityName + "/exportAsync");
CSVExportResponse response =
TestUtils.getWithResponse(
target, CSVExportResponse.class, ADMIN_AUTH_HEADERS, Status.ACCEPTED.getStatusCode());
@ -4088,8 +4093,10 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
assertEquals(dryRunResult.withDryRun(false), result);
// Finally, export CSV and ensure the exported CSV is same as imported CSV
String exportedCsv = receiveCsvViaSocketIO(entityName);
CsvUtilTest.assertCsv(csv, exportedCsv);
String exportedCsvAsync = receiveCsvViaSocketIO(entityName);
CsvUtilTest.assertCsv(csv, exportedCsvAsync);
String exportedCsvSync = exportCsv(entityName);
CsvUtilTest.assertCsv(csv, exportedCsvSync);
}
protected void testImportExport(

View File

@ -1561,9 +1561,16 @@ public class UserResourceTest extends EntityResourceTest<User, CreateUser> {
}
@Override
protected String initiateExport(String teamName) throws HttpResponseException {
protected String exportCsv(String teamName) throws HttpResponseException {
WebTarget target = getCollection().path("/export");
target = target.queryParam("team", teamName);
return TestUtils.get(target, String.class, ADMIN_AUTH_HEADERS);
}
@Override
protected String initiateExport(String teamName) throws HttpResponseException {
WebTarget target = getCollection().path("/exportAsync");
target = target.queryParam("team", teamName);
CSVExportResponse response =
TestUtils.getWithResponse(
target, CSVExportResponse.class, ADMIN_AUTH_HEADERS, Status.ACCEPTED.getStatusCode());

View File

@ -174,7 +174,7 @@ export const deleteGlossaryTerm = (id: string) => {
export const exportGlossaryInCSVFormat = async (glossaryName: string) => {
const response = await APIClient.get<CSVExportResponse>(
`/glossaries/name/${getEncodedFqn(glossaryName)}/export`
`/glossaries/name/${getEncodedFqn(glossaryName)}/exportAsync`
);
return response.data;

View File

@ -92,16 +92,19 @@ export const restoreTeam = async (id: string) => {
export const exportTeam = async (teamName: string) => {
const response = await APIClient.get<CSVExportResponse>(
`/teams/name/${getEncodedFqn(teamName)}/export`
`/teams/name/${getEncodedFqn(teamName)}/exportAsync`
);
return response.data;
};
export const exportUserOfTeam = async (team: string) => {
const response = await APIClient.get<CSVExportResponse>(`/users/export`, {
params: { team },
});
const response = await APIClient.get<CSVExportResponse>(
`/users/exportAsync`,
{
params: { team },
}
);
return response.data;
};