Add Bulk Assets for Domain , Data product and Team (#14222)

* Add Bulk Assets for Domain , Data product and Team

* repetitive code
This commit is contained in:
Mohit Yadav 2023-12-04 19:06:16 +05:30 committed by GitHub
parent 20cf8f63ab
commit 0ae2baa9f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 245 additions and 0 deletions

View File

@ -29,6 +29,8 @@ import org.openmetadata.schema.entity.domains.DataProduct;
import org.openmetadata.schema.type.EntityReference;
import org.openmetadata.schema.type.Include;
import org.openmetadata.schema.type.Relationship;
import org.openmetadata.schema.type.api.BulkAssets;
import org.openmetadata.schema.type.api.BulkOperationResult;
import org.openmetadata.service.Entity;
import org.openmetadata.service.resources.domains.DataProductResource;
import org.openmetadata.service.util.EntityUtil;
@ -90,6 +92,16 @@ public class DataProductRepository extends EntityRepository<DataProduct> {
return new DataProductUpdater(original, updated, operation);
}
public BulkOperationResult bulkAddAssets(String domainName, BulkAssets request) {
DataProduct dataProduct = getByName(null, domainName, getFields("id"));
return bulkAssetsOperation(dataProduct.getId(), DATA_PRODUCT, Relationship.HAS, request, true);
}
public BulkOperationResult bulkRemoveAssets(String domainName, BulkAssets request) {
DataProduct dataProduct = getByName(null, domainName, getFields("id"));
return bulkAssetsOperation(dataProduct.getId(), DATA_PRODUCT, Relationship.HAS, request, false);
}
@Override
public void restorePatchAttributes(DataProduct original, DataProduct updated) {
super.restorePatchAttributes(original, updated);

View File

@ -24,6 +24,8 @@ import org.openmetadata.schema.entity.domains.Domain;
import org.openmetadata.schema.type.EntityReference;
import org.openmetadata.schema.type.Include;
import org.openmetadata.schema.type.Relationship;
import org.openmetadata.schema.type.api.BulkAssets;
import org.openmetadata.schema.type.api.BulkOperationResult;
import org.openmetadata.service.Entity;
import org.openmetadata.service.resources.domains.DomainResource;
import org.openmetadata.service.util.EntityUtil.Fields;
@ -89,6 +91,16 @@ public class DomainRepository extends EntityRepository<Domain> {
return domain;
}
public BulkOperationResult bulkAddAssets(String domainName, BulkAssets request) {
Domain domain = getByName(null, domainName, getFields("id"));
return bulkAssetsOperation(domain.getId(), DOMAIN, Relationship.HAS, request, true);
}
public BulkOperationResult bulkRemoveAssets(String domainName, BulkAssets request) {
Domain domain = getByName(null, domainName, getFields("id"));
return bulkAssetsOperation(domain.getId(), DOMAIN, Relationship.HAS, request, false);
}
@Override
public EntityUpdater getUpdater(Domain original, Domain updated, Operation operation) {
return new DomainUpdater(original, updated, operation);

View File

@ -105,6 +105,7 @@ import org.openmetadata.schema.api.teams.CreateTeam;
import org.openmetadata.schema.entity.data.Table;
import org.openmetadata.schema.entity.teams.Team;
import org.openmetadata.schema.entity.teams.User;
import org.openmetadata.schema.type.ApiStatus;
import org.openmetadata.schema.type.ChangeDescription;
import org.openmetadata.schema.type.ChangeEvent;
import org.openmetadata.schema.type.Column;
@ -119,6 +120,8 @@ import org.openmetadata.schema.type.TagLabel;
import org.openmetadata.schema.type.TaskType;
import org.openmetadata.schema.type.ThreadType;
import org.openmetadata.schema.type.Votes;
import org.openmetadata.schema.type.api.BulkAssets;
import org.openmetadata.schema.type.api.BulkOperationResult;
import org.openmetadata.schema.type.csv.CsvImportResult;
import org.openmetadata.schema.utils.EntityInterfaceUtil;
import org.openmetadata.service.Entity;
@ -1630,6 +1633,34 @@ public abstract class EntityRepository<T extends EntityInterface> {
}
}
protected BulkOperationResult bulkAssetsOperation(
UUID entityId, String fromEntity, Relationship relationship, BulkAssets request, boolean isAdd) {
BulkOperationResult result = new BulkOperationResult().withStatus(ApiStatus.SUCCESS).withDryRun(false);
List<EntityReference> success = new ArrayList<>();
// Validate Assets
EntityUtil.populateEntityReferences(request.getAssets());
for (EntityReference ref : request.getAssets()) {
// Update Result Processed
result.setNumberOfRowsProcessed(result.getNumberOfRowsProcessed() + 1);
if (isAdd) {
addRelationship(entityId, ref.getId(), fromEntity, ref.getType(), relationship);
} else {
deleteRelationship(entityId, fromEntity, ref.getId(), ref.getType(), relationship);
}
success.add(ref);
result.setNumberOfRowsPassed(result.getNumberOfRowsPassed() + 1);
// Update ES
searchRepository.updateEntity(ref);
}
result.withSuccessRequest(success);
return result;
}
/** Remove owner relationship for a given entity */
@Transaction
private void removeOwner(T entity, EntityReference owner) {

View File

@ -48,6 +48,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
@ -63,6 +64,8 @@ import org.openmetadata.schema.entity.teams.TeamHierarchy;
import org.openmetadata.schema.type.EntityReference;
import org.openmetadata.schema.type.Include;
import org.openmetadata.schema.type.Relationship;
import org.openmetadata.schema.type.api.BulkAssets;
import org.openmetadata.schema.type.api.BulkOperationResult;
import org.openmetadata.schema.type.csv.CsvDocumentation;
import org.openmetadata.schema.type.csv.CsvErrorType;
import org.openmetadata.schema.type.csv.CsvHeader;
@ -137,6 +140,38 @@ public class TeamRepository extends EntityRepository<Team> {
validatePolicies(team.getPolicies());
}
public BulkOperationResult bulkAddAssets(String domainName, BulkAssets request) {
Team team = getByName(null, domainName, getFields("id"));
// Validate all to be users
validateAllRefUsers(request.getAssets());
for (EntityReference asset : request.getAssets()) {
if (!Objects.equals(asset.getType(), Entity.USER)) {
throw new IllegalArgumentException("Only users can be added to a Team");
}
}
return bulkAssetsOperation(team.getId(), TEAM, Relationship.HAS, request, true);
}
public BulkOperationResult bulkRemoveAssets(String domainName, BulkAssets request) {
Team team = getByName(null, domainName, getFields("id"));
// Validate all to be users
validateAllRefUsers(request.getAssets());
return bulkAssetsOperation(team.getId(), TEAM, Relationship.HAS, request, false);
}
private void validateAllRefUsers(List<EntityReference> refs) {
for (EntityReference asset : refs) {
if (!Objects.equals(asset.getType(), Entity.USER)) {
throw new IllegalArgumentException("Only users can be added to a Team");
}
}
}
@Override
public void storeEntity(Team team, boolean update) {
// Relationships and fields such as href are derived and not stored as part of json

View File

@ -51,9 +51,12 @@ import javax.ws.rs.core.UriInfo;
import lombok.extern.slf4j.Slf4j;
import org.openmetadata.schema.api.domains.CreateDataProduct;
import org.openmetadata.schema.entity.domains.DataProduct;
import org.openmetadata.schema.type.ChangeEvent;
import org.openmetadata.schema.type.EntityHistory;
import org.openmetadata.schema.type.EntityReference;
import org.openmetadata.schema.type.Include;
import org.openmetadata.schema.type.api.BulkAssets;
import org.openmetadata.schema.type.api.BulkOperationResult;
import org.openmetadata.service.Entity;
import org.openmetadata.service.jdbi3.DataProductRepository;
import org.openmetadata.service.jdbi3.ListFilter;
@ -269,6 +272,51 @@ public class DataProductResource extends EntityResource<DataProduct, DataProduct
return createOrUpdate(uriInfo, securityContext, dataProduct);
}
@PUT
@Path("/{name}/assets/add")
@Operation(
operationId = "bulkAddAssets",
summary = "Bulk Add Assets",
description = "Bulk Add Assets",
responses = {
@ApiResponse(
responseCode = "200",
description = "OK",
content =
@Content(mediaType = "application/json", schema = @Schema(implementation = BulkOperationResult.class))),
@ApiResponse(responseCode = "404", description = "model for instance {id} is not found")
})
public Response bulkAddAssets(
@Context UriInfo uriInfo,
@Context SecurityContext securityContext,
@Parameter(description = "Name of the Data product", schema = @Schema(type = "string")) @PathParam("name")
String name,
@Valid BulkAssets request) {
return Response.ok().entity(repository.bulkAddAssets(name, request)).build();
}
@PUT
@Path("/{name}/assets/remove")
@Operation(
operationId = "bulkRemoveAssets",
summary = "Bulk Remove Assets",
description = "Bulk Remove Assets",
responses = {
@ApiResponse(
responseCode = "200",
description = "OK",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ChangeEvent.class))),
@ApiResponse(responseCode = "404", description = "model for instance {id} is not found")
})
public Response bulkRemoveGlossaryFromAssets(
@Context UriInfo uriInfo,
@Context SecurityContext securityContext,
@Parameter(description = "Name of the Data Product", schema = @Schema(type = "string")) @PathParam("name")
String name,
@Valid BulkAssets request) {
return Response.ok().entity(repository.bulkRemoveAssets(name, request)).build();
}
@PATCH
@Path("/{id}")
@Operation(

View File

@ -47,8 +47,11 @@ import javax.ws.rs.core.UriInfo;
import lombok.extern.slf4j.Slf4j;
import org.openmetadata.schema.api.domains.CreateDomain;
import org.openmetadata.schema.entity.domains.Domain;
import org.openmetadata.schema.type.ChangeEvent;
import org.openmetadata.schema.type.EntityHistory;
import org.openmetadata.schema.type.Include;
import org.openmetadata.schema.type.api.BulkAssets;
import org.openmetadata.schema.type.api.BulkOperationResult;
import org.openmetadata.service.Entity;
import org.openmetadata.service.jdbi3.DomainRepository;
import org.openmetadata.service.jdbi3.ListFilter;
@ -248,6 +251,49 @@ public class DomainResource extends EntityResource<Domain, DomainRepository> {
return createOrUpdate(uriInfo, securityContext, domain);
}
@PUT
@Path("/{name}/assets/add")
@Operation(
operationId = "bulkAddAssets",
summary = "Bulk Add Assets",
description = "Bulk Add Assets",
responses = {
@ApiResponse(
responseCode = "200",
description = "OK",
content =
@Content(mediaType = "application/json", schema = @Schema(implementation = BulkOperationResult.class))),
@ApiResponse(responseCode = "404", description = "model for instance {id} is not found")
})
public Response bulkAddAssets(
@Context UriInfo uriInfo,
@Context SecurityContext securityContext,
@Parameter(description = "Name of the domain", schema = @Schema(type = "string")) @PathParam("name") String name,
@Valid BulkAssets request) {
return Response.ok().entity(repository.bulkAddAssets(name, request)).build();
}
@PUT
@Path("/{name}/assets/remove")
@Operation(
operationId = "bulkRemoveAssets",
summary = "Bulk Remove Assets",
description = "Bulk Remove Assets",
responses = {
@ApiResponse(
responseCode = "200",
description = "OK",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ChangeEvent.class))),
@ApiResponse(responseCode = "404", description = "model for instance {id} is not found")
})
public Response bulkRemoveGlossaryFromAssets(
@Context UriInfo uriInfo,
@Context SecurityContext securityContext,
@Parameter(description = "Name of the domain", schema = @Schema(type = "string")) @PathParam("name") String name,
@Valid BulkAssets request) {
return Response.ok().entity(repository.bulkRemoveAssets(name, request)).build();
}
@PATCH
@Path("/{id}")
@Operation(

View File

@ -55,9 +55,12 @@ import org.openmetadata.schema.api.teams.CreateTeam;
import org.openmetadata.schema.api.teams.CreateTeam.TeamType;
import org.openmetadata.schema.entity.teams.Team;
import org.openmetadata.schema.entity.teams.TeamHierarchy;
import org.openmetadata.schema.type.ChangeEvent;
import org.openmetadata.schema.type.EntityHistory;
import org.openmetadata.schema.type.Include;
import org.openmetadata.schema.type.MetadataOperation;
import org.openmetadata.schema.type.api.BulkAssets;
import org.openmetadata.schema.type.api.BulkOperationResult;
import org.openmetadata.schema.type.csv.CsvImportResult;
import org.openmetadata.service.Entity;
import org.openmetadata.service.OpenMetadataApplicationConfig;
@ -352,6 +355,49 @@ public class TeamResource extends EntityResource<Team, TeamRepository> {
return createOrUpdate(uriInfo, securityContext, team);
}
@PUT
@Path("/{name}/assets/add")
@Operation(
operationId = "bulkAddAssets",
summary = "Bulk Add Assets",
description = "Bulk Add Assets",
responses = {
@ApiResponse(
responseCode = "200",
description = "OK",
content =
@Content(mediaType = "application/json", schema = @Schema(implementation = BulkOperationResult.class))),
@ApiResponse(responseCode = "404", description = "model for instance {id} is not found")
})
public Response bulkAddAssets(
@Context UriInfo uriInfo,
@Context SecurityContext securityContext,
@Parameter(description = "Name of the Team", schema = @Schema(type = "string")) @PathParam("name") String name,
@Valid BulkAssets request) {
return Response.ok().entity(repository.bulkAddAssets(name, request)).build();
}
@PUT
@Path("/{name}/assets/remove")
@Operation(
operationId = "bulkRemoveAssets",
summary = "Bulk Remove Assets",
description = "Bulk Remove Assets",
responses = {
@ApiResponse(
responseCode = "200",
description = "OK",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ChangeEvent.class))),
@ApiResponse(responseCode = "404", description = "model for instance {id} is not found")
})
public Response bulkRemoveGlossaryFromAssets(
@Context UriInfo uriInfo,
@Context SecurityContext securityContext,
@Parameter(description = "Name of the Team", schema = @Schema(type = "string")) @PathParam("name") String name,
@Valid BulkAssets request) {
return Response.ok().entity(repository.bulkRemoveAssets(name, request)).build();
}
@PATCH
@Path("/{id}")
@Consumes(MediaType.APPLICATION_JSON_PATCH_JSON)

View File

@ -0,0 +1,15 @@
{
"$id": "https://open-metadata.org/schema/api/bulkAssets.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "BulkAssets",
"description": "Represents schema for adding bulk relationships to an entity.",
"type": "object",
"javaType": "org.openmetadata.schema.type.api.BulkAssets",
"properties": {
"assets": {
"description": "List of assets to be created against which the glossary needs to be added.",
"$ref": "../type/entityReferenceList.json"
}
},
"additionalProperties": false
}