Skip to content

Commit 7853eb7

Browse files
committed
adding scanning of dlls and adding controller endpoints
Signed-off-by: Neil South <[email protected]>
1 parent 44d2563 commit 7853eb7

File tree

14 files changed

+969
-15
lines changed

14 files changed

+969
-15
lines changed

src/Monai.Deploy.WorkflowManager.sln

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,10 @@ Global
140140
{013395D4-2091-4AB8-96CB-867C0F982096}.Debug|Any CPU.Build.0 = Debug|Any CPU
141141
{013395D4-2091-4AB8-96CB-867C0F982096}.Release|Any CPU.ActiveCfg = Release|Any CPU
142142
{013395D4-2091-4AB8-96CB-867C0F982096}.Release|Any CPU.Build.0 = Release|Any CPU
143+
{973A5B90-C143-46B6-899D-79E3D46370C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
144+
{973A5B90-C143-46B6-899D-79E3D46370C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
145+
{973A5B90-C143-46B6-899D-79E3D46370C4}.Release|Any CPU.ActiveCfg = Release|Any CPU
146+
{973A5B90-C143-46B6-899D-79E3D46370C4}.Release|Any CPU.Build.0 = Release|Any CPU
143147
{91A0D599-472F-4238-A1A3-07807F9C5F61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
144148
{91A0D599-472F-4238-A1A3-07807F9C5F61}.Debug|Any CPU.Build.0 = Debug|Any CPU
145149
{91A0D599-472F-4238-A1A3-07807F9C5F61}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -224,10 +228,6 @@ Global
224228
{75A4AEDA-0386-4B2D-9DBA-BC9AE733660E}.Debug|Any CPU.Build.0 = Debug|Any CPU
225229
{75A4AEDA-0386-4B2D-9DBA-BC9AE733660E}.Release|Any CPU.ActiveCfg = Release|Any CPU
226230
{75A4AEDA-0386-4B2D-9DBA-BC9AE733660E}.Release|Any CPU.Build.0 = Release|Any CPU
227-
{973A5B90-C143-46B6-899D-79E3D46370C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
228-
{973A5B90-C143-46B6-899D-79E3D46370C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
229-
{973A5B90-C143-46B6-899D-79E3D46370C4}.Release|Any CPU.ActiveCfg = Release|Any CPU
230-
{973A5B90-C143-46B6-899D-79E3D46370C4}.Release|Any CPU.Build.0 = Release|Any CPU
231231
EndGlobalSection
232232
GlobalSection(SolutionProperties) = preSolution
233233
HideSolutionNode = FALSE
@@ -246,6 +246,7 @@ Global
246246
{918E4DE3-A7BF-4B7F-9B5A-5C36FEFA3C30} = {71DDEE7B-E213-4E39-A7F4-4646783A27F7}
247247
{722C0D57-49F8-4178-88F0-06E369B797A3} = {71DDEE7B-E213-4E39-A7F4-4646783A27F7}
248248
{013395D4-2091-4AB8-96CB-867C0F982096} = {541C5347-5D7D-44B7-95D3-B6FB3D9EB955}
249+
{973A5B90-C143-46B6-899D-79E3D46370C4} = {71DDEE7B-E213-4E39-A7F4-4646783A27F7}
249250
{91A0D599-472F-4238-A1A3-07807F9C5F61} = {71DDEE7B-E213-4E39-A7F4-4646783A27F7}
250251
{7D85E95C-A263-429F-BF8B-8F4A922FD579} = {541C5347-5D7D-44B7-95D3-B6FB3D9EB955}
251252
{A966A7B9-2D4E-4A93-8D20-BD140E7A7F85} = {71DDEE7B-E213-4E39-A7F4-4646783A27F7}
@@ -268,7 +269,6 @@ Global
268269
{81E3F943-B992-4C81-AA09-A17C05081236} = {37A19144-CEA5-47A2-9FFD-22C522E8B895}
269270
{C853A9E3-C53D-4B1A-BFDA-228689A8C94C} = {71DDEE7B-E213-4E39-A7F4-4646783A27F7}
270271
{75A4AEDA-0386-4B2D-9DBA-BC9AE733660E} = {71DDEE7B-E213-4E39-A7F4-4646783A27F7}
271-
{973A5B90-C143-46B6-899D-79E3D46370C4} = {71DDEE7B-E213-4E39-A7F4-4646783A27F7}
272272
EndGlobalSection
273273
GlobalSection(ExtensibilityGlobals) = postSolution
274274
SolutionGuid = {DC0D56C8-D8CB-45CE-B528-F3DCF86D63ED}

src/Shared/Shared/PlugInAttribute.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright 2022 MONAI Consortium
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
namespace Monai.Deploy.WorkflowManager.Shared
18+
{
19+
[AttributeUsage(AttributeTargets.Assembly)]
20+
public class PlugInAttribute : Attribute
21+
{
22+
public PlugInAttribute() { }
23+
24+
}
25+
}

src/TaskManager/Plug-ins/Argo/ArgoClient.cs

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ public interface IArgoClient
3737
Task<Version?> Argo_GetVersionAsync();
3838

3939
Task<string?> Argo_Get_WorkflowLogsAsync(string argoNamespace, string name, string podName, string logOptions_container);
40+
41+
Task<WorkflowTemplate> Argo_CreateWorkflowTemplateAsync(string argoNamespace, WorkflowTemplateCreateRequest body, CancellationToken cancellationToken);
4042
}
4143

4244
public class ArgoClient : IArgoClient
@@ -62,7 +64,7 @@ public async Task<Workflow> Argo_CreateWorkflowAsync(string argoNamespace, Workf
6264

6365
var Method = "POST";
6466
var content = new StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(body));
65-
return await SendRequest(content, urlBuilder, Method, cancellationToken).ConfigureAwait(false);
67+
return await SendRequest<Workflow>(content, urlBuilder, Method, cancellationToken).ConfigureAwait(false);
6668

6769
}
6870

@@ -99,7 +101,7 @@ public async Task<Workflow> Argo_StopWorkflowAsync(string argoNamespace, string
99101

100102
var Method = "PUT";
101103
var content = new StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(body));
102-
return await SendRequest(content, urlBuilder, Method, new CancellationToken()).ConfigureAwait(false);
104+
return await SendRequest<Workflow>(content, urlBuilder, Method, new CancellationToken()).ConfigureAwait(false);
103105

104106
}
105107

@@ -114,7 +116,7 @@ public async Task<Workflow> Argo_TerminateWorkflowAsync(string argoNamespace, st
114116

115117
var Method = "PUT";
116118
var content = new StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(body));
117-
return await SendRequest(content, urlBuilder, Method, new CancellationToken()).ConfigureAwait(false);
119+
return await SendRequest<Workflow>(content, urlBuilder, Method, new CancellationToken()).ConfigureAwait(false);
118120
}
119121

120122
public async Task<WorkflowTemplate> Argo_GetWorkflowTemplateAsync(string argoNamespace, string name, string getOptions_resourceVersion)
@@ -162,7 +164,7 @@ public async Task<WorkflowTemplate> Argo_GetWorkflowTemplateAsync(string argoNam
162164
urlBuilder.Length--;
163165
return await GetRequest<string>(urlBuilder, true).ConfigureAwait(false);
164166
}
165-
private async Task<Workflow> SendRequest(StringContent stringContent, StringBuilder urlBuilder, string Method, CancellationToken cancellationToken)
167+
private async Task<T> SendRequest<T>(StringContent stringContent, StringBuilder urlBuilder, string Method, CancellationToken cancellationToken)
166168
{
167169
using (var request = new HttpRequestMessage())
168170
{
@@ -172,7 +174,17 @@ private async Task<Workflow> SendRequest(StringContent stringContent, StringBuil
172174
request.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json"));
173175
request.RequestUri = new Uri(urlBuilder.ToString(), UriKind.RelativeOrAbsolute);
174176

175-
var response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
177+
HttpResponseMessage? response = null;
178+
try
179+
{
180+
response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
181+
}
182+
catch (Exception ex)
183+
{
184+
var mess = ex.Message;
185+
throw;
186+
}
187+
176188

177189
try
178190
{
@@ -186,7 +198,7 @@ private async Task<Workflow> SendRequest(StringContent stringContent, StringBuil
186198
var status = (int)response.StatusCode;
187199
if (status == 200)
188200
{
189-
var objectResponse_ = await ReadObjectResponseAsync<Workflow>(response, headers).ConfigureAwait(false);
201+
var objectResponse_ = await ReadObjectResponseAsync<T>(response, headers).ConfigureAwait(false);
190202
if (objectResponse_.Object == null)
191203
{
192204
throw new ApiException("Response was null which was not expected.", status, objectResponse_.Text, headers, null);
@@ -336,6 +348,22 @@ protected virtual async Task<ObjectResponseResult<string>> ReadLogResponseAsync(
336348
}
337349
}
338350

351+
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
352+
/// <returns>A successful response.</returns>
353+
/// <exception cref="ApiException">A server side error occurred.</exception>
354+
public virtual async Task<WorkflowTemplate> Argo_CreateWorkflowTemplateAsync(string argoNamespace, WorkflowTemplateCreateRequest body, CancellationToken cancellationToken)
355+
{
356+
Guard.Against.NullOrWhiteSpace(argoNamespace);
357+
Guard.Against.Null(body);
358+
359+
var urlBuilder = new StringBuilder();
360+
urlBuilder.Append(CultureInfo.InvariantCulture, $"{FormattedBaseUrl}/api/v1/workflow-templates/{argoNamespace}");
361+
362+
var Method = "POST";
363+
var content = new StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(body));
364+
return await SendRequest<WorkflowTemplate>(content, urlBuilder, Method, cancellationToken).ConfigureAwait(false);
365+
}
366+
339367
protected struct ObjectResponseResult<T>
340368
{
341369
public ObjectResponseResult(T responseObject, string responseText)

src/TaskManager/Plug-ins/Argo/ArgoPlugin.cs

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,15 @@
2525
using Monai.Deploy.Messaging.Events;
2626
using Monai.Deploy.TaskManager.API;
2727
using Monai.Deploy.WorkflowManager.Configuration;
28+
using Monai.Deploy.WorkflowManager.Shared;
2829
using Monai.Deploy.WorkflowManager.TaskManager.API;
2930
using Monai.Deploy.WorkflowManager.TaskManager.API.Extensions;
3031
using Monai.Deploy.WorkflowManager.TaskManager.API.Models;
3132
using Monai.Deploy.WorkflowManager.TaskManager.Argo.Logging;
3233
using Monai.Deploy.WorkflowManager.TaskManager.Argo.StaticValues;
3334
using Newtonsoft.Json;
3435

36+
[assembly: PlugIn()]
3537
namespace Monai.Deploy.WorkflowManager.TaskManager.Argo
3638
{
3739
public sealed class ArgoPlugin : TaskPluginBase, IAsyncDisposable
@@ -45,7 +47,7 @@ public sealed class ArgoPlugin : TaskPluginBase, IAsyncDisposable
4547
private readonly ILogger<ArgoPlugin> _logger;
4648
private readonly ITaskDispatchEventService _taskDispatchEventService;
4749
private int? _activeDeadlineSeconds;
48-
private string _namespace;
50+
private string _namespace = "argo";
4951
private string _baseUrl = null!;
5052
private bool _allowInsecure = true;
5153
private string? _apiToken;
@@ -70,8 +72,15 @@ public ArgoPlugin(
7072
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
7173
_options = options ?? throw new ArgumentNullException(nameof(options));
7274

73-
ValidateEvent();
74-
Initialize();
75+
_baseUrl = _options.Value.TaskManager.ArgoPluginArguments.ServerUrl;
76+
77+
if (taskDispatchEvent.Inputs.Count != 0 ||
78+
taskDispatchEvent.Outputs.Count != 0 ||
79+
taskDispatchEvent.ExecutionId != "")
80+
{
81+
ValidateEvent();
82+
Initialize();
83+
}
7584
}
7685

7786
private void Initialize()
@@ -934,5 +943,31 @@ public override async Task HandleTimeout(string identity)
934943
Namespace = _namespace
935944
});
936945
}
946+
947+
public async Task<WorkflowTemplate> CreateArgoTemplate(string template)
948+
{
949+
try
950+
{
951+
WorkflowTemplateCreateRequest? templateCreateRequest = null;
952+
var client = _argoProvider.CreateClient(_baseUrl, _apiToken, _allowInsecure);
953+
try
954+
{
955+
templateCreateRequest = JsonConvert.DeserializeObject<WorkflowTemplateCreateRequest>(template);
956+
}
957+
catch (JsonReaderException ex)
958+
{
959+
_logger.ErrorDeserializingWorkflowTemplateCreateRequest(ex.Message, ex);
960+
var mess = ex.Message;
961+
throw new InvalidOperationException(mess);
962+
}
963+
964+
return await client.Argo_CreateWorkflowTemplateAsync(_namespace, templateCreateRequest, new CancellationToken()).ConfigureAwait(false);
965+
}
966+
catch (Exception ex)
967+
{
968+
_logger.ErrorCreatingWorkflowTemplate(ex);
969+
throw;
970+
}
971+
}
937972
}
938973
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
* Copyright 2022 MONAI Consortium
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
using System.Runtime.InteropServices;
17+
using System.Text;
18+
using Amazon.Runtime.Internal.Util;
19+
using Argo;
20+
using Microsoft.AspNetCore.Authorization;
21+
using Microsoft.AspNetCore.Mvc;
22+
using Microsoft.AspNetCore.Mvc.Formatters;
23+
using Microsoft.Extensions.DependencyInjection;
24+
using Microsoft.Extensions.Logging;
25+
using Microsoft.Extensions.Options;
26+
using Monai.Deploy.WorkflowManager.Configuration;
27+
using MongoDB.Bson.IO;
28+
29+
30+
31+
namespace Monai.Deploy.WorkflowManager.TaskManager.Argo.Controllers
32+
{
33+
[ApiController]
34+
[Authorize]
35+
[Route("argo/[controller]")]
36+
public class TemplateController : ControllerBase
37+
{
38+
private readonly ArgoPlugin _argoPlugin;
39+
private readonly ILogger<TemplateController> _tempLogger;
40+
public TemplateController(
41+
IServiceScopeFactory scopeFactory,
42+
ILogger<TemplateController> tempLogger,
43+
ILogger<ArgoPlugin> argoLogger,
44+
IOptions<WorkflowManagerOptions> options)
45+
{
46+
_tempLogger = tempLogger;
47+
48+
_argoPlugin = new ArgoPlugin(scopeFactory, argoLogger, options, new Messaging.Events.TaskDispatchEvent());
49+
50+
51+
}
52+
53+
[HttpGet]
54+
public ActionResult<IEnumerable<int>> Values()
55+
{
56+
return StatusCode(200, new List<int> { 12, 155, 12, 9 });
57+
}
58+
59+
[HttpPost]
60+
public async Task<ActionResult<WorkflowTemplate>> CreateArgoTemplate()
61+
{
62+
using StreamReader reader = new StreamReader(Request.Body, Encoding.UTF8);
63+
64+
var value2 = await reader.ReadToEndAsync();
65+
66+
if (String.IsNullOrWhiteSpace(value2))
67+
{
68+
return BadRequest("No file recieved");
69+
}
70+
WorkflowTemplate? workflowTemplate = null;
71+
try
72+
{
73+
workflowTemplate = await _argoPlugin.CreateArgoTemplate(value2);
74+
}
75+
catch (Exception)
76+
{
77+
return BadRequest("message: Argo unable to process template");
78+
}
79+
80+
81+
return Ok(workflowTemplate);
82+
}
83+
}
84+
}

src/TaskManager/Plug-ins/Argo/Logging/Log.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17+
using Argo;
1718
using Microsoft.Extensions.Logging;
1819

1920
namespace Monai.Deploy.WorkflowManager.TaskManager.Argo.Logging
@@ -70,5 +71,12 @@ public static partial class Log
7071

7172
[LoggerMessage(EventId = 1016, Level = LogLevel.Information, Message = "Argo: {logString}")]
7273
public static partial void ArgoLog(this ILogger logger, string logString);
74+
75+
[LoggerMessage(EventId = 1017, Level = LogLevel.Error, Message = "Error creating Template in Argo.")]
76+
public static partial void ErrorCreatingWorkflowTemplate(this ILogger logger, Exception ex);
77+
78+
[LoggerMessage(EventId = 1018, Level = LogLevel.Error, Message = "Error deserializing WorkflowTemplateCreateRequest. {message}")]
79+
public static partial void ErrorDeserializingWorkflowTemplateCreateRequest(this ILogger logger, string message, Exception ex);
80+
7381
}
7482
}

src/TaskManager/Plug-ins/Argo/Monai.Deploy.WorkflowManager.TaskManager.Argo.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333

3434
<ItemGroup>
3535
<PackageReference Include="KubernetesClient" Version="10.1.4" />
36+
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
3637
<PackageReference Include="Microsoft.Extensions.ApiDescription.Client" Version="6.0.15">
3738
<PrivateAssets>all</PrivateAssets>
3839
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
@@ -41,6 +42,7 @@
4142

4243
<ItemGroup>
4344
<ProjectReference Include="..\..\..\Shared\Configuration\Monai.Deploy.WorkflowManager.Configuration.csproj" />
45+
<ProjectReference Include="..\..\..\Shared\Shared\Monai.Deploy.WorkflowManager.Shared.csproj" />
4446
<ProjectReference Include="..\..\API\Monai.Deploy.WorkflowManager.TaskManager.API.csproj" />
4547
</ItemGroup>
4648

0 commit comments

Comments
 (0)