feat: plugins
This commit is contained in:
parent
cea3d11a41
commit
e676e35e02
4
.gitignore
vendored
4
.gitignore
vendored
@ -400,6 +400,10 @@ FodyWeavers.xsd
|
|||||||
*.sln.iml
|
*.sln.iml
|
||||||
|
|
||||||
# End of https://www.toptal.com/developers/gitignore/api/csharp
|
# End of https://www.toptal.com/developers/gitignore/api/csharp
|
||||||
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.vscode
|
.vscode
|
||||||
.idea
|
.idea
|
||||||
|
|
||||||
|
plugins/*
|
||||||
|
!plugins/.gitkeep
|
@ -7,7 +7,11 @@
|
|||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
||||||
|
<ProjectReference Include="../Automancer.Common/Automancer.Common.csproj" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.0-preview.3.25171.5" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.0-preview.3.25171.5" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.0-preview.3.25171.5" />
|
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.0-preview.3.25171.5" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="10.0.0-preview.3.25171.5" />
|
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="10.0.0-preview.3.25171.5" />
|
||||||
|
@ -4,21 +4,16 @@ using Spectre.Console.Cli;
|
|||||||
|
|
||||||
namespace Automancer.Command.Container;
|
namespace Automancer.Command.Container;
|
||||||
|
|
||||||
public class Module : ICommandModuleWithRegistry
|
public class Module : ICommandModule
|
||||||
{
|
{
|
||||||
public void Configure(IConfigurator config)
|
public string Name => "container";
|
||||||
{
|
public string Description => "Container operations";
|
||||||
// No implementation needed here
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Configure(IConfigurator config, CommandRegistry registry)
|
public void Configure(IConfigurator config, CommandRegistry registry)
|
||||||
{
|
{
|
||||||
config.AddBranch("container", container =>
|
config.AddBranch(Name, container =>
|
||||||
{
|
{
|
||||||
var description = "Container operations";
|
container.SetDescription(Description);
|
||||||
|
registry.Add(Name, Description);
|
||||||
container.SetDescription(description);
|
|
||||||
registry.Add("container", description);
|
|
||||||
|
|
||||||
container.AddCommand<PsCommand>("ps").WithDescription("List containers");
|
container.AddCommand<PsCommand>("ps").WithDescription("List containers");
|
||||||
});
|
});
|
||||||
|
@ -3,18 +3,15 @@ using Spectre.Console.Cli;
|
|||||||
|
|
||||||
namespace Automancer.Command.Image;
|
namespace Automancer.Command.Image;
|
||||||
|
|
||||||
public class Module : ICommandModuleWithRegistry
|
public class Module : ICommandModule
|
||||||
{
|
{
|
||||||
public void Configure(IConfigurator config)
|
public string Name => "image";
|
||||||
{
|
public string Description => "Docker/podman image operations";
|
||||||
// No implementation needed here
|
|
||||||
}
|
|
||||||
public void Configure(IConfigurator config, CommandRegistry registry)
|
public void Configure(IConfigurator config, CommandRegistry registry)
|
||||||
{
|
{
|
||||||
config.AddBranch("image", image => {
|
config.AddBranch(Name, image => {
|
||||||
var description = "Docker/podman image operations";
|
image.SetDescription(Description);
|
||||||
image.SetDescription(description);
|
registry.Add(Name, Description);
|
||||||
registry.Add("image", description);
|
|
||||||
|
|
||||||
image.AddCommand<BuildCommand>("build").WithDescription("Build a docker image");
|
image.AddCommand<BuildCommand>("build").WithDescription("Build a docker image");
|
||||||
image.AddCommand<PushCommand>("push").WithDescription("Push a docker image");
|
image.AddCommand<PushCommand>("push").WithDescription("Push a docker image");
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
namespace Automancer.Common;
|
|
||||||
|
|
||||||
public record CommandInfo(string Path, string? Description);
|
|
||||||
|
|
||||||
public class CommandRegistry
|
|
||||||
{
|
|
||||||
public List<CommandInfo> Commands { get; } = new();
|
|
||||||
|
|
||||||
public void Add(string path, string? description)
|
|
||||||
{
|
|
||||||
Commands.Add(new CommandInfo(path, description));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
namespace Automancer.Common;
|
|
||||||
|
|
||||||
using Spectre.Console.Cli;
|
|
||||||
|
|
||||||
public interface ICommandModule
|
|
||||||
{
|
|
||||||
|
|
||||||
void Configure(IConfigurator config);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface ICommandModuleWithRegistry : ICommandModule
|
|
||||||
{
|
|
||||||
void Configure(IConfigurator config, CommandRegistry registry);
|
|
||||||
}
|
|
40
Program.cs
40
Program.cs
@ -9,10 +9,10 @@ using Microsoft.Extensions.DependencyInjection;
|
|||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Spectre.Console.Cli;
|
using Spectre.Console.Cli;
|
||||||
using Spectre.Console;
|
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
|
|
||||||
using Automancer.Commands;
|
using Automancer.Commands;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
public abstract class Program
|
public abstract class Program
|
||||||
{
|
{
|
||||||
@ -41,6 +41,7 @@ public abstract class Program
|
|||||||
var registry = new CommandRegistry();
|
var registry = new CommandRegistry();
|
||||||
services.AddSingleton(registry);
|
services.AddSingleton(registry);
|
||||||
|
|
||||||
|
LoadPluginAssemblies("plugins");
|
||||||
RegisterCommandModules(services);
|
RegisterCommandModules(services);
|
||||||
|
|
||||||
var registrar = new TypeRegistrar(services);
|
var registrar = new TypeRegistrar(services);
|
||||||
@ -58,15 +59,9 @@ public abstract class Program
|
|||||||
|
|
||||||
foreach (var module in modules)
|
foreach (var module in modules)
|
||||||
{
|
{
|
||||||
if (module is ICommandModuleWithRegistry withRegistry)
|
module.Configure(config, registry);
|
||||||
{
|
|
||||||
withRegistry.Configure(config, registry);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
module.Configure(config);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.Build();
|
.Build();
|
||||||
@ -76,6 +71,7 @@ public abstract class Program
|
|||||||
|
|
||||||
private static void RegisterCommandModules(IServiceCollection services)
|
private static void RegisterCommandModules(IServiceCollection services)
|
||||||
{
|
{
|
||||||
|
|
||||||
var moduleType = typeof(ICommandModule);
|
var moduleType = typeof(ICommandModule);
|
||||||
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||||
|
|
||||||
@ -83,7 +79,9 @@ public abstract class Program
|
|||||||
.SelectMany(a =>
|
.SelectMany(a =>
|
||||||
{
|
{
|
||||||
try { return a.GetTypes(); }
|
try { return a.GetTypes(); }
|
||||||
catch { return []; }
|
catch {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.Where(t => moduleType.IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract)
|
.Where(t => moduleType.IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract)
|
||||||
.ToList();
|
.ToList();
|
||||||
@ -94,4 +92,24 @@ public abstract class Program
|
|||||||
services.AddSingleton(typeof(ICommandModule), type);
|
services.AddSingleton(typeof(ICommandModule), type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void LoadPluginAssemblies(string pluginDirectory)
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(pluginDirectory))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var dlls = Directory.GetFiles(pluginDirectory, "*.dll", SearchOption.AllDirectories);
|
||||||
|
|
||||||
|
foreach (var dll in dlls)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var asm = Assembly.LoadFrom(dll);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[WARN] Failed to load plugin '{dll}': {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
0
plugins/.gitkeep
Normal file
0
plugins/.gitkeep
Normal file
Loading…
x
Reference in New Issue
Block a user