From 566fc7e1453ef7e852a269229fae12aab37071d5 Mon Sep 17 00:00:00 2001 From: Buddhika Chathuranga Date: Wed, 12 Aug 2020 13:55:52 +0530 Subject: [PATCH] Use stong types instead object to manage extension confiuration with YAML --- .../Configuration/DefaultSettings.cs | 2 +- .../Configuration/IWinSWConfiguration.cs | 2 +- .../Configuration/YamlConfiguration.cs | 21 +++----- .../YamlExtensionConfiguration.cs | 51 +++++++++++++++++++ .../Extensions/AbstractWinSWExtension.cs | 2 +- .../WinSWCore/Extensions/IWinSWExtension.cs | 4 +- .../Extensions/WinSWExtensionDescriptor.cs | 19 +++---- .../Extensions/WinSWExtensionManager.cs | 27 +++------- src/Core/WinSWCore/ServiceDescriptor.cs | 2 +- .../RunawayProcessKillerExtension.cs | 8 +-- .../SharedDirectoryMapper.cs | 15 ++---- 11 files changed, 85 insertions(+), 68 deletions(-) create mode 100644 src/Core/WinSWCore/Configuration/YamlExtensionConfiguration.cs diff --git a/src/Core/WinSWCore/Configuration/DefaultSettings.cs b/src/Core/WinSWCore/Configuration/DefaultSettings.cs index d5c94bb..6c6de51 100644 --- a/src/Core/WinSWCore/Configuration/DefaultSettings.cs +++ b/src/Core/WinSWCore/Configuration/DefaultSettings.cs @@ -135,7 +135,7 @@ namespace WinSW.Configuration // Extensions public XmlNode? ExtensionsConfiguration => null; - public object? YamlExtensionsConfiguration => null; + public List? YamlExtensionsConfiguration => new List(0); public string BaseName { diff --git a/src/Core/WinSWCore/Configuration/IWinSWConfiguration.cs b/src/Core/WinSWCore/Configuration/IWinSWConfiguration.cs index 61d1493..7c6080f 100644 --- a/src/Core/WinSWCore/Configuration/IWinSWConfiguration.cs +++ b/src/Core/WinSWCore/Configuration/IWinSWConfiguration.cs @@ -76,7 +76,7 @@ namespace WinSW.Configuration // Extensions XmlNode? ExtensionsConfiguration { get; } - object? YamlExtensionsConfiguration { get; } + List? YamlExtensionsConfiguration { get; } List ExtensionIds { get; } diff --git a/src/Core/WinSWCore/Configuration/YamlConfiguration.cs b/src/Core/WinSWCore/Configuration/YamlConfiguration.cs index e3e20ba..976a648 100644 --- a/src/Core/WinSWCore/Configuration/YamlConfiguration.cs +++ b/src/Core/WinSWCore/Configuration/YamlConfiguration.cs @@ -638,33 +638,26 @@ namespace WinSW.Configuration public string LogMode => this.Log.Mode is null ? this.Defaults.LogMode : this.Log.Mode; - // TODO - Extensions public XmlNode? ExtensionsConfiguration => null; // YAML Extension [YamlMember(Alias = "extensions")] - public object? YamlExtensionsConfiguration { get; set; } + public List? YamlExtensionsConfiguration { get; set; } public List ExtensionIds { get { - var result = new List(); - - if (!(this.YamlExtensionsConfiguration is List extensions)) + if (this.YamlExtensionsConfiguration is null) { - return result; + return new List(0); } - foreach (var item in extensions) - { - if (!(item is Dictionary dict)) - { - continue; - } + var result = new List(); - var id = (string)dict["id"]; - result.Add(id); + foreach (var item in this.YamlExtensionsConfiguration) + { + result.Add(item.GetId()); } return result; diff --git a/src/Core/WinSWCore/Configuration/YamlExtensionConfiguration.cs b/src/Core/WinSWCore/Configuration/YamlExtensionConfiguration.cs new file mode 100644 index 0000000..cfc4a6f --- /dev/null +++ b/src/Core/WinSWCore/Configuration/YamlExtensionConfiguration.cs @@ -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? 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 GetSettings() + { + if (this.Settings is null) + { + throw new InvalidDataException("Extension settings not found"); + } + + return this.Settings; + } + } +} diff --git a/src/Core/WinSWCore/Extensions/AbstractWinSWExtension.cs b/src/Core/WinSWCore/Extensions/AbstractWinSWExtension.cs index 58132b3..141f2d2 100644 --- a/src/Core/WinSWCore/Extensions/AbstractWinSWExtension.cs +++ b/src/Core/WinSWCore/Extensions/AbstractWinSWExtension.cs @@ -16,7 +16,7 @@ namespace WinSW.Extensions // Do nothing } - public virtual void Configure(IWinSWConfiguration descriptor, object yamlObject) + public virtual void Configure(IWinSWConfiguration descriptor, YamlExtensionConfiguration config) { // Do nothing } diff --git a/src/Core/WinSWCore/Extensions/IWinSWExtension.cs b/src/Core/WinSWCore/Extensions/IWinSWExtension.cs index dabd13b..708968f 100644 --- a/src/Core/WinSWCore/Extensions/IWinSWExtension.cs +++ b/src/Core/WinSWCore/Extensions/IWinSWExtension.cs @@ -34,8 +34,8 @@ namespace WinSW.Extensions /// Configure the extension from Yaml configuration /// /// Yaml Service Descptor - /// Configuration Node - void Configure(IWinSWConfiguration descriptor, object yamlObject); + /// Configuration Node + void Configure(IWinSWConfiguration descriptor, YamlExtensionConfiguration config); /// /// Start handler. Called during startup of the service before the child process. diff --git a/src/Core/WinSWCore/Extensions/WinSWExtensionDescriptor.cs b/src/Core/WinSWCore/Extensions/WinSWExtensionDescriptor.cs index 383857b..838555b 100644 --- a/src/Core/WinSWCore/Extensions/WinSWExtensionDescriptor.cs +++ b/src/Core/WinSWCore/Extensions/WinSWExtensionDescriptor.cs @@ -1,7 +1,5 @@ -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Xml; +using System.Xml; +using WinSW.Configuration; using WinSW.Util; namespace WinSW.Extensions @@ -44,16 +42,11 @@ namespace WinSW.Extensions return new WinSWExtensionDescriptor(id, className, enabled); } - public static WinSWExtensionDescriptor FromYaml(object node) + public static WinSWExtensionDescriptor FromYaml(YamlExtensionConfiguration config) { - if (!(node is Dictionary config)) - { - throw new InvalidDataException("Cannot get the configuration entry"); - } - - bool enabled = ConfigHelper.YamlBoolParse((string)config["enabled"]); - string className = (string)config["classname"]; - string id = (string)config["id"]; + bool enabled = config.Enabled; + string className = config.GetClassName(); + string id = config.GetId(); return new WinSWExtensionDescriptor(id, className, enabled); } diff --git a/src/Core/WinSWCore/Extensions/WinSWExtensionManager.cs b/src/Core/WinSWCore/Extensions/WinSWExtensionManager.cs index c6809fa..d440950 100644 --- a/src/Core/WinSWCore/Extensions/WinSWExtensionManager.cs +++ b/src/Core/WinSWCore/Extensions/WinSWExtensionManager.cs @@ -160,7 +160,7 @@ namespace WinSW.Extensions catch (Exception ex) { // Consider any unexpected exception as fatal 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); @@ -174,19 +174,14 @@ namespace WinSW.Extensions private void LoadExtensionFromYaml(string id) { - var extensionConfigList = this.ServiceDescriptor.YamlExtensionsConfiguration as List; + var extensionConfigList = this.ServiceDescriptor.YamlExtensionsConfiguration; if (extensionConfigList is null) { throw new ExtensionException(id, "Cannot get the configuration entry"); } - object? configNode = GetYamlonfigById(extensionConfigList, id); - - if (configNode is null) - { - throw new ExtensionException(id, "Cannot get the configuration entry"); - } + var configNode = GetYamlonfigById(extensionConfigList, id); var descriptor = WinSWExtensionDescriptor.FromYaml(configNode); @@ -195,20 +190,14 @@ namespace WinSW.Extensions IWinSWExtension extension = this.CreateExtensionInstance(descriptor.Id, descriptor.ClassName); extension.Descriptor = descriptor; - if (!(configNode is Dictionary dict)) - { - // TODO : Replace with exntension exception - throw new InvalidDataException("Error in config node"); - } - try { - extension.Configure(this.ServiceDescriptor, dict["settings"]); + extension.Configure(this.ServiceDescriptor, configNode); } catch (Exception ex) { // Consider any unexpected exception as fatal 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); @@ -219,17 +208,17 @@ namespace WinSW.Extensions Log.Warn("Extension is disabled: " + id); } - object? GetYamlonfigById(List configs, string id) + YamlExtensionConfiguration GetYamlonfigById(List configs, string id) { foreach (var item in configs) { - if (item is Dictionary config && config["id"].Equals(id)) + if (item.GetId().Equals(id)) { return item; } } - return null; + throw new ExtensionException(id, $@"Can't find extension with id: ""{id}"" "); } } diff --git a/src/Core/WinSWCore/ServiceDescriptor.cs b/src/Core/WinSWCore/ServiceDescriptor.cs index b088987..8782307 100644 --- a/src/Core/WinSWCore/ServiceDescriptor.cs +++ b/src/Core/WinSWCore/ServiceDescriptor.cs @@ -704,6 +704,6 @@ namespace WinSW return environment; } - public object? YamlExtensionsConfiguration => null; + public List? YamlExtensionsConfiguration => Defaults.YamlExtensionsConfiguration; } } diff --git a/src/Plugins/RunawayProcessKiller/RunawayProcessKillerExtension.cs b/src/Plugins/RunawayProcessKiller/RunawayProcessKillerExtension.cs index 59e6761..13a82f5 100644 --- a/src/Plugins/RunawayProcessKiller/RunawayProcessKillerExtension.cs +++ b/src/Plugins/RunawayProcessKiller/RunawayProcessKillerExtension.cs @@ -194,13 +194,9 @@ namespace WinSW.Plugins.RunawayProcessKiller 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 dict)) - { - // TODO : throw ExtensionException - throw new InvalidDataException("Cann't configure"); - } + var dict = config.GetSettings(); this.Pidfile = (string)dict["pidfile"]; this.StopTimeout = TimeSpan.FromMilliseconds(int.Parse((string)dict["stopTimeOut"])); diff --git a/src/Plugins/SharedDirectoryMapper/SharedDirectoryMapper.cs b/src/Plugins/SharedDirectoryMapper/SharedDirectoryMapper.cs index 35aa45b..f638e5c 100644 --- a/src/Plugins/SharedDirectoryMapper/SharedDirectoryMapper.cs +++ b/src/Plugins/SharedDirectoryMapper/SharedDirectoryMapper.cs @@ -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 dict)) - { - // TODO : throw ExtensionException - throw new InvalidDataException("Conn't configure"); - } + var dict = config.GetSettings(); var mappingNode = dict["mapping"]; if (!(mappingNode is List mappings)) { - // TODO : throw ExtensionException - throw new InvalidDataException("Conn't configure"); + throw new InvalidDataException("SharedDirectoryMapper mapping should be a list"); } foreach (var map in mappings) { - var config = SharedDirectoryMapperConfig.FromYaml(map); - this._entries.Add(config); + var mapConfig = SharedDirectoryMapperConfig.FromYaml(map); + this._entries.Add(mapConfig); } }