From af814424629502923f5992634158a887bb9db16f Mon Sep 17 00:00:00 2001 From: Najeeb Date: Wed, 16 Oct 2024 11:15:37 +0530 Subject: [PATCH 01/20] feat:integrate orkes-workflow-visualizer --- ui/package.json | 5 +- .../pages/definition/WorkflowDefinition.jsx | 52 ++++++++++++------- ui/src/pages/execution/Execution.jsx | 7 ++- ui/src/pages/execution/TaskDetails.jsx | 15 +++--- 4 files changed, 51 insertions(+), 28 deletions(-) diff --git a/ui/package.json b/ui/package.json index 623a5c6dc..6b384d93e 100644 --- a/ui/package.json +++ b/ui/package.json @@ -20,12 +20,13 @@ "moment": "^2.29.2", "monaco-editor": "^0.44.0", "node-forge": "^1.3.0", + "orkes-workflow-visualizer": "^1.0.0", "parse-svg-path": "^0.1.2", "prop-types": "^15.7.2", - "react": "^16.8.0", + "react": "^18.3.1", "react-cron-generator": "^1.3.5", "react-data-table-component": "^6.11.8", - "react-dom": "^16.8.0", + "react-dom": "^18.3.1", "react-helmet": "^6.1.0", "react-is": "^17.0.2", "react-query": "^3.19.4", diff --git a/ui/src/pages/definition/WorkflowDefinition.jsx b/ui/src/pages/definition/WorkflowDefinition.jsx index 77963f518..7f18244ca 100644 --- a/ui/src/pages/definition/WorkflowDefinition.jsx +++ b/ui/src/pages/definition/WorkflowDefinition.jsx @@ -12,7 +12,6 @@ import { useWorkflowNamesAndVersions, } from "../../data/workflow"; import WorkflowDAG from "../../components/diagram/WorkflowDAG"; -import WorkflowGraph from "../../components/diagram/WorkflowGraph"; import ResetConfirmationDialog from "./ResetConfirmationDialog"; import { configureMonaco, @@ -23,6 +22,7 @@ import SaveWorkflowDialog from "./SaveWorkflowDialog"; import update from "immutability-helper"; import { usePushHistory } from "../../components/NavLink"; import { timestampRenderer } from "../../utils/helpers"; +import { WorkflowVisualizer } from "orkes-workflow-visualizer"; import { KeyboardArrowLeftRounded, @@ -67,8 +67,8 @@ const useStyles = makeStyles({ gap: 8, }, editorLineDecorator: { - backgroundColor: "rgb(45, 45, 45, 0.1)" - } + backgroundColor: "rgb(45, 45, 45, 0.1)", + }, }); const actions = { @@ -240,21 +240,26 @@ export default function Workflow() { }; const handleWorkflowNodeClick = (node) => { - let editor = editorRef.current.getModel() - let searchResult = editor.findMatches(`"taskReferenceName": "${node.ref}"`) - if (searchResult.length){ - editorRef.current.revealLineInCenter(searchResult[0]?.range?.startLineNumber, 0); - setDecorations(editorRef.current.deltaDecorations(decorations, [ - { - range: searchResult[0]?.range, - options: { - isWholeLine: true, - inlineClassName: classes.editorLineDecorator - } - } - ])) + let editor = editorRef.current.getModel(); + let searchResult = editor.findMatches(`"taskReferenceName": "${node.ref}"`); + if (searchResult.length) { + editorRef.current.revealLineInCenter( + searchResult[0]?.range?.startLineNumber, + 0 + ); + setDecorations( + editorRef.current.deltaDecorations(decorations, [ + { + range: searchResult[0]?.range, + options: { + isWholeLine: true, + inlineClassName: classes.editorLineDecorator, + }, + }, + ]) + ); } - } + }; return ( <> @@ -369,8 +374,17 @@ export default function Workflow() { className={classes.resizer} onMouseDown={(e) => handleMouseDown(e)} /> -
- {dag && } +
+ {dag && dag?.workflowDef && ( + handleWorkflowNodeClick({ ref: data?.id })} + /> + )}
diff --git a/ui/src/pages/execution/Execution.jsx b/ui/src/pages/execution/Execution.jsx index 656713697..2527f2436 100644 --- a/ui/src/pages/execution/Execution.jsx +++ b/ui/src/pages/execution/Execution.jsx @@ -222,7 +222,12 @@ export default function Execution() { )}
- Definition + + Definition +
Refresh diff --git a/ui/src/pages/execution/TaskDetails.jsx b/ui/src/pages/execution/TaskDetails.jsx index 6948f645f..0850a7d4f 100644 --- a/ui/src/pages/execution/TaskDetails.jsx +++ b/ui/src/pages/execution/TaskDetails.jsx @@ -1,9 +1,9 @@ -import React, { useState } from "react"; +import { useState } from "react"; import { Tabs, Tab, Paper } from "../../components"; import Timeline from "./Timeline"; import TaskList from "./TaskList"; -import WorkflowGraph from "../../components/diagram/WorkflowGraph"; import { makeStyles } from "@material-ui/styles"; +import { WorkflowVisualizer } from "orkes-workflow-visualizer"; const useStyles = makeStyles({ taskWrapper: { @@ -32,11 +32,14 @@ export default function TaskDetails({ {tabIndex === 0 && ( - setSelectedTask({ ref: data?.id })} /> )} {tabIndex === 1 && ( From 450720183200cc53826179136b53431bbccfc926 Mon Sep 17 00:00:00 2001 From: Shailesh Jagannath Padave Date: Mon, 18 Nov 2024 12:16:49 +0530 Subject: [PATCH 02/20] make BulkResponse parametrized --- .../netflix/conductor/common/model/BulkResponse.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/common/src/main/java/com/netflix/conductor/common/model/BulkResponse.java b/common/src/main/java/com/netflix/conductor/common/model/BulkResponse.java index b4133b5bf..6d4d16c3e 100644 --- a/common/src/main/java/com/netflix/conductor/common/model/BulkResponse.java +++ b/common/src/main/java/com/netflix/conductor/common/model/BulkResponse.java @@ -22,12 +22,12 @@ * Response object to return a list of succeeded entities and a map of failed ones, including error * message, for the bulk request. */ -public class BulkResponse { +public class BulkResponse { /** Key - entityId Value - error message processing this entity */ private final Map bulkErrorResults; - private final List bulkSuccessfulResults; + private final List bulkSuccessfulResults; private final String message = "Bulk Request has been processed."; public BulkResponse() { @@ -35,7 +35,7 @@ public BulkResponse() { this.bulkErrorResults = new HashMap<>(); } - public List getBulkSuccessfulResults() { + public List getBulkSuccessfulResults() { return bulkSuccessfulResults; } @@ -43,8 +43,8 @@ public Map getBulkErrorResults() { return bulkErrorResults; } - public void appendSuccessResponse(String id) { - bulkSuccessfulResults.add(id); + public void appendSuccessResponse(T result) { + bulkSuccessfulResults.add(result); } public void appendFailedResponse(String id, String errorMessage) { From b29c947ef76e86da9e93d953a9c19537e5525e38 Mon Sep 17 00:00:00 2001 From: Shailesh Jagannath Padave Date: Mon, 18 Nov 2024 13:07:43 +0530 Subject: [PATCH 03/20] code changes --- .../conductor/client/http/WorkflowClient.java | 2 +- .../conductor/common/model/BulkResponse.java | 3 +- .../conductor/client/http/WorkflowClient.java | 2 +- .../client/http/OrkesWorkflowClient.java | 10 +++---- .../client/http/WorkflowBulkResource.java | 2 +- .../conductor/service/MetadataService.java | 2 +- .../service/MetadataServiceImpl.java | 4 +-- .../service/WorkflowBulkService.java | 14 +++++----- .../service/WorkflowBulkServiceImpl.java | 28 +++++++++---------- .../service/MetadataServiceTest.java | 4 +-- .../rest/controllers/MetadataResource.java | 2 +- .../controllers/WorkflowBulkResource.java | 14 +++++----- 12 files changed, 43 insertions(+), 44 deletions(-) diff --git a/client/src/main/java/com/netflix/conductor/client/http/WorkflowClient.java b/client/src/main/java/com/netflix/conductor/client/http/WorkflowClient.java index a16ae421f..d3fb4bead 100644 --- a/client/src/main/java/com/netflix/conductor/client/http/WorkflowClient.java +++ b/client/src/main/java/com/netflix/conductor/client/http/WorkflowClient.java @@ -256,7 +256,7 @@ public void deleteWorkflow(String workflowId, boolean archiveWorkflow) { * @param reason the reason to be logged and displayed * @return the {@link BulkResponse} contains bulkErrorResults and bulkSuccessfulResults */ - public BulkResponse terminateWorkflows(List workflowIds, String reason) { + public BulkResponse terminateWorkflows(List workflowIds, String reason) { Validate.isTrue(!workflowIds.isEmpty(), "workflow id cannot be blank"); return postForEntity( "workflow/bulk/terminate", diff --git a/common/src/main/java/com/netflix/conductor/common/model/BulkResponse.java b/common/src/main/java/com/netflix/conductor/common/model/BulkResponse.java index 6d4d16c3e..a72d2a9f4 100644 --- a/common/src/main/java/com/netflix/conductor/common/model/BulkResponse.java +++ b/common/src/main/java/com/netflix/conductor/common/model/BulkResponse.java @@ -56,10 +56,9 @@ public boolean equals(Object o) { if (this == o) { return true; } - if (!(o instanceof BulkResponse)) { + if (!(o instanceof BulkResponse that)) { return false; } - BulkResponse that = (BulkResponse) o; return Objects.equals(bulkSuccessfulResults, that.bulkSuccessfulResults) && Objects.equals(bulkErrorResults, that.bulkErrorResults); } diff --git a/conductor-clients/java/conductor-java-sdk/conductor-client/src/main/java/com/netflix/conductor/client/http/WorkflowClient.java b/conductor-clients/java/conductor-java-sdk/conductor-client/src/main/java/com/netflix/conductor/client/http/WorkflowClient.java index bb5ae9048..63654e4b1 100644 --- a/conductor-clients/java/conductor-java-sdk/conductor-client/src/main/java/com/netflix/conductor/client/http/WorkflowClient.java +++ b/conductor-clients/java/conductor-java-sdk/conductor-client/src/main/java/com/netflix/conductor/client/http/WorkflowClient.java @@ -255,7 +255,7 @@ public void deleteWorkflow(String workflowId, boolean archiveWorkflow) { * @param reason the reason to be logged and displayed * @return the {@link BulkResponse} contains bulkErrorResults and bulkSuccessfulResults */ - public BulkResponse terminateWorkflows(List workflowIds, String reason) { + public BulkResponse terminateWorkflows(List workflowIds, String reason) { Validate.isTrue(!workflowIds.isEmpty(), "workflow id cannot be blank"); ConductorClientRequest request = ConductorClientRequest.builder() diff --git a/conductor-clients/java/conductor-java-sdk/orkes-client/src/main/java/io/orkes/conductor/client/http/OrkesWorkflowClient.java b/conductor-clients/java/conductor-java-sdk/orkes-client/src/main/java/io/orkes/conductor/client/http/OrkesWorkflowClient.java index 0b47c6ff3..acdef219e 100644 --- a/conductor-clients/java/conductor-java-sdk/orkes-client/src/main/java/io/orkes/conductor/client/http/OrkesWorkflowClient.java +++ b/conductor-clients/java/conductor-java-sdk/orkes-client/src/main/java/io/orkes/conductor/client/http/OrkesWorkflowClient.java @@ -120,23 +120,23 @@ public void terminateWorkflowWithFailure(String workflowId, String reason, boole workflowResource.terminateWithAReason(workflowId, reason, triggerFailureWorkflow); } - public BulkResponse pauseWorkflow(List workflowIds) { + public BulkResponse pauseWorkflow(List workflowIds) { return bulkResource.pauseWorkflows(workflowIds); } - public BulkResponse restartWorkflow(List workflowIds, Boolean useLatestDefinitions) { + public BulkResponse restartWorkflow(List workflowIds, Boolean useLatestDefinitions) { return bulkResource.restartWorkflows(workflowIds, useLatestDefinitions); } - public BulkResponse resumeWorkflow(List workflowIds) { + public BulkResponse resumeWorkflow(List workflowIds) { return bulkResource.resumeWorkflows(workflowIds); } - public BulkResponse retryWorkflow(List workflowIds) { + public BulkResponse retryWorkflow(List workflowIds) { return bulkResource.retryWorkflows(workflowIds); } - public BulkResponse terminateWorkflowsWithFailure(List workflowIds, String reason, boolean triggerFailureWorkflow) { + public BulkResponse terminateWorkflowsWithFailure(List workflowIds, String reason, boolean triggerFailureWorkflow) { return bulkResource.terminateWorkflows(workflowIds, reason, triggerFailureWorkflow); } diff --git a/conductor-clients/java/conductor-java-sdk/orkes-client/src/main/java/io/orkes/conductor/client/http/WorkflowBulkResource.java b/conductor-clients/java/conductor-java-sdk/orkes-client/src/main/java/io/orkes/conductor/client/http/WorkflowBulkResource.java index 31db8c05a..d00c636a6 100644 --- a/conductor-clients/java/conductor-java-sdk/orkes-client/src/main/java/io/orkes/conductor/client/http/WorkflowBulkResource.java +++ b/conductor-clients/java/conductor-java-sdk/orkes-client/src/main/java/io/orkes/conductor/client/http/WorkflowBulkResource.java @@ -84,7 +84,7 @@ BulkResponse retryWorkflows(List workflowIds) { return resp.getData(); } - public BulkResponse terminateWorkflows(List workflowIds, String reason, boolean triggerFailureWorkflow) { + public BulkResponse terminateWorkflows(List workflowIds, String reason, boolean triggerFailureWorkflow) { ConductorClientRequest request = ConductorClientRequest.builder() .method(Method.POST) .path("/workflow/bulk/terminate") diff --git a/core/src/main/java/com/netflix/conductor/service/MetadataService.java b/core/src/main/java/com/netflix/conductor/service/MetadataService.java index 5edd42ef5..413066689 100644 --- a/core/src/main/java/com/netflix/conductor/service/MetadataService.java +++ b/core/src/main/java/com/netflix/conductor/service/MetadataService.java @@ -69,7 +69,7 @@ void registerTaskDef( /** * @param workflowDefList Workflow definitions to be updated. */ - BulkResponse updateWorkflowDef( + BulkResponse updateWorkflowDef( @NotNull(message = "WorkflowDef list name cannot be null or empty") @Size(min = 1, message = "WorkflowDefList is empty") List<@NotNull(message = "WorkflowDef cannot be null") @Valid WorkflowDef> diff --git a/core/src/main/java/com/netflix/conductor/service/MetadataServiceImpl.java b/core/src/main/java/com/netflix/conductor/service/MetadataServiceImpl.java index 1399e9f08..2e9af4acb 100644 --- a/core/src/main/java/com/netflix/conductor/service/MetadataServiceImpl.java +++ b/core/src/main/java/com/netflix/conductor/service/MetadataServiceImpl.java @@ -124,8 +124,8 @@ public void updateWorkflowDef(WorkflowDef workflowDef) { /** * @param workflowDefList Workflow definitions to be updated. */ - public BulkResponse updateWorkflowDef(List workflowDefList) { - BulkResponse bulkResponse = new BulkResponse(); + public BulkResponse updateWorkflowDef(List workflowDefList) { + BulkResponse bulkResponse = new BulkResponse<>(); for (WorkflowDef workflowDef : workflowDefList) { try { updateWorkflowDef(workflowDef); diff --git a/core/src/main/java/com/netflix/conductor/service/WorkflowBulkService.java b/core/src/main/java/com/netflix/conductor/service/WorkflowBulkService.java index ca240b1a9..8ea185be7 100644 --- a/core/src/main/java/com/netflix/conductor/service/WorkflowBulkService.java +++ b/core/src/main/java/com/netflix/conductor/service/WorkflowBulkService.java @@ -26,7 +26,7 @@ public interface WorkflowBulkService { int MAX_REQUEST_ITEMS = 1000; - BulkResponse pauseWorkflow( + BulkResponse pauseWorkflow( @NotEmpty(message = "WorkflowIds list cannot be null.") @Size( max = MAX_REQUEST_ITEMS, @@ -34,7 +34,7 @@ BulkResponse pauseWorkflow( "Cannot process more than {max} workflows. Please use multiple requests.") List workflowIds); - BulkResponse resumeWorkflow( + BulkResponse resumeWorkflow( @NotEmpty(message = "WorkflowIds list cannot be null.") @Size( max = MAX_REQUEST_ITEMS, @@ -42,7 +42,7 @@ BulkResponse resumeWorkflow( "Cannot process more than {max} workflows. Please use multiple requests.") List workflowIds); - BulkResponse restart( + BulkResponse restart( @NotEmpty(message = "WorkflowIds list cannot be null.") @Size( max = MAX_REQUEST_ITEMS, @@ -51,7 +51,7 @@ BulkResponse restart( List workflowIds, boolean useLatestDefinitions); - BulkResponse retry( + BulkResponse retry( @NotEmpty(message = "WorkflowIds list cannot be null.") @Size( max = MAX_REQUEST_ITEMS, @@ -59,7 +59,7 @@ BulkResponse retry( "Cannot process more than {max} workflows. Please use multiple requests.") List workflowIds); - BulkResponse terminate( + BulkResponse terminate( @NotEmpty(message = "WorkflowIds list cannot be null.") @Size( max = MAX_REQUEST_ITEMS, @@ -68,7 +68,7 @@ BulkResponse terminate( List workflowIds, String reason); - BulkResponse deleteWorkflow( + BulkResponse deleteWorkflow( @NotEmpty(message = "WorkflowIds list cannot be null.") @Size( max = MAX_REQUEST_ITEMS, @@ -77,7 +77,7 @@ BulkResponse deleteWorkflow( List workflowIds, boolean archiveWorkflow); - BulkResponse terminateRemove( + BulkResponse terminateRemove( @NotEmpty(message = "WorkflowIds list cannot be null.") @Size( max = MAX_REQUEST_ITEMS, diff --git a/core/src/main/java/com/netflix/conductor/service/WorkflowBulkServiceImpl.java b/core/src/main/java/com/netflix/conductor/service/WorkflowBulkServiceImpl.java index fcbdbe3bc..30e52e3b1 100644 --- a/core/src/main/java/com/netflix/conductor/service/WorkflowBulkServiceImpl.java +++ b/core/src/main/java/com/netflix/conductor/service/WorkflowBulkServiceImpl.java @@ -45,9 +45,9 @@ public WorkflowBulkServiceImpl( * @return bulk response object containing a list of succeeded workflows and a list of failed * ones with errors */ - public BulkResponse pauseWorkflow(List workflowIds) { + public BulkResponse pauseWorkflow(List workflowIds) { - BulkResponse bulkResponse = new BulkResponse(); + BulkResponse bulkResponse = new BulkResponse<>(); for (String workflowId : workflowIds) { try { workflowExecutor.pauseWorkflow(workflowId); @@ -72,8 +72,8 @@ public BulkResponse pauseWorkflow(List workflowIds) { * @return bulk response object containing a list of succeeded workflows and a list of failed * ones with errors */ - public BulkResponse resumeWorkflow(List workflowIds) { - BulkResponse bulkResponse = new BulkResponse(); + public BulkResponse resumeWorkflow(List workflowIds) { + BulkResponse bulkResponse = new BulkResponse<>(); for (String workflowId : workflowIds) { try { workflowExecutor.resumeWorkflow(workflowId); @@ -98,8 +98,8 @@ public BulkResponse resumeWorkflow(List workflowIds) { * @return bulk response object containing a list of succeeded workflows and a list of failed * ones with errors */ - public BulkResponse restart(List workflowIds, boolean useLatestDefinitions) { - BulkResponse bulkResponse = new BulkResponse(); + public BulkResponse restart(List workflowIds, boolean useLatestDefinitions) { + BulkResponse bulkResponse = new BulkResponse<>(); for (String workflowId : workflowIds) { try { workflowExecutor.restart(workflowId, useLatestDefinitions); @@ -123,8 +123,8 @@ public BulkResponse restart(List workflowIds, boolean useLatestDefinitio * @return bulk response object containing a list of succeeded workflows and a list of failed * ones with errors */ - public BulkResponse retry(List workflowIds) { - BulkResponse bulkResponse = new BulkResponse(); + public BulkResponse retry(List workflowIds) { + BulkResponse bulkResponse = new BulkResponse<>(); for (String workflowId : workflowIds) { try { workflowExecutor.retry(workflowId, false); @@ -150,8 +150,8 @@ public BulkResponse retry(List workflowIds) { * @return bulk response object containing a list of succeeded workflows and a list of failed * ones with errors */ - public BulkResponse terminate(List workflowIds, String reason) { - BulkResponse bulkResponse = new BulkResponse(); + public BulkResponse terminate(List workflowIds, String reason) { + BulkResponse bulkResponse = new BulkResponse<>(); for (String workflowId : workflowIds) { try { workflowExecutor.terminateWorkflow(workflowId, reason); @@ -174,8 +174,8 @@ public BulkResponse terminate(List workflowIds, String reason) { * @param workflowIds List of WorkflowIDs of the workflows you want to remove from system. * @param archiveWorkflow Archives the workflow and associated tasks instead of removing them. */ - public BulkResponse deleteWorkflow(List workflowIds, boolean archiveWorkflow) { - BulkResponse bulkResponse = new BulkResponse(); + public BulkResponse deleteWorkflow(List workflowIds, boolean archiveWorkflow) { + BulkResponse bulkResponse = new BulkResponse<>(); for (String workflowId : workflowIds) { try { workflowService.deleteWorkflow( @@ -203,9 +203,9 @@ public BulkResponse deleteWorkflow(List workflowIds, boolean archiveWork * @return bulk response object containing a list of succeeded workflows and a list of failed * ones with errors */ - public BulkResponse terminateRemove( + public BulkResponse terminateRemove( List workflowIds, String reason, boolean archiveWorkflow) { - BulkResponse bulkResponse = new BulkResponse(); + BulkResponse bulkResponse = new BulkResponse<>(); for (String workflowId : workflowIds) { try { workflowExecutor.terminateWorkflow(workflowId, reason); diff --git a/core/src/test/java/com/netflix/conductor/service/MetadataServiceTest.java b/core/src/test/java/com/netflix/conductor/service/MetadataServiceTest.java index 255703be5..3f4c028c1 100644 --- a/core/src/test/java/com/netflix/conductor/service/MetadataServiceTest.java +++ b/core/src/test/java/com/netflix/conductor/service/MetadataServiceTest.java @@ -336,7 +336,7 @@ public void testUpdateWorkflowDefWithCaseExpression() { tasks.add(workflowTask); workflowDef.setTasks(tasks); - BulkResponse bulkResponse = + BulkResponse bulkResponse = metadataService.updateWorkflowDef(Collections.singletonList(workflowDef)); } @@ -366,7 +366,7 @@ public void testUpdateWorkflowDefWithJavscriptEvaluator() { tasks.add(workflowTask); workflowDef.setTasks(tasks); - BulkResponse bulkResponse = + BulkResponse bulkResponse = metadataService.updateWorkflowDef(Collections.singletonList(workflowDef)); } diff --git a/rest/src/main/java/com/netflix/conductor/rest/controllers/MetadataResource.java b/rest/src/main/java/com/netflix/conductor/rest/controllers/MetadataResource.java index 5ffda1ed4..234351883 100644 --- a/rest/src/main/java/com/netflix/conductor/rest/controllers/MetadataResource.java +++ b/rest/src/main/java/com/netflix/conductor/rest/controllers/MetadataResource.java @@ -59,7 +59,7 @@ public void validate(@RequestBody WorkflowDef workflowDef) { @PutMapping("/workflow") @Operation(summary = "Create or update workflow definition") - public BulkResponse update(@RequestBody List workflowDefs) { + public BulkResponse update(@RequestBody List workflowDefs) { return metadataService.updateWorkflowDef(workflowDefs); } diff --git a/rest/src/main/java/com/netflix/conductor/rest/controllers/WorkflowBulkResource.java b/rest/src/main/java/com/netflix/conductor/rest/controllers/WorkflowBulkResource.java index 9005b9343..b9f36679d 100644 --- a/rest/src/main/java/com/netflix/conductor/rest/controllers/WorkflowBulkResource.java +++ b/rest/src/main/java/com/netflix/conductor/rest/controllers/WorkflowBulkResource.java @@ -49,7 +49,7 @@ public WorkflowBulkResource(WorkflowBulkService workflowBulkService) { */ @PutMapping("/pause") @Operation(summary = "Pause the list of workflows") - public BulkResponse pauseWorkflow(@RequestBody List workflowIds) { + public BulkResponse pauseWorkflow(@RequestBody List workflowIds) { return workflowBulkService.pauseWorkflow(workflowIds); } @@ -62,7 +62,7 @@ public BulkResponse pauseWorkflow(@RequestBody List workflowIds) { */ @PutMapping("/resume") @Operation(summary = "Resume the list of workflows") - public BulkResponse resumeWorkflow(@RequestBody List workflowIds) { + public BulkResponse resumeWorkflow(@RequestBody List workflowIds) { return workflowBulkService.resumeWorkflow(workflowIds); } @@ -76,7 +76,7 @@ public BulkResponse resumeWorkflow(@RequestBody List workflowIds) { */ @PostMapping("/restart") @Operation(summary = "Restart the list of completed workflow") - public BulkResponse restart( + public BulkResponse restart( @RequestBody List workflowIds, @RequestParam(value = "useLatestDefinitions", defaultValue = "false", required = false) boolean useLatestDefinitions) { @@ -92,7 +92,7 @@ public BulkResponse restart( */ @PostMapping("/retry") @Operation(summary = "Retry the last failed task for each workflow from the list") - public BulkResponse retry(@RequestBody List workflowIds) { + public BulkResponse retry(@RequestBody List workflowIds) { return workflowBulkService.retry(workflowIds); } @@ -107,7 +107,7 @@ public BulkResponse retry(@RequestBody List workflowIds) { */ @PostMapping("/terminate") @Operation(summary = "Terminate workflows execution") - public BulkResponse terminate( + public BulkResponse terminate( @RequestBody List workflowIds, @RequestParam(value = "reason", required = false) String reason) { return workflowBulkService.terminate(workflowIds, reason); @@ -120,7 +120,7 @@ public BulkResponse terminate( * @return bulk reponse object containing a list of successfully deleted workflows */ @DeleteMapping("/remove") - public BulkResponse deleteWorkflow( + public BulkResponse deleteWorkflow( @RequestBody List workflowIds, @RequestParam(value = "archiveWorkflow", defaultValue = "true", required = false) boolean archiveWorkflow) { @@ -134,7 +134,7 @@ public BulkResponse deleteWorkflow( * @return bulk response object containing a list of successfully deleted workflows */ @DeleteMapping("/terminate-remove") - public BulkResponse terminateRemove( + public BulkResponse terminateRemove( @RequestBody List workflowIds, @RequestParam(value = "archiveWorkflow", defaultValue = "true", required = false) boolean archiveWorkflow, From d0967c1e293a81c99297a251527fd2345fcb10ce Mon Sep 17 00:00:00 2001 From: Shailesh Jagannath Padave Date: Mon, 18 Nov 2024 14:37:19 +0530 Subject: [PATCH 04/20] code changes for terminateWorkflows --- .../java/com/netflix/conductor/client/http/WorkflowClient.java | 2 +- .../java/com/netflix/conductor/common/model/BulkResponse.java | 2 ++ .../java/com/netflix/conductor/client/http/WorkflowClient.java | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/client/src/main/java/com/netflix/conductor/client/http/WorkflowClient.java b/client/src/main/java/com/netflix/conductor/client/http/WorkflowClient.java index d3fb4bead..a16ae421f 100644 --- a/client/src/main/java/com/netflix/conductor/client/http/WorkflowClient.java +++ b/client/src/main/java/com/netflix/conductor/client/http/WorkflowClient.java @@ -256,7 +256,7 @@ public void deleteWorkflow(String workflowId, boolean archiveWorkflow) { * @param reason the reason to be logged and displayed * @return the {@link BulkResponse} contains bulkErrorResults and bulkSuccessfulResults */ - public BulkResponse terminateWorkflows(List workflowIds, String reason) { + public BulkResponse terminateWorkflows(List workflowIds, String reason) { Validate.isTrue(!workflowIds.isEmpty(), "workflow id cannot be blank"); return postForEntity( "workflow/bulk/terminate", diff --git a/common/src/main/java/com/netflix/conductor/common/model/BulkResponse.java b/common/src/main/java/com/netflix/conductor/common/model/BulkResponse.java index a72d2a9f4..ff35ea5df 100644 --- a/common/src/main/java/com/netflix/conductor/common/model/BulkResponse.java +++ b/common/src/main/java/com/netflix/conductor/common/model/BulkResponse.java @@ -21,6 +21,8 @@ /** * Response object to return a list of succeeded entities and a map of failed ones, including error * message, for the bulk request. + * + * @param the type of entities included in the successful results */ public class BulkResponse { diff --git a/conductor-clients/java/conductor-java-sdk/conductor-client/src/main/java/com/netflix/conductor/client/http/WorkflowClient.java b/conductor-clients/java/conductor-java-sdk/conductor-client/src/main/java/com/netflix/conductor/client/http/WorkflowClient.java index 63654e4b1..bb5ae9048 100644 --- a/conductor-clients/java/conductor-java-sdk/conductor-client/src/main/java/com/netflix/conductor/client/http/WorkflowClient.java +++ b/conductor-clients/java/conductor-java-sdk/conductor-client/src/main/java/com/netflix/conductor/client/http/WorkflowClient.java @@ -255,7 +255,7 @@ public void deleteWorkflow(String workflowId, boolean archiveWorkflow) { * @param reason the reason to be logged and displayed * @return the {@link BulkResponse} contains bulkErrorResults and bulkSuccessfulResults */ - public BulkResponse terminateWorkflows(List workflowIds, String reason) { + public BulkResponse terminateWorkflows(List workflowIds, String reason) { Validate.isTrue(!workflowIds.isEmpty(), "workflow id cannot be blank"); ConductorClientRequest request = ConductorClientRequest.builder() From 9906b1557db4e7fb0e3d3bc6bf23ef1ba5755cd1 Mon Sep 17 00:00:00 2001 From: Shailesh Jagannath Padave Date: Mon, 18 Nov 2024 14:46:54 +0530 Subject: [PATCH 05/20] code changes for OrkesWorkflowClient --- .../conductor/client/http/OrkesWorkflowClient.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/conductor-clients/java/conductor-java-sdk/orkes-client/src/main/java/io/orkes/conductor/client/http/OrkesWorkflowClient.java b/conductor-clients/java/conductor-java-sdk/orkes-client/src/main/java/io/orkes/conductor/client/http/OrkesWorkflowClient.java index acdef219e..0b47c6ff3 100644 --- a/conductor-clients/java/conductor-java-sdk/orkes-client/src/main/java/io/orkes/conductor/client/http/OrkesWorkflowClient.java +++ b/conductor-clients/java/conductor-java-sdk/orkes-client/src/main/java/io/orkes/conductor/client/http/OrkesWorkflowClient.java @@ -120,23 +120,23 @@ public void terminateWorkflowWithFailure(String workflowId, String reason, boole workflowResource.terminateWithAReason(workflowId, reason, triggerFailureWorkflow); } - public BulkResponse pauseWorkflow(List workflowIds) { + public BulkResponse pauseWorkflow(List workflowIds) { return bulkResource.pauseWorkflows(workflowIds); } - public BulkResponse restartWorkflow(List workflowIds, Boolean useLatestDefinitions) { + public BulkResponse restartWorkflow(List workflowIds, Boolean useLatestDefinitions) { return bulkResource.restartWorkflows(workflowIds, useLatestDefinitions); } - public BulkResponse resumeWorkflow(List workflowIds) { + public BulkResponse resumeWorkflow(List workflowIds) { return bulkResource.resumeWorkflows(workflowIds); } - public BulkResponse retryWorkflow(List workflowIds) { + public BulkResponse retryWorkflow(List workflowIds) { return bulkResource.retryWorkflows(workflowIds); } - public BulkResponse terminateWorkflowsWithFailure(List workflowIds, String reason, boolean triggerFailureWorkflow) { + public BulkResponse terminateWorkflowsWithFailure(List workflowIds, String reason, boolean triggerFailureWorkflow) { return bulkResource.terminateWorkflows(workflowIds, reason, triggerFailureWorkflow); } From f878d5c0dbbdb0a9b163e4a1b56c373d2d183cd9 Mon Sep 17 00:00:00 2001 From: Shailesh Jagannath Padave Date: Mon, 18 Nov 2024 14:53:54 +0530 Subject: [PATCH 06/20] code changes for WorkflowBulkResource --- .../orkes/conductor/client/http/WorkflowBulkResource.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/conductor-clients/java/conductor-java-sdk/orkes-client/src/main/java/io/orkes/conductor/client/http/WorkflowBulkResource.java b/conductor-clients/java/conductor-java-sdk/orkes-client/src/main/java/io/orkes/conductor/client/http/WorkflowBulkResource.java index d00c636a6..56c3e92a5 100644 --- a/conductor-clients/java/conductor-java-sdk/orkes-client/src/main/java/io/orkes/conductor/client/http/WorkflowBulkResource.java +++ b/conductor-clients/java/conductor-java-sdk/orkes-client/src/main/java/io/orkes/conductor/client/http/WorkflowBulkResource.java @@ -31,7 +31,7 @@ class WorkflowBulkResource { this.client = client; } - BulkResponse pauseWorkflows(List workflowIds) { + BulkResponse pauseWorkflows(List workflowIds) { ConductorClientRequest request = ConductorClientRequest.builder() .method(Method.PUT) .path("/workflow/bulk/pause") @@ -44,7 +44,7 @@ BulkResponse pauseWorkflows(List workflowIds) { return resp.getData(); } - BulkResponse restartWorkflows(List workflowIds, Boolean useLatestDefinitions) { + BulkResponse restartWorkflows(List workflowIds, Boolean useLatestDefinitions) { ConductorClientRequest request = ConductorClientRequest.builder() .method(Method.POST) .path("/workflow/bulk/restart") @@ -58,7 +58,7 @@ BulkResponse restartWorkflows(List workflowIds, Boolean useLatestDefinit return resp.getData(); } - BulkResponse resumeWorkflows(List workflowIds) { + BulkResponse resumeWorkflows(List workflowIds) { ConductorClientRequest request = ConductorClientRequest.builder() .method(Method.PUT) .path("/workflow/bulk/resume") @@ -71,7 +71,7 @@ BulkResponse resumeWorkflows(List workflowIds) { return resp.getData(); } - BulkResponse retryWorkflows(List workflowIds) { + BulkResponse retryWorkflows(List workflowIds) { ConductorClientRequest request = ConductorClientRequest.builder() .method(Method.POST) .path("/workflow/bulk/retry") From c29b2b409388482feffc94622d5d451cd0be402d Mon Sep 17 00:00:00 2001 From: Shailesh Jagannath Padave Date: Mon, 18 Nov 2024 15:03:29 +0530 Subject: [PATCH 07/20] code changes for BulkResponse in client --- .../netflix/conductor/common/model/BulkResponse.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/conductor-clients/java/conductor-java-sdk/conductor-client/src/main/java/com/netflix/conductor/common/model/BulkResponse.java b/conductor-clients/java/conductor-java-sdk/conductor-client/src/main/java/com/netflix/conductor/common/model/BulkResponse.java index 99b3f48f9..d27d9dc9e 100644 --- a/conductor-clients/java/conductor-java-sdk/conductor-client/src/main/java/com/netflix/conductor/common/model/BulkResponse.java +++ b/conductor-clients/java/conductor-java-sdk/conductor-client/src/main/java/com/netflix/conductor/common/model/BulkResponse.java @@ -21,15 +21,17 @@ /** * Response object to return a list of succeeded entities and a map of failed ones, including error * message, for the bulk request. + * + * @param the type of entities included in the successful results */ -public class BulkResponse { +public class BulkResponse { /** * Key - entityId Value - error message processing this entity */ private final Map bulkErrorResults; - private final List bulkSuccessfulResults; + private final List bulkSuccessfulResults; private final String message = "Bulk Request has been processed."; @@ -38,7 +40,7 @@ public BulkResponse() { this.bulkErrorResults = new HashMap<>(); } - public List getBulkSuccessfulResults() { + public List getBulkSuccessfulResults() { return bulkSuccessfulResults; } @@ -46,8 +48,8 @@ public Map getBulkErrorResults() { return bulkErrorResults; } - public void appendSuccessResponse(String id) { - bulkSuccessfulResults.add(id); + public void appendSuccessResponse(T result) { + bulkSuccessfulResults.add(result); } public void appendFailedResponse(String id, String errorMessage) { From d9b623bfb74762a99976fe9f882719241de7c41b Mon Sep 17 00:00:00 2001 From: Shailesh Jagannath Padave Date: Mon, 18 Nov 2024 22:48:57 +0530 Subject: [PATCH 08/20] Added endpoint --- .../service/WorkflowBulkService.java | 10 ++++ .../service/WorkflowBulkServiceImpl.java | 53 ++++++++++++++----- .../controllers/WorkflowBulkResource.java | 15 ++++++ 3 files changed, 66 insertions(+), 12 deletions(-) diff --git a/core/src/main/java/com/netflix/conductor/service/WorkflowBulkService.java b/core/src/main/java/com/netflix/conductor/service/WorkflowBulkService.java index 8ea185be7..3be0ffe89 100644 --- a/core/src/main/java/com/netflix/conductor/service/WorkflowBulkService.java +++ b/core/src/main/java/com/netflix/conductor/service/WorkflowBulkService.java @@ -14,6 +14,7 @@ import java.util.List; +import com.netflix.conductor.model.WorkflowModel; import org.springframework.validation.annotation.Validated; import com.netflix.conductor.common.model.BulkResponse; @@ -86,4 +87,13 @@ BulkResponse terminateRemove( List workflowIds, String reason, boolean archiveWorkflow); + + BulkResponse searchWorkflow( + @NotEmpty(message = "WorkflowIds list cannot be null.") + @Size( + max = MAX_REQUEST_ITEMS, + message = + "Cannot process more than {max} workflows. Please use multiple requests.") + List workflowIds, + boolean includeTasks); } diff --git a/core/src/main/java/com/netflix/conductor/service/WorkflowBulkServiceImpl.java b/core/src/main/java/com/netflix/conductor/service/WorkflowBulkServiceImpl.java index 30e52e3b1..715c77b4c 100644 --- a/core/src/main/java/com/netflix/conductor/service/WorkflowBulkServiceImpl.java +++ b/core/src/main/java/com/netflix/conductor/service/WorkflowBulkServiceImpl.java @@ -14,6 +14,7 @@ import java.util.List; +import com.netflix.conductor.model.WorkflowModel; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; @@ -43,7 +44,7 @@ public WorkflowBulkServiceImpl( * * @param workflowIds - list of workflow Ids to perform pause operation on * @return bulk response object containing a list of succeeded workflows and a list of failed - * ones with errors + * ones with errors */ public BulkResponse pauseWorkflow(List workflowIds) { @@ -70,7 +71,7 @@ public BulkResponse pauseWorkflow(List workflowIds) { * * @param workflowIds - list of workflow Ids to perform resume operation on * @return bulk response object containing a list of succeeded workflows and a list of failed - * ones with errors + * ones with errors */ public BulkResponse resumeWorkflow(List workflowIds) { BulkResponse bulkResponse = new BulkResponse<>(); @@ -93,10 +94,10 @@ public BulkResponse resumeWorkflow(List workflowIds) { /** * Restart the list of workflows. * - * @param workflowIds - list of workflow Ids to perform restart operation on + * @param workflowIds - list of workflow Ids to perform restart operation on * @param useLatestDefinitions if true, use latest workflow and task definitions upon restart * @return bulk response object containing a list of succeeded workflows and a list of failed - * ones with errors + * ones with errors */ public BulkResponse restart(List workflowIds, boolean useLatestDefinitions) { BulkResponse bulkResponse = new BulkResponse<>(); @@ -121,7 +122,7 @@ public BulkResponse restart(List workflowIds, boolean useLatestD * * @param workflowIds - list of workflow Ids to perform retry operation on * @return bulk response object containing a list of succeeded workflows and a list of failed - * ones with errors + * ones with errors */ public BulkResponse retry(List workflowIds) { BulkResponse bulkResponse = new BulkResponse<>(); @@ -145,10 +146,10 @@ public BulkResponse retry(List workflowIds) { * Terminate workflows execution. * * @param workflowIds - list of workflow Ids to perform terminate operation on - * @param reason - description to be specified for the terminated workflow for future - * references. + * @param reason - description to be specified for the terminated workflow for future + * references. * @return bulk response object containing a list of succeeded workflows and a list of failed - * ones with errors + * ones with errors */ public BulkResponse terminate(List workflowIds, String reason) { BulkResponse bulkResponse = new BulkResponse<>(); @@ -171,7 +172,7 @@ public BulkResponse terminate(List workflowIds, String reason) { /** * Removes a list of workflows from the system. * - * @param workflowIds List of WorkflowIDs of the workflows you want to remove from system. + * @param workflowIds List of WorkflowIDs of the workflows you want to remove from system. * @param archiveWorkflow Archives the workflow and associated tasks instead of removing them. */ public BulkResponse deleteWorkflow(List workflowIds, boolean archiveWorkflow) { @@ -197,11 +198,11 @@ public BulkResponse deleteWorkflow(List workflowIds, boolean arc /** * Terminates execution for workflows in a list, then removes each workflow. * - * @param workflowIds List of workflow IDs to terminate and delete. - * @param reason Reason for terminating the workflow. + * @param workflowIds List of workflow IDs to terminate and delete. + * @param reason Reason for terminating the workflow. * @param archiveWorkflow Archives the workflow and associated tasks instead of removing them. * @return bulk response object containing a list of succeeded workflows and a list of failed - * ones with errors + * ones with errors */ public BulkResponse terminateRemove( List workflowIds, String reason, boolean archiveWorkflow) { @@ -233,4 +234,32 @@ public BulkResponse terminateRemove( } return bulkResponse; } + + /** + * Fetch workflow details for given workflowIds. + * + * @param workflowIds List of workflow IDs to terminate and delete. + * @param includeTasks includes tasks from workflow + * @return bulk response object containing a list of workflow details + */ + @Override + public BulkResponse searchWorkflow(List workflowIds, boolean includeTasks) { + BulkResponse bulkResponse = new BulkResponse<>(); + for (String workflowId : workflowIds) { + try { + WorkflowModel workflowModel = workflowExecutor.getWorkflow(workflowId, includeTasks); + bulkResponse.appendSuccessResponse(workflowModel); + } catch (Exception e) { + LOGGER.error( + "bulk search exception, workflowId {}, message: {} ", + workflowId, + e.getMessage(), + e); + bulkResponse.appendFailedResponse(workflowId, e.getMessage()); + } + } + return bulkResponse; + } + + } diff --git a/rest/src/main/java/com/netflix/conductor/rest/controllers/WorkflowBulkResource.java b/rest/src/main/java/com/netflix/conductor/rest/controllers/WorkflowBulkResource.java index b9f36679d..9a7da24e5 100644 --- a/rest/src/main/java/com/netflix/conductor/rest/controllers/WorkflowBulkResource.java +++ b/rest/src/main/java/com/netflix/conductor/rest/controllers/WorkflowBulkResource.java @@ -14,6 +14,7 @@ import java.util.List; +import com.netflix.conductor.model.WorkflowModel; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; @@ -141,4 +142,18 @@ public BulkResponse terminateRemove( @RequestParam(value = "reason", required = false) String reason) { return workflowBulkService.terminateRemove(workflowIds, reason, archiveWorkflow); } + + /** + * Search workflows for given list of workflows. + * + * @param workflowIds - list of workflow Ids to be searched + * @return bulk response object containing a list of workflows + */ + @PostMapping("/search") + public BulkResponse searchWorkflow( + @RequestBody List workflowIds, + @RequestParam(value = "includeTasks", defaultValue = "true", required = false) + boolean includeTasks) { + return workflowBulkService.searchWorkflow(workflowIds, includeTasks); + } } From 4f6427ccce8c41bd187393d375dbba7f3f46eec7 Mon Sep 17 00:00:00 2001 From: Shailesh Jagannath Padave Date: Mon, 18 Nov 2024 23:01:37 +0530 Subject: [PATCH 09/20] updated code --- .../service/WorkflowBulkService.java | 2 +- .../service/WorkflowBulkServiceImpl.java | 36 +++++++++---------- .../controllers/WorkflowBulkResource.java | 4 +-- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/core/src/main/java/com/netflix/conductor/service/WorkflowBulkService.java b/core/src/main/java/com/netflix/conductor/service/WorkflowBulkService.java index 3be0ffe89..a82a8d5f2 100644 --- a/core/src/main/java/com/netflix/conductor/service/WorkflowBulkService.java +++ b/core/src/main/java/com/netflix/conductor/service/WorkflowBulkService.java @@ -14,10 +14,10 @@ import java.util.List; -import com.netflix.conductor.model.WorkflowModel; import org.springframework.validation.annotation.Validated; import com.netflix.conductor.common.model.BulkResponse; +import com.netflix.conductor.model.WorkflowModel; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.Size; diff --git a/core/src/main/java/com/netflix/conductor/service/WorkflowBulkServiceImpl.java b/core/src/main/java/com/netflix/conductor/service/WorkflowBulkServiceImpl.java index 715c77b4c..aadacf9a1 100644 --- a/core/src/main/java/com/netflix/conductor/service/WorkflowBulkServiceImpl.java +++ b/core/src/main/java/com/netflix/conductor/service/WorkflowBulkServiceImpl.java @@ -14,7 +14,6 @@ import java.util.List; -import com.netflix.conductor.model.WorkflowModel; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; @@ -23,6 +22,7 @@ import com.netflix.conductor.annotations.Trace; import com.netflix.conductor.common.model.BulkResponse; import com.netflix.conductor.core.execution.WorkflowExecutor; +import com.netflix.conductor.model.WorkflowModel; @Audit @Trace @@ -44,7 +44,7 @@ public WorkflowBulkServiceImpl( * * @param workflowIds - list of workflow Ids to perform pause operation on * @return bulk response object containing a list of succeeded workflows and a list of failed - * ones with errors + * ones with errors */ public BulkResponse pauseWorkflow(List workflowIds) { @@ -71,7 +71,7 @@ public BulkResponse pauseWorkflow(List workflowIds) { * * @param workflowIds - list of workflow Ids to perform resume operation on * @return bulk response object containing a list of succeeded workflows and a list of failed - * ones with errors + * ones with errors */ public BulkResponse resumeWorkflow(List workflowIds) { BulkResponse bulkResponse = new BulkResponse<>(); @@ -94,10 +94,10 @@ public BulkResponse resumeWorkflow(List workflowIds) { /** * Restart the list of workflows. * - * @param workflowIds - list of workflow Ids to perform restart operation on + * @param workflowIds - list of workflow Ids to perform restart operation on * @param useLatestDefinitions if true, use latest workflow and task definitions upon restart * @return bulk response object containing a list of succeeded workflows and a list of failed - * ones with errors + * ones with errors */ public BulkResponse restart(List workflowIds, boolean useLatestDefinitions) { BulkResponse bulkResponse = new BulkResponse<>(); @@ -122,7 +122,7 @@ public BulkResponse restart(List workflowIds, boolean useLatestD * * @param workflowIds - list of workflow Ids to perform retry operation on * @return bulk response object containing a list of succeeded workflows and a list of failed - * ones with errors + * ones with errors */ public BulkResponse retry(List workflowIds) { BulkResponse bulkResponse = new BulkResponse<>(); @@ -146,10 +146,10 @@ public BulkResponse retry(List workflowIds) { * Terminate workflows execution. * * @param workflowIds - list of workflow Ids to perform terminate operation on - * @param reason - description to be specified for the terminated workflow for future - * references. + * @param reason - description to be specified for the terminated workflow for future + * references. * @return bulk response object containing a list of succeeded workflows and a list of failed - * ones with errors + * ones with errors */ public BulkResponse terminate(List workflowIds, String reason) { BulkResponse bulkResponse = new BulkResponse<>(); @@ -172,7 +172,7 @@ public BulkResponse terminate(List workflowIds, String reason) { /** * Removes a list of workflows from the system. * - * @param workflowIds List of WorkflowIDs of the workflows you want to remove from system. + * @param workflowIds List of WorkflowIDs of the workflows you want to remove from system. * @param archiveWorkflow Archives the workflow and associated tasks instead of removing them. */ public BulkResponse deleteWorkflow(List workflowIds, boolean archiveWorkflow) { @@ -198,11 +198,11 @@ public BulkResponse deleteWorkflow(List workflowIds, boolean arc /** * Terminates execution for workflows in a list, then removes each workflow. * - * @param workflowIds List of workflow IDs to terminate and delete. - * @param reason Reason for terminating the workflow. + * @param workflowIds List of workflow IDs to terminate and delete. + * @param reason Reason for terminating the workflow. * @param archiveWorkflow Archives the workflow and associated tasks instead of removing them. * @return bulk response object containing a list of succeeded workflows and a list of failed - * ones with errors + * ones with errors */ public BulkResponse terminateRemove( List workflowIds, String reason, boolean archiveWorkflow) { @@ -238,16 +238,18 @@ public BulkResponse terminateRemove( /** * Fetch workflow details for given workflowIds. * - * @param workflowIds List of workflow IDs to terminate and delete. + * @param workflowIds List of workflow IDs to terminate and delete. * @param includeTasks includes tasks from workflow * @return bulk response object containing a list of workflow details */ @Override - public BulkResponse searchWorkflow(List workflowIds, boolean includeTasks) { + public BulkResponse searchWorkflow( + List workflowIds, boolean includeTasks) { BulkResponse bulkResponse = new BulkResponse<>(); for (String workflowId : workflowIds) { try { - WorkflowModel workflowModel = workflowExecutor.getWorkflow(workflowId, includeTasks); + WorkflowModel workflowModel = + workflowExecutor.getWorkflow(workflowId, includeTasks); bulkResponse.appendSuccessResponse(workflowModel); } catch (Exception e) { LOGGER.error( @@ -260,6 +262,4 @@ public BulkResponse searchWorkflow(List workflowIds, bool } return bulkResponse; } - - } diff --git a/rest/src/main/java/com/netflix/conductor/rest/controllers/WorkflowBulkResource.java b/rest/src/main/java/com/netflix/conductor/rest/controllers/WorkflowBulkResource.java index 9a7da24e5..832e9d1da 100644 --- a/rest/src/main/java/com/netflix/conductor/rest/controllers/WorkflowBulkResource.java +++ b/rest/src/main/java/com/netflix/conductor/rest/controllers/WorkflowBulkResource.java @@ -14,7 +14,6 @@ import java.util.List; -import com.netflix.conductor.model.WorkflowModel; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; @@ -24,6 +23,7 @@ import org.springframework.web.bind.annotation.RestController; import com.netflix.conductor.common.model.BulkResponse; +import com.netflix.conductor.model.WorkflowModel; import com.netflix.conductor.service.WorkflowBulkService; import io.swagger.v3.oas.annotations.Operation; @@ -153,7 +153,7 @@ public BulkResponse terminateRemove( public BulkResponse searchWorkflow( @RequestBody List workflowIds, @RequestParam(value = "includeTasks", defaultValue = "true", required = false) - boolean includeTasks) { + boolean includeTasks) { return workflowBulkService.searchWorkflow(workflowIds, includeTasks); } } From 03c723e9eb7b707c5a1c96c8a97e14628360ffac Mon Sep 17 00:00:00 2001 From: Najeeb Date: Tue, 19 Nov 2024 19:16:20 +0530 Subject: [PATCH 10/20] fix:updated cypress node dependency version --- .github/workflows/ci.yml | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 44e8dfaba..c557d4e87 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,10 +3,10 @@ name: CI on: push: paths-ignore: - - 'conductor-clients/**' + - "conductor-clients/**" pull_request: paths-ignore: - - 'conductor-clients/**' + - "conductor-clients/**" jobs: build: @@ -21,8 +21,8 @@ jobs: - name: Set up Zulu JDK 17 uses: actions/setup-java@v3 with: - distribution: 'zulu' - java-version: '17' + distribution: "zulu" + java-version: "17" - name: Cache SonarCloud packages uses: actions/cache@v3 with: @@ -53,20 +53,20 @@ jobs: uses: mikepenz/action-junit-report@v3 if: always() with: - report_paths: '**/build/test-results/test/TEST-*.xml' + report_paths: "**/build/test-results/test/TEST-*.xml" - name: Upload build artifacts uses: actions/upload-artifact@v3 with: name: build-artifacts - path: '**/build/reports' + path: "**/build/reports" - name: Store Buildscan URL uses: actions/upload-artifact@v3 with: name: build-scan - path: 'buildscan.log' + path: "buildscan.log" build-ui: runs-on: ubuntu-latest - container: cypress/browsers:node14.17.6-chrome100-ff98 + container: cypress/browsers:node-22.11.0-chrome-130.0.6723.116-1-ff-132.0.1-edge-130.0.2849.68-1 defaults: run: working-directory: ui @@ -81,15 +81,15 @@ jobs: - name: Run E2E Tests uses: cypress-io/github-action@v4 - with: + with: working-directory: ui install: false start: yarn run serve-build - wait-on: 'http://localhost:5000' - + wait-on: "http://localhost:5000" + - name: Run Component Tests uses: cypress-io/github-action@v4 - with: + with: working-directory: ui install: false component: true @@ -100,11 +100,10 @@ jobs: with: name: cypress-screenshots path: ui/cypress/screenshots - + - name: Archive test videos uses: actions/upload-artifact@v3 if: always() with: name: cypress-videos path: ui/cypress/videos - From 094c402493b2286a90c2243754ab66f700ad3712 Mon Sep 17 00:00:00 2001 From: Jeff Bull Date: Tue, 19 Nov 2024 14:31:57 -0800 Subject: [PATCH 11/20] Update README.md 11-19-24 --- README.md | 54 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index bc37e6cab..7c427f11a 100644 --- a/README.md +++ b/README.md @@ -14,19 +14,27 @@ -Conductor is a platform _originally_ created at **Netflix** to orchestrate microservices and events. -[Conductor OSS](https://conductor-oss.org) is maintained by the team of developers at [Orkes.io](https://orkes.io/) along with members of the open source community. +Conductor is a platform _originally_ created at **Netflix** to orchestrate microservices and events. [Conductor OSS](https://conductor-oss.org) is maintained by the team of developers at [Orkes.io](https://orkes.io/) along with members of the open source community. + + +[![conductor_oss_getting_started](https://github.com/user-attachments/assets/6153aa58-8ad1-4ec5-93d1-38ba1b83e3f4)](https://youtu.be/4azDdDlx27M) - - - # Table of Contents 1. [What is Conductor?](#what-is-conductor) * [Key benefits](#key-benefits) * [Features](#features) -2. [Requirements](#requirements) -3. [Conductor Roadmap](#conductor-oss-roadmap) -4. [How to Contribute](#contributors) -5. [Additional Resources](#resources) -6. [Community & Support](#slack-community) +2. [Getting Started](#getting-started) + * [Requirements](#requirements) + * [Quick Start](#quick-start-guide) + * [Create your first workflow](#create-your-first-workflow) +3. [Documentation](#documentation) +4. [Database Specifications](#database-specifications) +5. [Deployment Options](#deployment-options) +6. [Conductor Roadmap](#conductor-oss-roadmap) +7. [How to Contribute](#contributors) +8. [Additional Resources](#resources) +9. [Community & Support](#slack-community) # What is Conductor? Conductor (or [Netflix Conductor](https://netflixtechblog.com/netflix-conductor-a-microservices-orchestrator-2e8d4771bf40)) is a microservices orchestration engine for distributed and asynchronous workflows. It empowers developers to create workflows that define interactions between services, databases, and other external systems. @@ -53,6 +61,7 @@ Conductor is designed to enable flexible, resilient, and scalable workflows. It * Install Java (JDK) 17 or newer * Node 14 for the UI to build * _Earlier versions may work, but are untested_ + ## Quick Start Guide @@ -82,12 +91,15 @@ docker compose -f docker/docker-compose.yaml up ##### Or use the REST API with your preferred HTTP client * http://localhost:8080 -## Database Requirements - +# Documentation +Check-out the [Conductor OSS docs](https://github.com/conductor-oss/conductor/tree/main/docs) for additional details +- - - +# Database Specifications * The default persistence used is Redis * The indexing backend is [Elasticsearch](https://www.elastic.co/) (7.x) -## Configuration for various database backends + +### Configuration for various database backends | Backend | Configuration | |----------------|---------------------------------------------------------------------------------------| @@ -97,7 +109,6 @@ docker compose -f docker/docker-compose.yaml up | MySQL + ES7 | [config-mysql.properties](docker/server/config/config-mysql.properties) | -- - - # Deployment Options In addition to the Docker Compose setup, Netflix Conductor supports several other deployment methods to suit various environments: @@ -114,19 +125,26 @@ Conductor provides several SDKs for interacting with the API and creating custom Each SDK is maintained as part of the Conductor project, providing examples and comprehensive API documentation. -# Documentation and Community -* **Official Documentation:** [Conductor documentation](https://docs.conductor-oss.org/index.html) contains detailed explanations of workflow concepts, API reference, and guides. -* **Conductor Slack:** [Join the Conductor Slack](https://join.slack.com/t/orkes-conductor/shared_invite/zt-2hmxn0i3n-_W~a9rWMbvMoYmlJo3Y15g) channel for community discussions and support. -* **Orkes Community Discourse:** [Hosted by Orkes.io](https://community.orkes.io) on Discourse, you can engage the Conductor & Orkes community, ask questions, and contribute ideas. - - # Conductor OSS Roadmap [See the roadmap for the Conductor](ROADMAP.md) - If you would like to participate in the roadmap and development, [please reach out](https://forms.gle/P2i1xHrxPQLrjzTB7). +# Documentation and Community +* **Official Documentation:** [Conductor documentation](https://docs.conductor-oss.org/index.html) contains detailed explanations of workflow concepts, API reference, and guides. +* **Conductor Slack:** [Join the Conductor Slack](https://join.slack.com/t/orkes-conductor/shared_invite/zt-2hmxn0i3n-_W~a9rWMbvMoYmlJo3Y15g) channel for community discussions and support. +* **Orkes Community Discourse:** [Hosted by Orkes.io](https://community.orkes.io) on Discourse, you can engage the Conductor & Orkes community, ask questions, and contribute ideas. +- - - # License Conductor is licensed under the Apache 2.0 License © [Conductor Open-source](https://conductor-oss.org/) +- - - +# Contributing + +We welcome contributions from everyone! + +- **Report Issues:** Found a bug or have a feature request? Open an [issue on GitHub](https://github.com/conductor-oss/conductor/issues). +- **Contribute Code:** Check out our [Contribution Guide](https://github.com/conductor-oss/conductor/blob/main/CONTRIBUTING.md) for initial guidelines, and explore our [good first issues](https://github.com/conductor-oss/conductor/labels/good%20first%20issue) for beginner-friendly tasks to tackle first. +- **Build a Conductor SDK:** Need an SDK not included with Conductor? Build your own using the [Swagger API](http://localhost:8080) included with your local deployment. +- **Contribute to our Docs:** Contribute edits or updates to keep our [documentation](https://github.com/conductor-oss/conductor/tree/main/docs) in great shape for the community. ## Contributors From 46ac8e2b99ea9519b779d920219d6f71dde5e804 Mon Sep 17 00:00:00 2001 From: Najeeb Date: Thu, 21 Nov 2024 10:17:47 +0530 Subject: [PATCH 12/20] fix:UI breaking while clicking on nested tasks in execution diagram --- ui/src/components/diagram/WorkflowDAG.js | 2 +- ui/src/pages/execution/Execution.jsx | 4 ++ ui/src/pages/execution/RightPanel.jsx | 21 ++++++++--- ui/src/pages/execution/TaskDetails.jsx | 16 +++++++- ui/src/utils/helpers.js | 47 +++++++++++++++++++++--- 5 files changed, 78 insertions(+), 12 deletions(-) diff --git a/ui/src/components/diagram/WorkflowDAG.js b/ui/src/components/diagram/WorkflowDAG.js index cabf35fa0..684fec032 100644 --- a/ui/src/components/diagram/WorkflowDAG.js +++ b/ui/src/components/diagram/WorkflowDAG.js @@ -580,7 +580,7 @@ export default class WorkflowDAG { return this.taskResultsById.get(taskPointer.id); } else { const node = this.graph.node(taskPointer.ref); - return _.last(node.taskResults); + return _.last(node?.taskResults); } } } diff --git a/ui/src/pages/execution/Execution.jsx b/ui/src/pages/execution/Execution.jsx index 2527f2436..b05970bb5 100644 --- a/ui/src/pages/execution/Execution.jsx +++ b/ui/src/pages/execution/Execution.jsx @@ -126,6 +126,7 @@ export default function Execution() { const [isFullWidth, setIsFullWidth] = useState(false); const [isResizing, setIsResizing] = useState(false); const [drawerWidth, setDrawerWidth] = useState(INIT_DRAWER_WIDTH); + const [selectedNode, setSelectedNode] = useState(); const [tabIndex, setTabIndex] = useQueryState("tabIndex", 0); const [selectedTaskRison, setSelectedTaskRison] = useQueryState("task", ""); @@ -265,6 +266,7 @@ export default function Execution() { execution={execution} setSelectedTask={setSelectedTask} selectedTask={selectedTask} + setSelectedNode={setSelectedNode} /> )} {tabIndex === 1 && } @@ -307,6 +309,8 @@ export default function Execution() { className={classes.rightPanel} selectedTask={selectedTask} dag={dag} + execution={execution} + selectedNode={selectedNode} onTaskChange={setSelectedTask} /> diff --git a/ui/src/pages/execution/RightPanel.jsx b/ui/src/pages/execution/RightPanel.jsx index 7e2e0572b..b3dc7b79e 100644 --- a/ui/src/pages/execution/RightPanel.jsx +++ b/ui/src/pages/execution/RightPanel.jsx @@ -8,6 +8,10 @@ import TaskLogs from "./TaskLogs"; import { makeStyles } from "@material-ui/styles"; import _ from "lodash"; import TaskPollData from "./TaskPollData"; +import { + pendingTaskSelection, + taskWithLatestIteration, +} from "../../utils/helpers"; const useStyles = makeStyles({ banner: { @@ -24,7 +28,13 @@ const useStyles = makeStyles({ }, }); -export default function RightPanel({ selectedTask, dag, onTaskChange }) { +export default function RightPanel({ + selectedTask, + dag, + execution, + onTaskChange, + selectedNode, +}) { const [tabIndex, setTabIndex] = useState("summary"); const classes = useStyles(); @@ -33,10 +43,11 @@ export default function RightPanel({ selectedTask, dag, onTaskChange }) { setTabIndex("summary"); // Reset to Status Tab on ref change }, [selectedTask]); - const taskResult = useMemo( - () => dag && dag.resolveTaskResult(selectedTask), - [dag, selectedTask] - ); + const taskResult = + selectedNode?.data?.task?.executionData?.status === "PENDING" + ? pendingTaskSelection(selectedNode?.data?.task) + : taskWithLatestIteration(execution?.tasks, selectedTask?.ref); + const dfOptions = useMemo( () => dag && dag.getSiblings(selectedTask), [dag, selectedTask] diff --git a/ui/src/pages/execution/TaskDetails.jsx b/ui/src/pages/execution/TaskDetails.jsx index 0850a7d4f..8cbfa192f 100644 --- a/ui/src/pages/execution/TaskDetails.jsx +++ b/ui/src/pages/execution/TaskDetails.jsx @@ -4,6 +4,10 @@ import Timeline from "./Timeline"; import TaskList from "./TaskList"; import { makeStyles } from "@material-ui/styles"; import { WorkflowVisualizer } from "orkes-workflow-visualizer"; +import { + pendingTaskSelection, + taskWithLatestIteration, +} from "../../utils/helpers"; const useStyles = makeStyles({ taskWrapper: { @@ -18,6 +22,7 @@ export default function TaskDetails({ dag, selectedTask, setSelectedTask, + setSelectedNode, }) { const [tabIndex, setTabIndex] = useState(0); const classes = useStyles(); @@ -39,7 +44,16 @@ export default function TaskDetails({ zoom={0.7} data={dag?.execution} executionMode={true} - onClick={(e, data) => setSelectedTask({ ref: data?.id })} + onClick={(e, data) => { + const selectedTaskRefName = + data?.data?.task?.executionData?.status === "PENDING" + ? pendingTaskSelection(data?.data?.task)?.workflowTask + ?.taskReferenceName + : taskWithLatestIteration(execution?.tasks, data?.id) + ?.referenceTaskName; + setSelectedNode(data); + setSelectedTask({ ref: selectedTaskRefName }); + }} /> )} {tabIndex === 1 && ( diff --git a/ui/src/utils/helpers.js b/ui/src/utils/helpers.js index 11bf45e94..407732f63 100644 --- a/ui/src/utils/helpers.js +++ b/ui/src/utils/helpers.js @@ -1,6 +1,7 @@ import { format, formatDuration, intervalToDuration } from "date-fns"; import _ from "lodash"; -import packageJson from '../../package.json'; +import packageJson from "../../package.json"; +import _nth from "lodash/nth"; export function timestampRenderer(date) { if (_.isNil(date)) return null; @@ -91,9 +92,45 @@ export function isEmptyIterable(iterable) { } export function getBasename() { - let basename = '/'; - try{ + let basename = "/"; + try { basename = new URL(packageJson.homepage).pathname; - } catch(e) {} - return _.isEmpty(basename) ? '/' : basename; + } catch (e) {} + return _.isEmpty(basename) ? "/" : basename; } + +export const taskWithLatestIteration = (tasksList, taskReferenceName) => { + const filteredTasks = tasksList?.filter( + (task) => + task?.workflowTask?.taskReferenceName === taskReferenceName || + task?.referenceTaskName === taskReferenceName + ); + + if (filteredTasks && filteredTasks.length === 1) { + // task without any retry/iteration + return _nth(filteredTasks, 0); + } else if (filteredTasks && filteredTasks.length > 1) { + const result = filteredTasks.reduce( + (acc, task, idx) => { + if (task?.seq && acc?.seqNumber < Number(task.seq)) { + return { seqNumber: Number(task.seq), idx }; + } + return acc; + }, + { seqNumber: 0, idx: -1 } + ); + + if (result?.idx > -1) { + return _nth(filteredTasks, result.idx); + } + } + return undefined; +}; + +export const pendingTaskSelection = (task) => { + const result = { + ...task?.executionData, + workflowTask: task, + }; + return result; +}; From 1d6b213fcc8f67357ad1ce9721e6b4b985ef5104 Mon Sep 17 00:00:00 2001 From: Miguel Prieto Date: Fri, 22 Nov 2024 14:50:04 -0300 Subject: [PATCH 13/20] Add new IdempotencyStrategy `FAIL_ON_RUNNING` --- .../common/metadata/workflow/IdempotencyStrategy.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/com/netflix/conductor/common/metadata/workflow/IdempotencyStrategy.java b/common/src/main/java/com/netflix/conductor/common/metadata/workflow/IdempotencyStrategy.java index 4b9ebd60b..a1dc436ac 100644 --- a/common/src/main/java/com/netflix/conductor/common/metadata/workflow/IdempotencyStrategy.java +++ b/common/src/main/java/com/netflix/conductor/common/metadata/workflow/IdempotencyStrategy.java @@ -14,5 +14,6 @@ public enum IdempotencyStrategy { FAIL, - RETURN_EXISTING + RETURN_EXISTING, + FAIL_ON_RUNNING } From 003fda3cb07cbbab2abd5fdee76a83445fdaf293 Mon Sep 17 00:00:00 2001 From: Viren Baraiya Date: Sun, 24 Nov 2024 20:15:03 -0800 Subject: [PATCH 14/20] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7c427f11a..6be3cba18 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ [![Github release](https://img.shields.io/github/v/release/conductor-oss/conductor.svg)](https://GitHub.com/Netflix/conductor-oss/releases) [![License](https://img.shields.io/github/license/conductor-oss/conductor.svg)](http://www.apache.org/licenses/LICENSE-2.0) -[![Conductor Slack](https://img.shields.io/badge/Slack-Join%20the%20Community-blueviolet?logo=slack)](https://join.slack.com/t/orkes-conductor/shared_invite/zt-2hmxn0i3n-_W~a9rWMbvMoYmlJo3Y15g) +[![Conductor Slack](https://img.shields.io/badge/Slack-Join%20the%20Community-blueviolet?logo=slack)](https://join.slack.com/t/orkes-conductor/shared_invite/zt-2vdbx239s-Eacdyqya9giNLHfrCavfaA) [![Community Forum](https://img.shields.io/badge/Discourse-Join%20the%20Community-blue?logo=discourse&logoColor=white)](https://community.orkes.io) [![Conductor OSS](https://img.shields.io/badge/Conductor%20OSS-Visit%20Site-blue)](https://conductor-oss.org) [![GitHub stars](https://img.shields.io/github/stars/conductor-oss/conductor?style=social)](https://github.com/conductor-oss/conductor/stargazers) @@ -131,7 +131,7 @@ If you would like to participate in the roadmap and development, [please reach o # Documentation and Community * **Official Documentation:** [Conductor documentation](https://docs.conductor-oss.org/index.html) contains detailed explanations of workflow concepts, API reference, and guides. -* **Conductor Slack:** [Join the Conductor Slack](https://join.slack.com/t/orkes-conductor/shared_invite/zt-2hmxn0i3n-_W~a9rWMbvMoYmlJo3Y15g) channel for community discussions and support. +* **Conductor Slack:** [Join the Conductor Slack](https://join.slack.com/t/orkes-conductor/shared_invite/zt-2vdbx239s-Eacdyqya9giNLHfrCavfaA) channel for community discussions and support. * **Orkes Community Discourse:** [Hosted by Orkes.io](https://community.orkes.io) on Discourse, you can engage the Conductor & Orkes community, ask questions, and contribute ideas. - - - # License From c10571903c7349a331d51d6ac2a8b04ee82ab219 Mon Sep 17 00:00:00 2001 From: Riza Farheen <82656175+RizaFarheen@users.noreply.github.com> Date: Mon, 25 Nov 2024 19:58:37 +0400 Subject: [PATCH 15/20] URL updates (#319) - Slack URL updates --- CONTRIBUTING.md | 2 +- conductor-clients/java/conductor-java-sdk/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b102a7a37..d8b513010 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -13,7 +13,7 @@ I have a question! We have a dedicated [discussion forum](https://github.com/conductor-oss/conductor/discussions) for asking "how to" questions and to discuss ideas. The discussion forum is a great place to start if you're considering creating a feature request or work on a Pull Request. *Please do not create issues to ask questions.* -Conductor users hangout in the [Slack channel](https://join.slack.com/t/orkes-conductor/shared_invite/zt-xyxqyseb-YZ3hwwAgHJH97bsrYRnSZg). Join the channel for more real-time communication! +Conductor users hangout in the [Slack channel](https://join.slack.com/t/orkes-conductor/shared_invite/zt-2vdbx239s-Eacdyqya9giNLHfrCavfaA). Join the channel for more real-time communication! I want to contribute! ------ diff --git a/conductor-clients/java/conductor-java-sdk/README.md b/conductor-clients/java/conductor-java-sdk/README.md index 024da8a8c..a6a18ceae 100644 --- a/conductor-clients/java/conductor-java-sdk/README.md +++ b/conductor-clients/java/conductor-java-sdk/README.md @@ -31,7 +31,7 @@ For insights into the Conductor project's future plans and upcoming features, ch We are building this based on feedback from our users and community. -We encourage everyone to share their thoughts and feedback! You can create new GitHub issues or comment on existing ones. You can also join our [Slack community](https://orkes-conductor.slack.com/) to connect with us. +We encourage everyone to share their thoughts and feedback! You can create new GitHub issues or comment on existing ones. You can also join our [Slack community](https://join.slack.com/t/orkes-conductor/shared_invite/zt-2vdbx239s-Eacdyqya9giNLHfrCavfaA) to connect with us. Thank you! ♥ From 3713828caf4874e6f1102ddf6e1360f31433070b Mon Sep 17 00:00:00 2001 From: Yong Sheng Tan Date: Mon, 25 Nov 2024 17:28:22 +0800 Subject: [PATCH 16/20] Add callTimeout field to ConductorClient builder --- .../netflix/conductor/client/http/ConductorClient.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/conductor-clients/java/conductor-java-sdk/conductor-client/src/main/java/com/netflix/conductor/client/http/ConductorClient.java b/conductor-clients/java/conductor-java-sdk/conductor-client/src/main/java/com/netflix/conductor/client/http/ConductorClient.java index 9cf7a7d21..127a55ae2 100644 --- a/conductor-clients/java/conductor-java-sdk/conductor-client/src/main/java/com/netflix/conductor/client/http/ConductorClient.java +++ b/conductor-clients/java/conductor-java-sdk/conductor-client/src/main/java/com/netflix/conductor/client/http/ConductorClient.java @@ -101,6 +101,10 @@ protected ConductorClient(Builder builder) { okHttpBuilder.writeTimeout(builder.writeTimeout, TimeUnit.MILLISECONDS); } + if (builder.callTimeout > -1) { + okHttpBuilder.callTimeout(builder.callTimeout, TimeUnit.MILLISECONDS); + } + if (builder.proxy != null) { okHttpBuilder.proxy(builder.proxy); } @@ -442,6 +446,7 @@ public static class Builder> { private long connectTimeout = -1; private long readTimeout = -1; private long writeTimeout = -1; + private long callTimeout = -1; private Proxy proxy; private ConnectionPoolConfig connectionPoolConfig; private Supplier objectMapperSupplier = () -> new ObjectMapperProvider().getObjectMapper(); @@ -487,6 +492,11 @@ public T writeTimeout(long writeTimeout) { return self(); } + public T callTimeout(long callTimeout) { + this.callTimeout = callTimeout; + return self(); + } + public T proxy(Proxy proxy) { this.proxy = proxy; return self(); From 93362c06a566757a0d55eb78a40931ec9d5fe853 Mon Sep 17 00:00:00 2001 From: Shailesh Jagannath Padave Date: Tue, 26 Nov 2024 20:21:24 +0530 Subject: [PATCH 17/20] Removed code changes from sdk v4 --- .../conductor/common/metadata/tasks/TaskDef.java | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/conductor-clients/java/conductor-java-sdk/conductor-client/src/main/java/com/netflix/conductor/common/metadata/tasks/TaskDef.java b/conductor-clients/java/conductor-java-sdk/conductor-client/src/main/java/com/netflix/conductor/common/metadata/tasks/TaskDef.java index 0bdd0f2d9..d4bfc0fc1 100644 --- a/conductor-clients/java/conductor-java-sdk/conductor-client/src/main/java/com/netflix/conductor/common/metadata/tasks/TaskDef.java +++ b/conductor-clients/java/conductor-java-sdk/conductor-client/src/main/java/com/netflix/conductor/common/metadata/tasks/TaskDef.java @@ -47,8 +47,6 @@ public enum RetryLogic { private long timeoutSeconds; - private long totalTimeoutSeconds; - private List inputKeys = new ArrayList<>(); private List outputKeys = new ArrayList<>(); @@ -174,14 +172,6 @@ public void setTimeoutSeconds(long timeoutSeconds) { this.timeoutSeconds = timeoutSeconds; } - public long getTotalTimeoutSeconds() { - return totalTimeoutSeconds; - } - - public void setTotalTimeoutSeconds(long totalTimeoutSeconds) { - this.totalTimeoutSeconds = totalTimeoutSeconds; - } - /** * @return Returns the input keys */ @@ -438,10 +428,10 @@ public boolean equals(Object o) { return false; } TaskDef taskDef = (TaskDef) o; - return getRetryCount() == taskDef.getRetryCount() && getTimeoutSeconds() == taskDef.getTimeoutSeconds() && getRetryDelaySeconds() == taskDef.getRetryDelaySeconds() && getBackoffScaleFactor() == taskDef.getBackoffScaleFactor() && getResponseTimeoutSeconds() == taskDef.getResponseTimeoutSeconds() && getTotalTimeoutSeconds() == taskDef.getTotalTimeoutSeconds() && Objects.equals(getName(), taskDef.getName()) && Objects.equals(getDescription(), taskDef.getDescription()) && Objects.equals(getInputKeys(), taskDef.getInputKeys()) && Objects.equals(getOutputKeys(), taskDef.getOutputKeys()) && getTimeoutPolicy() == taskDef.getTimeoutPolicy() && getRetryLogic() == taskDef.getRetryLogic() && Objects.equals(getConcurrentExecLimit(), taskDef.getConcurrentExecLimit()) && Objects.equals(getRateLimitPerFrequency(), taskDef.getRateLimitPerFrequency()) && Objects.equals(getInputTemplate(), taskDef.getInputTemplate()) && Objects.equals(getIsolationGroupId(), taskDef.getIsolationGroupId()) && Objects.equals(getExecutionNameSpace(), taskDef.getExecutionNameSpace()) && Objects.equals(getOwnerEmail(), taskDef.getOwnerEmail()) && Objects.equals(getBaseType(), taskDef.getBaseType()) && Objects.equals(getInputSchema(), taskDef.getInputSchema()) && Objects.equals(getOutputSchema(), taskDef.getOutputSchema()); + return getRetryCount() == taskDef.getRetryCount() && getTimeoutSeconds() == taskDef.getTimeoutSeconds() && getRetryDelaySeconds() == taskDef.getRetryDelaySeconds() && getBackoffScaleFactor() == taskDef.getBackoffScaleFactor() && getResponseTimeoutSeconds() == taskDef.getResponseTimeoutSeconds() && Objects.equals(getName(), taskDef.getName()) && Objects.equals(getDescription(), taskDef.getDescription()) && Objects.equals(getInputKeys(), taskDef.getInputKeys()) && Objects.equals(getOutputKeys(), taskDef.getOutputKeys()) && getTimeoutPolicy() == taskDef.getTimeoutPolicy() && getRetryLogic() == taskDef.getRetryLogic() && Objects.equals(getConcurrentExecLimit(), taskDef.getConcurrentExecLimit()) && Objects.equals(getRateLimitPerFrequency(), taskDef.getRateLimitPerFrequency()) && Objects.equals(getInputTemplate(), taskDef.getInputTemplate()) && Objects.equals(getIsolationGroupId(), taskDef.getIsolationGroupId()) && Objects.equals(getExecutionNameSpace(), taskDef.getExecutionNameSpace()) && Objects.equals(getOwnerEmail(), taskDef.getOwnerEmail()) && Objects.equals(getBaseType(), taskDef.getBaseType()) && Objects.equals(getInputSchema(), taskDef.getInputSchema()) && Objects.equals(getOutputSchema(), taskDef.getOutputSchema()); } public int hashCode() { - return Objects.hash(getName(), getDescription(), getRetryCount(), getTimeoutSeconds(), getInputKeys(), getOutputKeys(), getTimeoutPolicy(), getRetryLogic(), getRetryDelaySeconds(), getBackoffScaleFactor(), getResponseTimeoutSeconds(), getTotalTimeoutSeconds(), getConcurrentExecLimit(), getRateLimitPerFrequency(), getInputTemplate(), getIsolationGroupId(), getExecutionNameSpace(), getOwnerEmail(), getBaseType(), getInputSchema(), getOutputSchema()); + return Objects.hash(getName(), getDescription(), getRetryCount(), getTimeoutSeconds(), getInputKeys(), getOutputKeys(), getTimeoutPolicy(), getRetryLogic(), getRetryDelaySeconds(), getBackoffScaleFactor(), getResponseTimeoutSeconds(), getConcurrentExecLimit(), getRateLimitPerFrequency(), getInputTemplate(), getIsolationGroupId(), getExecutionNameSpace(), getOwnerEmail(), getBaseType(), getInputSchema(), getOutputSchema()); } } From c1a8e21c4ddf6a093ce4cbfd3932924dc3aa59e9 Mon Sep 17 00:00:00 2001 From: Vasiliy Pankov Date: Tue, 26 Nov 2024 20:54:28 +0400 Subject: [PATCH 18/20] Update generate_gh_pages.yml use GITHUB_TOKEN --- .github/workflows/generate_gh_pages.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/generate_gh_pages.yml b/.github/workflows/generate_gh_pages.yml index 8c429e1b8..19331936a 100644 --- a/.github/workflows/generate_gh_pages.yml +++ b/.github/workflows/generate_gh_pages.yml @@ -13,6 +13,6 @@ jobs: - name: Deploy docs uses: mhausenblas/mkdocs-deploy-gh-pages@master env: - GITHUB_TOKEN: ${{ secrets.DOCSITE_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} CONFIG_FILE: mkdocs.yml REQUIREMENTS: requirements.txt From ccbcbda99cb3206618efcd1d42dc3c606800f4c9 Mon Sep 17 00:00:00 2001 From: Shailesh Jagannath Padave Date: Wed, 27 Nov 2024 10:31:47 +0530 Subject: [PATCH 19/20] nit changes --- .../com/netflix/conductor/common/metadata/tasks/TaskDef.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/main/java/com/netflix/conductor/common/metadata/tasks/TaskDef.java b/common/src/main/java/com/netflix/conductor/common/metadata/tasks/TaskDef.java index b5a9d071b..b96c54245 100644 --- a/common/src/main/java/com/netflix/conductor/common/metadata/tasks/TaskDef.java +++ b/common/src/main/java/com/netflix/conductor/common/metadata/tasks/TaskDef.java @@ -472,7 +472,7 @@ public long getTotalTimeoutSeconds() { return totalTimeoutSeconds; } - public void setTotalTimeoutSeconds(@NotNull long totalTimeoutSeconds) { + public void setTotalTimeoutSeconds(long totalTimeoutSeconds) { this.totalTimeoutSeconds = totalTimeoutSeconds; } From 4ae5b18b8cd52a5b48e9b034cd465895e3cffad0 Mon Sep 17 00:00:00 2001 From: Abdul Salam <5775870+codehackerr@users.noreply.github.com> Date: Tue, 26 Nov 2024 22:03:22 -0800 Subject: [PATCH 20/20] Add name validation to task definitions and workflow definitions (#315) --- .../constraints/ValidNameConstraint.java | 72 +++++++++++++++++++ .../common/metadata/workflow/WorkflowDef.java | 5 +- .../common/constraints/NameValidatorTest.java | 52 ++++++++++++++ .../workflow/WorkflowDefValidatorTest.java | 2 + .../src/test/resources/application.properties | 1 + .../service/MetadataServiceTest.java | 7 +- .../integration/KafkaPublishTaskSpec.groovy | 4 +- .../grpc/mysql/MySQLGrpcEndToEndTest.java | 3 +- .../postgres/dao/PostgresLockDAOTest.java | 3 +- .../postgres/PostgresGrpcEndToEndTest.java | 3 +- .../src/main/resources/application.properties | 2 + .../resiliency/QueueResiliencySpec.groovy | 2 + .../test/resiliency/TaskResiliencySpec.groovy | 3 +- .../application-integrationtest.properties | 1 + ...orkflowStatusPublisherIntegrationTest.java | 3 +- 15 files changed, 151 insertions(+), 12 deletions(-) create mode 100644 common/src/main/java/com/netflix/conductor/common/constraints/ValidNameConstraint.java create mode 100644 common/src/test/java/com/netflix/conductor/common/constraints/NameValidatorTest.java create mode 100644 common/src/test/resources/application.properties diff --git a/common/src/main/java/com/netflix/conductor/common/constraints/ValidNameConstraint.java b/common/src/main/java/com/netflix/conductor/common/constraints/ValidNameConstraint.java new file mode 100644 index 000000000..41af1415a --- /dev/null +++ b/common/src/main/java/com/netflix/conductor/common/constraints/ValidNameConstraint.java @@ -0,0 +1,72 @@ +/* + * Copyright 2020 Conductor Authors. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package com.netflix.conductor.common.constraints; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.beans.factory.annotation.Value; + +import jakarta.validation.Constraint; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; +import jakarta.validation.Payload; + +import static java.lang.annotation.ElementType.FIELD; + +/** + * This constraint class validates following things. + * + *

    + *
  • 1. Name is valid or not + *
+ */ +@Documented +@Constraint(validatedBy = ValidNameConstraint.NameValidator.class) +@Target({FIELD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface ValidNameConstraint { + + String message() default ""; + + Class[] groups() default {}; + + Class[] payload() default {}; + + class NameValidator implements ConstraintValidator { + + private static final String NAME_PATTERN = "^[A-Za-z0-9_<>{}#\\s-]+$"; + public static final String INVALID_NAME_MESSAGE = + "Allowed characters are alphanumeric, underscores, spaces, hyphens, and special characters like <, >, {, }, #"; + + @Value("${conductor.app.workflow.name-validation.enabled}") + private boolean nameValidationEnabled; + + @Override + public void initialize(ValidNameConstraint constraintAnnotation) {} + + @Override + public boolean isValid(String name, ConstraintValidatorContext context) { + boolean valid = name == null || !nameValidationEnabled || name.matches(NAME_PATTERN); + if (!valid) { + context.disableDefaultConstraintViolation(); + context.buildConstraintViolationWithTemplate( + "Invalid name '" + name + "'. " + INVALID_NAME_MESSAGE) + .addConstraintViolation(); + } + return valid; + } + } +} diff --git a/common/src/main/java/com/netflix/conductor/common/metadata/workflow/WorkflowDef.java b/common/src/main/java/com/netflix/conductor/common/metadata/workflow/WorkflowDef.java index 2569294b8..e51e8ca17 100644 --- a/common/src/main/java/com/netflix/conductor/common/metadata/workflow/WorkflowDef.java +++ b/common/src/main/java/com/netflix/conductor/common/metadata/workflow/WorkflowDef.java @@ -17,9 +17,9 @@ import com.netflix.conductor.annotations.protogen.ProtoEnum; import com.netflix.conductor.annotations.protogen.ProtoField; import com.netflix.conductor.annotations.protogen.ProtoMessage; -import com.netflix.conductor.common.constraints.NoSemiColonConstraint; import com.netflix.conductor.common.constraints.OwnerEmailMandatoryConstraint; import com.netflix.conductor.common.constraints.TaskReferenceNameUniqueConstraint; +import com.netflix.conductor.common.constraints.ValidNameConstraint; import com.netflix.conductor.common.metadata.Auditable; import com.netflix.conductor.common.metadata.SchemaDef; import com.netflix.conductor.common.metadata.tasks.TaskType; @@ -39,8 +39,7 @@ public enum TimeoutPolicy { @NotEmpty(message = "WorkflowDef name cannot be null or empty") @ProtoField(id = 1) - @NoSemiColonConstraint( - message = "Workflow name cannot contain the following set of characters: ':'") + @ValidNameConstraint private String name; @ProtoField(id = 2) diff --git a/common/src/test/java/com/netflix/conductor/common/constraints/NameValidatorTest.java b/common/src/test/java/com/netflix/conductor/common/constraints/NameValidatorTest.java new file mode 100644 index 000000000..2fc196864 --- /dev/null +++ b/common/src/test/java/com/netflix/conductor/common/constraints/NameValidatorTest.java @@ -0,0 +1,52 @@ +/* + * Copyright 2024 Conductor Authors. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package com.netflix.conductor.common.constraints; + +import org.junit.Test; +import org.springframework.test.util.ReflectionTestUtils; + +import jakarta.validation.ConstraintValidatorContext; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class NameValidatorTest { + @Test + public void nameWithAllowedCharactersIsValid() { + ValidNameConstraint.NameValidator nameValidator = new ValidNameConstraint.NameValidator(); + assertTrue(nameValidator.isValid("workflowDef", null)); + } + + @Test + public void nonAllowedCharactersInNameIsInvalid() { + ValidNameConstraint.NameValidator nameValidator = new ValidNameConstraint.NameValidator(); + ConstraintValidatorContext context = mock(ConstraintValidatorContext.class); + ConstraintValidatorContext.ConstraintViolationBuilder builder = + mock(ConstraintValidatorContext.ConstraintViolationBuilder.class); + when(context.buildConstraintViolationWithTemplate(anyString())).thenReturn(builder); + + ReflectionTestUtils.setField(nameValidator, "nameValidationEnabled", true); + + assertFalse(nameValidator.isValid("workflowDef@", context)); + } + + // Null should be tested by @NotEmpty or @NotNull + @Test + public void nullIsValid() { + ValidNameConstraint.NameValidator nameValidator = new ValidNameConstraint.NameValidator(); + assertTrue(nameValidator.isValid(null, null)); + } +} diff --git a/common/src/test/java/com/netflix/conductor/common/workflow/WorkflowDefValidatorTest.java b/common/src/test/java/com/netflix/conductor/common/workflow/WorkflowDefValidatorTest.java index 132e33d99..c2b36e688 100644 --- a/common/src/test/java/com/netflix/conductor/common/workflow/WorkflowDefValidatorTest.java +++ b/common/src/test/java/com/netflix/conductor/common/workflow/WorkflowDefValidatorTest.java @@ -20,6 +20,7 @@ import org.junit.Before; import org.junit.Test; +import org.springframework.test.context.TestPropertySource; import com.netflix.conductor.common.metadata.tasks.TaskType; import com.netflix.conductor.common.metadata.workflow.WorkflowDef; @@ -33,6 +34,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +@TestPropertySource(properties = "conductor.app.workflow.name-validation.enabled=true") public class WorkflowDefValidatorTest { @Before diff --git a/common/src/test/resources/application.properties b/common/src/test/resources/application.properties new file mode 100644 index 000000000..7c95d0a4d --- /dev/null +++ b/common/src/test/resources/application.properties @@ -0,0 +1 @@ +conductor.app.workflow.name-validation.enabled=true diff --git a/core/src/test/java/com/netflix/conductor/service/MetadataServiceTest.java b/core/src/test/java/com/netflix/conductor/service/MetadataServiceTest.java index 3f4c028c1..37ed10450 100644 --- a/core/src/test/java/com/netflix/conductor/service/MetadataServiceTest.java +++ b/core/src/test/java/com/netflix/conductor/service/MetadataServiceTest.java @@ -21,6 +21,7 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.TestConfiguration; import org.springframework.context.annotation.Bean; +import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; import com.netflix.conductor.common.metadata.events.EventHandler; @@ -50,6 +51,7 @@ @SuppressWarnings("SpringJavaAutowiredMembersInspection") @RunWith(SpringRunner.class) +@TestPropertySource(properties = "conductor.app.workflow.name-validation.enabled=true") @EnableAutoConfiguration public class MetadataServiceTest { @@ -64,6 +66,7 @@ public MetadataDAO metadataDAO() { public ConductorProperties properties() { ConductorProperties properties = mock(ConductorProperties.class); when(properties.isOwnerEmailMandatory()).thenReturn(true); + return properties; } @@ -415,7 +418,7 @@ public void testRegisterWorkflowDefInvalidName() { assertTrue(messages.contains("WorkflowTask list cannot be empty")); assertTrue( messages.contains( - "Workflow name cannot contain the following set of characters: ':'")); + "Invalid name 'invalid:name'. Allowed characters are alphanumeric, underscores, spaces, hyphens, and special characters like <, >, {, }, #")); throw ex; } fail("metadataService.registerWorkflowDef did not throw ConstraintViolationException !"); @@ -434,7 +437,7 @@ public void testValidateWorkflowDefInvalidName() { assertTrue(messages.contains("WorkflowTask list cannot be empty")); assertTrue( messages.contains( - "Workflow name cannot contain the following set of characters: ':'")); + "Invalid name 'invalid:name'. Allowed characters are alphanumeric, underscores, spaces, hyphens, and special characters like <, >, {, }, #")); throw ex; } fail("metadataService.validateWorkflowDef did not throw ConstraintViolationException !"); diff --git a/kafka/src/test/groovy/com/netflix/conductor/test/integration/KafkaPublishTaskSpec.groovy b/kafka/src/test/groovy/com/netflix/conductor/test/integration/KafkaPublishTaskSpec.groovy index 8087dd9d4..671a6f212 100644 --- a/kafka/src/test/groovy/com/netflix/conductor/test/integration/KafkaPublishTaskSpec.groovy +++ b/kafka/src/test/groovy/com/netflix/conductor/test/integration/KafkaPublishTaskSpec.groovy @@ -16,15 +16,15 @@ import com.fasterxml.jackson.databind.ObjectMapper import com.netflix.conductor.common.metadata.tasks.TaskDef import com.netflix.conductor.common.metadata.tasks.TaskResult import com.netflix.conductor.common.metadata.tasks.TaskType -import com.netflix.conductor.common.metadata.workflow.StartWorkflowRequest import com.netflix.conductor.common.metadata.workflow.WorkflowDef import com.netflix.conductor.common.metadata.workflow.WorkflowTask import com.netflix.conductor.common.run.Workflow -import com.netflix.conductor.core.execution.StartWorkflowInput import com.netflix.conductor.test.base.AbstractSpecification import org.springframework.beans.factory.annotation.Autowired +import org.springframework.test.context.TestPropertySource import spock.lang.Shared +@TestPropertySource(properties = "conductor.app.workflow.name-validation.enabled=true") class KafkaPublishTaskSpec extends AbstractSpecification { @Autowired diff --git a/mysql-persistence/src/test/java/com/netflix/conductor/test/integration/grpc/mysql/MySQLGrpcEndToEndTest.java b/mysql-persistence/src/test/java/com/netflix/conductor/test/integration/grpc/mysql/MySQLGrpcEndToEndTest.java index 680623f43..1cc70310a 100644 --- a/mysql-persistence/src/test/java/com/netflix/conductor/test/integration/grpc/mysql/MySQLGrpcEndToEndTest.java +++ b/mysql-persistence/src/test/java/com/netflix/conductor/test/integration/grpc/mysql/MySQLGrpcEndToEndTest.java @@ -35,7 +35,8 @@ "spring.datasource.password=root", "spring.datasource.hikari.maximum-pool-size=8", "spring.datasource.hikari.minimum-idle=300000", - "conductor.elasticsearch.version=7" + "conductor.elasticsearch.version=7", + "conductor.app.workflow.name-validation.enabled=true" }) public class MySQLGrpcEndToEndTest extends AbstractGrpcEndToEndTest { diff --git a/postgres-persistence/src/test/java/com/netflix/conductor/postgres/dao/PostgresLockDAOTest.java b/postgres-persistence/src/test/java/com/netflix/conductor/postgres/dao/PostgresLockDAOTest.java index 695f15f10..a6fb4b8a3 100644 --- a/postgres-persistence/src/test/java/com/netflix/conductor/postgres/dao/PostgresLockDAOTest.java +++ b/postgres-persistence/src/test/java/com/netflix/conductor/postgres/dao/PostgresLockDAOTest.java @@ -48,7 +48,8 @@ @TestPropertySource( properties = { "conductor.workflow-execution-lock.type=postgres", - "spring.flyway.clean-disabled=false" + "spring.flyway.clean-disabled=false", + "conductor.app.workflow.name-validation.enabled=true" }) @SpringBootTest public class PostgresLockDAOTest { diff --git a/postgres-persistence/src/test/java/com/netflix/conductor/test/integration/grpc/postgres/PostgresGrpcEndToEndTest.java b/postgres-persistence/src/test/java/com/netflix/conductor/test/integration/grpc/postgres/PostgresGrpcEndToEndTest.java index 00651d34f..9b00cbbcc 100644 --- a/postgres-persistence/src/test/java/com/netflix/conductor/test/integration/grpc/postgres/PostgresGrpcEndToEndTest.java +++ b/postgres-persistence/src/test/java/com/netflix/conductor/test/integration/grpc/postgres/PostgresGrpcEndToEndTest.java @@ -39,7 +39,8 @@ "spring.datasource.password=postgres", "spring.datasource.hikari.maximum-pool-size=8", "spring.datasource.hikari.minimum-idle=300000", - "spring.flyway.clean-disabled=true" + "spring.flyway.clean-disabled=true", + "conductor.app.workflow.name-validation.enabled=true" }) public class PostgresGrpcEndToEndTest extends AbstractGrpcEndToEndTest { diff --git a/server/src/main/resources/application.properties b/server/src/main/resources/application.properties index 4fcb33594..e342c390e 100644 --- a/server/src/main/resources/application.properties +++ b/server/src/main/resources/application.properties @@ -72,6 +72,8 @@ conductor.default-event-queue.type=sqs #disable locking during workflow execution conductor.app.workflow-execution-lock-enabled=false conductor.workflow-execution-lock.type=noop_lock +# enable name validation on workflow/task definitions +conductor.app.workflow.name-validation.enabled=false #Redis cluster settings for locking module # conductor.redis-lock.serverType=single diff --git a/test-harness/src/test/groovy/com/netflix/conductor/test/resiliency/QueueResiliencySpec.groovy b/test-harness/src/test/groovy/com/netflix/conductor/test/resiliency/QueueResiliencySpec.groovy index 0149352bd..2b82a7867 100644 --- a/test-harness/src/test/groovy/com/netflix/conductor/test/resiliency/QueueResiliencySpec.groovy +++ b/test-harness/src/test/groovy/com/netflix/conductor/test/resiliency/QueueResiliencySpec.groovy @@ -14,6 +14,7 @@ package com.netflix.conductor.test.resiliency import org.springframework.beans.factory.annotation.Autowired import org.springframework.http.HttpStatus +import org.springframework.test.context.TestPropertySource import com.netflix.conductor.common.metadata.tasks.Task import com.netflix.conductor.common.metadata.tasks.TaskResult @@ -36,6 +37,7 @@ import com.netflix.conductor.test.base.AbstractResiliencySpecification * 2. Succeeds * 3. Doesn't involve QueueDAO */ +@TestPropertySource(properties = "conductor.app.workflow.name-validation.enabled=true") class QueueResiliencySpec extends AbstractResiliencySpecification { @Autowired diff --git a/test-harness/src/test/groovy/com/netflix/conductor/test/resiliency/TaskResiliencySpec.groovy b/test-harness/src/test/groovy/com/netflix/conductor/test/resiliency/TaskResiliencySpec.groovy index 4695d6587..1f6d311e4 100644 --- a/test-harness/src/test/groovy/com/netflix/conductor/test/resiliency/TaskResiliencySpec.groovy +++ b/test-harness/src/test/groovy/com/netflix/conductor/test/resiliency/TaskResiliencySpec.groovy @@ -13,6 +13,7 @@ package com.netflix.conductor.test.resiliency import org.springframework.beans.factory.annotation.Autowired +import org.springframework.test.context.TestPropertySource import com.netflix.conductor.common.metadata.tasks.Task import com.netflix.conductor.common.run.Workflow @@ -22,7 +23,7 @@ import com.netflix.conductor.test.base.AbstractResiliencySpecification import spock.lang.Shared import static com.netflix.conductor.test.util.WorkflowTestUtil.verifyPolledAndAcknowledgedTask - +@TestPropertySource(properties = "conductor.app.workflow.name-validation.enabled=true") class TaskResiliencySpec extends AbstractResiliencySpecification { @Autowired diff --git a/test-harness/src/test/resources/application-integrationtest.properties b/test-harness/src/test/resources/application-integrationtest.properties index b209c8054..e6390edce 100644 --- a/test-harness/src/test/resources/application-integrationtest.properties +++ b/test-harness/src/test/resources/application-integrationtest.properties @@ -35,6 +35,7 @@ conductor.workflow-reconciler.enabled=true conductor.workflow-repair-service.enabled=false conductor.app.workflow-execution-lock-enabled=false +conductor.app.workflow.name-validation.enabled=true conductor.app.workflow-input-payload-size-threshold=10KB conductor.app.max-workflow-input-payload-size-threshold=10240KB diff --git a/workflow-event-listener/src/test/java/com/netflix/conductor/test/listener/WorkflowStatusPublisherIntegrationTest.java b/workflow-event-listener/src/test/java/com/netflix/conductor/test/listener/WorkflowStatusPublisherIntegrationTest.java index 33d909a84..38e5f737b 100644 --- a/workflow-event-listener/src/test/java/com/netflix/conductor/test/listener/WorkflowStatusPublisherIntegrationTest.java +++ b/workflow-event-listener/src/test/java/com/netflix/conductor/test/listener/WorkflowStatusPublisherIntegrationTest.java @@ -58,7 +58,8 @@ "conductor.workflow-status-listener.type=queue_publisher", "conductor.workflow-status-listener.queue-publisher.successQueue=dummy", "conductor.workflow-status-listener.queue-publisher.failureQueue=dummy", - "conductor.workflow-status-listener.queue-publisher.finalizeQueue=final" + "conductor.workflow-status-listener.queue-publisher.finalizeQueue=final", + "conductor.app.workflow.name-validation.enabled=true" }) @TestPropertySource(locations = "classpath:application-integrationtest.properties") public class WorkflowStatusPublisherIntegrationTest {