ATLAS-4307 Atlas bulk clarification REST enhanced to associate classification to bulk entities with uniq attribute and type as well

Signed-off-by: sidmishra <sidmishra@apache.org>
This commit is contained in:
sidmishra 2021-05-25 17:14:24 -07:00 committed by sidmishra
parent 3bdc51ea1e
commit 6648af332a
2 changed files with 94 additions and 11 deletions

View File

@ -23,6 +23,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.apache.atlas.model.typedef.AtlasBaseTypeDef;
import org.apache.commons.collections.CollectionUtils;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
@ -32,6 +33,7 @@ import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE;
import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.PUBLIC_ONLY;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@JsonAutoDetect(getterVisibility=PUBLIC_ONLY, setterVisibility=PUBLIC_ONLY, fieldVisibility=NONE)
@ -40,8 +42,10 @@ import java.util.Objects;
@XmlRootElement
@XmlAccessorType(XmlAccessType.PROPERTY)
public class ClassificationAssociateRequest {
private AtlasClassification classification;
private List<String> entityGuids;
private AtlasClassification classification;
private List<String> entityGuids;
private List<Map<String, Object>> entitiesUniqueAttributes;
private String entityTypeName;
public ClassificationAssociateRequest() {
this(null, null);
@ -52,6 +56,35 @@ public class ClassificationAssociateRequest {
setClassification(classification);
}
public ClassificationAssociateRequest(String entityTypeName, List<Map<String, Object>> entitiesUniqueAttributes, AtlasClassification classification) {
setEntitiesUniqueAttributes(entitiesUniqueAttributes);
setClassification(classification);
setEntityTypeName(entityTypeName);
}
public ClassificationAssociateRequest(List<String> entityGuids, String entityTypeName, List<Map<String, Object>> entitiesUniqueAttributes, AtlasClassification classification) {
setEntityGuids(entityGuids);
setEntitiesUniqueAttributes(entitiesUniqueAttributes);
setClassification(classification);
setEntityTypeName(entityTypeName);
}
public String getEntityTypeName() {
return entityTypeName;
}
public void setEntityTypeName(String entityTypeName) {
this.entityTypeName = entityTypeName;
}
public List<Map<String, Object>> getEntitiesUniqueAttributes() {
return entitiesUniqueAttributes;
}
public void setEntitiesUniqueAttributes(List<Map<String, Object>> entitiesUniqueAttributes) {
this.entitiesUniqueAttributes = entitiesUniqueAttributes;
}
public AtlasClassification getClassification() { return classification; }
public void setClassification(AtlasClassification classification) { this.classification = classification; }
@ -68,12 +101,12 @@ public class ClassificationAssociateRequest {
ClassificationAssociateRequest that = (ClassificationAssociateRequest) o;
return Objects.equals(classification, that.classification) && Objects.equals(entityGuids, that.entityGuids);
return Objects.equals(classification, that.classification) && Objects.equals(entityGuids, that.entityGuids) && CollectionUtils.isEqualCollection(entitiesUniqueAttributes, that.entitiesUniqueAttributes);
}
@Override
public int hashCode() {
return Objects.hash(classification, entityGuids);
return Objects.hash(classification, entityGuids, entitiesUniqueAttributes);
}
public StringBuilder toString(StringBuilder sb) {
@ -86,9 +119,17 @@ public class ClassificationAssociateRequest {
if (classification != null) {
classification.toString(sb);
}
sb.append(", entityGuids=[");
sb.append("', entityGuids=[");
AtlasBaseTypeDef.dumpObjects(entityGuids, sb);
sb.append("]");
sb.append(", entityTypeName=[");
if (entityTypeName != null) {
sb.append(entityTypeName);
}
sb.append("]");
sb.append(", entitiesUniqueAttributes=[");
AtlasBaseTypeDef.dumpObjects(entitiesUniqueAttributes, sb);
sb.append("]");
sb.append('}');
return sb;
@ -98,5 +139,4 @@ public class ClassificationAssociateRequest {
public String toString() {
return toString(new StringBuilder()).toString();
}
}

View File

@ -21,6 +21,7 @@ import com.sun.jersey.core.header.FormDataContentDisposition;
import com.sun.jersey.multipart.FormDataParam;
import org.apache.atlas.AtlasErrorCode;
import org.apache.atlas.EntityAuditEvent;
import org.apache.atlas.RequestContext;
import org.apache.atlas.annotation.Timed;
import org.apache.atlas.authorize.AtlasAuthorizationUtils;
import org.apache.atlas.authorize.AtlasEntityAccessRequest;
@ -790,7 +791,10 @@ public class EntityREST {
}
/**
* Bulk API to associate a tag to multiple entities
* Bulk API to associate a tag to multiple entities.
* Option 1: List of GUIDs to associate a tag
* Option 2: Typename and list of uniq attributes for entities to associate a tag
* Option 3: List of GUIDs and Typename with list of uniq attributes for entities to associate a tag
*/
@POST
@Path("/bulk/classification")
@ -803,15 +807,49 @@ public class EntityREST {
perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, "EntityREST.addClassification(" + request + ")");
}
AtlasClassification classification = request == null ? null : request.getClassification();
List<String> entityGuids = request == null ? null : request.getEntityGuids();
AtlasClassification classification = request == null ? null : request.getClassification();
List<String> entityGuids = request == null ? null : request.getEntityGuids();
List<Map<String, Object>> entitiesUniqueAttributes = request == null ? null : request.getEntitiesUniqueAttributes();
String entityTypeName = request == null ? null : request.getEntityTypeName();
if (classification == null || StringUtils.isEmpty(classification.getTypeName())) {
throw new AtlasBaseException(AtlasErrorCode.INVALID_PARAMETERS, "no classification");
}
if (CollectionUtils.isEmpty(entityGuids)) {
throw new AtlasBaseException(AtlasErrorCode.INVALID_PARAMETERS, "empty guid list");
if (hasNoGUIDAndTypeNameAttributes(request)) {
throw new AtlasBaseException(AtlasErrorCode.INVALID_PARAMETERS, "Need either list of GUIDs or entity type and list of qualified Names");
}
if (CollectionUtils.isNotEmpty(entitiesUniqueAttributes) && entityTypeName != null) {
AtlasEntityType entityType = ensureEntityType(entityTypeName);
if (CollectionUtils.isEmpty(entityGuids)) {
entityGuids = new ArrayList<>();
}
for (Map<String, Object> eachEntityAttributes : entitiesUniqueAttributes) {
try {
String guid = entitiesStore.getGuidByUniqueAttributes(entityType, eachEntityAttributes);
if (guid != null) {
entityGuids.add(guid);
}
} catch (AtlasBaseException e) {
if (RequestContext.get().isSkipFailedEntities()) {
if (LOG.isDebugEnabled()) {
LOG.debug("getByIds(): ignoring failure for entity with unique attributes {} and typeName {}: error code={}, message={}", eachEntityAttributes, entityTypeName, e.getAtlasErrorCode(), e.getMessage());
}
continue;
}
throw e;
}
}
if (CollectionUtils.isEmpty(entityGuids)) {
throw new AtlasBaseException(AtlasErrorCode.INVALID_PARAMETERS, "No guid found for given entity Type Name and list of attributes");
}
}
entitiesStore.addClassification(entityGuids, classification);
@ -1298,4 +1336,9 @@ public class EntityREST {
return ret;
}
private boolean hasNoGUIDAndTypeNameAttributes(ClassificationAssociateRequest request) {
return (request == null || (CollectionUtils.isEmpty(request.getEntityGuids()) &&
(CollectionUtils.isEmpty(request.getEntitiesUniqueAttributes()) || request.getEntityTypeName() == null)));
}
}