Program.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. using Microsoft.Extensions.Configuration;
  2. using Microsoft.Extensions.DependencyInjection;
  3. using Microsoft.Extensions.Logging;
  4. using RackPeek.Commands;
  5. using RackPeek.Commands.Server;
  6. using RackPeek.Commands.Server.Cpus;
  7. using RackPeek.Commands.Server.Drives;
  8. using RackPeek.Commands.Server.Nics;
  9. using RackPeek.Commands.Switches;
  10. using RackPeek.Domain.Resources.Hardware;
  11. using RackPeek.Domain.Resources.Hardware.Reports;
  12. using RackPeek.Domain.Resources.Hardware.Server;
  13. using RackPeek.Domain.Resources.Hardware.Server.Cpu;
  14. using RackPeek.Domain.Resources.Hardware.Server.Drive;
  15. using RackPeek.Domain.Resources.Hardware.Server.Nic;
  16. using RackPeek.Domain.Resources.Hardware.Switchs;
  17. using RackPeek.Yaml;
  18. using Spectre.Console;
  19. using Spectre.Console.Cli;
  20. namespace RackPeek;
  21. public static class Program
  22. {
  23. public static async Task<int> Main(string[] args)
  24. {
  25. // Configuration
  26. var configuration = new ConfigurationBuilder()
  27. .SetBasePath(Directory.GetCurrentDirectory())
  28. .AddJsonFile("appsettings.json", true)
  29. .Build();
  30. // DI
  31. var services = new ServiceCollection();
  32. services.AddSingleton<IConfiguration>(configuration);
  33. // Infrastructure
  34. services.AddScoped<IHardwareRepository>(_ =>
  35. {
  36. var path = configuration["HardwareFile"] ?? "hardware.yaml";
  37. var collection = new YamlResourceCollection();
  38. collection.LoadFiles([
  39. "servers.yaml",
  40. "aps.yaml",
  41. "desktops.yaml",
  42. "switches.yaml",
  43. "ups.yaml",
  44. "firewalls.yaml",
  45. "laptops.yaml",
  46. "routers.yaml"
  47. ]);
  48. return new YamlHardwareRepository(collection);
  49. });
  50. services.AddLogging(configure =>
  51. configure
  52. .AddSimpleConsole(opts => { opts.TimestampFormat = "yyyy-MM-dd HH:mm:ss "; }));
  53. // Application
  54. services.AddScoped<ServerHardwareReportUseCase>();
  55. services.AddScoped<ServerReportCommand>();
  56. services.AddScoped<AccessPointHardwareReportUseCase>();
  57. services.AddScoped<AccessPointReportCommand>();
  58. services.AddScoped<SwitchHardwareReportUseCase>();
  59. services.AddScoped<SwitchReportCommand>();
  60. services.AddScoped<UpsHardwareReportUseCase>();
  61. services.AddScoped<UpsReportCommand>();
  62. services.AddScoped<DesktopHardwareReportUseCase>();
  63. services.AddScoped<DesktopReportCommand>();
  64. services.AddScoped<AddServerUseCase>();
  65. services.AddScoped<ServerAddCommand>();
  66. services.AddScoped<DeleteServerUseCase>();
  67. services.AddScoped<ServerDeleteCommand>();
  68. services.AddScoped<DescribeServerUseCase>();
  69. services.AddScoped<ServerDescribeCommand>();
  70. services.AddScoped<GetServerUseCase>();
  71. services.AddScoped<ServerGetByNameCommand>();
  72. services.AddScoped<UpdateServerUseCase>();
  73. services.AddScoped<ServerSetCommand>();
  74. // CPU use cases
  75. services.AddScoped<AddCpuUseCase>();
  76. services.AddScoped<UpdateCpuUseCase>();
  77. services.AddScoped<RemoveCpuUseCase>();
  78. // Drive use cases
  79. services.AddScoped<AddDrivesUseCase>();
  80. services.AddScoped<UpdateDriveUseCase>();
  81. services.AddScoped<RemoveDriveUseCase>();
  82. // CPU commands
  83. services.AddScoped<ServerCpuAddCommand>();
  84. services.AddScoped<ServerCpuSetCommand>();
  85. services.AddScoped<ServerCpuRemoveCommand>();
  86. // Switch commands
  87. services.AddScoped<SwitchAddCommand>();
  88. services.AddScoped<SwitchDeleteCommand>();
  89. services.AddScoped<SwitchDescribeCommand>();
  90. services.AddScoped<SwitchGetByNameCommand>();
  91. services.AddScoped<SwitchGetCommand>();
  92. services.AddScoped<SwitchSetCommand>();
  93. // Switch Usecases
  94. services.AddScoped<AddSwitchUseCase>();
  95. services.AddScoped<DeleteSwitchUseCase>();
  96. services.AddScoped<GetSwitchUseCase>();
  97. services.AddScoped<GetSwitchesUseCase>();
  98. services.AddScoped<UpdateSwitchUseCase>();
  99. // NIC use cases
  100. services.AddScoped<AddNicUseCase>();
  101. services.AddScoped<UpdateNicUseCase>();
  102. services.AddScoped<RemoveNicUseCase>();
  103. // NIC commands
  104. services.AddScoped<ServerNicAddCommand>();
  105. services.AddScoped<ServerNicUpdateCommand>();
  106. services.AddScoped<ServerNicRemoveCommand>();
  107. // Drive commands
  108. services.AddScoped<ServerDriveAddCommand>();
  109. services.AddScoped<ServerDriveUpdateCommand>();
  110. services.AddScoped<ServerDriveRemoveCommand>();
  111. // Spectre bootstrap
  112. var registrar = new TypeRegistrar(services);
  113. var app = new CommandApp(registrar);
  114. app.Configure(config =>
  115. {
  116. config.SetApplicationName("rackpeek");
  117. // ----------------------------
  118. // Server commands (CRUD-style)
  119. // ----------------------------
  120. config.AddBranch("servers", server =>
  121. {
  122. server.SetDescription("Manage servers");
  123. server.AddCommand<ServerReportCommand>("summary")
  124. .WithDescription("Show server hardware report");
  125. server.AddCommand<ServerAddCommand>("add")
  126. .WithDescription("Add a new server");
  127. server.AddCommand<ServerGetByNameCommand>("get")
  128. .WithDescription("List servers or get a server by name");
  129. server.AddCommand<ServerDescribeCommand>("describe")
  130. .WithDescription("Show detailed information about a server");
  131. server.AddCommand<ServerSetCommand>("set")
  132. .WithDescription("Update server properties");
  133. server.AddCommand<ServerDeleteCommand>("del")
  134. .WithDescription("Delete a server");
  135. server.AddBranch("cpu", cpu =>
  136. {
  137. cpu.SetDescription("Manage server CPUs");
  138. cpu.AddCommand<ServerCpuAddCommand>("add")
  139. .WithDescription("Add a CPU to a server");
  140. cpu.AddCommand<ServerCpuSetCommand>("set")
  141. .WithDescription("Update a CPU on a server");
  142. cpu.AddCommand<ServerCpuRemoveCommand>("del")
  143. .WithDescription("Remove a CPU from a server");
  144. });
  145. server.AddBranch("nic", nic =>
  146. {
  147. nic.SetDescription("Manage server NICs");
  148. nic.AddCommand<ServerNicAddCommand>("add")
  149. .WithDescription("Add a NIC to a server");
  150. nic.AddCommand<ServerNicUpdateCommand>("set")
  151. .WithDescription("Update a NIC on a server");
  152. nic.AddCommand<ServerNicRemoveCommand>("del")
  153. .WithDescription("Remove a NIC from a server");
  154. server.AddBranch("drive", drive =>
  155. {
  156. drive.SetDescription("Manage server drives");
  157. drive.AddCommand<ServerDriveAddCommand>("add")
  158. .WithDescription("Add a drive to a server");
  159. drive.AddCommand<ServerDriveUpdateCommand>("set")
  160. .WithDescription("Update a drive on a server");
  161. drive.AddCommand<ServerDriveRemoveCommand>("del")
  162. .WithDescription("Remove a drive from a server");
  163. });
  164. });
  165. config.AddBranch("switches", server =>
  166. {
  167. server.SetDescription("Manage switches");
  168. server.AddCommand<SwitchReportCommand>("summary")
  169. .WithDescription("Show switch hardware report");
  170. server.AddCommand<SwitchAddCommand>("add")
  171. .WithDescription("Add a new switch");
  172. server.AddCommand<SwitchGetByNameCommand>("get")
  173. .WithDescription("List switches or get a switches by name");
  174. server.AddCommand<SwitchDescribeCommand>("describe")
  175. .WithDescription("Show detailed information about a switch");
  176. server.AddCommand<SwitchSetCommand>("set")
  177. .WithDescription("Update switch properties");
  178. server.AddCommand<SwitchDeleteCommand>("del")
  179. .WithDescription("Delete a switch");
  180. });
  181. // ----------------------------
  182. // Reports (read-only summaries)
  183. // ----------------------------
  184. config.AddCommand<AccessPointReportCommand>("ap")
  185. .WithDescription("Show access point hardware report");
  186. config.AddCommand<DesktopReportCommand>("desktops")
  187. .WithDescription("Show desktop hardware report");
  188. config.AddCommand<UpsReportCommand>("ups")
  189. .WithDescription("Show UPS hardware report");
  190. config.ValidateExamples();
  191. });
  192. });
  193. return await app.RunAsync(args);
  194. }
  195. }
  196. public class SpectreConsoleLoggerProvider : ILoggerProvider
  197. {
  198. public ILogger CreateLogger(string categoryName)
  199. {
  200. return new SpectreConsoleLogger();
  201. }
  202. public void Dispose()
  203. {
  204. }
  205. }
  206. public class SpectreConsoleLogger : ILogger
  207. {
  208. public IDisposable BeginScope<T>(T state)
  209. {
  210. return null!;
  211. }
  212. public bool IsEnabled(LogLevel logLevel)
  213. {
  214. return true;
  215. }
  216. public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception,
  217. Func<TState, Exception, string> formatter)
  218. {
  219. var message = formatter(state, exception);
  220. var style = GetStyle(logLevel);
  221. AnsiConsole.MarkupLine($"[{style}] {message}[/]");
  222. }
  223. private Style GetStyle(LogLevel logLevel)
  224. {
  225. return logLevel switch
  226. {
  227. LogLevel.Trace => new Style(Color.Grey),
  228. LogLevel.Debug => new Style(Color.Grey),
  229. LogLevel.Information => new Style(Color.Green),
  230. LogLevel.Warning => new Style(Color.Yellow),
  231. LogLevel.Error => new Style(Color.Red),
  232. LogLevel.Critical => new Style(Color.Red),
  233. _ => new Style(Color.White)
  234. };
  235. }
  236. }