diff --git a/docs/changelog.md b/docs/changelog.md
index 7aea4128f..68ef2ff73 100644
--- a/docs/changelog.md
+++ b/docs/changelog.md
@@ -17,6 +17,44 @@
# Changelog
+## 0.4.0
+
+[GitHub Milestone 0.4.0](https://github.com/Project-MONAI/monai-deploy-informatics-gateway/milestone/5)
+
+- gh-435 Fix CLI to read log dir path from NLog config file.
+
+
+## 0.3.21
+
+[GitHub Milestone 0.3.21](https://github.com/Project-MONAI/monai-deploy-informatics-gateway/milestone/26)
+
+- Remove the need to double copy files to storage service.
+
+## 0.3.20
+
+[GitHub Milestone 0.3.20](https://github.com/Project-MONAI/monai-deploy-informatics-gateway/milestone/25)
+
+- gh-396 Spawn new thread for processing echo requests.
+
+## 0.3.19
+
+[GitHub Milestone 0.3.19](https://github.com/Project-MONAI/monai-deploy-informatics-gateway/milestone/24)
+
+- gh-392 Fix GET /config/aetitle URL.
+
+## 0.3.18
+
+[GitHub Milestone 0.3.18](https://github.com/Project-MONAI/monai-deploy-informatics-gateway/milestone/23)
+
+- gh-390 New API to retrieve registered source AETs.
+
+## 0.3.11
+
+[GitHub Milestone 0.3.17](https://github.com/Project-MONAI/monai-deploy-informatics-gateway/milestone/22)
+
+- gh-385 Resets ActionBlock if faulted or cancelled in Payload assembler pipeline.
+
+
## 0.3.16
[GitHub Milestone 0.3.16](https://github.com/Project-MONAI/monai-deploy-informatics-gateway/milestone/21)
diff --git a/src/CLI/Logging/Log.cs b/src/CLI/Logging/Log.cs
index 9c1a3d43f..818b6bd5f 100644
--- a/src/CLI/Logging/Log.cs
+++ b/src/CLI/Logging/Log.cs
@@ -133,8 +133,8 @@ public static partial class Log
[LoggerMessage(EventId = 30043, Level = LogLevel.Debug, Message = "Available manifest names {names}.")]
public static partial void AvailableManifest(this ILogger logger, string names);
- [LoggerMessage(EventId = 30044, Level = LogLevel.Information, Message = "Saving appsettings.json to {path}.")]
- public static partial void SaveAppSettings(this ILogger logger, string path);
+ [LoggerMessage(EventId = 30044, Level = LogLevel.Information, Message = "Saving {resource} to {path}.")]
+ public static partial void SaveAppSettings(this ILogger logger, string resource, string path);
[LoggerMessage(EventId = 30045, Level = LogLevel.Information, Message = "{path} updated successfully.")]
public static partial void AppSettingUpdated(this ILogger logger, string path);
diff --git a/src/CLI/Monai.Deploy.InformaticsGateway.CLI.csproj b/src/CLI/Monai.Deploy.InformaticsGateway.CLI.csproj
index c8ac72782..fc2a72c16 100644
--- a/src/CLI/Monai.Deploy.InformaticsGateway.CLI.csproj
+++ b/src/CLI/Monai.Deploy.InformaticsGateway.CLI.csproj
@@ -51,6 +51,7 @@
+
diff --git a/src/CLI/Options/Common.cs b/src/CLI/Options/Common.cs
index 41ab89436..7fc50b35d 100644
--- a/src/CLI/Options/Common.cs
+++ b/src/CLI/Options/Common.cs
@@ -25,9 +25,12 @@ public static class Common
public static readonly string MigDirectory = Path.Combine(HomeDir, ".mig");
public static readonly string ContainerApplicationRootPath = "/opt/monai/ig";
public static readonly string MountedConfigFilePath = Path.Combine(ContainerApplicationRootPath, "appsettings.json");
+ public static readonly string MountedNLogConfigFilePath = Path.Combine(ContainerApplicationRootPath, "nlog.config");
public static readonly string MountedDatabasePath = "/database";
public static readonly string MountedPlugInsPath = Path.Combine(ContainerApplicationRootPath, "plug-ins");
public static readonly string ConfigFilePath = Path.Combine(MigDirectory, "appsettings.json");
+ public static readonly string NLogConfigFilePath = Path.Combine(MigDirectory, "nlog.config");
public static readonly string AppSettingsResourceName = $"{typeof(Program).Namespace}.Resources.appsettings.json";
+ public static readonly string NLogConfigResourceName = $"{typeof(Program).Namespace}.Resources.nlog.config";
}
}
diff --git a/src/CLI/Program.cs b/src/CLI/Program.cs
index f21f666b0..7e5e7e4cd 100644
--- a/src/CLI/Program.cs
+++ b/src/CLI/Program.cs
@@ -63,6 +63,8 @@ internal static Parser BuildParser()
services.AddScoped();
services.AddScoped();
services.AddScoped();
+ services.AddScoped();
+ services.AddScoped();
services.AddHttpClient();
services.AddSingleton(p => p.GetRequiredService());
services.AddSingleton();
diff --git a/src/CLI/Properties/launchSettings.json b/src/CLI/Properties/launchSettings.json
index 284f8dba9..aff7ae893 100644
--- a/src/CLI/Properties/launchSettings.json
+++ b/src/CLI/Properties/launchSettings.json
@@ -2,7 +2,7 @@
"profiles": {
"Monai.Deploy.InformaticsGateway.CLI": {
"commandName": "Project",
- "commandLineArgs": "aet add -a Test"
+ "commandLineArgs": "start"
}
}
}
\ No newline at end of file
diff --git a/src/CLI/Services/ConfigurationOptionAccessor.cs b/src/CLI/Services/ConfigurationOptionAccessor.cs
index fd134c93e..c61ae761c 100644
--- a/src/CLI/Services/ConfigurationOptionAccessor.cs
+++ b/src/CLI/Services/ConfigurationOptionAccessor.cs
@@ -1,5 +1,5 @@
/*
- * Copyright 2021-2022 MONAI Consortium
+ * Copyright 2021-2023 MONAI Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -76,11 +76,6 @@ public interface IConfigurationOptionAccessor
///
Uri InformaticsGatewayServerUri { get; }
- ///
- /// Gets the log storage path from appsettings.json.
- ///
- string LogStoragePath { get; }
-
///
/// Gets or set the type of container runner from appsettings.json.
///
@@ -99,7 +94,7 @@ public class ConfigurationOptionAccessor : IConfigurationOptionAccessor
public ConfigurationOptionAccessor(IFileSystem fileSystem)
{
- _fileSystem = fileSystem;
+ _fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem));
}
public int DicomListeningPort
@@ -223,19 +218,6 @@ public Uri InformaticsGatewayServerUri
}
}
- public string LogStoragePath
- {
- get
- {
- var logPath = GetValueFromJsonPath("Logging.File.BasePath");
- if (logPath.StartsWith("/"))
- {
- return logPath;
- }
- return _fileSystem.Path.Combine(Common.ContainerApplicationRootPath, logPath);
- }
- }
-
public Runner Runner
{
get
@@ -255,7 +237,7 @@ public string TempStoragePath
{
get
{
- return GetValueFromJsonPath("InformaticsGateway.storage.temporary");
+ return GetValueFromJsonPath("InformaticsGateway.storage.localTemporaryStoragePath");
}
}
diff --git a/src/CLI/Services/ConfigurationService.cs b/src/CLI/Services/ConfigurationService.cs
index c46c16960..7e71c6afd 100644
--- a/src/CLI/Services/ConfigurationService.cs
+++ b/src/CLI/Services/ConfigurationService.cs
@@ -1,5 +1,5 @@
/*
- * Copyright 2021-2022 MONAI Consortium
+ * Copyright 2021-2023 MONAI Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
+using Ardalis.GuardClauses;
using Microsoft.Extensions.Logging;
namespace Monai.Deploy.InformaticsGateway.CLI.Services
@@ -35,13 +36,20 @@ public class ConfigurationService : IConfigurationService
public bool IsConfigExists => _fileSystem.File.Exists(Common.ConfigFilePath);
public IConfigurationOptionAccessor Configurations { get; }
+ public INLogConfigurationOptionAccessor NLogConfigurations { get; }
- public ConfigurationService(ILogger logger, IFileSystem fileSystem, IEmbeddedResource embeddedResource)
+ public ConfigurationService(
+ ILogger logger,
+ IFileSystem fileSystem,
+ IEmbeddedResource embeddedResource,
+ IConfigurationOptionAccessor configurationOptionAccessor,
+ INLogConfigurationOptionAccessor nLogConfigurationOptionAccessor)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem));
_embeddedResource = embeddedResource ?? throw new ArgumentNullException(nameof(embeddedResource));
- Configurations = new ConfigurationOptionAccessor(fileSystem);
+ Configurations = configurationOptionAccessor ?? throw new ArgumentNullException(nameof(configurationOptionAccessor));
+ NLogConfigurations = nLogConfigurationOptionAccessor ?? throw new ArgumentNullException(nameof(nLogConfigurationOptionAccessor));
}
public void CreateConfigDirectoryIfNotExist()
@@ -55,22 +63,32 @@ public void CreateConfigDirectoryIfNotExist()
public async Task Initialize(CancellationToken cancellationToken)
{
_logger.DebugMessage("Reading default application configurations...");
- using var stream = _embeddedResource.GetManifestResourceStream(Common.AppSettingsResourceName);
+ await WriteConfigFile(Common.AppSettingsResourceName, Common.ConfigFilePath, cancellationToken).ConfigureAwait(false);
+ await WriteConfigFile(Common.NLogConfigResourceName, Common.NLogConfigFilePath, cancellationToken).ConfigureAwait(false);
+ }
+
+ public async Task WriteConfigFile(string resourceName, string outputPath, CancellationToken cancellationToken)
+ {
+ Guard.Against.NullOrWhiteSpace(resourceName, nameof(resourceName));
+ Guard.Against.NullOrWhiteSpace(outputPath, nameof(outputPath));
+
+ using var stream = _embeddedResource.GetManifestResourceStream(resourceName);
if (stream is null)
{
_logger.AvailableManifest(string.Join(",", Assembly.GetExecutingAssembly().GetManifestResourceNames()));
- throw new ConfigurationException($"Default configuration file could not be loaded, please reinstall the CLI.");
+ throw new ConfigurationException($"Default configuration file: {resourceName} could not be loaded, please reinstall the CLI.");
}
CreateConfigDirectoryIfNotExist();
- _logger.SaveAppSettings(Common.ConfigFilePath);
- using (var fileStream = _fileSystem.FileStream.Create(Common.ConfigFilePath, FileMode.Create))
+ _logger.SaveAppSettings(resourceName, outputPath);
+ using (var fileStream = _fileSystem.FileStream.Create(outputPath, FileMode.Create))
{
await stream.CopyToAsync(fileStream, cancellationToken).ConfigureAwait(false);
await fileStream.FlushAsync(cancellationToken).ConfigureAwait(false);
}
- _logger.AppSettingUpdated(Common.ConfigFilePath);
+ _logger.AppSettingUpdated(outputPath);
+
}
}
}
diff --git a/src/CLI/Services/DockerRunner.cs b/src/CLI/Services/DockerRunner.cs
index 20d1c15a0..f3eb2abfb 100644
--- a/src/CLI/Services/DockerRunner.cs
+++ b/src/CLI/Services/DockerRunner.cs
@@ -1,5 +1,5 @@
/*
- * Copyright 2021-2022 MONAI Consortium
+ * Copyright 2021-2023 MONAI Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -114,6 +114,7 @@ public async Task StartApplication(ImageVersion imageVersion, Cancellation
};
createContainerParams.HostConfig.PortBindings = new Dictionary>();
+ createContainerParams.HostConfig.NetworkMode = "monaideploy";
_logger.DockerPrtBinding(_configurationService.Configurations.DicomListeningPort);
createContainerParams.ExposedPorts.Add($"{_configurationService.Configurations.DicomListeningPort}/tcp", new EmptyStruct());
@@ -135,9 +136,9 @@ public async Task StartApplication(ImageVersion imageVersion, Cancellation
_fileSystem.Directory.CreateDirectoryIfNotExists(_configurationService.Configurations.HostDatabaseStorageMount);
createContainerParams.HostConfig.Mounts.Add(new Mount { Type = "bind", ReadOnly = false, Source = _configurationService.Configurations.HostDatabaseStorageMount, Target = Common.MountedDatabasePath });
- _logger.DockerMountAppLogs(_configurationService.Configurations.HostLogsStorageMount, _configurationService.Configurations.LogStoragePath);
+ _logger.DockerMountAppLogs(_configurationService.Configurations.HostLogsStorageMount, _configurationService.NLogConfigurations.LogStoragePath);
_fileSystem.Directory.CreateDirectoryIfNotExists(_configurationService.Configurations.HostLogsStorageMount);
- createContainerParams.HostConfig.Mounts.Add(new Mount { Type = "bind", ReadOnly = false, Source = _configurationService.Configurations.HostLogsStorageMount, Target = _configurationService.Configurations.LogStoragePath });
+ createContainerParams.HostConfig.Mounts.Add(new Mount { Type = "bind", ReadOnly = false, Source = _configurationService.Configurations.HostLogsStorageMount, Target = _configurationService.NLogConfigurations.LogStoragePath });
_logger.DockerMountPlugins(_configurationService.Configurations.HostPlugInsStorageMount, Common.MountedPlugInsPath);
_fileSystem.Directory.CreateDirectoryIfNotExists(_configurationService.Configurations.HostPlugInsStorageMount);
diff --git a/src/CLI/Services/EmbeddedResource.cs b/src/CLI/Services/EmbeddedResource.cs
index 9b21c127e..d93151475 100644
--- a/src/CLI/Services/EmbeddedResource.cs
+++ b/src/CLI/Services/EmbeddedResource.cs
@@ -29,7 +29,8 @@ public class EmbeddedResource : IEmbeddedResource
public Stream GetManifestResourceStream(string name)
{
Guard.Against.NullOrWhiteSpace(name, nameof(name));
- return GetType().Assembly.GetManifestResourceStream(Common.AppSettingsResourceName);
+
+ return GetType().Assembly.GetManifestResourceStream(name);
}
}
}
diff --git a/src/CLI/Services/IConfigurationService.cs b/src/CLI/Services/IConfigurationService.cs
index a4a0d8fa0..77cfe108c 100644
--- a/src/CLI/Services/IConfigurationService.cs
+++ b/src/CLI/Services/IConfigurationService.cs
@@ -26,6 +26,11 @@ public interface IConfigurationService
///
IConfigurationOptionAccessor Configurations { get; }
+ ///
+ /// Gets the configurations inside nlog.config
+ ///
+ INLogConfigurationOptionAccessor NLogConfigurations { get; }
+
///
/// Gets whether the configuration file exists or not.
///
diff --git a/src/CLI/Services/NLogConfigurationOptionAccessor.cs b/src/CLI/Services/NLogConfigurationOptionAccessor.cs
new file mode 100644
index 000000000..404446704
--- /dev/null
+++ b/src/CLI/Services/NLogConfigurationOptionAccessor.cs
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2023 MONAI Consortium
+ *
+ * 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.
+ */
+
+using System;
+using System.IO.Abstractions;
+using System.Xml;
+
+namespace Monai.Deploy.InformaticsGateway.CLI.Services
+{
+ public interface INLogConfigurationOptionAccessor
+ {
+ ///
+ /// Gets the logs directory path.
+ ///
+ string LogStoragePath { get; }
+ }
+
+ public class NLogConfigurationOptionAccessor : INLogConfigurationOptionAccessor
+ {
+ private readonly XmlDocument _xmlDocument;
+ private readonly XmlNamespaceManager _namespaceManager;
+
+ public NLogConfigurationOptionAccessor(IFileSystem fileSystem)
+ {
+ if (fileSystem is null)
+ {
+ throw new ArgumentNullException(nameof(fileSystem));
+ }
+
+ var xml = fileSystem.File.ReadAllText(Common.NLogConfigFilePath);
+ _xmlDocument = new XmlDocument();
+ _xmlDocument.LoadXml(xml);
+ _namespaceManager = new XmlNamespaceManager(_xmlDocument.NameTable);
+ _namespaceManager.AddNamespace("ns", "http://www.nlog-project.org/schemas/NLog.xsd");
+ }
+
+ public string LogStoragePath
+ {
+ get
+ {
+ var value = _xmlDocument.SelectSingleNode("//ns:variable[@name='logDir']/@value", _namespaceManager).InnerText;
+ value = value.Replace("${basedir}", Common.ContainerApplicationRootPath);
+ return value;
+ }
+ }
+ }
+}
diff --git a/src/CLI/Test/ConfigurationOptionAccessorTest.cs b/src/CLI/Test/ConfigurationOptionAccessorTest.cs
new file mode 100644
index 000000000..5098ce214
--- /dev/null
+++ b/src/CLI/Test/ConfigurationOptionAccessorTest.cs
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2021-2023 MONAI Consortium
+ *
+ * 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.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.IO.Abstractions;
+using System.IO.Abstractions.TestingHelpers;
+using Ardalis.GuardClauses;
+using Monai.Deploy.InformaticsGateway.CLI.Services;
+using Xunit;
+
+namespace Monai.Deploy.InformaticsGateway.CLI.Test
+{
+ public class ConfigurationOptionAccessorTest
+ {
+ private readonly IFileSystem _fileSystem;
+
+ public ConfigurationOptionAccessorTest()
+ {
+ }
+
+ [Fact(DisplayName = "ConfigurationOptionAccessor Constructor")]
+ public void DockerRunner_Constructor()
+ {
+ Assert.Throws(() => new ConfigurationOptionAccessor(null));
+ }
+
+ [Fact]
+ public void DicomListeningPort_Get_ReturnsValue()
+ {
+ var fileSystem = SetupFileSystem("{\"InformaticsGateway\": {\"dicom\": {\"scp\": {\"port\": 104}}}}");
+ var configurationOptionAccessor = new ConfigurationOptionAccessor(fileSystem);
+
+ Assert.Equal(104, configurationOptionAccessor.DicomListeningPort);
+ }
+
+ [Fact]
+ public void DicomListeningPort_Set_UpdatesValue()
+ {
+ var fileSystem = SetupFileSystem("{\"InformaticsGateway\": {\"dicom\": {\"scp\": {\"port\": 104}}}}");
+ var configurationOptionAccessor = new ConfigurationOptionAccessor(fileSystem);
+ configurationOptionAccessor.DicomListeningPort = 1000;
+ Assert.Equal(1000, configurationOptionAccessor.DicomListeningPort);
+ }
+
+ [Fact]
+ public void Hl7ListeningPort_Get_ReturnsValue()
+ {
+ var fileSystem = SetupFileSystem("{\"InformaticsGateway\": {\"hl7\": {\"port\": 2575}}}");
+ var configurationOptionAccessor = new ConfigurationOptionAccessor(fileSystem);
+
+ Assert.Equal(2575, configurationOptionAccessor.Hl7ListeningPort);
+ }
+
+ [Fact]
+ public void Hl7ListeningPort_Set_UpdatesValue()
+ {
+ var fileSystem = SetupFileSystem("{\"InformaticsGateway\": {\"hl7\": {\"port\": 2575}}}");
+ var configurationOptionAccessor = new ConfigurationOptionAccessor(fileSystem);
+ configurationOptionAccessor.Hl7ListeningPort = 1000;
+ Assert.Equal(1000, configurationOptionAccessor.Hl7ListeningPort);
+ }
+
+ [Fact]
+ public void DockerImagePrefix_Get_ReturnsValue()
+ {
+ var fileSystem = SetupFileSystem("{\"Cli\": {\"DockerImagePrefix\": \"ghcr.io/project-monai/monai-deploy-informatics-gateway\"}}");
+ var configurationOptionAccessor = new ConfigurationOptionAccessor(fileSystem);
+
+ Assert.Equal("ghcr.io/project-monai/monai-deploy-informatics-gateway", configurationOptionAccessor.DockerImagePrefix);
+ }
+
+ [Fact]
+ public void HostDatabaseStorageMount_Get_ReturnsValue()
+ {
+ var fileSystem = SetupFileSystem("{\"Cli\": {\"HostDatabaseStorageMount\": \"~/.mig/database\"}}");
+ var configurationOptionAccessor = new ConfigurationOptionAccessor(fileSystem);
+
+ Assert.Equal($"{Common.HomeDir}/.mig/database", configurationOptionAccessor.HostDatabaseStorageMount);
+ }
+
+ [Fact]
+ public void HostDataStorageMount_Get_ReturnsValue()
+ {
+ var fileSystem = SetupFileSystem("{\"Cli\": {\"HostDataStorageMount\": \"~/.mig/data\"}}");
+ var configurationOptionAccessor = new ConfigurationOptionAccessor(fileSystem);
+
+ Assert.Equal($"{Common.HomeDir}/.mig/data", configurationOptionAccessor.HostDataStorageMount);
+ }
+
+ [Fact]
+ public void HostPlugInsStorageMount_Get_ReturnsValue()
+ {
+ var fileSystem = SetupFileSystem("{\"Cli\": {\"HostPlugInsStorageMount\": \"~/.mig/plug-ins\"}}");
+ var configurationOptionAccessor = new ConfigurationOptionAccessor(fileSystem);
+
+ Assert.Equal($"{Common.HomeDir}/.mig/plug-ins", configurationOptionAccessor.HostPlugInsStorageMount);
+ }
+
+ [Fact]
+ public void HostLogsStorageMount_Get_ReturnsValue()
+ {
+ var fileSystem = SetupFileSystem("{\"Cli\": {\"HostLogsStorageMount\": \"~/.mig/logs\"}}");
+ var configurationOptionAccessor = new ConfigurationOptionAccessor(fileSystem);
+
+ Assert.Equal($"{Common.HomeDir}/.mig/logs", configurationOptionAccessor.HostLogsStorageMount);
+ }
+
+ [Fact]
+ public void InformaticsGatewayServerEndpoint_Get_ReturnsValue()
+ {
+ var fileSystem = SetupFileSystem("{\"Cli\": {\"InformaticsGatewayServerEndpoint\": \"http://localhost:5000\"}}");
+ var configurationOptionAccessor = new ConfigurationOptionAccessor(fileSystem);
+
+ Assert.Equal("http://localhost:5000", configurationOptionAccessor.InformaticsGatewayServerEndpoint);
+ }
+
+ [Fact]
+ public void InformaticsGatewayServerEndpoint_Set_UpdatesValue()
+ {
+ var fileSystem = SetupFileSystem("{\"Cli\": {\"InformaticsGatewayServerEndpoint\": \"http://localhost:5000\"}}");
+ var configurationOptionAccessor = new ConfigurationOptionAccessor(fileSystem);
+ configurationOptionAccessor.InformaticsGatewayServerEndpoint = "http://hello-world";
+ Assert.Equal("http://hello-world", configurationOptionAccessor.InformaticsGatewayServerEndpoint);
+ }
+
+ [Fact]
+ public void InformaticsGatewayServerPort_Get_ReturnsValue()
+ {
+ var fileSystem = SetupFileSystem("{\"Cli\": {\"InformaticsGatewayServerEndpoint\": \"http://localhost:5000\"}}");
+ var configurationOptionAccessor = new ConfigurationOptionAccessor(fileSystem);
+
+ Assert.Equal(5000, configurationOptionAccessor.InformaticsGatewayServerPort);
+ }
+
+ [Fact]
+ public void InformaticsGatewayServerUri_Get_ReturnsValue()
+ {
+ var fileSystem = SetupFileSystem("{\"Cli\": {\"InformaticsGatewayServerEndpoint\": \"http://localhost:5000\"}}");
+ var configurationOptionAccessor = new ConfigurationOptionAccessor(fileSystem);
+
+ Assert.Equal(new Uri("http://localhost:5000"), configurationOptionAccessor.InformaticsGatewayServerUri);
+ }
+
+ [Fact]
+ public void Runner_Get_ReturnsValue()
+ {
+ var fileSystem = SetupFileSystem("{\"Cli\": {\"Runner\": \"Docker\"}}");
+ var configurationOptionAccessor = new ConfigurationOptionAccessor(fileSystem);
+
+ Assert.Equal(Runner.Docker, configurationOptionAccessor.Runner);
+ }
+
+ [Fact]
+ public void Runner_Set_UpdatesValue()
+ {
+ var fileSystem = SetupFileSystem("{\"Cli\": {\"Runner\": \"Docker\"}}");
+ var configurationOptionAccessor = new ConfigurationOptionAccessor(fileSystem);
+ configurationOptionAccessor.Runner = Runner.Kubernetes;
+ Assert.Equal(Runner.Kubernetes, configurationOptionAccessor.Runner);
+ }
+
+ [Fact]
+ public void TempStoragePath_Get_ReturnsValue()
+ {
+ var fileSystem = SetupFileSystem("{\"InformaticsGateway\": {\"storage\": {\"localTemporaryStoragePath\": \"/payloads\"}}}");
+ var configurationOptionAccessor = new ConfigurationOptionAccessor(fileSystem);
+ Assert.Equal("/payloads", configurationOptionAccessor.TempStoragePath);
+ }
+
+ private IFileSystem SetupFileSystem(string config)
+ {
+ Guard.Against.NullOrWhiteSpace(config, nameof(config));
+
+ return new MockFileSystem(new Dictionary
+ {
+ {Common.ConfigFilePath, new MockFileData(config) }
+ });
+ }
+ }
+}
diff --git a/src/CLI/Test/ConfigurationServiceTest.cs b/src/CLI/Test/ConfigurationServiceTest.cs
index 5fa218e31..0c295d44e 100644
--- a/src/CLI/Test/ConfigurationServiceTest.cs
+++ b/src/CLI/Test/ConfigurationServiceTest.cs
@@ -33,29 +33,35 @@ public class ConfigurationServiceTest
private readonly Mock> _logger;
private readonly Mock _fileSystem;
private readonly Mock _embeddedResource;
+ private readonly Mock _configurationOptionAccessor;
+ private readonly Mock _nLogConfigurationOptionAccessor;
public ConfigurationServiceTest()
{
_logger = new Mock>();
_fileSystem = new Mock();
_embeddedResource = new Mock();
+ _configurationOptionAccessor = new Mock();
+ _nLogConfigurationOptionAccessor = new Mock();
}
[Fact(DisplayName = "ConfigurationServiceTest constructor")]
public void ConfigurationServiceTest_Constructor()
{
- Assert.Throws(() => new ConfigurationService(null, null, null));
- Assert.Throws(() => new ConfigurationService(_logger.Object, null, null));
- Assert.Throws(() => new ConfigurationService(_logger.Object, _fileSystem.Object, null));
+ Assert.Throws(() => new ConfigurationService(null, null, null, null, null));
+ Assert.Throws(() => new ConfigurationService(_logger.Object, null, null, null, null));
+ Assert.Throws(() => new ConfigurationService(_logger.Object, _fileSystem.Object, null, null, null));
+ Assert.Throws(() => new ConfigurationService(_logger.Object, _fileSystem.Object, _embeddedResource.Object, null, null));
+ Assert.Throws(() => new ConfigurationService(_logger.Object, _fileSystem.Object, _embeddedResource.Object, _configurationOptionAccessor.Object, null));
- var svc = new ConfigurationService(_logger.Object, _fileSystem.Object, _embeddedResource.Object);
+ var svc = new ConfigurationService(_logger.Object, _fileSystem.Object, _embeddedResource.Object, _configurationOptionAccessor.Object, _nLogConfigurationOptionAccessor.Object);
Assert.NotNull(svc.Configurations);
}
[Fact(DisplayName = "CreateConfigDirectoryIfNotExist creates directory")]
public void CreateConfigDirectoryIfNotExist_CreateDirectory()
{
- var svc = new ConfigurationService(_logger.Object, _fileSystem.Object, _embeddedResource.Object);
+ var svc = new ConfigurationService(_logger.Object, _fileSystem.Object, _embeddedResource.Object, _configurationOptionAccessor.Object, _nLogConfigurationOptionAccessor.Object);
_fileSystem.Setup(p => p.Directory.Exists(It.IsAny())).Returns(false);
svc.CreateConfigDirectoryIfNotExist();
@@ -66,7 +72,7 @@ public void CreateConfigDirectoryIfNotExist_CreateDirectory()
[Fact(DisplayName = "CreateConfigDirectoryIfNotExist skips creating directory")]
public void CreateConfigDirectoryIfNotExist_SkipsCreation()
{
- var svc = new ConfigurationService(_logger.Object, _fileSystem.Object, _embeddedResource.Object);
+ var svc = new ConfigurationService(_logger.Object, _fileSystem.Object, _embeddedResource.Object, _configurationOptionAccessor.Object, _nLogConfigurationOptionAccessor.Object);
_fileSystem.Setup(p => p.Directory.Exists(It.IsAny())).Returns(true);
svc.CreateConfigDirectoryIfNotExist();
@@ -77,7 +83,7 @@ public void CreateConfigDirectoryIfNotExist_SkipsCreation()
[Fact(DisplayName = "IsInitialized")]
public void IsInitialized()
{
- var svc = new ConfigurationService(_logger.Object, _fileSystem.Object, _embeddedResource.Object);
+ var svc = new ConfigurationService(_logger.Object, _fileSystem.Object, _embeddedResource.Object, _configurationOptionAccessor.Object, _nLogConfigurationOptionAccessor.Object);
_fileSystem.Setup(p => p.Directory.Exists(It.IsAny())).Returns(true);
_fileSystem.Setup(p => p.File.Exists(It.IsAny())).Returns(true);
@@ -89,7 +95,7 @@ public void IsInitialized()
[Fact(DisplayName = "IsConfigExists")]
public void ConfigurationExists()
{
- var svc = new ConfigurationService(_logger.Object, _fileSystem.Object, _embeddedResource.Object);
+ var svc = new ConfigurationService(_logger.Object, _fileSystem.Object, _embeddedResource.Object, _configurationOptionAccessor.Object, _nLogConfigurationOptionAccessor.Object);
_fileSystem.Setup(p => p.File.Exists(It.IsAny())).Returns(true);
Assert.True(svc.IsConfigExists);
@@ -102,27 +108,33 @@ public async Task Initialize_ShallThrowWhenConfigReousrceIsMissing()
{
_embeddedResource.Setup(p => p.GetManifestResourceStream(It.IsAny())).Returns(default(Stream));
- var svc = new ConfigurationService(_logger.Object, _fileSystem.Object, _embeddedResource.Object);
+ var svc = new ConfigurationService(_logger.Object, _fileSystem.Object, _embeddedResource.Object, _configurationOptionAccessor.Object, _nLogConfigurationOptionAccessor.Object);
await Assert.ThrowsAsync(async () => await svc.Initialize(CancellationToken.None));
}
- [Fact(DisplayName = "Initialize creates the config file")]
- public async Task Initialize_CreatesTheConfigFile()
+ [Fact(DisplayName = "Initialize creates the config files")]
+ public async Task Initialize_CreatesTheConfigFiles()
{
var fileSystem = new MockFileSystem();
var testString = "hello world";
- var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(testString));
+ var appConfigMemoryStream = new MemoryStream(Encoding.UTF8.GetBytes(testString));
+ var nLogConfigMemoryStream = new MemoryStream(Encoding.UTF8.GetBytes(testString));
var mockSteam = new Mock();
- _embeddedResource.Setup(p => p.GetManifestResourceStream(It.IsAny())).Returns(memoryStream);
+ _embeddedResource.Setup(p => p.GetManifestResourceStream(It.Is(p => p == Common.AppSettingsResourceName))).Returns(appConfigMemoryStream);
+ _embeddedResource.Setup(p => p.GetManifestResourceStream(It.Is(p => p == Common.NLogConfigResourceName))).Returns(nLogConfigMemoryStream);
- var svc = new ConfigurationService(_logger.Object, fileSystem, _embeddedResource.Object);
+ var svc = new ConfigurationService(_logger.Object, fileSystem, _embeddedResource.Object, _configurationOptionAccessor.Object, _nLogConfigurationOptionAccessor.Object);
await svc.Initialize(CancellationToken.None);
_embeddedResource.Verify(p => p.GetManifestResourceStream(Common.AppSettingsResourceName), Times.Once());
+ _embeddedResource.Verify(p => p.GetManifestResourceStream(Common.NLogConfigResourceName), Times.Once());
var bytesWritten = await fileSystem.File.ReadAllBytesAsync(Common.ConfigFilePath).ConfigureAwait(false);
Assert.Equal(testString, Encoding.UTF8.GetString(bytesWritten));
+
+ bytesWritten = await fileSystem.File.ReadAllBytesAsync(Common.NLogConfigFilePath).ConfigureAwait(false);
+ Assert.Equal(testString, Encoding.UTF8.GetString(bytesWritten));
}
}
}
diff --git a/src/CLI/Test/DockerRunnerTest.cs b/src/CLI/Test/DockerRunnerTest.cs
index 2ecb446d5..b992bb6d2 100644
--- a/src/CLI/Test/DockerRunnerTest.cs
+++ b/src/CLI/Test/DockerRunnerTest.cs
@@ -163,7 +163,7 @@ public async Task StartApplication()
_configurationService.SetupGet(p => p.Configurations.HostLogsStorageMount).Returns("/logs");
_configurationService.SetupGet(p => p.Configurations.HostPlugInsStorageMount).Returns("/plug-ins");
_configurationService.SetupGet(p => p.Configurations.TempStoragePath).Returns("/tempdata");
- _configurationService.SetupGet(p => p.Configurations.LogStoragePath).Returns("/templogs");
+ _configurationService.SetupGet(p => p.NLogConfigurations.LogStoragePath).Returns("/templogs");
Assert.True(await runner.StartApplication(image, CancellationToken.None));
Assert.False(await runner.StartApplication(image, CancellationToken.None));
diff --git a/src/CLI/Test/NLogConfigurationOptionAccessorTest.cs b/src/CLI/Test/NLogConfigurationOptionAccessorTest.cs
new file mode 100644
index 000000000..469fb9f6f
--- /dev/null
+++ b/src/CLI/Test/NLogConfigurationOptionAccessorTest.cs
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2021-2023 MONAI Consortium
+ *
+ * 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.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.IO.Abstractions;
+using System.IO.Abstractions.TestingHelpers;
+using Monai.Deploy.InformaticsGateway.CLI.Services;
+using Xunit;
+
+namespace Monai.Deploy.InformaticsGateway.CLI.Test
+{
+ public class NLogConfigurationOptionAccessorTest
+ {
+ private readonly IFileSystem _fileSystem;
+
+ public NLogConfigurationOptionAccessorTest()
+ {
+ }
+
+ [Fact(DisplayName = "NLogConfigurationOptionAccessor Constructor")]
+ public void DockerRunner_Constructor()
+ {
+ Assert.Throws(() => new NLogConfigurationOptionAccessor(null));
+ }
+
+
+ [Fact]
+ public void DicomListeningPort_Get_ReturnsValue()
+ {
+ var fileSystem = SetupFileSystem();
+ var configurationOptionAccessor = new NLogConfigurationOptionAccessor(fileSystem);
+
+ Assert.Equal($"{Common.ContainerApplicationRootPath}/logs/", configurationOptionAccessor.LogStoragePath);
+ }
+
+ private IFileSystem SetupFileSystem()
+ {
+ return new MockFileSystem(new Dictionary
+ {
+ {Common.NLogConfigFilePath, new MockFileData("\r\n \r\n") }
+ });
+ }
+ }
+}
diff --git a/src/CLI/Test/ProgramTest.cs b/src/CLI/Test/ProgramTest.cs
index 82f8761f8..8ef0bc856 100644
--- a/src/CLI/Test/ProgramTest.cs
+++ b/src/CLI/Test/ProgramTest.cs
@@ -25,7 +25,7 @@ public class ProgramTest
public void Startup_RunsProperly()
{
var host = Program.BuildParser();
-
+
Assert.NotNull(host);
}
}