Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,17 @@
import static org.openmetadata.service.governance.workflows.Workflow.GLOBAL_NAMESPACE;
import static org.openmetadata.service.governance.workflows.Workflow.RELATED_ENTITY_ID_VARIABLE;

import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import lombok.extern.slf4j.Slf4j;
import org.flowable.common.engine.api.delegate.Expression;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.task.service.delegate.DelegateTask;
import org.flowable.variable.api.delegate.VariableScope;
import org.openmetadata.schema.EntityInterface;
import org.openmetadata.schema.type.Include;
import org.openmetadata.schema.utils.JsonUtils;
import org.openmetadata.service.Entity;
import org.openmetadata.service.resources.feeds.MessageParser;

Expand All @@ -24,6 +27,29 @@ public WorkflowVariableHandler(VariableScope varScope) {
this.varScope = varScope;
}

public static record InputNamespaces(Map<String, String> namespaces) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we add some comment on why we named this as InputNamespaces ? what is it used for and secondly why plural naming for the class

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

InputNamespaces is plural because it represents the full mapping for all input variables on a workflow node, not one namespace. Each input can point to a different namespace, for example relatedEntity -> approvalStage and recognizerFeedback -> global, so the record holds multiple input namespaces. A singular InputNamespace would sound like one namespace value instead of the node’s input to namespace map.

public InputNamespaces {
namespaces = namespaces != null ? Map.copyOf(namespaces) : Map.of();
}

public String namespaceFor(String variable) {
return namespaces.get(variable);
}

public String namespaceForOrDefault(String variable, String defaultNamespace) {
return namespaces.getOrDefault(variable, defaultNamespace);
}

public static InputNamespaces from(Expression expr, DelegateExecution execution) {
return read(expr.getValue(execution));
}

public static InputNamespaces read(Object rawValue) {
Map<String, String> map = JsonUtils.readOrConvertValue(rawValue, Map.class);
return new InputNamespaces(map);
}
Comment thread
yan-3005 marked this conversation as resolved.
}
Comment thread
yan-3005 marked this conversation as resolved.

public static String getNamespacedVariableName(String namespace, String varName) {
if (namespace != null) {
return String.format("%s_%s", namespace, varName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import static org.openmetadata.service.governance.workflows.Workflow.getResultFromBoolean;
import static org.openmetadata.service.governance.workflows.WorkflowHandler.getProcessDefinitionKeyFromId;

import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.flowable.common.engine.api.delegate.Expression;
Expand All @@ -18,9 +17,9 @@
import org.openmetadata.schema.ServiceEntityInterface;
import org.openmetadata.schema.entity.services.ingestionPipelines.PipelineType;
import org.openmetadata.schema.type.Include;
import org.openmetadata.schema.utils.JsonUtils;
import org.openmetadata.service.Entity;
import org.openmetadata.service.governance.workflows.WorkflowVariableHandler;
import org.openmetadata.service.governance.workflows.WorkflowVariableHandler.InputNamespaces;
import org.openmetadata.service.resources.feeds.MessageParser;
import org.openmetadata.service.resources.services.ingestionpipelines.IngestionPipelineMapper;

Expand All @@ -35,8 +34,7 @@ public class CreateIngestionPipelineDelegate implements JavaDelegate {
public void execute(DelegateExecution execution) {
WorkflowVariableHandler varHandler = new WorkflowVariableHandler(execution);
try {
Map<String, String> inputNamespaceMap =
JsonUtils.readOrConvertValue(inputNamespaceMapExpr.getValue(execution), Map.class);
InputNamespaces inputNamespaces = InputNamespaces.from(inputNamespaceMapExpr, execution);

PipelineType pipelineType =
PipelineType.fromValue((String) pipelineTypeExpr.getValue(execution));
Expand All @@ -48,7 +46,8 @@ public void execute(DelegateExecution execution) {
MessageParser.EntityLink.parse(
(String)
varHandler.getNamespacedVariable(
inputNamespaceMap.get(RELATED_ENTITY_VARIABLE), RELATED_ENTITY_VARIABLE));
inputNamespaces.namespaceFor(RELATED_ENTITY_VARIABLE),
RELATED_ENTITY_VARIABLE));

ServiceEntityInterface service =
Entity.getEntity(entityLink, "owners,ingestionRunner", Include.NON_DELETED);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,16 @@
import static org.openmetadata.service.governance.workflows.Workflow.getResultFromBoolean;
import static org.openmetadata.service.governance.workflows.WorkflowHandler.getProcessDefinitionKeyFromId;

import java.util.Map;
import java.util.UUID;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.flowable.common.engine.api.delegate.Expression;
import org.flowable.engine.delegate.BpmnError;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.JavaDelegate;
import org.openmetadata.schema.utils.JsonUtils;
import org.openmetadata.sdk.PipelineServiceClientInterface;
import org.openmetadata.service.governance.workflows.WorkflowVariableHandler;
import org.openmetadata.service.governance.workflows.WorkflowVariableHandler.InputNamespaces;

@Slf4j
public class RunIngestionPipelineDelegate implements JavaDelegate {
Expand All @@ -31,8 +30,7 @@ public class RunIngestionPipelineDelegate implements JavaDelegate {
public void execute(DelegateExecution execution) {
WorkflowVariableHandler varHandler = new WorkflowVariableHandler(execution);
try {
Map<String, String> inputNamespaceMap =
JsonUtils.readOrConvertValue(inputNamespaceMapExpr.getValue(execution), Map.class);
InputNamespaces inputNamespaces = InputNamespaces.from(inputNamespaceMapExpr, execution);

Comment thread
yan-3005 marked this conversation as resolved.
Outdated
boolean shouldRun = Boolean.parseBoolean((String) shouldRunExpr.getValue(execution));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import static org.openmetadata.service.governance.workflows.Workflow.WORKFLOW_RUNTIME_EXCEPTION;
import static org.openmetadata.service.governance.workflows.WorkflowHandler.getProcessDefinitionKeyFromId;

import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.flowable.common.engine.api.delegate.Expression;
Expand All @@ -17,6 +16,7 @@
import org.openmetadata.schema.utils.JsonUtils;
import org.openmetadata.service.Entity;
import org.openmetadata.service.governance.workflows.WorkflowVariableHandler;
import org.openmetadata.service.governance.workflows.WorkflowVariableHandler.InputNamespaces;
import org.openmetadata.service.jdbi3.RecognizerFeedbackRepository;

@Slf4j
Expand All @@ -28,16 +28,15 @@ public void execute(DelegateExecution execution) {
WorkflowVariableHandler varHandler = new WorkflowVariableHandler(execution);
try {
@SuppressWarnings("unchecked")
Map<String, String> inputNamespaceMap =
JsonUtils.readOrConvertValue(inputNamespaceMapExpr.getValue(execution), Map.class);
InputNamespaces inputNamespaces = InputNamespaces.from(inputNamespaceMapExpr, execution);
Comment thread
greptile-apps[bot] marked this conversation as resolved.
Outdated

String feedbackJson =
(String)
varHandler.getNamespacedVariable(
inputNamespaceMap.get(RECOGNIZER_FEEDBACK), RECOGNIZER_FEEDBACK);
inputNamespaces.namespaceFor(RECOGNIZER_FEEDBACK), RECOGNIZER_FEEDBACK);
RecognizerFeedback feedback = JsonUtils.readValue(feedbackJson, RecognizerFeedback.class);

String updatedByNamespace = inputNamespaceMap.get(UPDATED_BY_VARIABLE);
String updatedByNamespace = inputNamespaces.namespaceFor(UPDATED_BY_VARIABLE);
String reviewedBy = "governance-bot";
if (updatedByNamespace != null) {
String actualUser =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.openmetadata.schema.utils.JsonUtils;
import org.openmetadata.service.Entity;
import org.openmetadata.service.governance.workflows.WorkflowVariableHandler;
import org.openmetadata.service.governance.workflows.WorkflowVariableHandler.InputNamespaces;
import org.openmetadata.service.governance.workflows.util.FieldChangeValueExtractor;
import org.openmetadata.service.resources.feeds.MessageParser;

Expand All @@ -35,12 +36,11 @@ public class CheckChangeDescriptionTaskImpl implements JavaDelegate {
public void execute(DelegateExecution execution) {
WorkflowVariableHandler varHandler = new WorkflowVariableHandler(execution);
try {
Map<String, String> inputNamespaceMap =
JsonUtils.readOrConvertValue(inputNamespaceMapExpr.getValue(execution), Map.class);
InputNamespaces inputNamespaces = InputNamespaces.from(inputNamespaceMapExpr, execution);
String entityLinkStr =
(String)
varHandler.getNamespacedVariable(
inputNamespaceMap.get(RELATED_ENTITY_VARIABLE), RELATED_ENTITY_VARIABLE);
inputNamespaces.namespaceFor(RELATED_ENTITY_VARIABLE), RELATED_ENTITY_VARIABLE);

boolean result = checkChangeDescription(execution, entityLinkStr);
varHandler.setNodeVariable(RESULT_VARIABLE, result);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import static org.openmetadata.service.governance.workflows.Workflow.WORKFLOW_RUNTIME_EXCEPTION;
import static org.openmetadata.service.governance.workflows.WorkflowHandler.getProcessDefinitionKeyFromId;

import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.flowable.common.engine.api.delegate.Expression;
Expand All @@ -17,6 +16,7 @@
import org.openmetadata.schema.type.Include;
import org.openmetadata.schema.utils.JsonUtils;
import org.openmetadata.service.governance.workflows.WorkflowVariableHandler;
import org.openmetadata.service.governance.workflows.WorkflowVariableHandler.InputNamespaces;
import org.openmetadata.service.resources.feeds.MessageParser;
import org.openmetadata.service.rules.RuleEngine;

Expand All @@ -29,14 +29,14 @@ public class CheckEntityAttributesImpl implements JavaDelegate {
public void execute(DelegateExecution execution) {
WorkflowVariableHandler varHandler = new WorkflowVariableHandler(execution);
try {
Map<String, String> inputNamespaceMap =
JsonUtils.readOrConvertValue(inputNamespaceMapExpr.getValue(execution), Map.class);
InputNamespaces inputNamespaces = InputNamespaces.from(inputNamespaceMapExpr, execution);
String rules = (String) rulesExpr.getValue(execution);
MessageParser.EntityLink entityLink =
MessageParser.EntityLink.parse(
(String)
varHandler.getNamespacedVariable(
inputNamespaceMap.get(RELATED_ENTITY_VARIABLE), RELATED_ENTITY_VARIABLE));
inputNamespaces.namespaceFor(RELATED_ENTITY_VARIABLE),
RELATED_ENTITY_VARIABLE));
varHandler.setNodeVariable(RESULT_VARIABLE, checkAttributes(varHandler, entityLink, rules));
} catch (Exception exc) {
LOG.error(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.openmetadata.schema.utils.JsonUtils;
import org.openmetadata.service.Entity;
import org.openmetadata.service.governance.workflows.WorkflowVariableHandler;
import org.openmetadata.service.governance.workflows.WorkflowVariableHandler.InputNamespaces;
import org.openmetadata.service.resources.feeds.MessageParser;

@Slf4j
Expand All @@ -35,8 +36,7 @@ public void execute(DelegateExecution execution) {
WorkflowVariableHandler varHandler = new WorkflowVariableHandler(execution);
try {
// Get configuration
Map<String, String> inputNamespaceMap =
JsonUtils.readOrConvertValue(inputNamespaceMapExpr.getValue(execution), Map.class);
InputNamespaces inputNamespaces = InputNamespaces.from(inputNamespaceMapExpr, execution);
List<String> fieldsToCheck =
JsonUtils.readOrConvertValue(fieldsToCheckExpr.getValue(execution), List.class);
List<Map<String, Object>> qualityBandMaps =
Expand All @@ -53,7 +53,8 @@ public void execute(DelegateExecution execution) {
MessageParser.EntityLink.parse(
(String)
varHandler.getNamespacedVariable(
inputNamespaceMap.get(RELATED_ENTITY_VARIABLE), RELATED_ENTITY_VARIABLE));
inputNamespaces.namespaceFor(RELATED_ENTITY_VARIABLE),
RELATED_ENTITY_VARIABLE));

EntityInterface entity = Entity.getEntity(entityLink, "*", Include.ALL);
Map<String, Object> entityMap = JsonUtils.getMap(entity);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import static org.openmetadata.service.governance.workflows.Workflow.WORKFLOW_RUNTIME_EXCEPTION;
import static org.openmetadata.service.governance.workflows.WorkflowHandler.getProcessDefinitionKeyFromId;

import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.flowable.common.engine.api.delegate.Expression;
Expand All @@ -18,6 +17,7 @@
import org.openmetadata.schema.utils.JsonUtils;
import org.openmetadata.service.Entity;
import org.openmetadata.service.governance.workflows.WorkflowVariableHandler;
import org.openmetadata.service.governance.workflows.WorkflowVariableHandler.InputNamespaces;
import org.openmetadata.service.jdbi3.RecognizerFeedbackRepository;

@Slf4j
Expand All @@ -29,16 +29,15 @@ public void execute(DelegateExecution execution) {
WorkflowVariableHandler varHandler = new WorkflowVariableHandler(execution);
try {
@SuppressWarnings("unchecked")
Map<String, String> inputNamespaceMap =
JsonUtils.readOrConvertValue(inputNamespaceMapExpr.getValue(execution), Map.class);
InputNamespaces inputNamespaces = InputNamespaces.from(inputNamespaceMapExpr, execution);

String feedbackJson =
(String)
varHandler.getNamespacedVariable(
inputNamespaceMap.get(RECOGNIZER_FEEDBACK), RECOGNIZER_FEEDBACK);
inputNamespaces.namespaceFor(RECOGNIZER_FEEDBACK), RECOGNIZER_FEEDBACK);
RecognizerFeedback feedback = JsonUtils.readValue(feedbackJson, RecognizerFeedback.class);

String updatedByNamespace = inputNamespaceMap.get(UPDATED_BY_VARIABLE);
String updatedByNamespace = inputNamespaces.namespaceFor(UPDATED_BY_VARIABLE);
String reviewedBy = "governance-bot";
if (updatedByNamespace != null) {
String actualUser =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import lombok.extern.slf4j.Slf4j;
import org.flowable.common.engine.api.delegate.Expression;
Expand All @@ -20,6 +19,7 @@
import org.openmetadata.service.Entity;
import org.openmetadata.service.governance.workflows.Workflow;
import org.openmetadata.service.governance.workflows.WorkflowVariableHandler;
import org.openmetadata.service.governance.workflows.WorkflowVariableHandler.InputNamespaces;
import org.openmetadata.service.jdbi3.EntityRepository;
import org.openmetadata.service.resources.feeds.MessageParser;

Expand All @@ -37,8 +37,7 @@ public void execute(DelegateExecution execution) {
try {
WorkflowVariableHandler varHandler = new WorkflowVariableHandler(execution);

Map<String, String> inputNamespaceMap =
JsonUtils.readOrConvertValue(inputNamespaceMapExpr.getValue(execution), Map.class);
InputNamespaces inputNamespaces = InputNamespaces.from(inputNamespaceMapExpr, execution);

Object workflowInstanceExecutionIdObj =
execution.getVariable(WORKFLOW_INSTANCE_EXECUTION_ID_VARIABLE);
Expand All @@ -51,12 +50,13 @@ public void execute(DelegateExecution execution) {
MessageParser.EntityLink.parse(
(String)
varHandler.getNamespacedVariable(
inputNamespaceMap.get(RELATED_ENTITY_VARIABLE), RELATED_ENTITY_VARIABLE));
inputNamespaces.namespaceFor(RELATED_ENTITY_VARIABLE),
RELATED_ENTITY_VARIABLE));

String updatedBy =
(String)
varHandler.getNamespacedVariable(
inputNamespaceMap.get(UPDATED_BY_VARIABLE), UPDATED_BY_VARIABLE);
inputNamespaces.namespaceFor(UPDATED_BY_VARIABLE), UPDATED_BY_VARIABLE);
if (updatedBy == null || updatedBy.isEmpty()) {
updatedBy = "governance-bot";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import static org.openmetadata.service.governance.workflows.Workflow.WORKFLOW_RUNTIME_EXCEPTION;
import static org.openmetadata.service.governance.workflows.WorkflowHandler.getProcessDefinitionKeyFromId;

import java.util.Map;
import java.util.Optional;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
Expand All @@ -16,8 +15,8 @@
import org.flowable.engine.delegate.JavaDelegate;
import org.openmetadata.schema.EntityInterface;
import org.openmetadata.schema.type.Include;
import org.openmetadata.schema.utils.JsonUtils;
import org.openmetadata.service.governance.workflows.WorkflowVariableHandler;
import org.openmetadata.service.governance.workflows.WorkflowVariableHandler.InputNamespaces;
import org.openmetadata.service.resources.feeds.MessageParser;
import org.openmetadata.service.util.EntityFieldUtils;

Expand All @@ -31,10 +30,8 @@ public class SetEntityAttributeImpl implements JavaDelegate {
public void execute(DelegateExecution execution) {
WorkflowVariableHandler varHandler = new WorkflowVariableHandler(execution);
try {
// Extract entity from workflow context
Map<String, Object> inputNamespaceMap =
JsonUtils.readOrConvertValue(inputNamespaceMapExpr.getValue(execution), Map.class);
String relatedEntityNamespace = (String) inputNamespaceMap.get(RELATED_ENTITY_VARIABLE);
InputNamespaces inputNamespaces = InputNamespaces.from(inputNamespaceMapExpr, execution);
String relatedEntityNamespace = inputNamespaces.namespaceFor(RELATED_ENTITY_VARIABLE);
String relatedEntityValue =
(String)
varHandler.getNamespacedVariable(relatedEntityNamespace, RELATED_ENTITY_VARIABLE);
Expand All @@ -45,7 +42,6 @@ public void execute(DelegateExecution execution) {

String fieldName = fieldNameExpr != null ? (String) fieldNameExpr.getValue(execution) : "";

// Simple null check - if fieldValueExpr is null, treat as empty/null value
String fieldValue = null;
if (fieldValueExpr != null) {
Object value = fieldValueExpr.getValue(execution);
Expand All @@ -54,22 +50,18 @@ public void execute(DelegateExecution execution) {
}
}

String updatedByNamespace = (String) inputNamespaceMap.get(UPDATED_BY_VARIABLE);
String updatedByNamespace = inputNamespaces.namespaceFor(UPDATED_BY_VARIABLE);
String actualUser =
Optional.ofNullable(updatedByNamespace)
.map(ns -> (String) varHandler.getNamespacedVariable(ns, UPDATED_BY_VARIABLE))
.orElse(null);

// Apply the field change using shared utility with bot impersonation
// Note: fieldValue can be null to clear/remove a field value
// When actualUser is available, use it as the user and mark 'governance-bot' as impersonator
// Otherwise, use 'governance-bot' directly (for system-initiated workflows)
// fieldValue==null clears the field. When we have an acting user, preserve it and mark
// governance-bot as impersonator; otherwise attribute the write to governance-bot directly.
if (actualUser != null && !actualUser.isEmpty()) {
// User-initiated workflow: preserve actual user, mark bot as impersonator
EntityFieldUtils.setEntityField(
entity, entityType, actualUser, fieldName, fieldValue, true, "governance-bot");
} else {
// System-initiated workflow: use governance-bot directly
EntityFieldUtils.setEntityField(
entity, entityType, "governance-bot", fieldName, fieldValue, true, null);
}
Expand Down
Loading
Loading