diff --git a/ingestion/src/metadata/ingestion/models/patch_request.py b/ingestion/src/metadata/ingestion/models/patch_request.py index 0f6039f9d53..610f2d1cc40 100644 --- a/ingestion/src/metadata/ingestion/models/patch_request.py +++ b/ingestion/src/metadata/ingestion/models/patch_request.py @@ -29,6 +29,8 @@ ALLOWED_COLUMN_FIELDS = { "name": True, "dataType": True, "arrayDataType": True, + "description": True, + "tags": True, "dataLength": True, "constraint": True, "children": True, @@ -62,6 +64,8 @@ ALLOWED_COMMON_PATCH_FIELDS = { "name": True, "displayName": True, "sourceUrl": True, + "description": True, + "tags": True, # Table Entity Fields "tableType": True, "columns": {"__all__": ALLOWED_COLUMN_FIELDS}, @@ -116,3 +120,5 @@ ALLOWED_COMMON_PATCH_FIELDS = { "size": True, "fileFormats": True, } + +RESTRICT_UPDATE_LIST = ["description", "tags"] diff --git a/ingestion/src/metadata/ingestion/ometa/mixins/patch_mixin.py b/ingestion/src/metadata/ingestion/ometa/mixins/patch_mixin.py index 9a07930c3d0..0c47bec33a1 100644 --- a/ingestion/src/metadata/ingestion/ometa/mixins/patch_mixin.py +++ b/ingestion/src/metadata/ingestion/ometa/mixins/patch_mixin.py @@ -120,6 +120,7 @@ class OMetaPatchMixin(OMetaPatchMixinBase): source: T, destination: T, allowed_fields: Optional[Dict] = None, + restrict_update_fields: Optional[List] = None, ) -> Optional[T]: """ Given an Entity type and Source entity and Destination entity, @@ -129,6 +130,8 @@ class OMetaPatchMixin(OMetaPatchMixinBase): entity (T): Entity Type source: Source payload which is current state of the source in OpenMetadata destination: payload with changes applied to the source. + allowed_fields: List of field names to filter from source and destination models + restrict_update_fields: List of field names which will only support add operation Returns Updated Entity @@ -169,6 +172,18 @@ class OMetaPatchMixin(OMetaPatchMixinBase): ) return None + # for a user editable fields like descriptions, tags we only want to support "add" operation in patch + # we will remove the other operations for replace, remove from here + if restrict_update_fields: + patch.patch = [ + patch_ops + for patch_ops in patch.patch + if self._determine_restricted_operation( + patch_ops=patch_ops, + restrict_update_fields=restrict_update_fields, + ) + ] + res = self.client.patch( path=f"{self.get_suffix(entity)}/{model_str(source.id)}", data=str(patch), @@ -183,6 +198,19 @@ class OMetaPatchMixin(OMetaPatchMixinBase): return None + def _determine_restricted_operation( + self, patch_ops: Dict, restrict_update_fields: Optional[List] = None + ) -> bool: + """ + Only retain add operation for restrict_update_fields fields + """ + path = patch_ops.get("path") + op = patch_ops.get("op") + for field in restrict_update_fields or []: + if field in path and op != PatchOperation.ADD.value: + return False + return True + def patch_description( self, entity: Type[T], diff --git a/ingestion/src/metadata/ingestion/sink/metadata_rest.py b/ingestion/src/metadata/ingestion/sink/metadata_rest.py index 261ae73dd69..e5047f0f0aa 100644 --- a/ingestion/src/metadata/ingestion/sink/metadata_rest.py +++ b/ingestion/src/metadata/ingestion/sink/metadata_rest.py @@ -58,6 +58,7 @@ from metadata.ingestion.models.ometa_classification import OMetaTagAndClassifica from metadata.ingestion.models.ometa_topic_data import OMetaTopicSampleData from metadata.ingestion.models.patch_request import ( ALLOWED_COMMON_PATCH_FIELDS, + RESTRICT_UPDATE_LIST, PatchRequest, ) from metadata.ingestion.models.pipeline_status import OMetaPipelineStatus @@ -167,6 +168,7 @@ class MetadataRestSink(Sink): # pylint: disable=too-many-public-methods source=record.original_entity, destination=record.new_entity, allowed_fields=ALLOWED_COMMON_PATCH_FIELDS, + restrict_update_fields=RESTRICT_UPDATE_LIST, ) return Either(right=entity)