Use stong types instead object to manage extension confiuration with YAML

pull/638/head
Buddhika Chathuranga 2020-08-12 13:55:52 +05:30 committed by NextTurn
parent 8013ab3d9d
commit 566fc7e145
No known key found for this signature in database
GPG Key ID: 17A0D50ADDE1A0C4
11 changed files with 85 additions and 68 deletions

View File

@ -135,7 +135,7 @@ namespace WinSW.Configuration
// Extensions // Extensions
public XmlNode? ExtensionsConfiguration => null; public XmlNode? ExtensionsConfiguration => null;
public object? YamlExtensionsConfiguration => null; public List<YamlExtensionConfiguration>? YamlExtensionsConfiguration => new List<YamlExtensionConfiguration>(0);
public string BaseName public string BaseName
{ {

View File

@ -76,7 +76,7 @@ namespace WinSW.Configuration
// Extensions // Extensions
XmlNode? ExtensionsConfiguration { get; } XmlNode? ExtensionsConfiguration { get; }
object? YamlExtensionsConfiguration { get; } List<YamlExtensionConfiguration>? YamlExtensionsConfiguration { get; }
List<string> ExtensionIds { get; } List<string> ExtensionIds { get; }

View File

@ -638,33 +638,26 @@ namespace WinSW.Configuration
public string LogMode => this.Log.Mode is null ? this.Defaults.LogMode : this.Log.Mode; public string LogMode => this.Log.Mode is null ? this.Defaults.LogMode : this.Log.Mode;
// TODO - Extensions
public XmlNode? ExtensionsConfiguration => null; public XmlNode? ExtensionsConfiguration => null;
// YAML Extension // YAML Extension
[YamlMember(Alias = "extensions")] [YamlMember(Alias = "extensions")]
public object? YamlExtensionsConfiguration { get; set; } public List<YamlExtensionConfiguration>? YamlExtensionsConfiguration { get; set; }
public List<string> ExtensionIds public List<string> ExtensionIds
{ {
get get
{ {
if (this.YamlExtensionsConfiguration is null)
{
return new List<string>(0);
}
var result = new List<string>(); var result = new List<string>();
if (!(this.YamlExtensionsConfiguration is List<object> extensions)) foreach (var item in this.YamlExtensionsConfiguration)
{ {
return result; result.Add(item.GetId());
}
foreach (var item in extensions)
{
if (!(item is Dictionary<object, object> dict))
{
continue;
}
var id = (string)dict["id"];
result.Add(id);
} }
return result; return result;

View File

@ -0,0 +1,51 @@
using System.Collections.Generic;
using System.IO;
using YamlDotNet.Serialization;
namespace WinSW.Configuration
{
public class YamlExtensionConfiguration
{
[YamlMember(Alias = "id")]
public string? ExtensionId { get; set; }
[YamlMember(Alias = "classname")]
public string? ExtensionClassName { get; set; }
[YamlMember(Alias = "enabled")]
public bool Enabled { get; set; }
[YamlMember(Alias = "settings")]
public Dictionary<object, object>? Settings { get; set; }
public string GetId()
{
if (this.ExtensionId is null)
{
throw new InvalidDataException("Extension Id can't be empty");
}
return this.ExtensionId;
}
public string GetClassName()
{
if (this.ExtensionClassName is null)
{
throw new InvalidDataException("Extension ClassName can't be empty");
}
return this.ExtensionClassName;
}
public Dictionary<object, object> GetSettings()
{
if (this.Settings is null)
{
throw new InvalidDataException("Extension settings not found");
}
return this.Settings;
}
}
}

View File

@ -16,7 +16,7 @@ namespace WinSW.Extensions
// Do nothing // Do nothing
} }
public virtual void Configure(IWinSWConfiguration descriptor, object yamlObject) public virtual void Configure(IWinSWConfiguration descriptor, YamlExtensionConfiguration config)
{ {
// Do nothing // Do nothing
} }

View File

@ -34,8 +34,8 @@ namespace WinSW.Extensions
/// Configure the extension from Yaml configuration /// Configure the extension from Yaml configuration
/// </summary> /// </summary>
/// <param name="descriptor">Yaml Service Descptor</param> /// <param name="descriptor">Yaml Service Descptor</param>
/// <param name="yamlObject">Configuration Node</param> /// <param name="config">Configuration Node</param>
void Configure(IWinSWConfiguration descriptor, object yamlObject); void Configure(IWinSWConfiguration descriptor, YamlExtensionConfiguration config);
/// <summary> /// <summary>
/// Start handler. Called during startup of the service before the child process. /// Start handler. Called during startup of the service before the child process.

View File

@ -1,7 +1,5 @@
using System.Collections.Generic; using System.Xml;
using System.Diagnostics; using WinSW.Configuration;
using System.IO;
using System.Xml;
using WinSW.Util; using WinSW.Util;
namespace WinSW.Extensions namespace WinSW.Extensions
@ -44,16 +42,11 @@ namespace WinSW.Extensions
return new WinSWExtensionDescriptor(id, className, enabled); return new WinSWExtensionDescriptor(id, className, enabled);
} }
public static WinSWExtensionDescriptor FromYaml(object node) public static WinSWExtensionDescriptor FromYaml(YamlExtensionConfiguration config)
{ {
if (!(node is Dictionary<object, object> config)) bool enabled = config.Enabled;
{ string className = config.GetClassName();
throw new InvalidDataException("Cannot get the configuration entry"); string id = config.GetId();
}
bool enabled = ConfigHelper.YamlBoolParse((string)config["enabled"]);
string className = (string)config["classname"];
string id = (string)config["id"];
return new WinSWExtensionDescriptor(id, className, enabled); return new WinSWExtensionDescriptor(id, className, enabled);
} }

View File

@ -160,7 +160,7 @@ namespace WinSW.Extensions
catch (Exception ex) catch (Exception ex)
{ // Consider any unexpected exception as fatal { // Consider any unexpected exception as fatal
Log.Fatal("Failed to configure the extension " + id, ex); Log.Fatal("Failed to configure the extension " + id, ex);
throw ex; throw new ExtensionException(id, "Failed to configure the extension");
} }
this.Extensions.Add(id, extension); this.Extensions.Add(id, extension);
@ -174,19 +174,14 @@ namespace WinSW.Extensions
private void LoadExtensionFromYaml(string id) private void LoadExtensionFromYaml(string id)
{ {
var extensionConfigList = this.ServiceDescriptor.YamlExtensionsConfiguration as List<object>; var extensionConfigList = this.ServiceDescriptor.YamlExtensionsConfiguration;
if (extensionConfigList is null) if (extensionConfigList is null)
{ {
throw new ExtensionException(id, "Cannot get the configuration entry"); throw new ExtensionException(id, "Cannot get the configuration entry");
} }
object? configNode = GetYamlonfigById(extensionConfigList, id); var configNode = GetYamlonfigById(extensionConfigList, id);
if (configNode is null)
{
throw new ExtensionException(id, "Cannot get the configuration entry");
}
var descriptor = WinSWExtensionDescriptor.FromYaml(configNode); var descriptor = WinSWExtensionDescriptor.FromYaml(configNode);
@ -195,20 +190,14 @@ namespace WinSW.Extensions
IWinSWExtension extension = this.CreateExtensionInstance(descriptor.Id, descriptor.ClassName); IWinSWExtension extension = this.CreateExtensionInstance(descriptor.Id, descriptor.ClassName);
extension.Descriptor = descriptor; extension.Descriptor = descriptor;
if (!(configNode is Dictionary<object, object> dict))
{
// TODO : Replace with exntension exception
throw new InvalidDataException("Error in config node");
}
try try
{ {
extension.Configure(this.ServiceDescriptor, dict["settings"]); extension.Configure(this.ServiceDescriptor, configNode);
} }
catch (Exception ex) catch (Exception ex)
{ // Consider any unexpected exception as fatal { // Consider any unexpected exception as fatal
Log.Fatal("Failed to configure the extension " + id, ex); Log.Fatal("Failed to configure the extension " + id, ex);
throw ex; throw new ExtensionException(id, "Failed to configure the extension");
} }
this.Extensions.Add(id, extension); this.Extensions.Add(id, extension);
@ -219,17 +208,17 @@ namespace WinSW.Extensions
Log.Warn("Extension is disabled: " + id); Log.Warn("Extension is disabled: " + id);
} }
object? GetYamlonfigById(List<object> configs, string id) YamlExtensionConfiguration GetYamlonfigById(List<YamlExtensionConfiguration> configs, string id)
{ {
foreach (var item in configs) foreach (var item in configs)
{ {
if (item is Dictionary<object, object> config && config["id"].Equals(id)) if (item.GetId().Equals(id))
{ {
return item; return item;
} }
} }
return null; throw new ExtensionException(id, $@"Can't find extension with id: ""{id}"" ");
} }
} }

View File

@ -704,6 +704,6 @@ namespace WinSW
return environment; return environment;
} }
public object? YamlExtensionsConfiguration => null; public List<YamlExtensionConfiguration>? YamlExtensionsConfiguration => Defaults.YamlExtensionsConfiguration;
} }
} }

View File

@ -194,13 +194,9 @@ namespace WinSW.Plugins.RunawayProcessKiller
this.CheckWinSWEnvironmentVariable = checkWinSWEnvironmentVariable is null ? true : bool.Parse(checkWinSWEnvironmentVariable); this.CheckWinSWEnvironmentVariable = checkWinSWEnvironmentVariable is null ? true : bool.Parse(checkWinSWEnvironmentVariable);
} }
public override void Configure(IWinSWConfiguration descriptor, object yamlObject) public override void Configure(IWinSWConfiguration descriptor, YamlExtensionConfiguration config)
{ {
if (!(yamlObject is Dictionary<object, object> dict)) var dict = config.GetSettings();
{
// TODO : throw ExtensionException
throw new InvalidDataException("Cann't configure");
}
this.Pidfile = (string)dict["pidfile"]; this.Pidfile = (string)dict["pidfile"];
this.StopTimeout = TimeSpan.FromMilliseconds(int.Parse((string)dict["stopTimeOut"])); this.StopTimeout = TimeSpan.FromMilliseconds(int.Parse((string)dict["stopTimeOut"]));

View File

@ -44,26 +44,21 @@ namespace WinSW.Plugins.SharedDirectoryMapper
} }
} }
public override void Configure(IWinSWConfiguration descriptor, object yamlObject) public override void Configure(IWinSWConfiguration descriptor, YamlExtensionConfiguration config)
{ {
if (!(yamlObject is Dictionary<object, object> dict)) var dict = config.GetSettings();
{
// TODO : throw ExtensionException
throw new InvalidDataException("Conn't configure");
}
var mappingNode = dict["mapping"]; var mappingNode = dict["mapping"];
if (!(mappingNode is List<object> mappings)) if (!(mappingNode is List<object> mappings))
{ {
// TODO : throw ExtensionException throw new InvalidDataException("SharedDirectoryMapper mapping should be a list");
throw new InvalidDataException("Conn't configure");
} }
foreach (var map in mappings) foreach (var map in mappings)
{ {
var config = SharedDirectoryMapperConfig.FromYaml(map); var mapConfig = SharedDirectoryMapperConfig.FromYaml(map);
this._entries.Add(config); this._entries.Add(mapConfig);
} }
} }