Skip to content

Commit 864bfd0

Browse files
authored
Merge pull request #763 from Project-MONAI/samrooke/AC-2026-update-argo-workflow-validation-logic
Samrooke/ac 2026 update argo workflow validation logic
2 parents 6ce8360 + ca6a254 commit 864bfd0

File tree

4 files changed

+68
-7
lines changed

4 files changed

+68
-7
lines changed

src/Shared/Shared/ValidationConstants.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,21 @@ public static class ValidationConstants
5353
/// </summary>
5454
public static readonly string Notifications = "notifications";
5555

56+
/// <summary>
57+
/// Key for the CPU.
58+
/// </summary>
59+
public static readonly string Cpu = "cpu";
60+
61+
/// <summary>
62+
/// Key for the memory.
63+
/// </summary>
64+
public static readonly string Memory = "memory_gb";
65+
66+
/// <summary>
67+
/// Key for the GPU.
68+
/// </summary>
69+
public static readonly string Gpu = "gpu";
70+
5671
public enum ModeValues
5772
{
5873
QA,

src/TaskManager/Plug-ins/Argo/StaticValues/Keys.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,21 @@ internal static class Keys
8888
/// </summary>
8989
public static readonly string TaskPriorityClassName = "priority";
9090

91+
/// <summary>
92+
/// Key for CPU
93+
/// </summary>
94+
public static readonly string Cpu = "cpu";
95+
96+
/// <summary>
97+
/// Key for memory allocation
98+
/// </summary>
99+
public static readonly string Memory = "memory_gb";
100+
101+
/// <summary>
102+
/// Key for GPU
103+
/// </summary>
104+
public static readonly string Gpu = "number_gpu";
105+
91106
/// <summary>
92107
/// Required arguments to run the Argo workflow.
93108
/// </summary>

src/WorkflowManager/WorkflowManager/Validators/WorkflowValidator.cs

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,9 +152,9 @@ private void ValidateTasks(Workflow workflow, string firstTaskId)
152152
{
153153
// duplicate destinations
154154
var duplicates = destinations
155-
.GroupBy(i => i)
156-
.Where(g => g.Count() > 1)
157-
.Select(g => g.Key);
155+
.GroupBy(i => i)
156+
.Where(g => g.Count() > 1)
157+
.Select(g => g.Key);
158158

159159
foreach (var dupe in duplicates)
160160
{
@@ -348,6 +348,27 @@ private void ValidateArgoTask(TaskObject currentTask)
348348
break;
349349
}
350350
}
351+
352+
new List<string> { Cpu, Memory }.ForEach(key =>
353+
{
354+
if (
355+
currentTask.Args.TryGetValue(key, out var val) &&
356+
!string.IsNullOrEmpty(val) &&
357+
double.TryParse(val, out double parsedVal) &&
358+
(parsedVal < 1 || Math.Truncate(parsedVal) != parsedVal))
359+
{
360+
Errors.Add($"Task: '{currentTask.Id}' value '{val}' provided for argument '{key}' is not valid. The value needs to be a whole number greater than 0.");
361+
}
362+
});
363+
364+
if (
365+
currentTask.Args.TryGetValue(Gpu, out var gpu) &&
366+
!string.IsNullOrEmpty(gpu) &&
367+
double.TryParse(gpu, out double parsedGpu) &&
368+
(parsedGpu != 0 || parsedGpu != 1))
369+
{
370+
Errors.Add($"Task: '{currentTask.Id}' value '{gpu}' provided for argument '{Gpu}' is not valid. The value needs to be 0 or 1.");
371+
}
351372
}
352373

353374
private void ValidateClinicalReviewTask(TaskObject[] tasks, TaskObject currentTask)

tests/UnitTests/WorkflowManager.Tests/Validators/WorkflowValidatorTests.cs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@
1515
*/
1616

1717
using System;
18-
using System.Security.Cryptography.Xml;
1918
using System.Threading.Tasks;
20-
using Amazon.Runtime.Internal.Transform;
2119
using Microsoft.Extensions.Logging;
2220
using Monai.Deploy.WorkflowManager.Common.Interfaces;
2321
using Monai.Deploy.WorkflowManager.Contracts.Models;
@@ -206,7 +204,10 @@ public async Task ValidateWorkflow_ValidatesAWorkflow_ReturnsErrorsAndHasCorrect
206204
Type = "argo",
207205
Description = "Test Argo Task",
208206
Args = {
209-
{ "example", "value" }
207+
{ "example", "value" },
208+
{ "cpu", "0.1" },
209+
{ "memory_gb", "0.1" },
210+
{ "gpu", "2" }
210211
},
211212
TaskDestinations = new TaskDestination[]
212213
{
@@ -347,7 +348,7 @@ public async Task ValidateWorkflow_ValidatesAWorkflow_ReturnsErrorsAndHasCorrect
347348

348349
Assert.True(errors.Count > 0);
349350

350-
Assert.Equal(40, errors.Count);
351+
Assert.Equal(43, errors.Count);
351352

352353
var convergingTasksDestinations = "Converging Tasks Destinations in tasks: (test-clinical-review-2, example-task) on task: example-task";
353354
Assert.Contains(convergingTasksDestinations, errors);
@@ -385,6 +386,15 @@ public async Task ValidateWorkflow_ValidatesAWorkflow_ReturnsErrorsAndHasCorrect
385386
var missingArgoArgs = "Task: 'test-argo-task' workflow_template_name must be specified, this corresponds to an Argo template name.";
386387
Assert.Contains(missingArgoArgs, errors);
387388

389+
var invalidArgoArg1 = "Task: 'test-argo-task' value '0.1' provided for argument 'cpu' is not valid. The value needs to be a whole number greater than 0.";
390+
Assert.Contains(invalidArgoArg1, errors);
391+
392+
var invalidArgoArg2 = "Task: 'test-argo-task' value '0.1' provided for argument 'memory_gb' is not valid. The value needs to be a whole number greater than 0.";
393+
Assert.Contains(invalidArgoArg2, errors);
394+
395+
var invalidArgoArg3 = "Task: 'test-argo-task' value '2' provided for argument 'gpu' is not valid. The value needs to be 0 or 1.";
396+
Assert.Contains(invalidArgoArg3, errors);
397+
388398
var incorrectClinicalReviewValueFormat = $"Invalid Value property on input artifact 'Invalid Value Format' in task: 'test-clinical-review'. Incorrect format.";
389399
Assert.Contains(incorrectClinicalReviewValueFormat, errors);
390400

0 commit comments

Comments
 (0)