Program.cs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. using Microsoft.Extensions.Configuration;
  2. using Microsoft.Extensions.DependencyInjection;
  3. using RackPeek.Domain.Resources.Hardware;
  4. using Spectre.Console;
  5. using Spectre.Console.Cli;
  6. using Microsoft.Extensions.Logging;
  7. using RackPeek.Domain.Resources.Hardware.Crud;
  8. using RackPeek.Domain.Resources.Hardware.Reports;
  9. namespace RackPeek;
  10. public static class Program
  11. {
  12. public static async Task<int> Main(string[] args)
  13. {
  14. // Configuration
  15. var configuration = new ConfigurationBuilder()
  16. .SetBasePath(Directory.GetCurrentDirectory())
  17. .AddJsonFile("appsettings.json", optional: true)
  18. .Build();
  19. // DI
  20. var services = new ServiceCollection();
  21. services.AddSingleton<IConfiguration>(configuration);
  22. // Application
  23. services.AddScoped<ServerHardwareReportUseCase>();
  24. services.AddScoped<ServerReportCommand>();
  25. services.AddScoped<AccessPointHardwareReportUseCase>();
  26. services.AddScoped<AccessPointReportCommand>();
  27. services.AddScoped<SwitchHardwareReportUseCase>();
  28. services.AddScoped<SwitchReportCommand>();
  29. services.AddScoped<UpsHardwareReportUseCase>();
  30. services.AddScoped<UpsReportCommand>();
  31. services.AddScoped<DesktopHardwareReportUseCase>();
  32. services.AddScoped<DesktopReportCommand>();
  33. services.AddScoped<AddServerUseCase>();
  34. services.AddScoped<ServerAddCommand>();
  35. services.AddScoped<DeleteServerUseCase>();
  36. services.AddScoped<ServerDeleteCommand>();
  37. services.AddScoped<DescribeServerUseCase>();
  38. services.AddScoped<ServerDescribeCommand>();
  39. services.AddScoped<GetServerUseCase>();
  40. services.AddScoped<ServerGetByNameCommand>();
  41. services.AddScoped<UpdateServerUseCase>();
  42. services.AddScoped<ServerSetCommand>();
  43. // Infrastructure
  44. services.AddScoped<IHardwareRepository>(_ =>
  45. {
  46. var path = configuration["HardwareFile"] ?? "hardware.yaml";
  47. var collection = new YamlResourceCollection();
  48. collection.LoadFiles([
  49. "servers.yaml",
  50. "aps.yaml",
  51. "desktops.yaml",
  52. "switches.yaml",
  53. "ups.yaml",
  54. "firewalls.yaml",
  55. "laptops.yaml",
  56. "routers.yaml"]);
  57. return new YamlHardwareRepository(collection);
  58. });
  59. services.AddLogging(configure =>
  60. configure
  61. .AddSimpleConsole(opts => { opts.TimestampFormat = "yyyy-MM-dd HH:mm:ss "; }));
  62. // Spectre bootstrap
  63. var registrar = new TypeRegistrar(services);
  64. var app = new CommandApp(registrar);
  65. app.Configure(config =>
  66. {
  67. config.SetApplicationName("rackpeek");
  68. // ----------------------------
  69. // Server commands (CRUD-style)
  70. // ----------------------------
  71. config.AddBranch("servers", server =>
  72. {
  73. server.SetDescription("Manage servers");
  74. server.AddCommand<ServerReportCommand>("summary")
  75. .WithDescription("Show server hardware report");
  76. server.AddCommand<ServerAddCommand>("add")
  77. .WithDescription("Add a new server");
  78. server.AddCommand<ServerGetByNameCommand>("get")
  79. .WithDescription("List servers or get a server by name");
  80. server.AddCommand<ServerDescribeCommand>("describe")
  81. .WithDescription("Show detailed information about a server");
  82. server.AddCommand<ServerSetCommand>("set")
  83. .WithDescription("Update server properties");
  84. server.AddCommand<ServerDeleteCommand>("delete")
  85. .WithDescription("Delete a server");
  86. });
  87. // ----------------------------
  88. // Reports (read-only summaries)
  89. // ----------------------------
  90. config.AddCommand<AccessPointReportCommand>("ap")
  91. .WithDescription("Show access point hardware report");
  92. config.AddCommand<DesktopReportCommand>("desktops")
  93. .WithDescription("Show desktop hardware report");
  94. config.AddCommand<SwitchReportCommand>("switches")
  95. .WithDescription("Show switch hardware report");
  96. config.AddCommand<UpsReportCommand>("ups")
  97. .WithDescription("Show UPS hardware report");
  98. config.ValidateExamples();
  99. });
  100. return await app.RunAsync(args);
  101. }
  102. }
  103. public class SpectreConsoleLoggerProvider : ILoggerProvider
  104. {
  105. public ILogger CreateLogger(string categoryName)
  106. {
  107. return new SpectreConsoleLogger();
  108. }
  109. public void Dispose()
  110. {
  111. }
  112. }
  113. public class SpectreConsoleLogger : ILogger
  114. {
  115. public IDisposable BeginScope<T>(T state)
  116. {
  117. return null!;
  118. }
  119. public bool IsEnabled(LogLevel logLevel)
  120. {
  121. return true;
  122. }
  123. public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception,
  124. Func<TState, Exception, string> formatter)
  125. {
  126. var message = formatter(state, exception);
  127. var style = GetStyle(logLevel);
  128. AnsiConsole.MarkupLine($"[{style}] {message}[/]");
  129. }
  130. private Style GetStyle(LogLevel logLevel)
  131. {
  132. return logLevel switch
  133. {
  134. LogLevel.Trace => new Style(Color.Grey),
  135. LogLevel.Debug => new Style(Color.Grey),
  136. LogLevel.Information => new Style(Color.Green),
  137. LogLevel.Warning => new Style(Color.Yellow),
  138. LogLevel.Error => new Style(Color.Red),
  139. LogLevel.Critical => new Style(Color.Red),
  140. _ => new Style(Color.White)
  141. };
  142. }
  143. }