CliBootstrap.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. using System.ComponentModel.DataAnnotations;
  2. using Microsoft.Extensions.Configuration;
  3. using Microsoft.Extensions.DependencyInjection;
  4. using RackPeek.Commands;
  5. using RackPeek.Commands.AccessPoints;
  6. using RackPeek.Commands.Desktops;
  7. using RackPeek.Commands.Desktops.Cpus;
  8. using RackPeek.Commands.Desktops.Drive;
  9. using RackPeek.Commands.Desktops.Gpus;
  10. using RackPeek.Commands.Desktops.Nics;
  11. using RackPeek.Commands.Firewalls;
  12. using RackPeek.Commands.Firewalls.Ports;
  13. using RackPeek.Commands.Laptops;
  14. using RackPeek.Commands.Laptops.Cpus;
  15. using RackPeek.Commands.Laptops.Drive;
  16. using RackPeek.Commands.Laptops.Gpus;
  17. using RackPeek.Commands.Routers;
  18. using RackPeek.Commands.Routers.Ports;
  19. using RackPeek.Commands.Servers;
  20. using RackPeek.Commands.Servers.Cpus;
  21. using RackPeek.Commands.Servers.Drives;
  22. using RackPeek.Commands.Servers.Gpus;
  23. using RackPeek.Commands.Servers.Nics;
  24. using RackPeek.Commands.Services;
  25. using RackPeek.Commands.Switches;
  26. using RackPeek.Commands.Switches.Ports;
  27. using RackPeek.Commands.Systems;
  28. using RackPeek.Commands.Ups;
  29. using RackPeek.Domain;
  30. using RackPeek.Domain.Helpers;
  31. using RackPeek.Domain.Persistence;
  32. using RackPeek.Domain.Persistence.Yaml;
  33. using RackPeek.Domain.Resources;
  34. using RackPeek.Domain.Resources.Hardware;
  35. using RackPeek.Domain.Resources.Services;
  36. using RackPeek.Domain.Resources.SystemResources;
  37. using RackPeek.Yaml;
  38. using Spectre.Console;
  39. using Spectre.Console.Cli;
  40. namespace RackPeek;
  41. public static class CliBootstrap
  42. {
  43. public static async Task RegisterInternals(IServiceCollection services, IConfiguration configuration,
  44. string yamlDir, string yamlFile)
  45. {
  46. services.AddSingleton(configuration);
  47. var basePath = configuration["HardwarePath"] ?? Directory.GetCurrentDirectory();
  48. // Resolve yamlDir as relative to basePath
  49. var yamlPath = Path.IsPathRooted(yamlDir) ? yamlDir : Path.Combine(basePath, yamlDir);
  50. if (!Directory.Exists(yamlPath)) throw new DirectoryNotFoundException($"YAML directory not found: {yamlPath}");
  51. var collection = new YamlResourceCollection(Path.Combine(yamlDir, yamlFile), new PhysicalTextFileStore(), new ResourceCollection());
  52. await collection.LoadAsync();
  53. services.AddSingleton<IResourceCollection>(collection);
  54. // Infrastructure
  55. services.AddYamlRepos();
  56. // Application
  57. services.AddUseCases();
  58. services.AddCommands();
  59. }
  60. public static void BuildApp(CommandApp app)
  61. {
  62. // Spectre bootstrap
  63. app.Configure(config =>
  64. {
  65. config.SetApplicationName("rpk");
  66. config.ValidateExamples();
  67. config.SetApplicationVersion("0.0.3");
  68. config.SetExceptionHandler(HandleException);
  69. // Global summary
  70. config.AddCommand<GetTotalSummaryCommand>("summary")
  71. .WithDescription("Show a summarized report of all resources in the system.");
  72. // ----------------------------
  73. // Server commands (CRUD-style)
  74. // ----------------------------
  75. config.AddBranch("servers", server =>
  76. {
  77. server.SetDescription("Manage servers and their components.");
  78. server.AddCommand<ServerReportCommand>("summary")
  79. .WithDescription("Show a summarized hardware report for all servers.");
  80. server.AddCommand<ServerAddCommand>("add").WithDescription("Add a new server to the inventory.");
  81. server.AddCommand<ServerGetByNameCommand>("get")
  82. .WithDescription("List all servers or retrieve a specific server by name.");
  83. server.AddCommand<ServerDescribeCommand>("describe")
  84. .WithDescription("Display detailed information about a specific server.");
  85. server.AddCommand<ServerSetCommand>("set").WithDescription("Update properties of an existing server.");
  86. server.AddCommand<ServerDeleteCommand>("del").WithDescription("Delete a server from the inventory.");
  87. server.AddCommand<ServerTreeCommand>("tree")
  88. .WithDescription("Display the dependency tree of a server.");
  89. // Server CPUs
  90. server.AddBranch("cpu", cpu =>
  91. {
  92. cpu.SetDescription("Manage CPUs attached to a server.");
  93. cpu.AddCommand<ServerCpuAddCommand>("add").WithDescription("Add a CPU to a specific server.");
  94. cpu.AddCommand<ServerCpuSetCommand>("set").WithDescription("Update configuration of a server CPU.");
  95. cpu.AddCommand<ServerCpuRemoveCommand>("del").WithDescription("Remove a CPU from a server.");
  96. });
  97. // Server Drives
  98. server.AddBranch("drive", drive =>
  99. {
  100. drive.SetDescription("Manage drives attached to a server.");
  101. drive.AddCommand<ServerDriveAddCommand>("add").WithDescription("Add a storage drive to a server.");
  102. drive.AddCommand<ServerDriveUpdateCommand>("set")
  103. .WithDescription("Update properties of a server drive.");
  104. drive.AddCommand<ServerDriveRemoveCommand>("del").WithDescription("Remove a drive from a server.");
  105. });
  106. // Server GPUs
  107. server.AddBranch("gpu", gpu =>
  108. {
  109. gpu.SetDescription("Manage GPUs attached to a server.");
  110. gpu.AddCommand<ServerGpuAddCommand>("add").WithDescription("Add a GPU to a server.");
  111. gpu.AddCommand<ServerGpuUpdateCommand>("set").WithDescription("Update properties of a server GPU.");
  112. gpu.AddCommand<ServerGpuRemoveCommand>("del").WithDescription("Remove a GPU from a server.");
  113. });
  114. // Server NICs
  115. server.AddBranch("nic", nic =>
  116. {
  117. nic.SetDescription("Manage network interface cards (NICs) for a server.");
  118. nic.AddCommand<ServerNicAddCommand>("add").WithDescription("Add a NIC to a server.");
  119. nic.AddCommand<ServerNicUpdateCommand>("set").WithDescription("Update properties of a server NIC.");
  120. nic.AddCommand<ServerNicRemoveCommand>("del").WithDescription("Remove a NIC from a server.");
  121. });
  122. });
  123. // ----------------------------
  124. // Switch commands
  125. // ----------------------------
  126. config.AddBranch("switches", switches =>
  127. {
  128. switches.SetDescription("Manage network switches.");
  129. switches.AddCommand<SwitchReportCommand>("summary")
  130. .WithDescription("Show a hardware report for all switches.");
  131. switches.AddCommand<SwitchAddCommand>("add")
  132. .WithDescription("Add a new network switch to the inventory.");
  133. switches.AddCommand<SwitchGetCommand>("list").WithDescription("List all switches in the system.");
  134. switches.AddCommand<SwitchGetByNameCommand>("get")
  135. .WithDescription("Retrieve details of a specific switch by name.");
  136. switches.AddCommand<SwitchDescribeCommand>("describe")
  137. .WithDescription("Show detailed information about a switch.");
  138. switches.AddCommand<SwitchSetCommand>("set").WithDescription("Update properties of a switch.");
  139. switches.AddCommand<SwitchDeleteCommand>("del").WithDescription("Delete a switch from the inventory.");
  140. switches.AddBranch("port", port =>
  141. {
  142. port.SetDescription("Manage ports on a network switch.");
  143. port.AddCommand<SwitchPortAddCommand>("add").WithDescription("Add a port to a switch.");
  144. port.AddCommand<SwitchPortUpdateCommand>("set").WithDescription("Update a switch port.");
  145. port.AddCommand<SwitchPortRemoveCommand>("del").WithDescription("Remove a port from a switch.");
  146. });
  147. });
  148. // ----------------------------
  149. // Routers commands
  150. // ----------------------------
  151. config.AddBranch("routers", routers =>
  152. {
  153. routers.SetDescription("Manage network routers.");
  154. routers.AddCommand<RouterReportCommand>("summary")
  155. .WithDescription("Show a hardware report for all routers.");
  156. routers.AddCommand<RouterAddCommand>("add")
  157. .WithDescription("Add a new network router to the inventory.");
  158. routers.AddCommand<RouterGetCommand>("list").WithDescription("List all routers in the system.");
  159. routers.AddCommand<RouterGetByNameCommand>("get")
  160. .WithDescription("Retrieve details of a specific router by name.");
  161. routers.AddCommand<RouterDescribeCommand>("describe")
  162. .WithDescription("Show detailed information about a router.");
  163. routers.AddCommand<RouterSetCommand>("set").WithDescription("Update properties of a router.");
  164. routers.AddCommand<RouterDeleteCommand>("del").WithDescription("Delete a router from the inventory.");
  165. routers.AddBranch("port", port =>
  166. {
  167. port.SetDescription("Manage ports on a router.");
  168. port.AddCommand<RouterPortAddCommand>("add").WithDescription("Add a port to a router.");
  169. port.AddCommand<RouterPortUpdateCommand>("set").WithDescription("Update a router port.");
  170. port.AddCommand<RouterPortRemoveCommand>("del").WithDescription("Remove a port from a router.");
  171. });
  172. });
  173. // ----------------------------
  174. // Firewalls commands
  175. // ----------------------------
  176. config.AddBranch("firewalls", firewalls =>
  177. {
  178. firewalls.SetDescription("Manage firewalls.");
  179. firewalls.AddCommand<FirewallReportCommand>("summary")
  180. .WithDescription("Show a hardware report for all firewalls.");
  181. firewalls.AddCommand<FirewallAddCommand>("add").WithDescription("Add a new firewall to the inventory.");
  182. firewalls.AddCommand<FirewallGetCommand>("list").WithDescription("List all firewalls in the system.");
  183. firewalls.AddCommand<FirewallGetByNameCommand>("get")
  184. .WithDescription("Retrieve details of a specific firewall by name.");
  185. firewalls.AddCommand<FirewallDescribeCommand>("describe")
  186. .WithDescription("Show detailed information about a firewall.");
  187. firewalls.AddCommand<FirewallSetCommand>("set").WithDescription("Update properties of a firewall.");
  188. firewalls.AddCommand<FirewallDeleteCommand>("del")
  189. .WithDescription("Delete a firewall from the inventory.");
  190. firewalls.AddBranch("port", port =>
  191. {
  192. port.SetDescription("Manage ports on a firewall.");
  193. port.AddCommand<FirewallPortAddCommand>("add").WithDescription("Add a port to a firewall.");
  194. port.AddCommand<FirewallPortUpdateCommand>("set").WithDescription("Update a firewall port.");
  195. port.AddCommand<FirewallPortRemoveCommand>("del").WithDescription("Remove a port from a firewall.");
  196. });
  197. });
  198. // ----------------------------
  199. // System commands
  200. // ----------------------------
  201. config.AddBranch("systems", system =>
  202. {
  203. system.SetDescription("Manage systems and their dependencies.");
  204. system.AddCommand<SystemReportCommand>("summary")
  205. .WithDescription("Show a summary report for all systems.");
  206. system.AddCommand<SystemAddCommand>("add").WithDescription("Add a new system to the inventory.");
  207. system.AddCommand<SystemGetCommand>("list").WithDescription("List all systems.");
  208. system.AddCommand<SystemGetByNameCommand>("get").WithDescription("Retrieve a system by name.");
  209. system.AddCommand<SystemDescribeCommand>("describe")
  210. .WithDescription("Display detailed information about a system.");
  211. system.AddCommand<SystemSetCommand>("set").WithDescription("Update properties of a system.");
  212. system.AddCommand<SystemDeleteCommand>("del").WithDescription("Delete a system from the inventory.");
  213. system.AddCommand<SystemTreeCommand>("tree")
  214. .WithDescription("Display the dependency tree for a system.");
  215. });
  216. // ----------------------------
  217. // Access Points
  218. // ----------------------------
  219. config.AddBranch("accesspoints", ap =>
  220. {
  221. ap.SetDescription("Manage access points.");
  222. ap.AddCommand<AccessPointReportCommand>("summary")
  223. .WithDescription("Show a hardware report for all access points.");
  224. ap.AddCommand<AccessPointAddCommand>("add").WithDescription("Add a new access point.");
  225. ap.AddCommand<AccessPointGetCommand>("list").WithDescription("List all access points.");
  226. ap.AddCommand<AccessPointGetByNameCommand>("get").WithDescription("Retrieve an access point by name.");
  227. ap.AddCommand<AccessPointDescribeCommand>("describe")
  228. .WithDescription("Show detailed information about an access point.");
  229. ap.AddCommand<AccessPointSetCommand>("set").WithDescription("Update properties of an access point.");
  230. ap.AddCommand<AccessPointDeleteCommand>("del").WithDescription("Delete an access point.");
  231. });
  232. // ----------------------------
  233. // UPS units
  234. // ----------------------------
  235. config.AddBranch("ups", ups =>
  236. {
  237. ups.SetDescription("Manage UPS units.");
  238. ups.AddCommand<UpsReportCommand>("summary")
  239. .WithDescription("Show a hardware report for all UPS units.");
  240. ups.AddCommand<UpsAddCommand>("add").WithDescription("Add a new UPS unit.");
  241. ups.AddCommand<UpsGetCommand>("list").WithDescription("List all UPS units.");
  242. ups.AddCommand<UpsGetByNameCommand>("get").WithDescription("Retrieve a UPS unit by name.");
  243. ups.AddCommand<UpsDescribeCommand>("describe")
  244. .WithDescription("Show detailed information about a UPS unit.");
  245. ups.AddCommand<UpsSetCommand>("set").WithDescription("Update properties of a UPS unit.");
  246. ups.AddCommand<UpsDeleteCommand>("del").WithDescription("Delete a UPS unit.");
  247. });
  248. // ----------------------------
  249. // Desktops
  250. // ----------------------------
  251. config.AddBranch("desktops", desktops =>
  252. {
  253. desktops.SetDescription("Manage desktop computers and their components.");
  254. // CRUD
  255. desktops.AddCommand<DesktopAddCommand>("add").WithDescription("Add a new desktop.");
  256. desktops.AddCommand<DesktopGetCommand>("list").WithDescription("List all desktops.");
  257. desktops.AddCommand<DesktopGetByNameCommand>("get").WithDescription("Retrieve a desktop by name.");
  258. desktops.AddCommand<DesktopDescribeCommand>("describe")
  259. .WithDescription("Show detailed information about a desktop.");
  260. desktops.AddCommand<DesktopSetCommand>("set").WithDescription("Update properties of a desktop.");
  261. desktops.AddCommand<DesktopDeleteCommand>("del")
  262. .WithDescription("Delete a desktop from the inventory.");
  263. desktops.AddCommand<DesktopReportCommand>("summary")
  264. .WithDescription("Show a summarized hardware report for all desktops.");
  265. desktops.AddCommand<DesktopTreeCommand>("tree")
  266. .WithDescription("Display the dependency tree for a desktop.");
  267. // CPU
  268. desktops.AddBranch("cpu", cpu =>
  269. {
  270. cpu.SetDescription("Manage CPUs attached to desktops.");
  271. cpu.AddCommand<DesktopCpuAddCommand>("add").WithDescription("Add a CPU to a desktop.");
  272. cpu.AddCommand<DesktopCpuSetCommand>("set").WithDescription("Update a desktop CPU.");
  273. cpu.AddCommand<DesktopCpuRemoveCommand>("del").WithDescription("Remove a CPU from a desktop.");
  274. });
  275. // Drives
  276. desktops.AddBranch("drive", drive =>
  277. {
  278. drive.SetDescription("Manage storage drives attached to desktops.");
  279. drive.AddCommand<DesktopDriveAddCommand>("add").WithDescription("Add a drive to a desktop.");
  280. drive.AddCommand<DesktopDriveSetCommand>("set").WithDescription("Update a desktop drive.");
  281. drive.AddCommand<DesktopDriveRemoveCommand>("del")
  282. .WithDescription("Remove a drive from a desktop.");
  283. });
  284. // GPUs
  285. desktops.AddBranch("gpu", gpu =>
  286. {
  287. gpu.SetDescription("Manage GPUs attached to desktops.");
  288. gpu.AddCommand<DesktopGpuAddCommand>("add").WithDescription("Add a GPU to a desktop.");
  289. gpu.AddCommand<DesktopGpuSetCommand>("set").WithDescription("Update a desktop GPU.");
  290. gpu.AddCommand<DesktopGpuRemoveCommand>("del").WithDescription("Remove a GPU from a desktop.");
  291. });
  292. // NICs
  293. desktops.AddBranch("nic", nic =>
  294. {
  295. nic.SetDescription("Manage network interface cards (NICs) for desktops.");
  296. nic.AddCommand<DesktopNicAddCommand>("add").WithDescription("Add a NIC to a desktop.");
  297. nic.AddCommand<DesktopNicSetCommand>("set").WithDescription("Update a desktop NIC.");
  298. nic.AddCommand<DesktopNicRemoveCommand>("del").WithDescription("Remove a NIC from a desktop.");
  299. });
  300. });
  301. // ----------------------------
  302. // Laptops
  303. // ----------------------------
  304. config.AddBranch("Laptops", Laptops =>
  305. {
  306. Laptops.SetDescription("Manage Laptop computers and their components.");
  307. // CRUD
  308. Laptops.AddCommand<LaptopAddCommand>("add").WithDescription("Add a new Laptop.");
  309. Laptops.AddCommand<LaptopGetCommand>("list").WithDescription("List all Laptops.");
  310. Laptops.AddCommand<LaptopGetByNameCommand>("get").WithDescription("Retrieve a Laptop by name.");
  311. Laptops.AddCommand<LaptopDescribeCommand>("describe")
  312. .WithDescription("Show detailed information about a Laptop.");
  313. Laptops.AddCommand<LaptopDeleteCommand>("del").WithDescription("Delete a Laptop from the inventory.");
  314. Laptops.AddCommand<LaptopReportCommand>("summary")
  315. .WithDescription("Show a summarized hardware report for all Laptops.");
  316. Laptops.AddCommand<LaptopTreeCommand>("tree")
  317. .WithDescription("Display the dependency tree for a Laptop.");
  318. // CPU
  319. Laptops.AddBranch("cpu", cpu =>
  320. {
  321. cpu.SetDescription("Manage CPUs attached to Laptops.");
  322. cpu.AddCommand<LaptopCpuAddCommand>("add").WithDescription("Add a CPU to a Laptop.");
  323. cpu.AddCommand<LaptopCpuSetCommand>("set").WithDescription("Update a Laptop CPU.");
  324. cpu.AddCommand<LaptopCpuRemoveCommand>("del").WithDescription("Remove a CPU from a Laptop.");
  325. });
  326. // Drives
  327. Laptops.AddBranch("drive", drive =>
  328. {
  329. drive.SetDescription("Manage storage drives attached to Laptops.");
  330. drive.AddCommand<LaptopDriveAddCommand>("add").WithDescription("Add a drive to a Laptop.");
  331. drive.AddCommand<LaptopDriveSetCommand>("set").WithDescription("Update a Laptop drive.");
  332. drive.AddCommand<LaptopDriveRemoveCommand>("del").WithDescription("Remove a drive from a Laptop.");
  333. });
  334. // GPUs
  335. Laptops.AddBranch("gpu", gpu =>
  336. {
  337. gpu.SetDescription("Manage GPUs attached to Laptops.");
  338. gpu.AddCommand<LaptopGpuAddCommand>("add").WithDescription("Add a GPU to a Laptop.");
  339. gpu.AddCommand<LaptopGpuSetCommand>("set").WithDescription("Update a Laptop GPU.");
  340. gpu.AddCommand<LaptopGpuRemoveCommand>("del").WithDescription("Remove a GPU from a Laptop.");
  341. });
  342. });
  343. // ----------------------------
  344. // Services
  345. // ----------------------------
  346. config.AddBranch("services", service =>
  347. {
  348. service.SetDescription("Manage services and their configurations.");
  349. service.AddCommand<ServiceReportCommand>("summary")
  350. .WithDescription("Show a summary report for all services.");
  351. service.AddCommand<ServiceAddCommand>("add").WithDescription("Add a new service.");
  352. service.AddCommand<ServiceGetCommand>("list").WithDescription("List all services.");
  353. service.AddCommand<ServiceGetByNameCommand>("get").WithDescription("Retrieve a service by name.");
  354. service.AddCommand<ServiceDescribeCommand>("describe")
  355. .WithDescription("Show detailed information about a service.");
  356. service.AddCommand<ServiceSetCommand>("set").WithDescription("Update properties of a service.");
  357. service.AddCommand<ServiceDeleteCommand>("del").WithDescription("Delete a service.");
  358. service.AddCommand<ServiceSubnetsCommand>("subnets")
  359. .WithDescription("List subnets associated with a service, optionally filtered by CIDR.");
  360. });
  361. });
  362. }
  363. private static int HandleException(Exception ex, ITypeResolver? arg2)
  364. {
  365. switch (ex)
  366. {
  367. case ValidationException ve:
  368. AnsiConsole.MarkupLine($"[yellow]Validation error:[/] {ve.Message}");
  369. return 2;
  370. case ConflictException ce:
  371. AnsiConsole.MarkupLine($"[red]Conflict:[/] {ce.Message}");
  372. return 3;
  373. case NotFoundException ne:
  374. AnsiConsole.MarkupLine($"[red]Not found:[/] {ne.Message}");
  375. return 4;
  376. default:
  377. AnsiConsole.MarkupLine("[red]Unexpected error occurred.[/]");
  378. AnsiConsole.WriteException(ex, ExceptionFormats.ShortenEverything);
  379. return 99;
  380. }
  381. }
  382. }