Fix #17723: Generate Incremental Change Events even when consolidation of events applied (#19550)

* Fix #17723: Generate Incremental Change Events even when consolidation of events applied

* Fix #17723: Generate Incremental Change Events even when consolidation of events applied

* fix tests

* Fix tests

* clean policy tests

* update search methods to use incrementalChangeDescription part-1

* Fix the version page playwrights

* update search methods to use incrementalChangeDescription part-2

* introduce new field incrementalChangeDescription for search part-3

* fix mvn endpoint test

* fix followers and page search test

* fix following of assets

---------

Co-authored-by: Pere Miquel Brull <peremiquelbrull@gmail.com>
Co-authored-by: sonikashah <sonikashah94@gmail.com>
Co-authored-by: Aniket Katkar <aniketkatkar97@gmail.com>
Co-authored-by: sonika-shah <58761340+sonika-shah@users.noreply.github.com>
This commit is contained in:
Sriharsha Chintalapani 2025-02-19 20:53:08 -08:00 committed by GitHub
parent 3b5218b923
commit a924064c09
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
162 changed files with 1584 additions and 933 deletions

View File

@ -214,17 +214,37 @@ class OMetaRolePolicyTest(TestCase):
policies = cls.metadata.list_entities(entity=Policy)
for policy in policies.entities:
if model_str(policy.name).startswith(model_str(cls.policy_entity.name)):
cls.metadata.delete(entity=Policy, entity_id=model_str(policy.id))
cls.metadata.delete(
entity=Policy,
entity_id=model_str(policy.id),
hard_delete=True,
recursive=True,
)
cls.metadata.delete(entity=Policy, entity_id=model_str(cls.role_policy_1.id))
cls.metadata.delete(entity=Policy, entity_id=model_str(cls.role_policy_2.id))
cls.metadata.delete(
entity=Policy,
entity_id=model_str(cls.role_policy_1.id),
hard_delete=True,
recursive=True,
)
cls.metadata.delete(
entity=Policy,
entity_id=model_str(cls.role_policy_2.id),
hard_delete=True,
recursive=True,
)
roles = cls.metadata.list_entities(entity=Role)
for role in roles.entities:
if model_str(role.name.root).startswith(
model_str(cls.role_entity.name.root)
):
cls.metadata.delete(entity=Role, entity_id=model_str(role.id))
cls.metadata.delete(
entity=Role,
entity_id=model_str(role.id),
hard_delete=True,
recursive=True,
)
def test_policy_create(self):
"""
@ -328,7 +348,12 @@ class OMetaRolePolicyTest(TestCase):
res_id = self.metadata.get_by_id(entity=Policy, entity_id=res_name.id)
# Delete
self.metadata.delete(entity=Policy, entity_id=model_str(res_id.id))
self.metadata.delete(
entity=Policy,
entity_id=model_str(res_id.id),
hard_delete=True,
recursive=True,
)
# Then we should not find it
res = self.metadata.list_entities(entity=Policy)
@ -547,7 +572,9 @@ class OMetaRolePolicyTest(TestCase):
res_id = self.metadata.get_by_id(entity=Role, entity_id=res_name.id)
# Delete
self.metadata.delete(entity=Role, entity_id=str(res_id.id.root))
self.metadata.delete(
entity=Role, entity_id=str(res_id.id.root), hard_delete=True, recursive=True
)
# Then we should not find it
res = self.metadata.list_entities(entity=Role)
@ -626,7 +653,9 @@ class OMetaRolePolicyTest(TestCase):
)
assert res.users.root[0].id == user.id
self.metadata.delete(entity=User, entity_id=user.id)
self.metadata.delete(
entity=User, entity_id=user.id, hard_delete=True, recursive=True
)
def test_role_add_team(self):
"""
@ -657,8 +686,12 @@ class OMetaRolePolicyTest(TestCase):
)
assert res.teams.root[0].id == team.id
self.metadata.delete(entity=Team, entity_id=team.id)
self.metadata.delete(entity=User, entity_id=user.id)
self.metadata.delete(
entity=Team, entity_id=team.id, hard_delete=True, recursive=True
)
self.metadata.delete(
entity=User, entity_id=user.id, hard_delete=True, recursive=True
)
def test_role_patch_policies(self):
"""

View File

@ -111,6 +111,7 @@ public final class Entity {
public static final String FIELD_DELETED = "deleted";
public static final String FIELD_PIPELINE_STATUS = "pipelineStatus";
public static final String FIELD_DISPLAY_NAME = "displayName";
public static final String FIELD_FULLY_QUALIFIED_NAME = "fullyQualifiedName";
public static final String FIELD_EXTENSION = "extension";
public static final String FIELD_USAGE_SUMMARY = "usageSummary";
public static final String FIELD_CHILDREN = "children";

View File

@ -39,7 +39,6 @@ public class APICollectionRepository extends EntityRepository<APICollection> {
"",
"");
supportsSearch = true;
parent = true;
}
@Override

View File

@ -16,6 +16,5 @@ public class APIServiceRepository extends ServiceEntityRepository<ApiService, Ap
"",
ServiceType.API);
supportsSearch = true;
parent = true;
}
}

View File

@ -54,7 +54,6 @@ public class ClassificationRepository extends EntityRepository<Classification> {
quoteFqn = true;
supportsSearch = true;
renameAllowed = true;
parent = true;
}
@Override

View File

@ -33,6 +33,5 @@ public class DashboardServiceRepository
"",
ServiceType.DASHBOARD);
supportsSearch = true;
parent = true;
}
}

View File

@ -69,7 +69,6 @@ public class DatabaseRepository extends EntityRepository<Database> {
"",
"");
supportsSearch = true;
parent = true;
fieldFetchers.put("name", this::fetchAndSetService);
}

View File

@ -74,7 +74,6 @@ public class DatabaseSchemaRepository extends EntityRepository<DatabaseSchema> {
"",
"");
supportsSearch = true;
parent = true;
}
@Override

View File

@ -60,7 +60,6 @@ public class DatabaseServiceRepository
"",
ServiceType.DATABASE);
supportsSearch = true;
parent = true;
}
@Override

View File

@ -54,7 +54,6 @@ public class DomainRepository extends EntityRepository<Domain> {
UPDATE_FIELDS,
UPDATE_FIELDS);
supportsSearch = true;
parent = true;
}
@Override

View File

@ -272,7 +272,6 @@ public abstract class EntityRepository<T extends EntityInterface> {
@Getter protected final Fields putFields;
protected boolean supportsSearch = false;
@Getter protected boolean parent = false;
protected final Map<String, BiConsumer<List<T>, Fields>> fieldFetchers = new HashMap<>();
protected EntityRepository(
@ -1049,8 +1048,12 @@ public abstract class EntityRepository<T extends EntityInterface> {
// Update the attributes and relationships of an entity
EntityUpdater entityUpdater = getUpdater(original, updated, Operation.PUT);
entityUpdater.update();
EventType change = entityUpdater.fieldsChanged() ? EventType.ENTITY_UPDATED : ENTITY_NO_CHANGE;
EventType change =
entityUpdater.incrementalFieldsChanged() ? EventType.ENTITY_UPDATED : ENTITY_NO_CHANGE;
setInheritedFields(updated, new Fields(allowedFields));
if (change == ENTITY_UPDATED) {
updated.setChangeDescription(entityUpdater.getIncrementalChangeDescription());
}
return new PutResponse<>(Status.OK, withHref(uriInfo, updated), change);
}
@ -1061,29 +1064,7 @@ public abstract class EntityRepository<T extends EntityInterface> {
setInheritedFields(original, patchFields);
// Apply JSON patch to the original entity to get the updated entity
T updated = JsonUtils.applyPatch(original, patch, entityClass);
updated.setUpdatedBy(user);
updated.setUpdatedAt(System.currentTimeMillis());
prepareInternal(updated, true);
// Validate and populate owners
List<EntityReference> validatedOwners = getValidatedOwners(updated.getOwners());
updated.setOwners(validatedOwners);
restorePatchAttributes(original, updated);
// Update the attributes and relationships of an entity
EntityUpdater entityUpdater = getUpdater(original, updated, Operation.PATCH);
entityUpdater.update();
entityRelationshipReindex(original, updated);
EventType change = ENTITY_NO_CHANGE;
if (entityUpdater.fieldsChanged()) {
change = EventType.ENTITY_UPDATED;
setInheritedFields(updated, patchFields); // Restore inherited fields after a change
}
return new PatchResponse<>(Status.OK, withHref(uriInfo, updated), change);
return patchCommon(original, patch, user, uriInfo);
}
/**
@ -1096,6 +1077,10 @@ public abstract class EntityRepository<T extends EntityInterface> {
setInheritedFields(original, patchFields);
// Apply JSON patch to the original entity to get the updated entity
return patchCommon(original, patch, user, uriInfo);
}
private PatchResponse<T> patchCommon(T original, JsonPatch patch, String user, UriInfo uriInfo) {
T updated = JsonUtils.applyPatch(original, patch, entityClass);
updated.setUpdatedBy(user);
updated.setUpdatedAt(System.currentTimeMillis());
@ -1109,12 +1094,14 @@ public abstract class EntityRepository<T extends EntityInterface> {
// Update the attributes and relationships of an entity
EntityUpdater entityUpdater = getUpdater(original, updated, Operation.PATCH);
entityUpdater.update();
EventType change = ENTITY_NO_CHANGE;
if (entityUpdater.fieldsChanged()) {
change = EventType.ENTITY_UPDATED;
setInheritedFields(updated, patchFields); // Restore inherited fields after a change
}
return new PatchResponse<>(Status.OK, withHref(uriInfo, updated), change);
updated.setChangeDescription(entityUpdater.getIncrementalChangeDescription());
if (entityUpdater.incrementalFieldsChanged()) {
return new PatchResponse<>(Status.OK, withHref(uriInfo, updated), ENTITY_UPDATED);
}
return new PatchResponse<>(Status.OK, withHref(uriInfo, updated), ENTITY_NO_CHANGE);
}
@Transaction
@ -1138,6 +1125,7 @@ public abstract class EntityRepository<T extends EntityInterface> {
.withId(UUID.randomUUID())
.withEntity(entity)
.withChangeDescription(change)
.withIncrementalChangeDescription(change)
.withEventType(EventType.ENTITY_UPDATED)
.withEntityType(entityType)
.withEntityId(entityId)
@ -1146,6 +1134,8 @@ public abstract class EntityRepository<T extends EntityInterface> {
.withTimestamp(System.currentTimeMillis())
.withCurrentVersion(entity.getVersion())
.withPreviousVersion(change.getPreviousVersion());
entity.setIncrementalChangeDescription(change);
entity.setChangeDescription(change);
postUpdate(entity, entity);
return new PutResponse<>(Status.OK, changeEvent, ENTITY_FIELDS_CHANGED);
@ -1186,6 +1176,7 @@ public abstract class EntityRepository<T extends EntityInterface> {
.withId(UUID.randomUUID())
.withEntity(originalEntity)
.withChangeDescription(change)
.withIncrementalChangeDescription(change)
.withEventType(EventType.ENTITY_UPDATED)
.withEntityType(entityType)
.withEntityId(entityId)
@ -1439,6 +1430,7 @@ public abstract class EntityRepository<T extends EntityInterface> {
.withId(UUID.randomUUID())
.withEntity(entity)
.withChangeDescription(change)
.withIncrementalChangeDescription(change)
.withEventType(EventType.ENTITY_UPDATED)
.withEntityFullyQualifiedName(entity.getFullyQualifiedName())
.withEntityType(entityType)
@ -1448,6 +1440,9 @@ public abstract class EntityRepository<T extends EntityInterface> {
.withCurrentVersion(entity.getVersion())
.withPreviousVersion(change.getPreviousVersion());
entity.setChangeDescription(change);
entity.setIncrementalChangeDescription(change);
postUpdate(entity, entity);
return new PutResponse<>(Status.OK, changeEvent, ENTITY_FIELDS_CHANGED);
}
@ -2507,6 +2502,35 @@ public abstract class EntityRepository<T extends EntityInterface> {
.withPreviousVersion(prevVersion);
}
protected void createAndInsertChangeEvent(
T original, T updated, ChangeDescription changeDescription, EventType eventType) {
if (changeDescription == null) {
return;
}
if (changeDescription.getPreviousVersion() == null) {
changeDescription.withPreviousVersion(original.getVersion());
}
ChangeEvent changeEvent =
new ChangeEvent()
.withId(UUID.randomUUID())
.withEventType(eventType)
.withEntityType(entityType)
.withEntityId(updated.getId())
.withEntityFullyQualifiedName(updated.getFullyQualifiedName())
.withUserName(updated.getUpdatedBy())
.withTimestamp(System.currentTimeMillis())
.withCurrentVersion(updated.getVersion())
.withPreviousVersion(changeDescription.getPreviousVersion())
.withChangeDescription(changeDescription)
.withEntity(updated);
daoCollection.changeEventDAO().insert(JsonUtils.pojoToJson(changeEvent));
LOG.debug(
"Inserted incremental ChangeEvent for {} version {}", entityType, updated.getVersion());
}
/** Remove owner relationship for a given entity */
@Transaction
private void removeOwners(T entity, List<EntityReference> owners) {
@ -2807,6 +2831,7 @@ public abstract class EntityRepository<T extends EntityInterface> {
protected boolean majorVersionChange = false;
protected final User updatingUser;
private boolean entityChanged = false;
@Getter protected ChangeDescription incrementalChangeDescription = null;
public EntityUpdater(T original, T updated, Operation operation) {
this.original = original;
@ -2822,20 +2847,25 @@ public abstract class EntityRepository<T extends EntityInterface> {
@Transaction
public final void update() {
boolean consolidateChanges = consolidateChanges(original, updated, operation);
// Revert the changes previously made by the user with in a session and consolidate all the
// changes
incrementalChange();
if (consolidateChanges) {
revert();
}
// Now updated from previous/original to updated one
changeDescription = new ChangeDescription();
updateInternal();
// Store the updated entity
storeUpdate();
postUpdate(original, updated);
}
private void incrementalChange() {
changeDescription = new ChangeDescription();
updateInternal(false);
incrementalChangeDescription = changeDescription;
incrementalChangeDescription.setPreviousVersion(original.getVersion());
updated.setIncrementalChangeDescription(incrementalChangeDescription);
}
@Transaction
private void revert() {
// Revert from current version to previous version to go back to the previous version
@ -2846,6 +2876,7 @@ public abstract class EntityRepository<T extends EntityInterface> {
LOG.debug(
"In session change consolidation. Reverting to previous version {}",
previous.getVersion());
changeDescription = new ChangeDescription();
updated = previous;
updateInternal(true);
LOG.info(
@ -3283,6 +3314,15 @@ public abstract class EntityRepository<T extends EntityInterface> {
|| !changeDescription.getFieldsDeleted().isEmpty();
}
public final boolean incrementalFieldsChanged() {
if (incrementalChangeDescription == null) {
return false;
}
return !incrementalChangeDescription.getFieldsAdded().isEmpty()
|| !incrementalChangeDescription.getFieldsUpdated().isEmpty()
|| !incrementalChangeDescription.getFieldsDeleted().isEmpty();
}
public final <K> boolean recordChange(String field, K orig, K updated) {
return recordChange(field, orig, updated, false, objectMatch, true);
}
@ -3540,9 +3580,7 @@ public abstract class EntityRepository<T extends EntityInterface> {
private boolean consolidateChanges(T original, T updated, Operation operation) {
// If user is the same and the new update is with in the user session timeout
return !parent // Parent entity shouldn't consolidate changes, as we need ChangeDescription to
// propagate to children
&& original.getVersion() > 0.1 // First update on an entity that
return original.getVersion() > 0.1 // First update on an entity that
&& operation == Operation.PATCH
&& !Boolean.TRUE.equals(original.getDeleted()) // Entity is not soft deleted
&& !operation.isDelete() // Operation must be an update

View File

@ -89,7 +89,6 @@ public class GlossaryRepository extends EntityRepository<Glossary> {
quoteFqn = true;
supportsSearch = true;
renameAllowed = true;
parent = true;
}
@Override

View File

@ -34,6 +34,5 @@ public class MessagingServiceRepository
UPDATE_FIELDS,
ServiceType.MESSAGING);
supportsSearch = true;
parent = true;
}
}

View File

@ -19,6 +19,5 @@ public class MetadataServiceRepository
UPDATE_FIELDS,
ServiceType.METADATA);
supportsSearch = true;
parent = true;
}
}

View File

@ -34,6 +34,5 @@ public class MlModelServiceRepository
UPDATE_FIELDS,
ServiceType.ML_MODEL);
supportsSearch = true;
parent = true;
}
}

View File

@ -33,6 +33,5 @@ public class PipelineServiceRepository
"",
ServiceType.PIPELINE);
supportsSearch = true;
parent = true;
}
}

View File

@ -17,6 +17,5 @@ public class SearchServiceRepository
"",
ServiceType.SEARCH);
supportsSearch = true;
parent = true;
}
}

View File

@ -17,6 +17,5 @@ public class StorageServiceRepository
"",
ServiceType.STORAGE);
supportsSearch = true;
parent = true;
}
}

View File

@ -113,7 +113,6 @@ public class TeamRepository extends EntityRepository<Team> {
TEAM_UPDATE_FIELDS);
this.quoteFqn = true;
supportsSearch = true;
parent = true;
}
@Override

View File

@ -514,6 +514,7 @@ public class TestCaseRepository extends EntityRepository<TestCase> {
.withName("testSuites")
.withNewValue(updatedTestCase.getTestSuites())));
updatedTestCase.setChangeDescription(change);
postUpdate(testCase, updatedTestCase);
updateLogicalTestSuite(testSuiteId);
testCase.setTestSuite(updatedTestCase.getTestSuite());

View File

@ -107,7 +107,6 @@ public class TestSuiteRepository extends EntityRepository<TestSuite> {
UPDATE_FIELDS);
quoteFqn = false;
supportsSearch = true;
parent = true;
}
@Override

View File

@ -59,6 +59,8 @@ public interface SearchClient {
String PROPAGATE_FIELD_SCRIPT = "ctx._source.put('%s', '%s')";
String PROPAGATE_NESTED_FIELD_SCRIPT = "ctx._source.%s = params.%s";
String REMOVE_PROPAGATED_ENTITY_REFERENCE_FIELD_SCRIPT =
"if ((ctx._source.%s != null) && (ctx._source.%s.inherited == true)){ ctx._source.remove('%s');}";
String REMOVE_PROPAGATED_FIELD_SCRIPT = "ctx._source.remove('%s')";
@ -110,6 +112,19 @@ public interface SearchClient {
+ "params.deletedOwners.stream().anyMatch(deletedOwner -> deletedOwner.id == owner.id) && owner.inherited == true); "
+ "}";
String UPDATE_TAGS_FIELD_SCRIPT =
"if (ctx._source.tags != null) { "
+ "for (int i = 0; i < ctx._source.tags.size(); i++) { "
+ "if (ctx._source.tags[i].tagFQN == params.tagFQN) { "
+ "for (String field : params.updates.keySet()) { "
+ "if (field != null && params.updates[field] != null) { "
+ "ctx._source.tags[i][field] = params.updates[field]; "
+ "} "
+ "} "
+ "} "
+ "} "
+ "}";
String NOT_IMPLEMENTED_ERROR_TYPE = "NOT_IMPLEMENTED";
String ENTITY_RELATIONSHIP_DIRECTION_ENTITY = "entityRelationship.entity.fqnHash.keyword";
@ -283,7 +298,8 @@ public interface SearchClient {
Pair<String, String> fieldAndValue,
Pair<String, Map<String, Object>> updates);
void updateByFqnPrefix(String indexName, String oldParentFQN, String newParentFQN);
void updateByFqnPrefix(
String indexName, String oldParentFQN, String newParentFQN, String prefixFieldCondition);
void updateChildren(
List<String> indexName,

View File

@ -3,7 +3,11 @@ package org.openmetadata.service.search;
import static org.openmetadata.common.utils.CommonUtil.nullOrEmpty;
import static org.openmetadata.service.Entity.AGGREGATED_COST_ANALYSIS_REPORT_DATA;
import static org.openmetadata.service.Entity.ENTITY_REPORT_DATA;
import static org.openmetadata.service.Entity.FIELD_DISPLAY_NAME;
import static org.openmetadata.service.Entity.FIELD_DOMAIN;
import static org.openmetadata.service.Entity.FIELD_FOLLOWERS;
import static org.openmetadata.service.Entity.FIELD_FULLY_QUALIFIED_NAME;
import static org.openmetadata.service.Entity.FIELD_NAME;
import static org.openmetadata.service.Entity.FIELD_OWNERS;
import static org.openmetadata.service.Entity.FIELD_USAGE_SUMMARY;
import static org.openmetadata.service.Entity.QUERY;
@ -15,6 +19,7 @@ import static org.openmetadata.service.search.SearchClient.DEFAULT_UPDATE_SCRIPT
import static org.openmetadata.service.search.SearchClient.GLOBAL_SEARCH_ALIAS;
import static org.openmetadata.service.search.SearchClient.PROPAGATE_ENTITY_REFERENCE_FIELD_SCRIPT;
import static org.openmetadata.service.search.SearchClient.PROPAGATE_FIELD_SCRIPT;
import static org.openmetadata.service.search.SearchClient.PROPAGATE_NESTED_FIELD_SCRIPT;
import static org.openmetadata.service.search.SearchClient.PROPAGATE_TEST_SUITES_SCRIPT;
import static org.openmetadata.service.search.SearchClient.REMOVE_DATA_PRODUCTS_CHILDREN_SCRIPT;
import static org.openmetadata.service.search.SearchClient.REMOVE_DOMAINS_CHILDREN_SCRIPT;
@ -27,6 +32,7 @@ import static org.openmetadata.service.search.SearchClient.SOFT_DELETE_RESTORE_S
import static org.openmetadata.service.search.SearchClient.UPDATE_ADDED_DELETE_GLOSSARY_TAGS;
import static org.openmetadata.service.search.SearchClient.UPDATE_CERTIFICATION_SCRIPT;
import static org.openmetadata.service.search.SearchClient.UPDATE_PROPAGATED_ENTITY_REFERENCE_FIELD_SCRIPT;
import static org.openmetadata.service.search.SearchClient.UPDATE_TAGS_FIELD_SCRIPT;
import static org.openmetadata.service.search.models.IndexMapping.indexNameSeparator;
import static org.openmetadata.service.util.EntityUtil.compareEntityReferenceById;
@ -78,6 +84,7 @@ import org.openmetadata.service.search.indexes.SearchIndex;
import org.openmetadata.service.search.models.IndexMapping;
import org.openmetadata.service.search.opensearch.OpenSearchClient;
import org.openmetadata.service.security.policyevaluator.SubjectContext;
import org.openmetadata.service.util.FullyQualifiedName;
import org.openmetadata.service.util.JsonUtils;
import org.openmetadata.service.workflows.searchIndex.ReindexingUtil;
@ -93,7 +100,12 @@ public class SearchRepository {
@Getter @Setter public SearchIndexFactory searchIndexFactory = new SearchIndexFactory();
private final List<String> inheritableFields =
List.of(FIELD_OWNERS, Entity.FIELD_DOMAIN, Entity.FIELD_DISABLED, Entity.FIELD_TEST_SUITES);
List.of(
FIELD_OWNERS,
Entity.FIELD_DOMAIN,
Entity.FIELD_DISABLED,
Entity.FIELD_TEST_SUITES,
FIELD_DISPLAY_NAME);
private final List<String> propagateFields = List.of(Entity.FIELD_TAGS);
@Getter private final ElasticSearchConfiguration elasticSearchConfiguration;
@ -381,10 +393,24 @@ public class SearchRepository {
IndexMapping indexMapping = entityIndexMap.get(entityType);
String scriptTxt = DEFAULT_UPDATE_SCRIPT;
Map<String, Object> doc = new HashMap<>();
if (entity.getChangeDescription() != null
ChangeDescription incrementalChangeDescription = entity.getIncrementalChangeDescription();
ChangeDescription changeDescription;
if (incrementalChangeDescription != null
&& (!incrementalChangeDescription.getFieldsAdded().isEmpty()
|| !incrementalChangeDescription.getFieldsUpdated().isEmpty()
|| !incrementalChangeDescription.getFieldsDeleted().isEmpty())) {
changeDescription = incrementalChangeDescription;
} else {
changeDescription = entity.getChangeDescription();
}
if (changeDescription != null
&& entity.getChangeDescription() != null
&& Objects.equals(
entity.getVersion(), entity.getChangeDescription().getPreviousVersion())) {
scriptTxt = getScriptWithParams(entity, doc);
scriptTxt = getScriptWithParams(entity, doc, changeDescription);
} else {
SearchIndex elasticSearchIndex = searchIndexFactory.buildIndex(entityType, entity);
doc = elasticSearchIndex.buildSearchIndexDoc();
@ -392,12 +418,10 @@ public class SearchRepository {
searchClient.updateEntity(
indexMapping.getIndexName(clusterAlias), entityId, doc, scriptTxt);
propagateInheritedFieldsToChildren(
entityType, entityId, entity.getChangeDescription(), indexMapping, entity);
propagateGlossaryTags(
entityType, entity.getFullyQualifiedName(), entity.getChangeDescription());
propagateCertificationTags(entityType, entity);
propagatetoRelatedEntities(
entityType, entityId, entity.getChangeDescription(), indexMapping, entity);
entityType, entityId, changeDescription, indexMapping, entity);
propagateGlossaryTags(entityType, entity.getFullyQualifiedName(), changeDescription);
propagateCertificationTags(entityType, entity, changeDescription);
propagatetoRelatedEntities(entityType, entityId, changeDescription, indexMapping, entity);
} catch (Exception ie) {
LOG.error(
"Issue in Updating the search document for entity [{}] and entityType [{}]. Reason[{}], Cause[{}], Stack [{}]",
@ -428,7 +452,9 @@ public class SearchRepository {
Pair<String, Map<String, Object>> updates =
getInheritedFieldChanges(changeDescription, entity);
Pair<String, String> parentMatch;
if (!updates.getValue().isEmpty() && updates.getValue().containsKey("domain")) {
if (!updates.getValue().isEmpty()
&& (updates.getValue().containsKey(FIELD_DOMAIN)
|| updates.getValue().containsKey(FIELD_DISPLAY_NAME))) {
if (entityType.equalsIgnoreCase(Entity.DATABASE_SERVICE)
|| entityType.equalsIgnoreCase(Entity.DASHBOARD_SERVICE)
|| entityType.equalsIgnoreCase(Entity.MESSAGING_SERVICE)
@ -481,8 +507,8 @@ public class SearchRepository {
}
}
public void propagateCertificationTags(String entityType, EntityInterface entity) {
ChangeDescription changeDescription = entity.getChangeDescription();
public void propagateCertificationTags(
String entityType, EntityInterface entity, ChangeDescription changeDescription) {
if (changeDescription != null && entityType.equalsIgnoreCase(Entity.TAG)) {
Tag tagEntity = (Tag) entity;
if (tagEntity.getClassification().getFullyQualifiedName().equals("Certification")) {
@ -507,13 +533,14 @@ public class SearchRepository {
EntityInterface entity) {
if (changeDescription != null && entityType.equalsIgnoreCase(Entity.PAGE)) {
String indexName = indexMapping.getIndexName(clusterAlias);
String indexName = indexMapping.getIndexName();
for (FieldChange field : changeDescription.getFieldsAdded()) {
if (field.getName().contains("parent")) {
String oldParentFQN = entity.getName();
String newParentFQN = entity.getFullyQualifiedName();
// Propagate FQN updates to all subchildren
searchClient.updateByFqnPrefix(indexName, oldParentFQN, newParentFQN);
searchClient.updateByFqnPrefix(
indexName, oldParentFQN, newParentFQN, FIELD_FULLY_QUALIFIED_NAME);
}
}
@ -523,10 +550,11 @@ public class SearchRepository {
JsonUtils.readValue(field.getOldValue().toString(), EntityReference.class);
// Propagate FQN updates to all subchildren
String originalFqn =
String.join(
".", entityReferenceBeforeUpdate.getFullyQualifiedName(), entity.getName());
FullyQualifiedName.add(
entityReferenceBeforeUpdate.getFullyQualifiedName(), entity.getName());
String updatedFqn = entity.getFullyQualifiedName();
searchClient.updateByFqnPrefix(indexName, originalFqn, updatedFqn);
searchClient.updateByFqnPrefix(
indexName, originalFqn, updatedFqn, FIELD_FULLY_QUALIFIED_NAME);
}
}
@ -536,9 +564,45 @@ public class SearchRepository {
JsonUtils.readValue(field.getOldValue().toString(), EntityReference.class);
// Propagate FQN updates to all subchildren
String originalFqn =
String.join(
".", entityReferenceBeforeUpdate.getFullyQualifiedName(), entity.getName());
searchClient.updateByFqnPrefix(indexName, originalFqn, "");
FullyQualifiedName.add(
entityReferenceBeforeUpdate.getFullyQualifiedName(), entity.getName());
searchClient.updateByFqnPrefix(indexName, originalFqn, "", FIELD_FULLY_QUALIFIED_NAME);
}
}
} else if (changeDescription != null
&& (entityType.equalsIgnoreCase(Entity.CLASSIFICATION)
|| entityType.equalsIgnoreCase(Entity.GLOSSARY)
|| entityType.equalsIgnoreCase(Entity.GLOSSARY_TERM)
|| entityType.equalsIgnoreCase(Entity.TAG))) {
// Update the assets associated with the tags/terms in classification/glossary
Map<String, Object> paramMap = new HashMap<>();
for (FieldChange field : changeDescription.getFieldsUpdated()) {
String parentFQN = FullyQualifiedName.getParentFQN(entity.getFullyQualifiedName());
String oldFQN;
String newFQN;
if (!nullOrEmpty(parentFQN)) {
oldFQN = FullyQualifiedName.add(parentFQN, field.getOldValue().toString());
newFQN = FullyQualifiedName.add(parentFQN, field.getNewValue().toString());
} else {
oldFQN = FullyQualifiedName.quoteName(field.getOldValue().toString());
newFQN = FullyQualifiedName.quoteName(field.getNewValue().toString());
}
if (field.getName().contains(FIELD_NAME)) {
searchClient.updateByFqnPrefix(GLOBAL_SEARCH_ALIAS, oldFQN, newFQN, "tags.tagFQN");
}
if (field.getName().equalsIgnoreCase(Entity.FIELD_DISPLAY_NAME)) {
Map<String, Object> updates = new HashMap<>();
updates.put("displayName", field.getNewValue().toString());
paramMap.put("tagFQN", oldFQN);
paramMap.put("updates", updates);
searchClient.updateChildren(
GLOBAL_SEARCH_ALIAS,
new ImmutablePair<>("tags.tagFQN", oldFQN),
new ImmutablePair<>(UPDATE_TAGS_FIELD_SCRIPT, paramMap));
}
}
}
@ -600,6 +664,12 @@ public class SearchRepository {
if (field.getName().equals(Entity.FIELD_TEST_SUITES)) {
scriptTxt.append(PROPAGATE_TEST_SUITES_SCRIPT);
fieldData.put(Entity.FIELD_TEST_SUITES, field.getNewValue());
} else if (field.getName().equals(Entity.FIELD_DISPLAY_NAME)) {
String fieldPath =
getFieldPath(entity.getEntityReference().getType(), field.getName());
fieldData.put(field.getName(), field.getNewValue().toString());
scriptTxt.append(
String.format(PROPAGATE_NESTED_FIELD_SCRIPT, fieldPath, field.getName()));
} else {
scriptTxt.append(
String.format(PROPAGATE_FIELD_SCRIPT, field.getName(), field.getNewValue()));
@ -634,9 +704,17 @@ public class SearchRepository {
}
scriptTxt.append(" ");
} catch (UnhandledServerException e) {
scriptTxt.append(
String.format(PROPAGATE_FIELD_SCRIPT, field.getName(), field.getNewValue()));
scriptTxt.append(" ");
if (field.getName().equals(Entity.FIELD_DISPLAY_NAME)) {
String fieldPath =
getFieldPath(entity.getEntityReference().getType(), field.getName());
fieldData.put(field.getName(), field.getNewValue().toString());
scriptTxt.append(
String.format(PROPAGATE_NESTED_FIELD_SCRIPT, fieldPath, field.getName()));
} else {
scriptTxt.append(
String.format(PROPAGATE_FIELD_SCRIPT, field.getName(), field.getNewValue()));
scriptTxt.append(" ");
}
}
}
}
@ -644,6 +722,21 @@ public class SearchRepository {
return new ImmutablePair<>(scriptTxt.toString(), fieldData);
}
private String getFieldPath(String entityType, String fieldName) {
if (entityType.equalsIgnoreCase(Entity.DATABASE_SERVICE)
|| entityType.equalsIgnoreCase(Entity.DASHBOARD_SERVICE)
|| entityType.equalsIgnoreCase(Entity.MESSAGING_SERVICE)
|| entityType.equalsIgnoreCase(Entity.PIPELINE_SERVICE)
|| entityType.equalsIgnoreCase(Entity.MLMODEL_SERVICE)
|| entityType.equalsIgnoreCase(Entity.STORAGE_SERVICE)
|| entityType.equalsIgnoreCase(Entity.SEARCH_SERVICE)
|| entityType.equalsIgnoreCase(Entity.API_SERVICE)) {
return "service." + fieldName;
} else {
return entityType + "." + fieldName;
}
}
public void deleteByScript(String entityType, String scriptTxt, Map<String, Object> params) {
try {
IndexMapping indexMapping = getIndexMapping(entityType);
@ -841,9 +934,10 @@ public class SearchRepository {
}
}
public String getScriptWithParams(EntityInterface entity, Map<String, Object> fieldAddParams) {
ChangeDescription changeDescription = entity.getChangeDescription();
public String getScriptWithParams(
EntityInterface entity,
Map<String, Object> fieldAddParams,
ChangeDescription changeDescription) {
List<FieldChange> fieldsAdded = changeDescription.getFieldsAdded();
StringBuilder scriptTxt = new StringBuilder();
fieldAddParams.put("updatedAt", entity.getUpdatedAt());

View File

@ -2240,12 +2240,13 @@ public class ElasticSearchClient implements SearchClient {
}
@Override
public void updateByFqnPrefix(String indexName, String oldParentFQN, String newParentFQN) {
public void updateByFqnPrefix(
String indexName, String oldParentFQN, String newParentFQN, String prefixFieldCondition) {
// Match all children documents whose fullyQualifiedName starts with the old parent's FQN
PrefixQueryBuilder prefixQuery =
new PrefixQueryBuilder("fullyQualifiedName", oldParentFQN + ".");
PrefixQueryBuilder prefixQuery = new PrefixQueryBuilder(prefixFieldCondition, oldParentFQN);
UpdateByQueryRequest updateByQueryRequest = new UpdateByQueryRequest(indexName);
UpdateByQueryRequest updateByQueryRequest =
new UpdateByQueryRequest(Entity.getSearchRepository().getIndexOrAliasName(indexName));
updateByQueryRequest.setQuery(prefixQuery);
Map<String, Object> params = new HashMap<>();
@ -2261,6 +2262,14 @@ public class ElasticSearchClient implements SearchClient {
+ " String parentFQN = ctx._source.parent.fullyQualifiedName; "
+ " ctx._source.parent.fullyQualifiedName = parentFQN.replace(params.oldParentFQN, params.newParentFQN); "
+ " } "
+ "} "
+ "if (ctx._source.containsKey('tags')) { "
+ " for (int i = 0; i < ctx._source.tags.size(); i++) { "
+ " if (ctx._source.tags[i].containsKey('tagFQN')) { "
+ " String tagFQN = ctx._source.tags[i].tagFQN; "
+ " ctx._source.tags[i].tagFQN = tagFQN.replace(params.oldParentFQN, params.newParentFQN); "
+ " } "
+ " } "
+ "}";
Script inlineScript =

View File

@ -42,7 +42,11 @@ import org.openmetadata.service.util.JsonUtils;
public interface SearchIndex {
Set<String> DEFAULT_EXCLUDED_FIELDS =
Set.of("changeDescription", "lineage.pipeline.changeDescription", "connection");
Set.of(
"changeDescription",
"incrementalChangeDescription",
"lineage.pipeline.changeDescription",
"connection");
public static final SearchClient searchClient = Entity.getSearchRepository().getSearchClient();
default Map<String, Object> buildSearchIndexDoc() {

View File

@ -11,7 +11,7 @@ import lombok.extern.jackson.Jacksonized;
@Getter
@Builder
public class IndexMapping {
String indexName;
@Getter String indexName;
String indexMappingFile;
String alias;
List<String> parentAliases;
@ -42,10 +42,6 @@ public class IndexMapping {
: childAliases;
}
private String getIndexName() {
return indexName;
}
private String getAlias() {
return alias;
}

View File

@ -2227,12 +2227,12 @@ public class OpenSearchClient implements SearchClient {
}
@Override
public void updateByFqnPrefix(String indexName, String oldParentFQN, String newParentFQN) {
public void updateByFqnPrefix(
String indexName, String oldParentFQN, String newParentFQN, String prefixFieldCondition) {
// Match all children documents whose fullyQualifiedName starts with the old parent's FQN
PrefixQueryBuilder prefixQuery =
new PrefixQueryBuilder("fullyQualifiedName", oldParentFQN + ".");
UpdateByQueryRequest updateByQueryRequest = new UpdateByQueryRequest(indexName);
PrefixQueryBuilder prefixQuery = new PrefixQueryBuilder(prefixFieldCondition, oldParentFQN);
UpdateByQueryRequest updateByQueryRequest =
new UpdateByQueryRequest(Entity.getSearchRepository().getIndexOrAliasName(indexName));
updateByQueryRequest.setQuery(prefixQuery);
Map<String, Object> params = new HashMap<>();
@ -2248,6 +2248,14 @@ public class OpenSearchClient implements SearchClient {
+ " String parentFQN = ctx._source.parent.fullyQualifiedName; "
+ " ctx._source.parent.fullyQualifiedName = parentFQN.replace(params.oldParentFQN, params.newParentFQN); "
+ " } "
+ "} "
+ "if (ctx._source.containsKey('tags')) { "
+ " for (int i = 0; i < ctx._source.tags.size(); i++) { "
+ " if (ctx._source.tags[i].containsKey('tagFQN')) { "
+ " String tagFQN = ctx._source.tags[i].tagFQN; "
+ " ctx._source.tags[i].tagFQN = tagFQN.replace(params.oldParentFQN, params.newParentFQN); "
+ " } "
+ " } "
+ "}";
Script inlineScript =
new Script(ScriptType.INLINE, Script.DEFAULT_SCRIPT_LANG, painlessScript, params);

View File

@ -1575,26 +1575,16 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
checkOwnerOwns(TEAM11_REF, entity.getId(), true);
// V0-2 (consolidated) - Change owner from TEAM_OWNER1 to USER_OWNER1 using PATCH request
if (!isParent()) {
json = JsonUtils.pojoToJson(entity);
entity.setOwners(List.of(USER1_REF));
change = getChangeDescription(entity, getChangeType());
fieldAdded(change, FIELD_OWNERS, List.of(USER1_REF));
entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, getChangeType(), change);
checkOwnerOwns(USER1_REF, entity.getId(), true);
checkOwnerOwns(TEAM11_REF, entity.getId(), false);
} else {
json = JsonUtils.pojoToJson(entity);
entity.setOwners(List.of(USER1_REF));
change = getChangeDescription(entity, getChangeType());
fieldAdded(change, FIELD_OWNERS, List.of(USER1_REF));
fieldDeleted(change, FIELD_OWNERS, List.of(TEAM11_REF));
entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, getChangeType(), change);
checkOwnerOwns(USER1_REF, entity.getId(), true);
checkOwnerOwns(TEAM11_REF, entity.getId(), false);
}
json = JsonUtils.pojoToJson(entity);
entity.setOwners(List.of(USER1_REF));
change = getChangeDescription(entity, getChangeType());
fieldAdded(change, FIELD_OWNERS, List.of(USER1_REF));
fieldDeleted(change, FIELD_OWNERS, List.of(TEAM11_REF));
entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, getChangeType(), change);
checkOwnerOwns(USER1_REF, entity.getId(), true);
checkOwnerOwns(TEAM11_REF, entity.getId(), false);
// V0.2 (no change) - Set the owner to the existing owner. No ownership change must be recorded.
change = new ChangeDescription().withPreviousVersion(entity.getVersion());
json = JsonUtils.pojoToJson(entity);
entity.setOwners(List.of(USER1_REF));
entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, NO_CHANGE, change);
@ -1602,20 +1592,12 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
// V0.1 (revert) - Remove ownership (USER_OWNER1) using PATCH. We are back to original state no
// owner and no change
if (!isParent()) {
json = JsonUtils.pojoToJson(entity);
entity.setOwners(null);
change = getChangeDescription(entity, REVERT);
patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, REVERT, change);
checkOwnerOwns(USER1_REF, entity.getId(), false);
} else {
json = JsonUtils.pojoToJson(entity);
entity.setOwners(null);
change = getChangeDescription(entity, MINOR_UPDATE);
fieldDeleted(change, FIELD_OWNERS, List.of(USER1_REF));
patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
checkOwnerOwns(USER1_REF, entity.getId(), false);
}
json = JsonUtils.pojoToJson(entity);
entity.setOwners(null);
change = getChangeDescription(entity, MINOR_UPDATE);
fieldDeleted(change, FIELD_OWNERS, List.of(USER1_REF));
patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
checkOwnerOwns(USER1_REF, entity.getId(), false);
// set random type as entity. Check if the ownership validate.
T newEntity = entity;
@ -1920,71 +1902,39 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
//
// Replace description, add tags tier, owner - Changes are consolidated
//
if (!isParent()) {
origJson = JsonUtils.pojoToJson(entity);
entity.setDescription("description1");
entity.setDisplayName("displayName1");
change = getChangeDescription(entity, CHANGE_CONSOLIDATED);
fieldUpdated(change, "description", "", "description1");
fieldAdded(change, "displayName", "displayName1");
if (supportsOwners) {
entity.setOwners(List.of(USER1_REF));
fieldAdded(change, FIELD_OWNERS, List.of(USER1_REF));
}
if (supportsTags) {
entity.getTags().add(TIER1_TAG_LABEL);
fieldAdded(
change,
FIELD_TAGS,
List.of(USER_ADDRESS_TAG_LABEL, GLOSSARY2_TERM1_LABEL, TIER1_TAG_LABEL));
}
entity = patchEntityAndCheck(entity, origJson, ADMIN_AUTH_HEADERS, getChangeType(), change);
//
// Remove description, tier, owner - Changes are reverted going to 0.1 version of the entity
//
origJson = JsonUtils.pojoToJson(entity);
change = getChangeDescription(entity, REVERT);
entity.setDescription("");
entity.setDisplayName(null);
entity.setOwners(null);
entity.setTags(null);
patchEntityAndCheck(entity, origJson, ADMIN_AUTH_HEADERS, REVERT, change);
} else {
origJson = JsonUtils.pojoToJson(entity);
entity.setDescription("description1");
entity.setDisplayName("displayName1");
change = getChangeDescription(entity, MINOR_UPDATE);
fieldUpdated(change, "description", "description", "description1");
fieldUpdated(change, "displayName", "displayName", "displayName1");
if (supportsOwners) {
entity.setOwners(List.of(USER1_REF));
fieldAdded(change, FIELD_OWNERS, List.of(USER1_REF));
fieldDeleted(change, FIELD_OWNERS, List.of(TEAM11_REF));
}
if (supportsTags) {
entity.getTags().add(TIER1_TAG_LABEL);
fieldAdded(change, FIELD_TAGS, List.of(TIER1_TAG_LABEL));
}
entity = patchEntityAndCheck(entity, origJson, ADMIN_AUTH_HEADERS, getChangeType(), change);
origJson = JsonUtils.pojoToJson(entity);
change = getChangeDescription(entity, MINOR_UPDATE);
entity.setDescription("");
entity.setDisplayName(null);
entity.setOwners(null);
entity.setTags(null);
fieldUpdated(change, "description", "description1", "");
fieldDeleted(change, "displayName", "displayName1");
if (supportsOwners) {
fieldDeleted(change, FIELD_OWNERS, List.of(USER1_REF));
}
if (supportsTags) {
fieldDeleted(change, FIELD_TAGS, List.of(TIER1_TAG_LABEL));
}
patchEntityAndCheck(entity, origJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
origJson = JsonUtils.pojoToJson(entity);
entity.setDescription("description1");
entity.setDisplayName("displayName1");
change = getChangeDescription(entity, MINOR_UPDATE);
fieldUpdated(change, "description", "description", "description1");
fieldUpdated(change, "displayName", "displayName", "displayName1");
if (supportsOwners) {
entity.setOwners(List.of(USER1_REF));
fieldAdded(change, FIELD_OWNERS, List.of(USER1_REF));
fieldDeleted(change, FIELD_OWNERS, List.of(TEAM11_REF));
}
if (supportsTags) {
entity.getTags().add(TIER1_TAG_LABEL);
fieldAdded(change, FIELD_TAGS, List.of(TIER1_TAG_LABEL));
}
entity = patchEntityAndCheck(entity, origJson, ADMIN_AUTH_HEADERS, getChangeType(), change);
origJson = JsonUtils.pojoToJson(entity);
change = getChangeDescription(entity, MINOR_UPDATE);
entity.setDescription("");
entity.setDisplayName(null);
entity.setOwners(null);
entity.setTags(null);
fieldUpdated(change, "description", "description1", "");
fieldDeleted(change, "displayName", "displayName1");
if (supportsOwners) {
fieldDeleted(change, FIELD_OWNERS, List.of(USER1_REF));
}
if (supportsTags) {
fieldDeleted(change, FIELD_TAGS, List.of(TIER1_TAG_LABEL));
}
patchEntityAndCheck(entity, origJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
}
@Test
@ -2022,62 +1972,31 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
// Update description with a new description and the version changes as admin - the changes are
// consolidated
if (!isParent()) {
json = JsonUtils.pojoToJson(entity);
entity.setDescription("description2");
change = getChangeDescription(entity, getChangeType()); // Version changes
fieldUpdated(change, "description", "description", "description2");
entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, getChangeType(), change);
json = JsonUtils.pojoToJson(entity);
entity.setDescription("description2");
change = getChangeDescription(entity, MINOR_UPDATE); // Version changes
fieldUpdated(change, "description", "description1", "description2");
entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
// Update displayName with a new displayName - but as USER1
// Since the previous change is done by a different user, changes ** are not ** consolidated
json = JsonUtils.pojoToJson(entity);
entity.setDisplayName("displayName");
change = getChangeDescription(entity, CHANGE_CONSOLIDATED); // Version changes
fieldUpdated(change, "description", "description", "description2");
fieldAdded(change, "displayName", "displayName");
entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
// Update displayName with a new displayName - but as USER1
// Since the previous change is done by a different user, changes ** are not ** consolidated
json = JsonUtils.pojoToJson(entity);
entity.setDisplayName("displayName");
change = getChangeDescription(entity, MINOR_UPDATE); // Version changes
fieldAdded(change, "displayName", "displayName");
entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
// Update displayName to a new displayName.
// In this test, the user who previously made a change makes the change after session timeout.
// The changes are not consolidated.
EntityUpdater.setSessionTimeout(1); // Reduce the session timeout for this test
java.lang.Thread.sleep(2);
json = JsonUtils.pojoToJson(entity);
entity.setDisplayName("displayName1");
change = getChangeDescription(entity, MINOR_UPDATE); // Version changes
fieldUpdated(change, "displayName", "displayName", "displayName1");
patchEntityAndCheck(entity, json, authHeaders(USER1.getName()), MINOR_UPDATE, change);
EntityUpdater.setSessionTimeout(10 * 60 * 10000); // Reset the session timeout back
} else {
json = JsonUtils.pojoToJson(entity);
entity.setDescription("description2");
change = getChangeDescription(entity, getChangeType()); // Version changes
fieldUpdated(change, "description", "description1", "description2");
entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, getChangeType(), change);
// Update displayName with a new displayName - but as USER1
// Since the previous change is done by a different user, changes ** are not ** consolidated
json = JsonUtils.pojoToJson(entity);
entity.setDisplayName("displayName");
change = getChangeDescription(entity, MINOR_UPDATE); // Version changes
fieldAdded(change, "displayName", "displayName");
entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
// Update displayName to a new displayName.
// In this test, the user who previously made a change makes the change after session timeout.
// The changes are not consolidated.
EntityUpdater.setSessionTimeout(1); // Reduce the session timeout for this test
java.lang.Thread.sleep(2);
json = JsonUtils.pojoToJson(entity);
entity.setDisplayName("displayName1");
change = getChangeDescription(entity, MINOR_UPDATE); // Version changes
fieldUpdated(change, "displayName", "displayName", "displayName1");
patchEntityAndCheck(entity, json, authHeaders(USER1.getName()), MINOR_UPDATE, change);
EntityUpdater.setSessionTimeout(10 * 60 * 10000); // Reset the session timeout back
}
// Update displayName to a new displayName.
// In this test, the user who previously made a change makes the change after session timeout.
// The changes are not consolidated.
EntityUpdater.setSessionTimeout(1); // Reduce the session timeout for this test
java.lang.Thread.sleep(2);
json = JsonUtils.pojoToJson(entity);
entity.setDisplayName("displayName1");
change = getChangeDescription(entity, MINOR_UPDATE); // Version changes
fieldUpdated(change, "displayName", "displayName", "displayName1");
patchEntityAndCheck(entity, json, authHeaders(USER1.getName()), MINOR_UPDATE, change);
EntityUpdater.setSessionTimeout(10 * 60 * 10000); // Reset the session timeout back
}
@Test
@ -2110,13 +2029,13 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
String json = JsonUtils.pojoToJson(entityType);
ChangeDescription change =
getChangeDescription(entityType, CHANGE_CONSOLIDATED); // Patch operation update is
// consolidated in a session
fieldAdded(change, "customProperties", CommonUtil.listOf(fieldA, fieldB));
getChangeDescription(entityType, MINOR_UPDATE); // Patch operation update is
fieldAdded(change, "customProperties", CommonUtil.listOf(fieldB));
entityType.getCustomProperties().add(fieldB);
entityType =
typeResourceTest.patchEntityAndCheck(
entityType, json, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
entityType, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
// PUT invalid custom fields to the entity - custom field has invalid type
Type invalidType =
@ -2169,20 +2088,9 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
jsonNode.set("stringB", stringBValue);
entity.setExtension(jsonNode);
change = getChangeDescription(entity, getChangeType()); // PATCH operation update is not
if (!isParent()) {
fieldUpdated(
change,
EntityUtil.getExtensionField("intA"),
mapper.convertValue(1, JsonNode.class),
intAValue);
fieldAdded(change, "extension", List.of(JsonUtils.getObjectNode("stringB", stringBValue)));
entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, getChangeType(), change);
assertEquals(JsonUtils.valueToTree(jsonNode), JsonUtils.valueToTree(entity.getExtension()));
} else {
fieldAdded(change, "extension", List.of(JsonUtils.getObjectNode("stringB", stringBValue)));
entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, getChangeType(), change);
assertEquals(JsonUtils.valueToTree(jsonNode), JsonUtils.valueToTree(entity.getExtension()));
}
fieldAdded(change, "extension", List.of(JsonUtils.getObjectNode("stringB", stringBValue)));
entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, getChangeType(), change);
assertEquals(JsonUtils.valueToTree(jsonNode), JsonUtils.valueToTree(entity.getExtension()));
// PUT and remove field intA from the entity extension - *** for BOT this should be ignored ***
JsonNode oldNode = JsonUtils.valueToTree(entity.getExtension());
@ -2201,34 +2109,15 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
entity = updateAndCheckEntity(create, Status.OK, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
assertEquals(
JsonUtils.valueToTree(create.getExtension()), JsonUtils.valueToTree(entity.getExtension()));
if (!isParent()) {
// PATCH and remove field stringB from the entity extension
json = JsonUtils.pojoToJson(entity);
jsonNode.remove("stringB");
entity.setExtension(jsonNode);
change =
getChangeDescription(
entity, CHANGE_CONSOLIDATED); // PATCH operation update is consolidated into a session
fieldDeleted(
change,
"extension",
List.of(
JsonUtils.getObjectNode("intA", intAValue),
JsonUtils.getObjectNode("stringB", stringBValue)));
entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, getChangeType(), change);
assertEquals(JsonUtils.valueToTree(jsonNode), JsonUtils.valueToTree(entity.getExtension()));
} else {
json = JsonUtils.pojoToJson(entity);
jsonNode.remove("stringB");
entity.setExtension(jsonNode);
change =
getChangeDescription(
entity, MINOR_UPDATE); // PATCH operation update is consolidated into a session
fieldDeleted(change, "extension", List.of(JsonUtils.getObjectNode("stringB", stringBValue)));
entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, getChangeType(), change);
assertEquals(JsonUtils.valueToTree(jsonNode), JsonUtils.valueToTree(entity.getExtension()));
}
json = JsonUtils.pojoToJson(entity);
jsonNode.remove("stringB");
entity.setExtension(jsonNode);
change =
getChangeDescription(
entity, MINOR_UPDATE); // PATCH operation update is consolidated into a session
fieldDeleted(change, "extension", List.of(JsonUtils.getObjectNode("stringB", stringBValue)));
entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, getChangeType(), change);
assertEquals(JsonUtils.valueToTree(jsonNode), JsonUtils.valueToTree(entity.getExtension()));
// Now set the entity custom property to an invalid value
jsonNode.set(
@ -3140,14 +3029,17 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
validateCommonEntityFields(updated, returned, updatedBy);
compareEntities(updated, returned, authHeaders);
validateChangeDescription(returned, updateType, expectedChange);
validateEntityHistory(returned.getId(), updateType, expectedChange, authHeaders);
validateLatestVersion(returned, updateType, expectedChange, authHeaders);
// since we are returning incremental changeevent as in response, this part would be difficult
// to test
// requires the test to pass incremental and aggregate change events
// validateEntityHistory(returned.getId(), updateType, expectedChange, authHeaders);
// validateLatestVersion(returned, updateType, expectedChange, authHeaders);
// GET the entity and Validate information returned
T getEntity = getEntity(returned.getId(), authHeaders);
validateCommonEntityFields(updated, returned, updatedBy);
compareEntities(updated, getEntity, authHeaders);
validateChangeDescription(getEntity, updateType, expectedChange);
// validateChangeDescription(getEntity, updateType, expectedChange);
// Check if the entity change events are record
if (listOf(CREATED, MINOR_UPDATE, MAJOR_UPDATE).contains(updateType)) {
@ -3180,14 +3072,14 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
validateCommonEntityFields(updated, returned, updatedBy);
compareEntities(updated, returned, authHeaders);
validateChangeDescription(returned, updateType, expectedChange);
validateEntityHistory(returned.getId(), updateType, expectedChange, authHeaders);
validateLatestVersion(returned, updateType, expectedChange, authHeaders);
// validateEntityHistory(returned.getId(), updateType, expectedChange, authHeaders);
// validateLatestVersion(returned, updateType, expectedChange, authHeaders);
// GET the entity and Validate information returned
T getEntity = getEntity(returned.getId(), authHeaders);
validateCommonEntityFields(updated, returned, updatedBy);
compareEntities(updated, getEntity, authHeaders);
validateChangeDescription(getEntity, updateType, expectedChange);
// validateChangeDescription(getEntity, updateType, expectedChange);
// Check if the entity change events are record
if (listOf(CREATED, MINOR_UPDATE, MAJOR_UPDATE).contains(updateType)) {
@ -4426,14 +4318,6 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
}
public UpdateType getChangeType() {
if (isParent()) {
return MINOR_UPDATE;
} else {
return CHANGE_CONSOLIDATED;
}
}
public boolean isParent() {
return PARENT_ENTITY_TYPES.contains(entityType);
return MINOR_UPDATE;
}
}

View File

@ -247,6 +247,7 @@ public class APIEndpointResourceTest extends EntityResourceTest<APIEndpoint, Cre
endpoint = getAPIEndpoint(apiEndpoint.getId(), "tags", ADMIN_AUTH_HEADERS);
List<Field> requestFields = endpoint.getRequestSchema().getSchemaFields();
assertFields(api_response_fields, requestFields);
endpointJson = JsonUtils.pojoToJson(endpoint);
requestFields.get(0).getTags().add(PII_SENSITIVE_TAG_LABEL);
requestFields.get(0).getTags().add(USER_ADDRESS_TAG_LABEL);
patchEntity(endpoint.getId(), endpointJson, endpoint, ADMIN_AUTH_HEADERS);

View File

@ -23,7 +23,6 @@ import static org.openmetadata.service.util.EntityUtil.fieldAdded;
import static org.openmetadata.service.util.EntityUtil.fieldDeleted;
import static org.openmetadata.service.util.EntityUtil.fieldUpdated;
import static org.openmetadata.service.util.TestUtils.ADMIN_AUTH_HEADERS;
import static org.openmetadata.service.util.TestUtils.UpdateType.CHANGE_CONSOLIDATED;
import static org.openmetadata.service.util.TestUtils.UpdateType.MINOR_UPDATE;
import static org.openmetadata.service.util.TestUtils.assertListNotNull;
import static org.openmetadata.service.util.TestUtils.assertListNull;
@ -164,12 +163,12 @@ public class ChartResourceTest extends EntityResourceTest<Chart, CreateChart> {
// Update description, chartType and chart url and verify patch
// Changes from this PATCH is consolidated with the previous changes
originalJson = JsonUtils.pojoToJson(chart);
change = getChangeDescription(chart, CHANGE_CONSOLIDATED);
fieldAdded(change, "description", "desc2");
fieldAdded(change, "chartType", type2);
fieldAdded(change, "sourceUrl", "url2");
change = getChangeDescription(chart, MINOR_UPDATE);
fieldUpdated(change, "description", "desc1", "desc2");
fieldUpdated(change, "chartType", type1, type2);
fieldUpdated(change, "sourceUrl", "url1", "url2");
chart.withChartType(type2).withSourceUrl("url2").withDescription("desc2");
patchEntityAndCheck(chart, originalJson, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
patchEntityAndCheck(chart, originalJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
}
@Test
@ -277,13 +276,12 @@ public class ChartResourceTest extends EntityResourceTest<Chart, CreateChart> {
// Update description, chartType and chart url and verify patch
// Changes from this PATCH is consolidated with the previous changes
originalJson = JsonUtils.pojoToJson(chart);
change = getChangeDescription(chart, CHANGE_CONSOLIDATED);
fieldAdded(change, "description", "desc2");
fieldAdded(change, "chartType", type2);
fieldAdded(change, "sourceUrl", "url2");
change = getChangeDescription(chart, MINOR_UPDATE);
fieldUpdated(change, "description", "desc1", "desc2");
fieldUpdated(change, "chartType", type1, type2);
fieldUpdated(change, "sourceUrl", "url1", "url2");
chart.withChartType(type2).withSourceUrl("url2").withDescription("desc2");
patchEntityUsingFqnAndCheck(
chart, originalJson, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
patchEntityUsingFqnAndCheck(chart, originalJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
}
@Test

View File

@ -59,11 +59,9 @@ import static org.openmetadata.service.util.EntityUtil.tagLabelMatch;
import static org.openmetadata.service.util.FullyQualifiedName.build;
import static org.openmetadata.service.util.RestUtil.DATE_FORMAT;
import static org.openmetadata.service.util.TestUtils.*;
import static org.openmetadata.service.util.TestUtils.UpdateType.CHANGE_CONSOLIDATED;
import static org.openmetadata.service.util.TestUtils.UpdateType.MAJOR_UPDATE;
import static org.openmetadata.service.util.TestUtils.UpdateType.MINOR_UPDATE;
import static org.openmetadata.service.util.TestUtils.UpdateType.NO_CHANGE;
import static org.openmetadata.service.util.TestUtils.UpdateType.REVERT;
import com.google.common.collect.Lists;
import es.org.elasticsearch.client.Request;
@ -430,7 +428,7 @@ public class TableResourceTest extends EntityResourceTest<Table, CreateTable> {
// Change the case of the column name for column2, and it shouldn't update
column2.setName("COLUMN2");
change = getChangeDescription(table, NO_CHANGE);
updateAndCheckEntity(create, OK, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
updateAndCheckEntity(create, OK, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
}
public static Column getColumn(String name, ColumnDataType columnDataType, TagLabel tag) {
@ -1836,25 +1834,30 @@ public class TableResourceTest extends EntityResourceTest<Table, CreateTable> {
.withConstraintType(ConstraintType.UNIQUE)
.withColumns(List.of(C2)));
originalJson = JsonUtils.pojoToJson(table);
change = getChangeDescription(table, CHANGE_CONSOLIDATED);
change = getChangeDescription(table, MINOR_UPDATE);
change.setPreviousVersion(table.getVersion());
table.withTableType(TableType.External).withTableConstraints(tableConstraints1);
fieldAdded(change, "tableType", TableType.External);
fieldUpdated(change, "tableType", TableType.Regular, TableType.External);
fieldAdded(change, "tableConstraints", tableConstraints1);
table =
patchEntityAndCheck(table, originalJson, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
fieldDeleted(change, "tableConstraints", tableConstraints);
table = patchEntityAndCheck(table, originalJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
// Remove tableType, tableConstraints
// Changes from this PATCH is consolidated with the previous changes resulting in no change
change = getChangeDescription(table, MINOR_UPDATE);
fieldDeleted(change, "tableType", TableType.External);
fieldDeleted(change, "tableConstraints", tableConstraints1);
originalJson = JsonUtils.pojoToJson(table);
table.withTableType(null).withTableConstraints(null);
patchEntityAndCheck(table, originalJson, ADMIN_AUTH_HEADERS, REVERT, null);
table = patchEntityAndCheck(table, originalJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
// add retention period
originalJson = JsonUtils.pojoToJson(table);
table.withRetentionPeriod("10D");
change = getChangeDescription(table, CHANGE_CONSOLIDATED);
change = getChangeDescription(table, MINOR_UPDATE);
change.setPreviousVersion(table.getVersion());
fieldAdded(change, "retentionPeriod", "10D");
patchEntityAndCheck(table, originalJson, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
patchEntityAndCheck(table, originalJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
}
@Test
@ -1893,13 +1896,8 @@ public class TableResourceTest extends EntityResourceTest<Table, CreateTable> {
// Now reduce the precision and make sure it is a backward incompatible change
// Changes from this PATCH is consolidated with the previous changes
change = getChangeDescription(table, CHANGE_CONSOLIDATED);
fieldAdded(change, build("columns", C1, "description"), "new0");
fieldAdded(change, build("columns", C1, "tags"), List.of(GLOSSARY1_TERM1_LABEL));
fieldUpdated(change, build("columns", C2, "description"), C2, "new1");
fieldDeleted(change, build("columns", C3, "tags"), List.of(GLOSSARY1_TERM1_LABEL));
fieldAdded(change, build("columns", C3, "precision"), 7); // Change in this patch
fieldAdded(change, build("columns", C3, "scale"), 3);
change = getChangeDescription(table, MINOR_UPDATE);
fieldUpdated(change, build("columns", C3, "precision"), 10, 7); // Change in this patch
originalJson = JsonUtils.pojoToJson(table);
columns = table.getColumns();
columns
@ -1907,19 +1905,13 @@ public class TableResourceTest extends EntityResourceTest<Table, CreateTable> {
.withPrecision(7)
.withScale(3); // Precision change from 10 to 7. Scale remains the same
table.setColumns(columns);
table =
patchEntityAndCheck(table, originalJson, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
table = patchEntityAndCheck(table, originalJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
assertColumns(columns, table.getColumns());
// Now reduce the scale and make sure it is a backward incompatible change
// Changes from this PATCH is consolidated with the previous changes
change = getChangeDescription(table, CHANGE_CONSOLIDATED);
fieldAdded(change, build("columns", C1, "description"), "new0");
fieldAdded(change, build("columns", C1, "tags"), List.of(GLOSSARY1_TERM1_LABEL));
fieldUpdated(change, build("columns", C2, "description"), C2, "new1");
fieldDeleted(change, build("columns", C3, "tags"), List.of(GLOSSARY1_TERM1_LABEL));
fieldAdded(change, build("columns", C3, "precision"), 7);
fieldAdded(change, build("columns", C3, "scale"), 1); // Change in this patch
change = getChangeDescription(table, MINOR_UPDATE);
fieldUpdated(change, build("columns", C3, "scale"), 3, 1); // Change in this patch
originalJson = JsonUtils.pojoToJson(table);
columns = table.getColumns();
columns
@ -1927,8 +1919,7 @@ public class TableResourceTest extends EntityResourceTest<Table, CreateTable> {
.withPrecision(7)
.withScale(1); // Scale change from 10 to 7. Scale remains the same
table.setColumns(columns);
table =
patchEntityAndCheck(table, originalJson, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
table = patchEntityAndCheck(table, originalJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
assertColumns(columns, table.getColumns());
}
@ -2017,27 +2008,32 @@ public class TableResourceTest extends EntityResourceTest<Table, CreateTable> {
.withConstraintType(ConstraintType.UNIQUE)
.withColumns(List.of(C2)));
originalJson = JsonUtils.pojoToJson(table);
change = getChangeDescription(table, CHANGE_CONSOLIDATED);
change = getChangeDescription(table, MINOR_UPDATE);
table.withTableType(TableType.External).withTableConstraints(tableConstraints1);
fieldAdded(change, "tableType", TableType.External);
fieldUpdated(change, "tableType", TableType.Regular, TableType.External);
fieldDeleted(change, "tableConstraints", tableConstraints);
fieldAdded(change, "tableConstraints", tableConstraints1);
table =
patchEntityUsingFqnAndCheck(
table, originalJson, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
patchEntityUsingFqnAndCheck(table, originalJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
// Remove tableType, tableConstraints
// Changes from this PATCH is consolidated with the previous changes resulting in no change
change = getChangeDescription(table, MINOR_UPDATE);
change.setPreviousVersion(table.getVersion());
fieldDeleted(change, "tableType", TableType.External);
fieldDeleted(change, "tableConstraints", tableConstraints1);
originalJson = JsonUtils.pojoToJson(table);
table.withTableType(null).withTableConstraints(null);
patchEntityUsingFqnAndCheck(table, originalJson, ADMIN_AUTH_HEADERS, REVERT, null);
table =
patchEntityUsingFqnAndCheck(table, originalJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
// add retention period
originalJson = JsonUtils.pojoToJson(table);
table.withRetentionPeriod("10D");
change = getChangeDescription(table, CHANGE_CONSOLIDATED);
change = getChangeDescription(table, MINOR_UPDATE);
change.setPreviousVersion(table.getVersion());
fieldAdded(change, "retentionPeriod", "10D");
patchEntityUsingFqnAndCheck(
table, originalJson, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
patchEntityUsingFqnAndCheck(table, originalJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
}
@Test
@ -2077,13 +2073,8 @@ public class TableResourceTest extends EntityResourceTest<Table, CreateTable> {
// Now reduce the precision and make sure it is a backward incompatible change
// Changes from this PATCH is consolidated with the previous changes
change = getChangeDescription(table, CHANGE_CONSOLIDATED);
fieldAdded(change, build("columns", C1, "description"), "new0");
fieldAdded(change, build("columns", C1, "tags"), List.of(GLOSSARY1_TERM1_LABEL));
fieldUpdated(change, build("columns", C2, "description"), C2, "new1");
fieldDeleted(change, build("columns", C3, "tags"), List.of(GLOSSARY1_TERM1_LABEL));
fieldAdded(change, build("columns", C3, "precision"), 7); // Change in this patch
fieldAdded(change, build("columns", C3, "scale"), 3);
change = getChangeDescription(table, MINOR_UPDATE);
fieldUpdated(change, build("columns", C3, "precision"), 10, 7); // Change in this patch
originalJson = JsonUtils.pojoToJson(table);
columns = table.getColumns();
columns
@ -2092,19 +2083,13 @@ public class TableResourceTest extends EntityResourceTest<Table, CreateTable> {
.withScale(3); // Precision change from 10 to 7. Scale remains the same
table.setColumns(columns);
table =
patchEntityUsingFqnAndCheck(
table, originalJson, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
patchEntityUsingFqnAndCheck(table, originalJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
assertColumns(columns, table.getColumns());
// Now reduce the scale and make sure it is a backward incompatible change
// Changes from this PATCH is consolidated with the previous changes
change = getChangeDescription(table, CHANGE_CONSOLIDATED);
fieldAdded(change, build("columns", C1, "description"), "new0");
fieldAdded(change, build("columns", C1, "tags"), List.of(GLOSSARY1_TERM1_LABEL));
fieldUpdated(change, build("columns", C2, "description"), C2, "new1");
fieldDeleted(change, build("columns", C3, "tags"), List.of(GLOSSARY1_TERM1_LABEL));
fieldAdded(change, build("columns", C3, "precision"), 7);
fieldAdded(change, build("columns", C3, "scale"), 1); // Change in this patch
change = getChangeDescription(table, MINOR_UPDATE);
fieldUpdated(change, build("columns", C3, "scale"), 3, 1);
originalJson = JsonUtils.pojoToJson(table);
columns = table.getColumns();
columns
@ -2113,8 +2098,7 @@ public class TableResourceTest extends EntityResourceTest<Table, CreateTable> {
.withScale(1); // Scale change from 10 to 7. Scale remains the same
table.setColumns(columns);
table =
patchEntityUsingFqnAndCheck(
table, originalJson, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
patchEntityUsingFqnAndCheck(table, originalJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
assertColumns(columns, table.getColumns());
}
@ -3509,6 +3493,8 @@ public class TableResourceTest extends EntityResourceTest<Table, CreateTable> {
List<TableConstraint> actualConstraints =
JsonUtils.readObjects(actual.toString(), TableConstraint.class);
assertEquals(expectedConstraints, actualConstraints);
} else if (fieldName.contains("columns") && fieldName.equals("precision")) {
assertEquals(expected, actual);
} else if (fieldName.contains("columns") && !fieldName.endsWith(FIELD_TAGS)) {
assertColumnsFieldChange(expected, actual);
} else if (fieldName.endsWith("tableType")) {

View File

@ -10,7 +10,6 @@ import static org.openmetadata.service.util.EntityUtil.fieldAdded;
import static org.openmetadata.service.util.EntityUtil.fieldDeleted;
import static org.openmetadata.service.util.TestUtils.*;
import static org.openmetadata.service.util.TestUtils.UpdateType.MINOR_UPDATE;
import static org.openmetadata.service.util.TestUtils.UpdateType.REVERT;
import java.io.IOException;
import java.util.HashMap;
@ -88,9 +87,10 @@ public class DataProductResourceTest extends EntityResourceTest<DataProduct, Cre
// Version 0.2 - Changes from this PATCH is consolidated with the previous changes resulting in
// no change
String json = JsonUtils.pojoToJson(product);
change = getChangeDescription(product, REVERT);
change = getChangeDescription(product, MINOR_UPDATE);
fieldAdded(change, FIELD_ASSETS, listOf(topic.getEntityReference()));
product.withAssets(List.of(TEST_TABLE1.getEntityReference(), topic.getEntityReference()));
product = patchEntityAndCheck(product, json, ADMIN_AUTH_HEADERS, REVERT, change);
product = patchEntityAndCheck(product, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
entityInDataProduct(topic, product, true); // topic is part of data product
// Remove asset topic with PATCH
@ -98,9 +98,9 @@ public class DataProductResourceTest extends EntityResourceTest<DataProduct, Cre
// topic
json = JsonUtils.pojoToJson(product);
product.withAssets(List.of(TEST_TABLE1.getEntityReference()));
change = getChangeDescription(product, REVERT);
change = getChangeDescription(product, MINOR_UPDATE);
fieldDeleted(change, FIELD_ASSETS, listOf(topic.getEntityReference()));
product = patchEntityAndCheck(product, json, ADMIN_AUTH_HEADERS, REVERT, change);
product = patchEntityAndCheck(product, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
entityInDataProduct(topic, product, false); // topic is not part of data product
}
@ -125,17 +125,19 @@ public class DataProductResourceTest extends EntityResourceTest<DataProduct, Cre
// Add User2 as expert using PATCH
// Changes from this PATCH is consolidated resulting in revert of previous PUT
String json = JsonUtils.pojoToJson(product);
change = getChangeDescription(product, REVERT);
change = getChangeDescription(product, MINOR_UPDATE);
fieldAdded(change, "experts", listOf(USER2.getEntityReference()));
product.withExperts(List.of(USER1.getEntityReference(), USER2.getEntityReference()));
product = patchEntityAndCheck(product, json, ADMIN_AUTH_HEADERS, REVERT, change);
product = patchEntityAndCheck(product, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
// Remove User2 as expert using PATCH
// Changes from this PATCH is consolidated with the previous changes resulting in deletion of
// USER2
json = JsonUtils.pojoToJson(product);
product.withExperts(List.of(USER1.getEntityReference()));
change = getChangeDescription(product, REVERT);
patchEntityAndCheck(product, json, ADMIN_AUTH_HEADERS, REVERT, change);
change = getChangeDescription(product, MINOR_UPDATE);
fieldDeleted(change, "experts", listOf(USER2.getEntityReference()));
patchEntityAndCheck(product, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
}
@Test

View File

@ -43,7 +43,6 @@ import static org.openmetadata.service.util.EntityUtil.fieldUpdated;
import static org.openmetadata.service.util.TestUtils.ADMIN_AUTH_HEADERS;
import static org.openmetadata.service.util.TestUtils.TEST_AUTH_HEADERS;
import static org.openmetadata.service.util.TestUtils.TEST_USER_NAME;
import static org.openmetadata.service.util.TestUtils.UpdateType.CHANGE_CONSOLIDATED;
import static org.openmetadata.service.util.TestUtils.UpdateType.MINOR_UPDATE;
import static org.openmetadata.service.util.TestUtils.assertEntityPagination;
import static org.openmetadata.service.util.TestUtils.assertListNotEmpty;
@ -1237,11 +1236,12 @@ public class TestCaseResourceTest extends EntityResourceTest<TestCase, CreateTes
// Update description with PATCH
// Changes from this PATCH is consolidated with the previous changes
newDescription = "description2";
change = getChangeDescription(testCase, CHANGE_CONSOLIDATED);
fieldUpdated(change, "description", oldDescription, newDescription);
change = getChangeDescription(testCase, MINOR_UPDATE);
change.setPreviousVersion(testCase.getVersion());
fieldUpdated(change, "description", "description1", newDescription);
String json = JsonUtils.pojoToJson(testCase);
testCase.setDescription(newDescription);
testCase = patchEntityAndCheck(testCase, json, ownerAuthHeaders, CHANGE_CONSOLIDATED, change);
testCase = patchEntityAndCheck(testCase, json, ownerAuthHeaders, MINOR_UPDATE, change);
// Delete the testcase
deleteAndCheckEntity(testCase, ownerAuthHeaders);

View File

@ -40,10 +40,7 @@ import static org.openmetadata.service.util.EntityUtil.getFqn;
import static org.openmetadata.service.util.EntityUtil.getId;
import static org.openmetadata.service.util.EntityUtil.toTagLabels;
import static org.openmetadata.service.util.TestUtils.*;
import static org.openmetadata.service.util.TestUtils.UpdateType.CHANGE_CONSOLIDATED;
import static org.openmetadata.service.util.TestUtils.UpdateType.MINOR_UPDATE;
import static org.openmetadata.service.util.TestUtils.UpdateType.NO_CHANGE;
import static org.openmetadata.service.util.TestUtils.UpdateType.REVERT;
import java.io.IOException;
import java.net.URI;
@ -303,11 +300,11 @@ public class GlossaryTermResourceTest extends EntityResourceTest<GlossaryTerm, C
term.withReviewers(List.of(USER1_REF, USER2_REF))
.withSynonyms(List.of("synonym1", "synonym2"))
.withReferences(List.of(reference1, reference2));
change = getChangeDescription(term, CHANGE_CONSOLIDATED);
fieldAdded(change, "reviewers", List.of(USER1_REF, USER2_REF));
fieldAdded(change, "synonyms", List.of("synonym1", "synonym2"));
fieldAdded(change, "references", List.of(reference1, reference2));
term = patchEntityAndCheck(term, origJson, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
change = getChangeDescription(term, MINOR_UPDATE);
fieldAdded(change, "reviewers", List.of(USER2_REF));
fieldAdded(change, "synonyms", List.of("synonym2"));
fieldAdded(change, "references", List.of(reference2));
term = patchEntityAndCheck(term, origJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
// Remove a reviewer USER1, synonym1, reference1 in PATCH request
// Changes from this PATCH is consolidated with the previous changes resulting in no change
@ -315,11 +312,11 @@ public class GlossaryTermResourceTest extends EntityResourceTest<GlossaryTerm, C
term.withReviewers(List.of(USER2_REF))
.withSynonyms(List.of("synonym2"))
.withReferences(List.of(reference2));
change = getChangeDescription(term, CHANGE_CONSOLIDATED);
fieldAdded(change, "reviewers", List.of(USER2_REF));
fieldAdded(change, "synonyms", List.of("synonym2"));
fieldAdded(change, "references", List.of(reference2));
patchEntityAndCheck(term, origJson, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
change = getChangeDescription(term, MINOR_UPDATE);
fieldDeleted(change, "reviewers", List.of(USER1_REF));
fieldDeleted(change, "synonyms", List.of("synonym1"));
fieldDeleted(change, "references", List.of(reference1));
patchEntityAndCheck(term, origJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
// Note: We are re-enabling the GlossaryTermApprovalWorkflow.
WorkflowHandler.getInstance().resumeWorkflow("GlossaryTermApprovalWorkflow");
@ -343,8 +340,9 @@ public class GlossaryTermResourceTest extends EntityResourceTest<GlossaryTerm, C
// Remove reference in PATCH request
origJson = JsonUtils.pojoToJson(term);
term.withReferences(null);
change = getChangeDescription(term, REVERT);
patchEntityAndCheck(term, origJson, ADMIN_AUTH_HEADERS, REVERT, change);
change = getChangeDescription(term, MINOR_UPDATE);
fieldDeleted(change, "references", List.of(reference1));
patchEntityAndCheck(term, origJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
}
@Test
@ -498,7 +496,7 @@ public class GlossaryTermResourceTest extends EntityResourceTest<GlossaryTerm, C
// Due to the Glossary Workflow changing the Status from 'DRAFT' to 'IN_REVIEW' as a
// GovernanceBot, two changes are created.
assertEquals(g2t5.getVersion(), previousVersion + 0.2, 0.0001);
assertEquals(g2t5.getVersion(), previousVersion + 0.1);
assertTrue(
g2t5.getReviewers().containsAll(newReviewers)
&& newReviewers.containsAll(g2t5.getReviewers()));
@ -541,13 +539,11 @@ public class GlossaryTermResourceTest extends EntityResourceTest<GlossaryTerm, C
term.withReviewers(List.of(USER1_REF, USER2_REF))
.withSynonyms(List.of("synonym1", "synonym2"))
.withReferences(List.of(reference1, reference2));
change = getChangeDescription(term, CHANGE_CONSOLIDATED);
fieldAdded(change, "reviewers", List.of(USER1_REF, USER2_REF));
fieldAdded(change, "synonyms", List.of("synonym1", "synonym2"));
fieldAdded(change, "references", List.of(reference1, reference2));
term =
patchEntityUsingFqnAndCheck(
term, origJson, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
change = getChangeDescription(term, MINOR_UPDATE);
fieldAdded(change, "reviewers", List.of(USER2_REF));
fieldAdded(change, "synonyms", List.of("synonym2"));
fieldAdded(change, "references", List.of(reference2));
term = patchEntityUsingFqnAndCheck(term, origJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
// Remove a reviewer USER1, synonym1, reference1 in PATCH request
// Changes from this PATCH is consolidated with the previous changes resulting in no change
@ -555,11 +551,11 @@ public class GlossaryTermResourceTest extends EntityResourceTest<GlossaryTerm, C
term.withReviewers(List.of(USER2_REF))
.withSynonyms(List.of("synonym2"))
.withReferences(List.of(reference2));
change = getChangeDescription(term, CHANGE_CONSOLIDATED);
fieldAdded(change, "reviewers", List.of(USER2_REF));
fieldAdded(change, "synonyms", List.of("synonym2"));
fieldAdded(change, "references", List.of(reference2));
patchEntityUsingFqnAndCheck(term, origJson, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
change = getChangeDescription(term, MINOR_UPDATE);
fieldDeleted(change, "reviewers", List.of(USER1_REF));
fieldDeleted(change, "synonyms", List.of("synonym1"));
fieldDeleted(change, "references", List.of(reference1));
patchEntityUsingFqnAndCheck(term, origJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
}
@Test
@ -580,8 +576,9 @@ public class GlossaryTermResourceTest extends EntityResourceTest<GlossaryTerm, C
// Remove reference in PATCH request
origJson = JsonUtils.pojoToJson(term);
term.withReferences(null);
change = getChangeDescription(term, REVERT);
patchEntityUsingFqnAndCheck(term, origJson, ADMIN_AUTH_HEADERS, REVERT, change);
change = getChangeDescription(term, MINOR_UPDATE);
fieldDeleted(change, "references", List.of(reference1));
patchEntityUsingFqnAndCheck(term, origJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
}
@Test
@ -747,8 +744,9 @@ public class GlossaryTermResourceTest extends EntityResourceTest<GlossaryTerm, C
// Changes from this PATCH is consolidated with the previous changes resulting in no change
json = JsonUtils.pojoToJson(term1);
term1.setStyle(null);
change = getChangeDescription(term1, REVERT);
patchEntityAndCheck(term1, json, ADMIN_AUTH_HEADERS, REVERT, change);
change = getChangeDescription(term1, MINOR_UPDATE);
fieldDeleted(change, "style", style);
patchEntityAndCheck(term1, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
term1 = getEntity(term1.getId(), ADMIN_AUTH_HEADERS);
assertNull(term1.getStyle());
}
@ -1300,7 +1298,7 @@ public class GlossaryTermResourceTest extends EntityResourceTest<GlossaryTerm, C
change = change == null ? getChangeDescription(term, update) : change;
fieldUpdated(change, "parent", oldParent, newParent);
} else {
update = update != null ? update : NO_CHANGE;
update = update != null ? update : MINOR_UPDATE;
change = change == null ? getChangeDescription(term, update) : change;
}

View File

@ -19,7 +19,6 @@ import static org.openmetadata.common.utils.CommonUtil.listOrEmpty;
import static org.openmetadata.service.util.EntityUtil.fieldAdded;
import static org.openmetadata.service.util.EntityUtil.fieldUpdated;
import static org.openmetadata.service.util.TestUtils.ADMIN_AUTH_HEADERS;
import static org.openmetadata.service.util.TestUtils.UpdateType.CHANGE_CONSOLIDATED;
import static org.openmetadata.service.util.TestUtils.UpdateType.MINOR_UPDATE;
import static org.openmetadata.service.util.TestUtils.assertCustomProperties;
import static org.openmetadata.service.util.TestUtils.assertResponse;
@ -141,15 +140,14 @@ public class TypeResourceTest extends EntityResourceTest<Type, CreateType> {
fieldA.withDescription("updated2").withDisplayName("Updated Integer A 2");
String json = JsonUtils.pojoToJson(topicEntity);
topicEntity.setCustomProperties(List.of(fieldA));
change = getChangeDescription(topicEntity, CHANGE_CONSOLIDATED);
fieldUpdated(change, EntityUtil.getCustomField(fieldA, "description"), "intA", "updated2");
change = getChangeDescription(topicEntity, MINOR_UPDATE);
fieldUpdated(change, EntityUtil.getCustomField(fieldA, "description"), "updated", "updated2");
fieldUpdated(
change,
EntityUtil.getCustomField(fieldA, "displayName"),
"Integer A",
"Updated Integer A",
"Updated Integer A 2");
topicEntity =
patchEntityAndCheck(topicEntity, json, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
topicEntity = patchEntityAndCheck(topicEntity, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
// Add a second property with name intB with type integer
// Note that since this is PUT operation, the previous changes are not consolidated
@ -279,21 +277,6 @@ public class TypeResourceTest extends EntityResourceTest<Type, CreateType> {
tableEntity.getId(), enumFieldA, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change5);
assertCustomProperties(new ArrayList<>(List.of(enumFieldA)), tableEntity.getCustomProperties());
// Changing custom property description with PATCH
// Changes from this PATCH is consolidated with the previous changes
enumFieldA.withDescription("updated2");
String json = JsonUtils.pojoToJson(tableEntity);
tableEntity.setCustomProperties(List.of(enumFieldA));
change = getChangeDescription(tableEntity, CHANGE_CONSOLIDATED);
fieldUpdated(
change5,
EntityUtil.getCustomField(enumFieldA, "description"),
"updatedEnumTest",
"updated2");
tableEntity =
patchEntityAndCheck(tableEntity, json, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change5);
/* // Add a second property with name intB with type integer
// Note that since this is PUT operation, the previous changes are not consolidated
EntityReference typeRef =
@ -424,16 +407,7 @@ public class TypeResourceTest extends EntityResourceTest<Type, CreateType> {
tableTypeFieldA.withDescription("updated tableCustomPropertyTest description 2");
String json = JsonUtils.pojoToJson(databaseEntity);
databaseEntity.setCustomProperties(List.of(tableTypeFieldA));
change = getChangeDescription(databaseEntity, CHANGE_CONSOLIDATED);
fieldUpdated(
change6,
EntityUtil.getCustomField(tableTypeFieldA, "description"),
"updated tableCustomPropertyTest description",
"updated tableCustomPropertyTest description 2");
databaseEntity =
patchEntityAndCheck(databaseEntity, json, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change6);
change6 = getChangeDescription(databaseEntity, MINOR_UPDATE);
}
@Test

View File

@ -521,30 +521,30 @@ public class PipelineResourceTest extends EntityResourceTest<Pipeline, CreatePip
// add description and tags to an existing task - taskEmpty
// Changes from this PATCH is consolidated with the previous changes
origJson = JsonUtils.pojoToJson(pipeline);
change = getChangeDescription(pipeline, CHANGE_CONSOLIDATED);
change = getChangeDescription(pipeline, MINOR_UPDATE);
List<Task> newTasks = new ArrayList<>();
Task taskWithDesc =
taskEmptyDesc
.withDescription("taskDescription")
.withTags(List.of(USER_ADDRESS_TAG_LABEL, PII_SENSITIVE_TAG_LABEL));
newTasks.add(taskWithDesc);
fieldAdded(change, "tasks", newTasks);
fieldUpdated(change, "description", "", "newDescription");
fieldAdded(change, "tasks.taskEmpty.description", "taskDescription");
fieldAdded(
change, "tasks.taskEmpty.tags", List.of(USER_ADDRESS_TAG_LABEL, PII_SENSITIVE_TAG_LABEL));
List<Task> updatedNewTasks =
Stream.concat(TASKS.stream(), newTasks.stream()).collect(Collectors.toList());
pipeline.setTasks(updatedNewTasks);
pipeline =
patchEntityAndCheck(pipeline, origJson, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
pipeline = patchEntityAndCheck(pipeline, origJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
// Update the descriptions of pipeline and task and add tags to tasks
// Changes from this PATCH is consolidated with the previous changes
origJson = JsonUtils.pojoToJson(pipeline);
change = getChangeDescription(pipeline, CHANGE_CONSOLIDATED);
change = getChangeDescription(pipeline, MINOR_UPDATE);
newTasks = new ArrayList<>();
taskWithDesc = taskEmptyDesc.withDescription("newTaskDescription");
newTasks.add(taskWithDesc);
fieldAdded(change, "tasks", tasks);
fieldUpdated(change, "description", "", "newDescription2");
fieldUpdated(change, "description", "newDescription", "newDescription2");
fieldUpdated(change, "tasks.taskEmpty.description", "taskDescription", "newTaskDescription");
updatedNewTasks = Stream.concat(TASKS.stream(), newTasks.stream()).collect(Collectors.toList());
pipeline.setTasks(updatedNewTasks);
pipeline.setDescription("newDescription2");
@ -554,16 +554,16 @@ public class PipelineResourceTest extends EntityResourceTest<Pipeline, CreatePip
// Delete task and pipeline description by setting them to null
// Changes from this PATCH is consolidated with the previous changes
origJson = JsonUtils.pojoToJson(pipeline);
change = getChangeDescription(pipeline, CHANGE_CONSOLIDATED);
change = getChangeDescription(pipeline, MINOR_UPDATE);
newTasks = new ArrayList<>();
Task taskWithoutDesc = taskEmptyDesc.withDescription(null);
newTasks.add(taskWithoutDesc);
updatedNewTasks = Stream.concat(TASKS.stream(), newTasks.stream()).collect(Collectors.toList());
fieldAdded(change, "tasks", newTasks);
pipeline.setTasks(updatedNewTasks);
pipeline.setDescription(
""); // Since description started out to be empty, during consolidation, no change
patchEntityAndCheck(pipeline, origJson, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
pipeline.setDescription("");
fieldUpdated(change, "description", "newDescription2", "");
fieldDeleted(change, "tasks.taskEmpty.description", "newTaskDescription");
patchEntityAndCheck(pipeline, origJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
}
@Test
@ -651,52 +651,51 @@ public class PipelineResourceTest extends EntityResourceTest<Pipeline, CreatePip
// add description and tags to an existing task - taskEmpty
// Changes from this PATCH is consolidated with the previous changes
origJson = JsonUtils.pojoToJson(pipeline);
change = getChangeDescription(pipeline, CHANGE_CONSOLIDATED);
change = getChangeDescription(pipeline, MINOR_UPDATE);
List<Task> newTasks = new ArrayList<>();
Task taskWithDesc =
taskEmptyDesc
.withDescription("taskDescription")
.withTags(List.of(USER_ADDRESS_TAG_LABEL, PII_SENSITIVE_TAG_LABEL));
newTasks.add(taskWithDesc);
fieldAdded(change, "tasks", newTasks);
fieldUpdated(change, "description", "", "newDescription");
fieldAdded(change, "tasks.taskEmpty.description", "taskDescription");
fieldAdded(
change, "tasks.taskEmpty.tags", List.of(USER_ADDRESS_TAG_LABEL, PII_SENSITIVE_TAG_LABEL));
List<Task> updatedNewTasks =
Stream.concat(TASKS.stream(), newTasks.stream()).collect(Collectors.toList());
pipeline.setTasks(updatedNewTasks);
pipeline =
patchEntityUsingFqnAndCheck(
pipeline, origJson, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
patchEntityUsingFqnAndCheck(pipeline, origJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
// Update the descriptions of pipeline and task and add tags to tasks
// Changes from this PATCH is consolidated with the previous changes
origJson = JsonUtils.pojoToJson(pipeline);
change = getChangeDescription(pipeline, CHANGE_CONSOLIDATED);
change = getChangeDescription(pipeline, MINOR_UPDATE);
newTasks = new ArrayList<>();
taskWithDesc = taskEmptyDesc.withDescription("newTaskDescription");
newTasks.add(taskWithDesc);
fieldAdded(change, "tasks", tasks);
fieldUpdated(change, "description", "", "newDescription2");
fieldUpdated(change, "description", "newDescription", "newDescription2");
fieldUpdated(change, "tasks.taskEmpty.description", "taskDescription", "newTaskDescription");
updatedNewTasks = Stream.concat(TASKS.stream(), newTasks.stream()).collect(Collectors.toList());
pipeline.setTasks(updatedNewTasks);
pipeline.setDescription("newDescription2");
pipeline =
patchEntityUsingFqnAndCheck(
pipeline, origJson, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
patchEntityUsingFqnAndCheck(pipeline, origJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
// Delete task and pipeline description by setting them to null
// Changes from this PATCH is consolidated with the previous changes
origJson = JsonUtils.pojoToJson(pipeline);
change = getChangeDescription(pipeline, CHANGE_CONSOLIDATED);
change = getChangeDescription(pipeline, MINOR_UPDATE);
newTasks = new ArrayList<>();
Task taskWithoutDesc = taskEmptyDesc.withDescription(null);
newTasks.add(taskWithoutDesc);
updatedNewTasks = Stream.concat(TASKS.stream(), newTasks.stream()).collect(Collectors.toList());
fieldAdded(change, "tasks", newTasks);
fieldUpdated(change, "description", "newDescription2", "");
fieldDeleted(change, "tasks.taskEmpty.description", "newTaskDescription");
pipeline.setTasks(updatedNewTasks);
pipeline.setDescription(
""); // Since description started out to be empty, during consolidation, no change
patchEntityUsingFqnAndCheck(
pipeline, origJson, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
patchEntityUsingFqnAndCheck(pipeline, origJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
}
@Test

View File

@ -34,7 +34,6 @@ import static org.openmetadata.service.util.EntityUtil.fieldDeleted;
import static org.openmetadata.service.util.EntityUtil.fieldUpdated;
import static org.openmetadata.service.util.EntityUtil.getRuleField;
import static org.openmetadata.service.util.TestUtils.ADMIN_AUTH_HEADERS;
import static org.openmetadata.service.util.TestUtils.UpdateType.CHANGE_CONSOLIDATED;
import static org.openmetadata.service.util.TestUtils.UpdateType.MINOR_UPDATE;
import static org.openmetadata.service.util.TestUtils.assertListNotNull;
import static org.openmetadata.service.util.TestUtils.assertListNull;
@ -356,16 +355,12 @@ public class PolicyResourceTest extends EntityResourceTest<Policy, CreatePolicy>
// Change existing rule1 fields. Update description and condition
// Changes from this PATCH is consolidated with the previous changes
origJson = JsonUtils.pojoToJson(policy);
change = getChangeDescription(policy, CHANGE_CONSOLIDATED);
change = getChangeDescription(policy, MINOR_UPDATE);
rule1.withDescription("newDescription").withCondition("noOwner()");
fieldAdded(change, getRuleField(rule1, FIELD_DESCRIPTION), "newDescription");
fieldUpdated(change, getRuleField(rule1, "effect"), ALLOW, DENY);
fieldUpdated(
change, getRuleField(rule1, "resources"), List.of(ALL_RESOURCES), List.of("table"));
fieldUpdated(change, getRuleField(rule1, "operations"), List.of(VIEW_ALL), List.of(EDIT_ALL));
fieldAdded(change, getRuleField(rule1, "condition"), "noOwner()");
fieldUpdated(change, getRuleField(rule1, FIELD_DESCRIPTION), "description", "newDescription");
fieldUpdated(change, getRuleField(rule1, "condition"), "isOwner()", "noOwner()");
policy.setRules(List.of(rule1));
policy = patchEntityAndCheck(policy, origJson, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
policy = patchEntityAndCheck(policy, origJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
// Add a new rule - Changes from this PATCH is consolidated with the previous changes
origJson = JsonUtils.pojoToJson(policy);
@ -373,26 +368,17 @@ public class PolicyResourceTest extends EntityResourceTest<Policy, CreatePolicy>
accessControlRule(
"newRule", List.of(ALL_RESOURCES), List.of(MetadataOperation.EDIT_DESCRIPTION), ALLOW);
policy.getRules().add(newRule);
change = getChangeDescription(policy, CHANGE_CONSOLIDATED);
fieldAdded(change, getRuleField(rule1, FIELD_DESCRIPTION), "newDescription");
fieldUpdated(change, getRuleField(rule1, "effect"), ALLOW, DENY);
fieldUpdated(
change, getRuleField(rule1, "resources"), List.of(ALL_RESOURCES), List.of("table"));
fieldUpdated(change, getRuleField(rule1, "operations"), List.of(VIEW_ALL), List.of(EDIT_ALL));
fieldAdded(change, getRuleField(rule1, "condition"), "noOwner()");
fieldAdded(change, "rules", List.of(newRule));
policy = patchEntityAndCheck(policy, origJson, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
change = getChangeDescription(policy, MINOR_UPDATE);
fieldAdded(change, "rules", listOf(newRule));
policy = patchEntityAndCheck(policy, origJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
// Delete rule1 rule
// Changes from this PATCH is consolidated with the previous changes
origJson = JsonUtils.pojoToJson(policy);
policy.setRules(List.of(newRule));
change = getChangeDescription(policy, CHANGE_CONSOLIDATED);
// Revert all the changes made to rule1 to the state when it was added first
rule1 = accessControlRule("rule1", List.of(ALL_RESOURCES), List.of(VIEW_ALL), ALLOW);
fieldAdded(change, "rules", List.of(newRule));
change = getChangeDescription(policy, MINOR_UPDATE);
fieldDeleted(change, "rules", List.of(rule1));
patchEntityAndCheck(policy, origJson, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
patchEntityAndCheck(policy, origJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
}
@Test
@ -475,18 +461,13 @@ public class PolicyResourceTest extends EntityResourceTest<Policy, CreatePolicy>
// Change existing rule1 fields. Update description and condition
// Changes from this PATCH is consolidated with the previous changes
origJson = JsonUtils.pojoToJson(policy);
change = getChangeDescription(policy, CHANGE_CONSOLIDATED);
change = getChangeDescription(policy, MINOR_UPDATE);
rule1.withDescription("newDescription").withCondition("noOwner()");
fieldAdded(change, getRuleField(rule1, FIELD_DESCRIPTION), "newDescription");
fieldUpdated(change, getRuleField(rule1, "effect"), ALLOW, DENY);
fieldUpdated(
change, getRuleField(rule1, "resources"), List.of(ALL_RESOURCES), List.of("table"));
fieldUpdated(change, getRuleField(rule1, "operations"), List.of(VIEW_ALL), List.of(EDIT_ALL));
fieldAdded(change, getRuleField(rule1, "condition"), "noOwner()");
fieldUpdated(change, getRuleField(rule1, FIELD_DESCRIPTION), "description", "newDescription");
fieldUpdated(change, getRuleField(rule1, "condition"), "isOwner()", "noOwner()");
policy.setRules(List.of(rule1));
policy =
patchEntityUsingFqnAndCheck(
policy, origJson, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
patchEntityUsingFqnAndCheck(policy, origJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
// Add a new rule - Changes from this PATCH is consolidated with the previous changes
origJson = JsonUtils.pojoToJson(policy);
@ -494,28 +475,19 @@ public class PolicyResourceTest extends EntityResourceTest<Policy, CreatePolicy>
accessControlRule(
"newRule", List.of(ALL_RESOURCES), List.of(MetadataOperation.EDIT_DESCRIPTION), ALLOW);
policy.getRules().add(newRule);
change = getChangeDescription(policy, CHANGE_CONSOLIDATED);
fieldAdded(change, getRuleField(rule1, FIELD_DESCRIPTION), "newDescription");
fieldUpdated(change, getRuleField(rule1, "effect"), ALLOW, DENY);
fieldUpdated(
change, getRuleField(rule1, "resources"), List.of(ALL_RESOURCES), List.of("table"));
fieldUpdated(change, getRuleField(rule1, "operations"), List.of(VIEW_ALL), List.of(EDIT_ALL));
fieldAdded(change, getRuleField(rule1, "condition"), "noOwner()");
fieldAdded(change, "rules", List.of(newRule));
change = getChangeDescription(policy, MINOR_UPDATE);
fieldAdded(change, "rules", listOf(newRule));
policy =
patchEntityUsingFqnAndCheck(
policy, origJson, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
patchEntityUsingFqnAndCheck(policy, origJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
// Delete rule1 rule
// Changes from this PATCH is consolidated with the previous changes
origJson = JsonUtils.pojoToJson(policy);
policy.setRules(List.of(newRule));
change = getChangeDescription(policy, CHANGE_CONSOLIDATED);
change = getChangeDescription(policy, MINOR_UPDATE);
// Revert all the changes made to rule1 to the state when it was added first
rule1 = accessControlRule("rule1", List.of(ALL_RESOURCES), List.of(VIEW_ALL), ALLOW);
fieldAdded(change, "rules", List.of(newRule));
fieldDeleted(change, "rules", List.of(rule1));
patchEntityUsingFqnAndCheck(policy, origJson, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
patchEntityUsingFqnAndCheck(policy, origJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
}
@Test

View File

@ -255,6 +255,7 @@ public class ContainerResourceTest extends EntityResourceTest<Container, CreateC
// Changes from this PATCH is consolidated with the previous changes
originalJson = JsonUtils.pojoToJson(container);
change = getChangeDescription(container, CHANGE_CONSOLIDATED);
change.setPreviousVersion(container.getVersion());
ContainerDataModel newModel =
new ContainerDataModel()
.withIsPartitioned(false)
@ -263,22 +264,19 @@ public class ContainerResourceTest extends EntityResourceTest<Container, CreateC
List.of(ContainerFileFormat.Gz, ContainerFileFormat.Csv);
container.withPrefix("prefix2").withDataModel(newModel).withFileFormats(newFileFormats);
fieldAdded(change, "dataModel", newModel);
fieldAdded(change, "prefix", "prefix2");
fieldUpdated(change, "prefix", "prefix1", "prefix2");
fieldUpdated(change, "dataModel.partition", true, false);
fieldDeleted(change, "fileFormats", FILE_FORMATS);
fieldAdded(change, "fileFormats", newFileFormats);
patchEntityAndCheck(container, originalJson, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
patchEntityAndCheck(container, originalJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
// Update the container size and number of objects
// Changes from this PATCH is consolidated with the previous changes
originalJson = JsonUtils.pojoToJson(container);
change = getChangeDescription(container, CHANGE_CONSOLIDATED);
fieldAdded(change, "dataModel", newModel);
fieldAdded(change, "prefix", "prefix2");
fieldAdded(change, "fileFormats", newFileFormats);
change = getChangeDescription(container, MINOR_UPDATE);
container.withSize(2.0).withNumberOfObjects(3.0);
container =
patchEntityAndCheck(
container, originalJson, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
patchEntityAndCheck(container, originalJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
assertEquals(2.0, container.getSize());
assertEquals(3.0, container.getNumberOfObjects());
}
@ -345,7 +343,7 @@ public class ContainerResourceTest extends EntityResourceTest<Container, CreateC
// Update description, chartType and chart url and verify patch
// Changes from this PATCH is consolidated with the previous changes
originalJson = JsonUtils.pojoToJson(container);
change = getChangeDescription(container, CHANGE_CONSOLIDATED);
change = getChangeDescription(container, MINOR_UPDATE);
ContainerDataModel newModel =
new ContainerDataModel()
.withIsPartitioned(false)
@ -354,23 +352,20 @@ public class ContainerResourceTest extends EntityResourceTest<Container, CreateC
List.of(ContainerFileFormat.Gz, ContainerFileFormat.Csv);
container.withPrefix("prefix2").withDataModel(newModel).withFileFormats(newFileFormats);
fieldAdded(change, "dataModel", newModel);
fieldAdded(change, "prefix", "prefix2");
fieldUpdated(change, "prefix", "prefix1", "prefix2");
fieldUpdated(change, "dataModel.partition", true, false);
fieldDeleted(change, "fileFormats", FILE_FORMATS);
fieldAdded(change, "fileFormats", newFileFormats);
patchEntityUsingFqnAndCheck(
container, originalJson, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
patchEntityUsingFqnAndCheck(container, originalJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
// Update the container size and number of objects
// Changes from this PATCH is consolidated with the previous changes
originalJson = JsonUtils.pojoToJson(container);
change = getChangeDescription(container, CHANGE_CONSOLIDATED);
fieldAdded(change, "dataModel", newModel);
fieldAdded(change, "prefix", "prefix2");
fieldAdded(change, "fileFormats", newFileFormats);
change = getChangeDescription(container, MINOR_UPDATE);
container.withSize(2.0).withNumberOfObjects(3.0);
container =
patchEntityUsingFqnAndCheck(
container, originalJson, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
container, originalJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
assertEquals(2.0, container.getSize());
assertEquals(3.0, container.getNumberOfObjects());
}

View File

@ -24,7 +24,6 @@ import static org.openmetadata.service.util.EntityUtil.fieldDeleted;
import static org.openmetadata.service.util.TestUtils.ADMIN_AUTH_HEADERS;
import static org.openmetadata.service.util.TestUtils.TEST_AUTH_HEADERS;
import static org.openmetadata.service.util.TestUtils.TEST_USER_NAME;
import static org.openmetadata.service.util.TestUtils.UpdateType.CHANGE_CONSOLIDATED;
import static org.openmetadata.service.util.TestUtils.UpdateType.MINOR_UPDATE;
import static org.openmetadata.service.util.TestUtils.assertListNotNull;
import static org.openmetadata.service.util.TestUtils.assertListNull;
@ -136,10 +135,9 @@ public class RoleResourceTest extends EntityResourceTest<Role, CreateRole> {
// Changes from this PATCH is consolidated with the previous changes
originalJson = JsonUtils.pojoToJson(role);
role.setPolicies(DATA_STEWARD_ROLE.getPolicies());
change = getChangeDescription(role, CHANGE_CONSOLIDATED);
change = getChangeDescription(role, MINOR_UPDATE);
fieldDeleted(change, "policies", DATA_CONSUMER_ROLE.getPolicies());
fieldAdded(change, "policies", DATA_STEWARD_ROLE.getPolicies());
role = patchEntityAndCheck(role, originalJson, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
role = patchEntityAndCheck(role, originalJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
// Remove all the policies. It should be disallowed
final String originalJson1 = JsonUtils.pojoToJson(role);

View File

@ -53,7 +53,6 @@ import static org.openmetadata.service.util.TestUtils.TEST_AUTH_HEADERS;
import static org.openmetadata.service.util.TestUtils.TEST_USER_NAME;
import static org.openmetadata.service.util.TestUtils.USER_WITH_CREATE_HEADERS;
import static org.openmetadata.service.util.TestUtils.UpdateType.MINOR_UPDATE;
import static org.openmetadata.service.util.TestUtils.UpdateType.NO_CHANGE;
import static org.openmetadata.service.util.TestUtils.assertListNotNull;
import static org.openmetadata.service.util.TestUtils.assertResponse;
import static org.openmetadata.service.util.TestUtils.validateEntityReferences;
@ -750,8 +749,8 @@ public class TeamResourceTest extends EntityResourceTest<Team, CreateTeam> {
// Remove email from the team - changes from this PATCH and the previous are consolidated to no
// change
json = JsonUtils.pojoToJson(team);
change = getChangeDescription(team, NO_CHANGE);
patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, NO_CHANGE, change);
change = getChangeDescription(team, MINOR_UPDATE);
patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
}
@Test

View File

@ -57,9 +57,7 @@ import static org.openmetadata.service.util.TestUtils.TEST_AUTH_HEADERS;
import static org.openmetadata.service.util.TestUtils.TEST_USER_NAME;
import static org.openmetadata.service.util.TestUtils.USER_WITH_CREATE_HEADERS;
import static org.openmetadata.service.util.TestUtils.USER_WITH_CREATE_PERMISSION_NAME;
import static org.openmetadata.service.util.TestUtils.UpdateType.CHANGE_CONSOLIDATED;
import static org.openmetadata.service.util.TestUtils.UpdateType.MINOR_UPDATE;
import static org.openmetadata.service.util.TestUtils.UpdateType.REVERT;
import static org.openmetadata.service.util.TestUtils.assertDeleted;
import static org.openmetadata.service.util.TestUtils.assertListNotNull;
import static org.openmetadata.service.util.TestUtils.assertListNull;
@ -754,17 +752,20 @@ public class UserResourceTest extends EntityResourceTest<User, CreateUser> {
.withIsBot(true)
.withIsAdmin(false);
change = getChangeDescription(user, CHANGE_CONSOLIDATED);
change = getChangeDescription(user, MINOR_UPDATE);
fieldAdded(change, "roles", listOf(role2));
fieldDeleted(change, "teams", listOf(ORG_TEAM.getEntityReference()));
fieldAdded(change, "teams", teams1);
fieldAdded(change, "timezone", timezone1);
fieldAdded(change, "displayName", "displayName1");
fieldAdded(change, "profile", profile1);
fieldAdded(change, "teams", listOf(team3));
fieldDeleted(change, "roles", listOf(role1));
fieldDeleted(change, "teams", listOf(team2));
fieldDeleted(change, "personas", List.of(DATA_SCIENTIST.getEntityReference()));
fieldUpdated(change, "displayName", "displayName", "displayName1");
fieldUpdated(change, "profile", profile, profile1);
fieldUpdated(change, "timezone", timezone, timezone1);
fieldUpdated(change, "isBot", false, true);
fieldAdded(change, "defaultPersona", DATA_SCIENTIST.getEntityReference());
fieldAdded(change, "personas", List.of(DATA_ENGINEER.getEntityReference()));
user = patchEntityAndCheck(user, origJson, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
user = patchEntityAndCheck(user, origJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
//
// Remove the attributes - Consolidating changes from this patch with previous results in no
@ -780,11 +781,6 @@ public class UserResourceTest extends EntityResourceTest<User, CreateUser> {
.withPersonas(null)
.withIsBot(null)
.withIsAdmin(false);
// Note non-empty display field is not deleted. When teams are deleted, Organization is added
// back as default team.
change = getChangeDescription(user, REVERT);
patchEntityAndCheck(user, origJson, ADMIN_AUTH_HEADERS, REVERT, change);
}
@Test
@ -1319,9 +1315,9 @@ public class UserResourceTest extends EntityResourceTest<User, CreateUser> {
// removed
json = JsonUtils.pojoToJson(user);
user.withProfile(null);
change = getChangeDescription(user, CHANGE_CONSOLIDATED);
fieldDeleted(change, "profile", PROFILE);
patchEntityAndCheck(user, json, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
change = getChangeDescription(user, MINOR_UPDATE);
fieldDeleted(change, "profile", profile1);
patchEntityAndCheck(user, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
}
@Test

View File

@ -54,6 +54,8 @@ public interface EntityInterface {
ChangeDescription getChangeDescription();
ChangeDescription getIncrementalChangeDescription();
default List<EntityReference> getOwners() {
return null;
}
@ -124,6 +126,8 @@ public interface EntityInterface {
void setChangeDescription(ChangeDescription changeDescription);
void setIncrementalChangeDescription(ChangeDescription incrementalChangeDescription);
void setFullyQualifiedName(String fullyQualifiedName);
default void setDeleted(Boolean flag) {}

View File

@ -56,6 +56,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -112,6 +112,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -118,6 +118,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -75,6 +75,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -147,6 +147,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -56,6 +56,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -96,6 +96,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -54,6 +54,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -55,6 +55,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -79,6 +79,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"provider": {
"$ref": "../../type/basic.json#/definitions/providerType"
},

View File

@ -80,6 +80,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -142,6 +142,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -134,6 +134,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -152,6 +152,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -118,6 +118,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -121,6 +121,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -87,6 +87,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"default": {
"description": "Some databases don't support a database/catalog in the hierarchy and use default database. For example, `MySql`. For such databases, set this flag to true to indicate that this is a default database.",
"type": "boolean",

View File

@ -88,6 +88,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -76,6 +76,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -122,6 +122,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"status": {
"description": "Status of the glossary term.",
"$ref": "#/definitions/status"

View File

@ -175,6 +175,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -256,6 +256,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -245,6 +245,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -47,6 +47,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"owners": {
"description": "Owners of this Query.",
"$ref": "../../type/entityReferenceList.json",

View File

@ -60,6 +60,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -241,6 +241,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -123,6 +123,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"databaseSchema": {
"description": "Reference to Database Schema that contains this stored procedure.",
"$ref": "../../type/entityReference.json"

View File

@ -1097,6 +1097,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -145,6 +145,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -55,6 +55,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"href": {
"description": "Link to the resource corresponding to this entity.",
"$ref": "../../type/basic.json#/definitions/href"

View File

@ -68,6 +68,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"extension": {
"description": "Entity extension data with custom attributes added to the entity.",
"$ref": "../../type/basic.json#/definitions/entityExtension"

View File

@ -85,6 +85,10 @@
"changeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
}
},
"required": ["id", "name", "description", "domainType"],

View File

@ -66,6 +66,10 @@
"description": "Change that led to this version of the Policy.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"rules": {
"description": "Set of rules that the policy contains.",
"$ref": "#/definitions/rules"

View File

@ -117,6 +117,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -92,6 +92,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -216,6 +216,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -419,6 +419,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -206,6 +206,10 @@
"description": "Change that led to this version of the entity.",
"$ref": "../../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -135,6 +135,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -139,6 +139,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -133,6 +133,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -232,6 +232,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -127,6 +127,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -134,6 +134,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -55,6 +55,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"domain" : {
"description": "Domain the asset belongs to. When not set, the asset inherits the domain from the parent it belongs to.",
"$ref": "../../type/entityReference.json"

View File

@ -48,6 +48,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"allowDelete" : {
"description": "Some system roles can't be deleted",
"type" : "boolean"

View File

@ -107,6 +107,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -119,6 +119,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -87,6 +87,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../type/entityHistory.json#/definitions/changeDescription"
},
"domain" : {
"description": "Domain the asset belongs to. When not set, the asset inherits the domain from the parent it belongs to.",
"$ref": "../type/entityReference.json"

View File

@ -279,6 +279,10 @@
"description": "Change that led to this version of the Event Subscription.",
"$ref": "../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../type/entityHistory.json#/definitions/changeDescription"
},
"alertType": {
"description": "Type of Alert",
"$ref": "#/definitions/alertType"

View File

@ -62,6 +62,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -105,6 +105,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -193,6 +193,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -115,6 +115,10 @@
"description": "Change that lead to this version of the entity.",
"$ref": "../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../type/entityHistory.json#/definitions/changeDescription"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",

View File

@ -49,6 +49,10 @@
"description": "For `eventType` `entityUpdated` this field captures details about what fields were added/updated/deleted. For `eventType` `entityCreated` or `entityDeleted` this field is null.",
"$ref": "entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../type/entityHistory.json#/definitions/changeDescription"
},
"entity": {
"description": "For `eventType` `entityCreated`, this field captures JSON coded string of the entity using the schema corresponding to `entityType`."
}

View File

@ -65,6 +65,39 @@
}
},
"additionalProperties": false
},
"incrementalChangeDescription": {
"description": "Description of the change.",
"type": "object",
"javaType": "org.openmetadata.schema.type.ChangeDescription",
"properties": {
"fieldsAdded": {
"description": "Names of fields added during the version changes.",
"type": "array",
"items": {
"$ref": "#/definitions/fieldChange"
}
},
"fieldsUpdated": {
"description": "Fields modified during the version changes with old and new values.",
"type": "array",
"items": {
"$ref": "#/definitions/fieldChange"
}
},
"fieldsDeleted": {
"description": "Fields deleted during the version changes with old value before deleted.",
"type": "array",
"items": {
"$ref": "#/definitions/fieldChange"
}
},
"previousVersion": {
"description": "When a change did not result in change, this could be same as the current version.",
"$ref": "#/definitions/entityVersion"
}
},
"additionalProperties": false
}
},
"properties": {

View File

@ -13,6 +13,7 @@
import test from '@playwright/test';
import { SidebarItem } from '../../constant/sidebar';
import { EntityDataClass } from '../../support/entity/EntityDataClass';
import { EntityDataClassCreationConfig } from '../../support/entity/EntityDataClass.interface';
import { TableClass } from '../../support/entity/TableClass';
import { Glossary } from '../../support/glossary/Glossary';
import { GlossaryTerm } from '../../support/glossary/GlossaryTerm';
@ -32,6 +33,18 @@ test.describe.configure({
timeout: 4 * 60 * 1000,
});
const creationConfig: EntityDataClassCreationConfig = {
table: true,
topic: true,
dashboard: true,
mlModel: true,
pipeline: true,
dashboardDataModel: true,
apiCollection: true,
searchIndex: true,
container: true,
};
const user = new UserClass();
const table = new TableClass(undefined, 'Regular');
let glossaryEntity: Glossary;
@ -44,7 +57,7 @@ test.describe('Advanced Search', { tag: '@advanced-search' }, () => {
test.beforeAll('Setup pre-requests', async ({ browser }) => {
const { page, apiContext, afterAction } = await createNewPage(browser);
await EntityDataClass.preRequisitesForTests(apiContext);
await EntityDataClass.preRequisitesForTests(apiContext, creationConfig);
await user.create(apiContext);
glossaryEntity = new Glossary(undefined, [
{
@ -234,7 +247,7 @@ test.describe('Advanced Search', { tag: '@advanced-search' }, () => {
test.afterAll('Cleanup', async ({ browser }) => {
const { apiContext, afterAction } = await createNewPage(browser);
await EntityDataClass.postRequisitesForTests(apiContext);
await EntityDataClass.postRequisitesForTests(apiContext, creationConfig);
await glossaryEntity.delete(apiContext);
await user.delete(apiContext);
await table.delete(apiContext);

View File

@ -80,12 +80,12 @@ test('Classification version page', async ({ page }) => {
await patchClassificationResponse;
// Verify disabled state
await page.click('[data-testid="version-button"]:has-text("0.3")');
await page.click('[data-testid="version-button"]:has-text("0.2")');
await expect(page.locator('[data-testid="disabled"]')).toBeVisible();
// Toggle back to enabled
await page.click('[data-testid="version-button"]:has-text("0.3")');
await page.click('[data-testid="version-button"]:has-text("0.2")');
await page.click('[data-testid="manage-button"]');
const patchClassificationResponse2 = page.waitForResponse(
`/api/v1/classifications/${classification.responseData?.id}`
@ -94,7 +94,7 @@ test('Classification version page', async ({ page }) => {
await patchClassificationResponse2;
// Verify enabled state
await page.click('[data-testid="version-button"]:has-text("0.4")');
await page.click('[data-testid="version-button"]:has-text("0.2")');
await expect(
page.locator(`[data-testid="classification-${classification.data.name}"]`)

Some files were not shown because too many files have changed in this diff Show More