ATLAS-4067: Updates in Custom Attributes and Business Attributes must be captured separately in entity audits.
Signed-off-by: Ashutosh Mestry <amestry@cloudera.com>
diff --git a/dashboardv2/public/js/utils/Enums.js b/dashboardv2/public/js/utils/Enums.js
index ebfceba..d2e476d 100644
--- a/dashboardv2/public/js/utils/Enums.js
+++ b/dashboardv2/public/js/utils/Enums.js
@@ -42,6 +42,7 @@
BUSINESS_ATTRIBUTE_ADD: "Business Attribute(s) Added",
BUSINESS_ATTRIBUTE_UPDATE: "Business Attribute(s) Updated",
BUSINESS_ATTRIBUTE_DELETE: "Business Attribute(s) Deleted",
+ CUSTOM_ATTRIBUTE_UPDATE: "User-defined Attribute(s) Updated",
TYPE_DEF_UPDATE: "Type Updated",
TYPE_DEF_CREATE: "Type Created",
TYPE_DEF_DELETE: "Type Deleted",
diff --git a/dashboardv3/public/js/utils/Enums.js b/dashboardv3/public/js/utils/Enums.js
index ebfceba..d2e476d 100644
--- a/dashboardv3/public/js/utils/Enums.js
+++ b/dashboardv3/public/js/utils/Enums.js
@@ -42,6 +42,7 @@
BUSINESS_ATTRIBUTE_ADD: "Business Attribute(s) Added",
BUSINESS_ATTRIBUTE_UPDATE: "Business Attribute(s) Updated",
BUSINESS_ATTRIBUTE_DELETE: "Business Attribute(s) Deleted",
+ CUSTOM_ATTRIBUTE_UPDATE: "User-defined Attribute(s) Updated",
TYPE_DEF_UPDATE: "Type Updated",
TYPE_DEF_CREATE: "Type Created",
TYPE_DEF_DELETE: "Type Deleted",
diff --git a/intg/src/main/java/org/apache/atlas/exception/AtlasBaseException.java b/intg/src/main/java/org/apache/atlas/exception/AtlasBaseException.java
index 5538702..88a26f4 100644
--- a/intg/src/main/java/org/apache/atlas/exception/AtlasBaseException.java
+++ b/intg/src/main/java/org/apache/atlas/exception/AtlasBaseException.java
@@ -19,7 +19,6 @@
import org.apache.atlas.AtlasErrorCode;
-import javax.ws.rs.core.Response;
import java.util.List;
/**
diff --git a/intg/src/main/java/org/apache/atlas/model/audit/EntityAuditEventV2.java b/intg/src/main/java/org/apache/atlas/model/audit/EntityAuditEventV2.java
index c37e282..083acac 100644
--- a/intg/src/main/java/org/apache/atlas/model/audit/EntityAuditEventV2.java
+++ b/intg/src/main/java/org/apache/atlas/model/audit/EntityAuditEventV2.java
@@ -54,7 +54,7 @@
CLASSIFICATION_ADD, CLASSIFICATION_DELETE, CLASSIFICATION_UPDATE,
PROPAGATED_CLASSIFICATION_ADD, PROPAGATED_CLASSIFICATION_DELETE, PROPAGATED_CLASSIFICATION_UPDATE,
TERM_ADD, TERM_DELETE, LABEL_ADD, LABEL_DELETE, ENTITY_PURGE,
- BUSINESS_ATTRIBUTE_UPDATE;
+ BUSINESS_ATTRIBUTE_UPDATE, CUSTOM_ATTRIBUTE_UPDATE;
public static EntityAuditActionV2 fromString(String strValue) {
switch (strValue) {
@@ -97,6 +97,8 @@
return LABEL_DELETE;
case "BUSINESS_ATTRIBUTE_UPDATE":
return BUSINESS_ATTRIBUTE_UPDATE;
+ case "CUSTOM_ATTRIBUTE_UPDATE":
+ return CUSTOM_ATTRIBUTE_UPDATE;
}
throw new IllegalArgumentException("No enum constant " + EntityAuditActionV2.class.getCanonicalName() + "." + strValue);
diff --git a/repository/src/main/java/org/apache/atlas/repository/audit/EntityAuditListenerV2.java b/repository/src/main/java/org/apache/atlas/repository/audit/EntityAuditListenerV2.java
index ca6f373..0043f1c 100644
--- a/repository/src/main/java/org/apache/atlas/repository/audit/EntityAuditListenerV2.java
+++ b/repository/src/main/java/org/apache/atlas/repository/audit/EntityAuditListenerV2.java
@@ -63,6 +63,7 @@
import static org.apache.atlas.model.audit.EntityAuditEventV2.EntityAuditActionV2.ENTITY_IMPORT_DELETE;
import static org.apache.atlas.model.audit.EntityAuditEventV2.EntityAuditActionV2.ENTITY_IMPORT_UPDATE;
import static org.apache.atlas.model.audit.EntityAuditEventV2.EntityAuditActionV2.ENTITY_UPDATE;
+import static org.apache.atlas.model.audit.EntityAuditEventV2.EntityAuditActionV2.CUSTOM_ATTRIBUTE_UPDATE;
import static org.apache.atlas.model.audit.EntityAuditEventV2.EntityAuditActionV2.LABEL_ADD;
import static org.apache.atlas.model.audit.EntityAuditEventV2.EntityAuditActionV2.LABEL_DELETE;
import static org.apache.atlas.model.audit.EntityAuditEventV2.EntityAuditActionV2.PROPAGATED_CLASSIFICATION_ADD;
@@ -109,7 +110,11 @@
FixedBufferList<EntityAuditEventV2> updatedEvents = getAuditEventsList();
for (AtlasEntity entity : entities) {
- createEvent(updatedEvents.next(), entity, isImport ? ENTITY_IMPORT_UPDATE : ENTITY_UPDATE);
+ EntityAuditActionV2 action = isImport ? ENTITY_IMPORT_UPDATE :
+ RequestContext.get().checkIfEntityIsForCustomAttributeUpdate(entity.getGuid()) ? CUSTOM_ATTRIBUTE_UPDATE :
+ RequestContext.get().checkIfEntityIsForBusinessAttributeUpdate(entity.getGuid()) ? BUSINESS_ATTRIBUTE_UPDATE :
+ ENTITY_UPDATE;
+ createEvent(updatedEvents.next(), entity, action);
}
auditRepository.putEventsV2(updatedEvents.toList());
@@ -579,6 +584,12 @@
case ENTITY_UPDATE:
ret = "Updated: ";
break;
+ case CUSTOM_ATTRIBUTE_UPDATE:
+ ret = "Updated custom attribute: ";
+ break;
+ case BUSINESS_ATTRIBUTE_UPDATE:
+ ret = "Updated business attribute: ";
+ break;
case ENTITY_DELETE:
ret = "Deleted: ";
break;
diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasEntityStoreV2.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasEntityStoreV2.java
index b80e42e..2440722 100644
--- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasEntityStoreV2.java
+++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasEntityStoreV2.java
@@ -1149,7 +1149,7 @@
String guid = entity.getGuid();
AtlasVertex vertex = context.getVertex(guid);
AtlasEntityType entityType = typeRegistry.getEntityTypeByName(entity.getTypeName());
- boolean hasUpdates = false;
+ boolean hasUpdates = false, hasUpdatesInCustAttr = false, hasUpdatesInBusAttr = false;
if (!hasUpdates) {
hasUpdates = entity.getStatus() == AtlasEntity.Status.DELETED; // entity status could be updated during import
@@ -1199,21 +1199,21 @@
}
}
- if (!hasUpdates && entity.getCustomAttributes() != null) {
+ if (entity.getCustomAttributes() != null) {
Map<String, String> currCustomAttributes = getCustomAttributes(vertex);
Map<String, String> newCustomAttributes = entity.getCustomAttributes();
if (!Objects.equals(currCustomAttributes, newCustomAttributes)) {
- hasUpdates = true;
+ hasUpdatesInCustAttr = true;
}
}
- if (!hasUpdates && replaceBusinessAttributes) {
+ if (replaceBusinessAttributes) {
Map<String, Map<String, Object>> currBusinessMetadata = entityRetriever.getBusinessMetadata(vertex);
Map<String, Map<String, Object>> newBusinessMetadata = entity.getBusinessAttributes();
if (!Objects.equals(currBusinessMetadata, newBusinessMetadata)) {
- hasUpdates = true;
+ hasUpdatesInBusAttr = true;
}
}
@@ -1231,6 +1231,14 @@
}
}
+ if(!hasUpdates && (hasUpdatesInCustAttr || hasUpdatesInBusAttr)) {
+ hasUpdates = true;
+ if (hasUpdatesInCustAttr ^ hasUpdatesInBusAttr) {
+ if(hasUpdatesInCustAttr) RequestContext.get().recordEntityWithCustomAttributeUpdate(entity.getGuid());
+ if(hasUpdatesInBusAttr) RequestContext.get().recordEntityWithBusinessAttributeUpdate(entity.getGuid());
+ }
+ }
+
if (!hasUpdates) {
if (entitiesToSkipUpdate == null) {
entitiesToSkipUpdate = new ArrayList<>();
diff --git a/server-api/src/main/java/org/apache/atlas/RequestContext.java b/server-api/src/main/java/org/apache/atlas/RequestContext.java
index 7f0cfe5..216ba08 100644
--- a/server-api/src/main/java/org/apache/atlas/RequestContext.java
+++ b/server-api/src/main/java/org/apache/atlas/RequestContext.java
@@ -58,6 +58,8 @@
private final AtlasPerfMetrics metrics = isMetricsEnabled ? new AtlasPerfMetrics() : null;
private List<EntityGuidPair> entityGuidInRequest = null;
private final Set<String> entitiesToSkipUpdate = new HashSet<>();
+ private final Set<String> onlyCAUpdateEntities = new HashSet<>();
+ private final Set<String> onlyBAUpdateEntities = new HashSet<>();
private String user;
private Set<String> userGroups;
@@ -115,6 +117,8 @@
this.addedPropagations.clear();
this.removedPropagations.clear();
this.entitiesToSkipUpdate.clear();
+ this.onlyCAUpdateEntities.clear();
+ this.onlyBAUpdateEntities.clear();
if (metrics != null && !metrics.isEmpty()) {
METRICS.debug(metrics.toString());
@@ -243,6 +247,26 @@
}
}
+ public void recordEntityWithCustomAttributeUpdate(String guid) {
+ if(! StringUtils.isEmpty(guid)) {
+ onlyCAUpdateEntities.add(guid);
+ }
+ }
+
+ public void recordEntityWithBusinessAttributeUpdate(String guid) {
+ if(! StringUtils.isEmpty(guid)) {
+ onlyBAUpdateEntities.add(guid);
+ }
+ }
+
+ public boolean checkIfEntityIsForCustomAttributeUpdate(String guid) {
+ return StringUtils.isNotEmpty(guid) && onlyCAUpdateEntities.contains(guid);
+ }
+
+ public boolean checkIfEntityIsForBusinessAttributeUpdate(String guid) {
+ return StringUtils.isNotEmpty(guid) && onlyBAUpdateEntities.contains(guid);
+ }
+
public void recordEntityDelete(AtlasEntityHeader entity) {
if (entity != null && entity.getGuid() != null) {
deletedEntities.put(entity.getGuid(), entity);