From 9a3ffdd6d3ce1ccbdf2d51c81d53d95f36be8480 Mon Sep 17 00:00:00 2001 From: Dennis Beuchler Date: Thu, 30 Sep 2021 12:49:55 +0200 Subject: [PATCH] Added support for internal controllers --- .../CustomControllerFeatureProvider.cs | 45 +++++++++++++++++++ src/Moryx.Runtime.Kestrel/Startup.cs | 4 +- .../Common/Endpoint/CommonMaintenance.cs | 10 ++--- .../Plugins/Common/HostHelper.cs | 7 +-- .../Databases/Endpoint/DatabaseMaintenance.cs | 18 +------- .../Logging/Endpoint/LogMaintenance.cs | 16 ++----- .../Plugins/Logging/ILoggingAppender.cs | 2 +- .../Modules/Endpoint/ModuleMaintenance.cs | 17 +------ .../Controllers/TestController.cs | 2 +- 9 files changed, 65 insertions(+), 56 deletions(-) create mode 100644 src/Moryx.Runtime.Kestrel/CustomControllerFeatureProvider.cs diff --git a/src/Moryx.Runtime.Kestrel/CustomControllerFeatureProvider.cs b/src/Moryx.Runtime.Kestrel/CustomControllerFeatureProvider.cs new file mode 100644 index 000000000..1a53af754 --- /dev/null +++ b/src/Moryx.Runtime.Kestrel/CustomControllerFeatureProvider.cs @@ -0,0 +1,45 @@ +using System; +using System.Reflection; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Controllers; + +namespace Moryx.Runtime.Kestrel +{ + /// + /// Custom override to allow internal containers and only controllers which are inherit + /// + internal class CustomControllerFeatureProvider : ControllerFeatureProvider + { + private const string ControllerTypeNameSuffix = "Controller"; + + protected override bool IsController(TypeInfo typeInfo) + { + // Ignore interfaces + if (!typeInfo.IsClass) + return false; + + // Ignore abstracts + if (typeInfo.IsAbstract) + return false; + + // Ignore generics + if (typeInfo.ContainsGenericParameters) + return false; + + // Ignore none controllers + if (typeInfo.IsDefined(typeof(NonControllerAttribute))) + return false; + + // Controller must end with suffix OR must have the controller attribute + if (!typeInfo.Name.EndsWith(ControllerTypeNameSuffix, StringComparison.OrdinalIgnoreCase) && + !typeInfo.IsDefined(typeof(ControllerAttribute))) + return false; + + // Allow only Controllers + if (!typeof(Controller).IsAssignableFrom(typeInfo)) + return false; + + return true; + } + } +} \ No newline at end of file diff --git a/src/Moryx.Runtime.Kestrel/Startup.cs b/src/Moryx.Runtime.Kestrel/Startup.cs index 23c8dacb1..9f4e86265 100644 --- a/src/Moryx.Runtime.Kestrel/Startup.cs +++ b/src/Moryx.Runtime.Kestrel/Startup.cs @@ -26,7 +26,7 @@ public void ConfigureServices(IServiceCollection services) }) .ConfigureApplicationPartManager(manager => { - // Find all Controllers and add them to the local container + // Find all assemblies with defined controllers and add them to the application parts var assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (var assembly in assemblies.Where(a => manager.ApplicationParts.All(p => p.Name != a.GetName().Name))) @@ -36,6 +36,8 @@ public void ConfigureServices(IServiceCollection services) manager.ApplicationParts.Add(new AssemblyPart(assembly)); } } + + manager.FeatureProviders.Add(new CustomControllerFeatureProvider()); }) .AddControllersAsServices(); diff --git a/src/Moryx.Runtime.Maintenance/Plugins/Common/Endpoint/CommonMaintenance.cs b/src/Moryx.Runtime.Maintenance/Plugins/Common/Endpoint/CommonMaintenance.cs index b19b330ea..ca8c1c6da 100644 --- a/src/Moryx.Runtime.Maintenance/Plugins/Common/Endpoint/CommonMaintenance.cs +++ b/src/Moryx.Runtime.Maintenance/Plugins/Common/Endpoint/CommonMaintenance.cs @@ -5,6 +5,7 @@ using System.Diagnostics; using System.Globalization; using Moryx.Container; + #if USE_WCF using System.ServiceModel; #else @@ -20,16 +21,15 @@ namespace Moryx.Runtime.Maintenance.Plugins.Common [Plugin(LifeCycle.Transient, typeof(ICommonMaintenance))] #if USE_WCF [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, IncludeExceptionDetailInFaults = true)] - public class CommonMaintenance : ICommonMaintenance + internal class CommonMaintenance : ICommonMaintenance #else [ApiController, Route(Endpoint), Produces("application/json")] [Endpoint(Name = nameof(ICommonMaintenance), Version = "3.0.0")] - public class CommonMaintenance : Controller, ICommonMaintenance + internal class CommonMaintenance : Controller, ICommonMaintenance #endif { internal const string Endpoint = "common"; - /// #if !USE_WCF [HttpGet("time")] #endif @@ -41,7 +41,6 @@ public ServerTimeResponse GetServerTime() }; } - /// #if !USE_WCF [HttpGet("info/application")] #endif @@ -57,7 +56,6 @@ public ApplicationInformationResponse GetApplicationInfo() }; } - /// #if !USE_WCF [HttpGet("info/system")] #endif @@ -71,7 +69,6 @@ public HostInformationResponse GetHostInfo() }; } - /// #if !USE_WCF [HttpGet("info/system/load")] #endif @@ -87,7 +84,6 @@ public SystemLoadResponse GetSystemLoad() }; } - /// #if !USE_WCF [HttpGet("info/application/load")] #endif diff --git a/src/Moryx.Runtime.Maintenance/Plugins/Common/HostHelper.cs b/src/Moryx.Runtime.Maintenance/Plugins/Common/HostHelper.cs index 5287b9a2d..f0a15e82f 100644 --- a/src/Moryx.Runtime.Maintenance/Plugins/Common/HostHelper.cs +++ b/src/Moryx.Runtime.Maintenance/Plugins/Common/HostHelper.cs @@ -25,7 +25,7 @@ public static ulong PhysicalMemory() var moc = mc.GetInstances(); return (from ManagementObject item in moc select Convert.ToUInt64(item.Properties["TotalPhysicalMemory"].Value)).FirstOrDefault(); #else - return 0; // TODO: Remove in Core 4 + return 42; // TODO: Replace in Core 4 #endif } @@ -40,7 +40,7 @@ public static ulong FreePhysicalMemory() var moc = mc.GetInstances(); return (from ManagementObject item in moc select Convert.ToUInt64(item.Properties["FreePhysicalMemory"].Value) * 1024).FirstOrDefault(); #else - return 0; // TODO: Remove in Core 4 + return 32; // TODO: Replace in Core 4 #endif } @@ -58,7 +58,8 @@ public static ulong ProcessorTimePercentage(string processName = "_Total") return (ulong)processorTime; #else - return 0; // TODO: Remove in Core 4 + + return 0; // TODO: Replace in Core 4 #endif } } diff --git a/src/Moryx.Runtime.Maintenance/Plugins/Databases/Endpoint/DatabaseMaintenance.cs b/src/Moryx.Runtime.Maintenance/Plugins/Databases/Endpoint/DatabaseMaintenance.cs index 763d636ae..a45db4e24 100644 --- a/src/Moryx.Runtime.Maintenance/Plugins/Databases/Endpoint/DatabaseMaintenance.cs +++ b/src/Moryx.Runtime.Maintenance/Plugins/Databases/Endpoint/DatabaseMaintenance.cs @@ -17,18 +17,17 @@ using Moryx.Communication.Endpoints; #endif - namespace Moryx.Runtime.Maintenance.Plugins.Databases { [Plugin(LifeCycle.Transient, typeof(IDatabaseMaintenance))] #if USE_WCF [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, IncludeExceptionDetailInFaults = true)] - public class DatabaseMaintenance : IDatabaseMaintenance + internal class DatabaseMaintenance : IDatabaseMaintenance #else [ApiController, Route(Endpoint), Produces("application/json")] [Endpoint(Name = nameof(IDatabaseMaintenance), Version = "3.0.0")] - public class DatabaseMaintenance : Controller, IDatabaseMaintenance + internal class DatabaseMaintenance : Controller, IDatabaseMaintenance #endif { internal const string Endpoint = "databases"; @@ -59,7 +58,6 @@ public class DatabaseMaintenance : Controller, IDatabaseMaintenance #endregion - /// #if !USE_WCF [HttpGet] #endif @@ -68,7 +66,6 @@ public DataModel[] GetAll() return DbContextManager.Contexts.Select(Convert).ToArray(); } - /// #if !USE_WCF [HttpGet("model/{targetModel}")] #endif @@ -77,7 +74,6 @@ public DataModel GetModel(string targetModel) return Convert(DbContextManager.Contexts.FirstOrDefault(context => TargetModelName(context) == targetModel)); } - /// #if !USE_WCF [HttpPost("model/{targetModel}/config")] #endif @@ -93,7 +89,6 @@ public void SetDatabaseConfig(string targetModel, DatabaseConfigModel config) } - /// #if !USE_WCF [HttpPost("model/{targetModel}/config/test")] #endif @@ -110,7 +105,6 @@ public TestConnectionResponse TestDatabaseConfig(string targetModel, DatabaseCon return new TestConnectionResponse { Result = result }; } - /// #if !USE_WCF [HttpPost("createall")] #endif @@ -120,7 +114,6 @@ public InvocationResponse CreateAll() return string.IsNullOrEmpty(bulkResult) ? new InvocationResponse() : new InvocationResponse(bulkResult); } - /// #if !USE_WCF [HttpPost("model/{targetModel}/create")] #endif @@ -146,7 +139,6 @@ public InvocationResponse CreateDatabase(string targetModel, DatabaseConfigModel } } - /// #if !USE_WCF [HttpDelete("/")] #endif @@ -156,7 +148,6 @@ public InvocationResponse EraseAll() return string.IsNullOrEmpty(bulkResult) ? new InvocationResponse() : new InvocationResponse(bulkResult); } - /// #if !USE_WCF [HttpDelete("model/{targetModel}")] #endif @@ -180,7 +171,6 @@ public InvocationResponse EraseDatabase(string targetModel, DatabaseConfigModel } } - /// #if !USE_WCF [HttpPost("model/{targetModel}/dump")] #endif @@ -201,7 +191,6 @@ public InvocationResponse DumpDatabase(string targetModel, DatabaseConfigModel c return new InvocationResponse(); } - /// #if !USE_WCF [HttpPost("model/{targetModel}/restore")] #endif @@ -218,7 +207,6 @@ public InvocationResponse RestoreDatabase(string targetModel, RestoreDatabaseReq return new InvocationResponse(); } - /// #if !USE_WCF [HttpPost("model/{targetModel}/{migrationName}/migrate")] #endif @@ -232,7 +220,6 @@ public DatabaseUpdateSummary MigrateDatabaseModel(string targetModel, string mig return targetConfigurator.MigrateDatabase(config, migrationName); } - /// #if !USE_WCF [HttpPost("model/{targetModel}/rollback")] #endif @@ -248,7 +235,6 @@ public InvocationResponse RollbackDatabase(string targetModel, DatabaseConfigMod return rollbackResult ? new InvocationResponse() : new InvocationResponse("Error while rollback!"); } - /// #if !USE_WCF [HttpPost("model/{targetModel}/setup")] #endif diff --git a/src/Moryx.Runtime.Maintenance/Plugins/Logging/Endpoint/LogMaintenance.cs b/src/Moryx.Runtime.Maintenance/Plugins/Logging/Endpoint/LogMaintenance.cs index 671038c89..15d222948 100644 --- a/src/Moryx.Runtime.Maintenance/Plugins/Logging/Endpoint/LogMaintenance.cs +++ b/src/Moryx.Runtime.Maintenance/Plugins/Logging/Endpoint/LogMaintenance.cs @@ -19,11 +19,11 @@ namespace Moryx.Runtime.Maintenance.Plugins.Logging [Plugin(LifeCycle.Transient, typeof(ILogMaintenance))] #if USE_WCF [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, IncludeExceptionDetailInFaults = true)] - public class LogMaintenance : ILogMaintenance, ILoggingComponent + internal class LogMaintenance : ILogMaintenance, ILoggingComponent #else [ApiController, Route(Endpoint), Produces("application/json")] [Endpoint(Name = nameof(ILogMaintenance), Version = "3.0.0")] - public class LogMaintenance : Controller, ILogMaintenance, ILoggingComponent + internal class LogMaintenance : Controller, ILogMaintenance, ILoggingComponent #endif { internal const string Endpoint = "loggers"; @@ -34,15 +34,11 @@ public class LogMaintenance : Controller, ILogMaintenance, ILoggingComponent public ILoggingAppender LoggingAppender { get; set; } - /// - /// Logger of this component - /// - [UseChild("WcfService")] + [UseChild("LogMaintenance")] public IModuleLogger Logger { get; set; } #endregion - /// #if !USE_WCF [HttpGet] #endif @@ -51,7 +47,6 @@ public LoggerModel[] GetAllLoggers() return LoggerManagement.Select(Convert).ToArray(); } - /// #if !USE_WCF [HttpPut("logger/{loggerName}/loglevel")] #endif @@ -61,7 +56,6 @@ public InvocationResponse SetLogLevel(string loggerName, SetLogLevelRequest requ return new InvocationResponse(); } - /// #if !USE_WCF [HttpPost("appender")] #endif @@ -73,7 +67,6 @@ public AddAppenderResponse AddAppender(AddAppenderRequest request) }; } - /// #if !USE_WCF [HttpGet("appender/{appenderId}")] #endif @@ -87,7 +80,7 @@ public LogMessageModel[] GetMessages(string appenderId) // ReSharper disable once PossibleNullReferenceException ctx.OutgoingResponse.StatusCode = HttpStatusCode.NotFound; #else - Response.StatusCode = (int)HttpStatusCode.InternalServerError; + Response.StatusCode = (int)HttpStatusCode.InternalServerError; #endif return new LogMessageModel[0]; } @@ -96,7 +89,6 @@ public LogMessageModel[] GetMessages(string appenderId) return messages.ToArray(); } - /// #if !USE_WCF [HttpDelete("appender/{appenderId}")] #endif diff --git a/src/Moryx.Runtime.Maintenance/Plugins/Logging/ILoggingAppender.cs b/src/Moryx.Runtime.Maintenance/Plugins/Logging/ILoggingAppender.cs index 0341d6966..0c8c085ea 100644 --- a/src/Moryx.Runtime.Maintenance/Plugins/Logging/ILoggingAppender.cs +++ b/src/Moryx.Runtime.Maintenance/Plugins/Logging/ILoggingAppender.cs @@ -6,7 +6,7 @@ namespace Moryx.Runtime.Maintenance.Plugins.Logging { - public interface ILoggingAppender : IMaintenancePlugin + internal interface ILoggingAppender : IMaintenancePlugin { /// /// Add a remote appender to the logging stream diff --git a/src/Moryx.Runtime.Maintenance/Plugins/Modules/Endpoint/ModuleMaintenance.cs b/src/Moryx.Runtime.Maintenance/Plugins/Modules/Endpoint/ModuleMaintenance.cs index 3deabbeb7..716985f83 100644 --- a/src/Moryx.Runtime.Maintenance/Plugins/Modules/Endpoint/ModuleMaintenance.cs +++ b/src/Moryx.Runtime.Maintenance/Plugins/Modules/Endpoint/ModuleMaintenance.cs @@ -30,11 +30,11 @@ namespace Moryx.Runtime.Maintenance.Plugins.Modules [Plugin(LifeCycle.Transient, typeof(IModuleMaintenance))] #if USE_WCF [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, IncludeExceptionDetailInFaults = true)] - public class ModuleMaintenance : IModuleMaintenance, ILoggingComponent + internal class ModuleMaintenance : IModuleMaintenance, ILoggingComponent #else [ApiController, Route(Endpoint), Produces("application/json")] [Endpoint(Name = nameof(IModuleMaintenance), Version = "3.0.0")] - public class ModuleMaintenance : Controller, IModuleMaintenance, ILoggingComponent + internal class ModuleMaintenance : Controller, IModuleMaintenance, ILoggingComponent #endif { internal const string Endpoint = "modules"; @@ -52,7 +52,6 @@ public class ModuleMaintenance : Controller, IModuleMaintenance, ILoggingCompone #endregion - /// #if !USE_WCF [HttpGet("dependencies")] #endif @@ -61,7 +60,6 @@ public DependencyEvaluation GetDependencyEvaluation() return new DependencyEvaluation(ModuleManager.DependencyTree); } - /// #if !USE_WCF [HttpGet] #endif @@ -96,7 +94,6 @@ public ServerModuleModel[] GetAll() return models.ToArray(); } - /// #if !USE_WCF [HttpGet("module/{moduleName}/healthstate")] #endif @@ -119,7 +116,6 @@ public ServerModuleState HealthState(string moduleName) return ServerModuleState.Failure; } - /// #if !USE_WCF [HttpGet("module/{moduleName}/notifications")] #endif @@ -141,7 +137,6 @@ public NotificationModel[] Notifications(string moduleName) return new NotificationModel[0]; } - /// #if !USE_WCF [HttpPost("module/{moduleName}/start")] #endif @@ -151,7 +146,6 @@ public void Start(string moduleName) ModuleManager.StartModule(module); } - /// #if !USE_WCF [HttpPost("module/{moduleName}/stop")] #endif @@ -161,7 +155,6 @@ public void Stop(string moduleName) ModuleManager.StopModule(module); } - /// #if !USE_WCF [HttpPost("module/{moduleName}/reincarnate")] #endif @@ -171,7 +164,6 @@ public void Reincarnate(string moduleName) ParallelOperations.ExecuteParallel(ModuleManager.ReincarnateModule, module); } - /// #if !USE_WCF [HttpPost("module/{moduleName}")] #endif @@ -194,7 +186,6 @@ public void Update(string moduleName, ServerModuleModel module) } } - /// #if !USE_WCF [HttpPost("module/{moduleName}/confirm")] #endif @@ -208,7 +199,6 @@ public void ConfirmWarning(string moduleName) ModuleManager.InitializeModule(module); } - /// #if !USE_WCF [HttpGet("module/{moduleName}/config")] #endif @@ -241,7 +231,6 @@ public Config GetConfig(string moduleName) } } - /// #if !USE_WCF [HttpPost("module/{moduleName}/config")] #endif @@ -272,7 +261,6 @@ public void SetConfig(string moduleName, SaveConfigRequest request) } } - /// #if !USE_WCF [HttpGet("module/{moduleName}/console")] #endif @@ -289,7 +277,6 @@ public MethodEntry[] GetMethods(string moduleName) return methods; } - /// #if !USE_WCF [HttpPost("module/{moduleName}/console")] #endif diff --git a/src/Moryx.TestModule.Kestrel/Controllers/TestController.cs b/src/Moryx.TestModule.Kestrel/Controllers/TestController.cs index a277ed828..f88365d12 100644 --- a/src/Moryx.TestModule.Kestrel/Controllers/TestController.cs +++ b/src/Moryx.TestModule.Kestrel/Controllers/TestController.cs @@ -8,7 +8,7 @@ namespace Moryx.TestModule.Kestrel { [ApiController] [Component(LifeCycle.Transient)] - public class TestController : Controller + internal class TestController : Controller { [HttpGet("foo/{value}")] [Produces("application/json")]