Просмотр исходного кода

Abstracted Cpu & Drive resources

Tim Jones 1 месяц назад
Родитель
Сommit
e591427ba5
100 измененных файлов с 419 добавлено и 754 удалено
  1. 1 1
      RackPeek.Domain/Persistence/Yaml/Converters.cs
  2. 2 0
      RackPeek.Domain/Persistence/Yaml/NotesStringYamlConverter.cs
  3. 2 3
      RackPeek.Domain/Persistence/Yaml/YamlResourceCollection.cs
  4. 0 31
      RackPeek.Domain/Resources/Hardware/Desktops/Cpus/AddDesktopCpuUseCase.cs
  5. 0 24
      RackPeek.Domain/Resources/Hardware/Desktops/Cpus/RemoveDesktopCpuUseCase.cs
  6. 0 35
      RackPeek.Domain/Resources/Hardware/Desktops/Cpus/UpdateDesktopCpuUseCase.cs
  7. 0 32
      RackPeek.Domain/Resources/Hardware/Desktops/Drives/AddDesktopDriveUseCase.cs
  8. 0 24
      RackPeek.Domain/Resources/Hardware/Desktops/Drives/RemoveDesktopDriveUseCase.cs
  9. 0 29
      RackPeek.Domain/Resources/Hardware/Desktops/Drives/UpdateDesktopDriveUseCase.cs
  10. 0 24
      RackPeek.Domain/Resources/Hardware/Laptops/Cpus/AddDesktopCpuUseCase.cs
  11. 0 24
      RackPeek.Domain/Resources/Hardware/Laptops/Cpus/RemoveDesktopCpuUseCase.cs
  12. 0 33
      RackPeek.Domain/Resources/Hardware/Laptops/Cpus/UpdateDesktopCpuUseCase.cs
  13. 0 31
      RackPeek.Domain/Resources/Hardware/Laptops/Drives/AddDesktopDriveUseCase.cs
  14. 0 23
      RackPeek.Domain/Resources/Hardware/Laptops/Drives/RemoveDesktopDriveUseCase.cs
  15. 0 29
      RackPeek.Domain/Resources/Hardware/Laptops/Drives/UpdateDesktopDriveUseCase.cs
  16. 0 36
      RackPeek.Domain/Resources/Hardware/Servers/Cpus/AddCpuUseCase.cs
  17. 0 28
      RackPeek.Domain/Resources/Hardware/Servers/Cpus/RemoveCpuUseCase.cs
  18. 0 38
      RackPeek.Domain/Resources/Hardware/Servers/Cpus/UpdateCpuUseCase.cs
  19. 0 35
      RackPeek.Domain/Resources/Hardware/Servers/Drives/AddDriveUseCase.cs
  20. 0 25
      RackPeek.Domain/Resources/Hardware/Servers/Drives/RemoveDriveUseCase.cs
  21. 0 31
      RackPeek.Domain/Resources/Hardware/Servers/Drives/UpdateDriveUseCase.cs
  22. 1 1
      RackPeek.Domain/Resources/Models/Desktop.cs
  23. 1 1
      RackPeek.Domain/Resources/Models/Laptop.cs
  24. 11 1
      RackPeek.Domain/Resources/Models/Server.cs
  25. 1 1
      RackPeek.Domain/Resources/SystemResources/SystemResource.cs
  26. 0 33
      RackPeek.Domain/Resources/SystemResources/UseCases/Drives/AddSystemDriveUseCase.cs
  27. 0 22
      RackPeek.Domain/Resources/SystemResources/UseCases/Drives/RemoveSystemDriveUseCase.cs
  28. 0 31
      RackPeek.Domain/Resources/SystemResources/UseCases/Drives/UpdateSystemDriveUseCase.cs
  29. 12 0
      RackPeek.Domain/ServiceCollectionExtensions.cs
  30. 49 0
      RackPeek.Domain/UseCases/Cpus/AddCpuUseCase.cs
  31. 39 0
      RackPeek.Domain/UseCases/Cpus/RemoveCpuUseCase.cs
  32. 52 0
      RackPeek.Domain/UseCases/Cpus/UpdateCpuUseCase.cs
  33. 46 0
      RackPeek.Domain/UseCases/Drives/AddDriveUseCase.cs
  34. 37 0
      RackPeek.Domain/UseCases/Drives/RemoveDriveUseCase.cs
  35. 43 0
      RackPeek.Domain/UseCases/Drives/UpdateDriveUseCase.cs
  36. 1 0
      RackPeek.Web.Viewer/Program.cs
  37. 0 1
      RackPeek.Web/Program.cs
  38. 1 0
      RackPeek/Program.cs
  39. 1 1
      RackPeek/RackPeek.csproj
  40. 2 0
      Shared.Rcl/AnsiToHtml.cs
  41. 26 31
      Shared.Rcl/CliBootstrap.cs
  42. 1 1
      Shared.Rcl/Commands/AccessPoints/AccessCommands.cs
  43. 1 2
      Shared.Rcl/Commands/AccessPoints/AccessPointAddCommand.cs
  44. 1 2
      Shared.Rcl/Commands/AccessPoints/AccessPointDeleteCommand.cs
  45. 1 2
      Shared.Rcl/Commands/AccessPoints/AccessPointDescribeCommand.cs
  46. 1 2
      Shared.Rcl/Commands/AccessPoints/AccessPointGetByNameCommand.cs
  47. 1 1
      Shared.Rcl/Commands/AccessPoints/AccessPointGetCommand.cs
  48. 1 1
      Shared.Rcl/Commands/AccessPoints/AccessPointReportCommand.cs
  49. 2 2
      Shared.Rcl/Commands/AccessPoints/AccessPointSetCommand.cs
  50. 4 3
      Shared.Rcl/Commands/Desktops/Cpus/DesktopCpuAddCommand.cs
  51. 1 1
      Shared.Rcl/Commands/Desktops/Cpus/DesktopCpuAddSettings.cs
  52. 4 3
      Shared.Rcl/Commands/Desktops/Cpus/DesktopCpuRemoveCommand.cs
  53. 1 1
      Shared.Rcl/Commands/Desktops/Cpus/DesktopCpuRemoveSettings.cs
  54. 4 3
      Shared.Rcl/Commands/Desktops/Cpus/DesktopCpuSetCommand.cs
  55. 1 1
      Shared.Rcl/Commands/Desktops/Cpus/DesktopCpuSetSettings.cs
  56. 1 2
      Shared.Rcl/Commands/Desktops/DesktopAddCommand.cs
  57. 1 1
      Shared.Rcl/Commands/Desktops/DesktopCommands.cs
  58. 1 2
      Shared.Rcl/Commands/Desktops/DesktopDeleteCommand.cs
  59. 1 1
      Shared.Rcl/Commands/Desktops/DesktopDescribeCommand.cs
  60. 1 2
      Shared.Rcl/Commands/Desktops/DesktopGetByNameCommand.cs
  61. 1 2
      Shared.Rcl/Commands/Desktops/DesktopGetCommand.cs
  62. 1 1
      Shared.Rcl/Commands/Desktops/DesktopReportCommand.cs
  63. 1 1
      Shared.Rcl/Commands/Desktops/DesktopSetCommand.cs
  64. 1 1
      Shared.Rcl/Commands/Desktops/DesktopTreeCommand.cs
  65. 4 3
      Shared.Rcl/Commands/Desktops/Drive/DesktopDriveAddCommand.cs
  66. 1 1
      Shared.Rcl/Commands/Desktops/Drive/DesktopDriveAddSettings.cs
  67. 4 3
      Shared.Rcl/Commands/Desktops/Drive/DesktopDriveRemoveCommand.cs
  68. 1 1
      Shared.Rcl/Commands/Desktops/Drive/DesktopDriveRemoveSettings.cs
  69. 4 3
      Shared.Rcl/Commands/Desktops/Drive/DesktopDriveSetCommand.cs
  70. 1 1
      Shared.Rcl/Commands/Desktops/Drive/DesktopDriveSetSettings.cs
  71. 1 1
      Shared.Rcl/Commands/Desktops/Gpus/DesktopGpuAddCommand.cs
  72. 1 1
      Shared.Rcl/Commands/Desktops/Gpus/DesktopGpuAddSettings.cs
  73. 1 1
      Shared.Rcl/Commands/Desktops/Gpus/DesktopGpuRemoveCommand.cs
  74. 1 1
      Shared.Rcl/Commands/Desktops/Gpus/DesktopGpuRemoveSettings.cs
  75. 1 1
      Shared.Rcl/Commands/Desktops/Gpus/DesktopGpuSetCommand.cs
  76. 1 1
      Shared.Rcl/Commands/Desktops/Gpus/DesktopGpuSetSettings.cs
  77. 1 1
      Shared.Rcl/Commands/Desktops/Nics/DesktopNicAddCommand.cs
  78. 1 1
      Shared.Rcl/Commands/Desktops/Nics/DesktopNicAddSettings.cs
  79. 1 1
      Shared.Rcl/Commands/Desktops/Nics/DesktopNicRemoveCommand.cs
  80. 1 1
      Shared.Rcl/Commands/Desktops/Nics/DesktopNicRemoveSettings.cs
  81. 1 1
      Shared.Rcl/Commands/Desktops/Nics/DesktopNicSetCommand.cs
  82. 1 1
      Shared.Rcl/Commands/Desktops/Nics/DesktopNicSetSettings.cs
  83. 1 2
      Shared.Rcl/Commands/Firewalls/FirewallAddCommand.cs
  84. 1 1
      Shared.Rcl/Commands/Firewalls/FirewallCommands.cs
  85. 1 2
      Shared.Rcl/Commands/Firewalls/FirewallDeleteCommand.cs
  86. 1 1
      Shared.Rcl/Commands/Firewalls/FirewallDescribeCommand.cs
  87. 1 1
      Shared.Rcl/Commands/Firewalls/FirewallGetByNameCommand.cs
  88. 1 1
      Shared.Rcl/Commands/Firewalls/FirewallGetCommand.cs
  89. 1 1
      Shared.Rcl/Commands/Firewalls/FirewallReportCommand.cs
  90. 2 2
      Shared.Rcl/Commands/Firewalls/FirewallSetCommand.cs
  91. 2 3
      Shared.Rcl/Commands/Firewalls/Ports/FirewallPortAddCommand.cs
  92. 2 3
      Shared.Rcl/Commands/Firewalls/Ports/FirewallPortRemoveCommand.cs
  93. 2 3
      Shared.Rcl/Commands/Firewalls/Ports/FirewallPortUpdateCommand.cs
  94. 1 1
      Shared.Rcl/Commands/GetTotalSummaryCommand.cs
  95. 4 3
      Shared.Rcl/Commands/Laptops/Cpus/LaptopCpuAddCommand.cs
  96. 1 1
      Shared.Rcl/Commands/Laptops/Cpus/LaptopCpuAddSettings.cs
  97. 4 3
      Shared.Rcl/Commands/Laptops/Cpus/LaptopCpuRemoveCommand.cs
  98. 1 1
      Shared.Rcl/Commands/Laptops/Cpus/LaptopCpuRemoveSettings.cs
  99. 4 3
      Shared.Rcl/Commands/Laptops/Cpus/LaptopCpuSetCommand.cs
  100. 1 1
      Shared.Rcl/Commands/Laptops/Cpus/LaptopCpuSetSettings.cs

+ 1 - 1
RackPeek.Domain/Persistence/Yaml/Converters.cs

@@ -4,7 +4,7 @@ using YamlDotNet.Core;
 using YamlDotNet.Core.Events;
 using YamlDotNet.Serialization;
 
-namespace RackPeek.Yaml;
+namespace RackPeek.Domain.Persistence.Yaml;
 
 public static class StorageSizeParser
 {

+ 2 - 0
RackPeek.Domain/Persistence/Yaml/NotesStringYamlConverter.cs

@@ -2,6 +2,8 @@ using YamlDotNet.Core;
 using YamlDotNet.Core.Events;
 using YamlDotNet.Serialization;
 
+namespace RackPeek.Domain.Persistence.Yaml;
+
 public sealed class NotesStringYamlConverter : IYamlTypeConverter
 {
     public bool Accepts(Type type) => type == typeof(string);

+ 2 - 3
RackPeek.Domain/Persistence/Yaml/YamlResourceCollection.cs

@@ -1,15 +1,14 @@
 using System.Collections.Specialized;
-using RackPeek.Domain.Persistence;
-using RackPeek.Domain.Persistence.Yaml;
 using RackPeek.Domain.Resources;
 using RackPeek.Domain.Resources.Models;
 using RackPeek.Domain.Resources.Services;
 using RackPeek.Domain.Resources.SystemResources;
-using RackPeek.Yaml;
 using YamlDotNet.Core;
 using YamlDotNet.Serialization;
 using YamlDotNet.Serialization.NamingConventions;
 
+namespace RackPeek.Domain.Persistence.Yaml;
+
 public class ResourceCollection
 {
     public List<Resource> Resources { get; } = new();

+ 0 - 31
RackPeek.Domain/Resources/Hardware/Desktops/Cpus/AddDesktopCpuUseCase.cs

@@ -1,31 +0,0 @@
-using RackPeek.Domain.Helpers;
-using RackPeek.Domain.Persistence;
-using RackPeek.Domain.Resources.Models;
-
-namespace RackPeek.Domain.Resources.Hardware.Desktops.Cpus;
-
-public class AddDesktopCpuUseCase(IResourceCollection repository) : IUseCase
-{
-    public async Task ExecuteAsync(string name, string? model, int? cores, int? threads)
-    {
-        name = Normalize.HardwareName(name);
-        ThrowIfInvalid.ResourceName(name);
-
-        // ToDo validate / normalize all inputs
-
-        var cpu = new Cpu
-        {
-            Model = model,
-            Cores = cores,
-            Threads = threads
-        };
-
-        var desktop = await repository.GetByNameAsync(name) as Desktop
-                      ?? throw new InvalidOperationException($"Desktop '{name}' not found.");
-
-        desktop.Cpus ??= new List<Cpu>();
-        desktop.Cpus.Add(cpu);
-
-        await repository.UpdateAsync(desktop);
-    }
-}

+ 0 - 24
RackPeek.Domain/Resources/Hardware/Desktops/Cpus/RemoveDesktopCpuUseCase.cs

@@ -1,24 +0,0 @@
-using RackPeek.Domain.Helpers;
-using RackPeek.Domain.Persistence;
-using RackPeek.Domain.Resources.Models;
-
-namespace RackPeek.Domain.Resources.Hardware.Desktops.Cpus;
-
-public class RemoveDesktopCpuUseCase(IResourceCollection repository) : IUseCase
-{
-    public async Task ExecuteAsync(string name, int index)
-    {
-        name = Normalize.HardwareName(name);
-        ThrowIfInvalid.ResourceName(name);
-
-        var desktop = await repository.GetByNameAsync(name) as Desktop
-                      ?? throw new NotFoundException($"Desktop '{name}' not found.");
-
-        if (desktop.Cpus == null || index < 0 || index >= desktop.Cpus.Count)
-            throw new NotFoundException($"CPU index {index} not found on desktop '{name}'.");
-
-        desktop.Cpus.RemoveAt(index);
-
-        await repository.UpdateAsync(desktop);
-    }
-}

+ 0 - 35
RackPeek.Domain/Resources/Hardware/Desktops/Cpus/UpdateDesktopCpuUseCase.cs

@@ -1,35 +0,0 @@
-using RackPeek.Domain.Helpers;
-using RackPeek.Domain.Persistence;
-using RackPeek.Domain.Resources.Models;
-
-namespace RackPeek.Domain.Resources.Hardware.Desktops.Cpus;
-
-public class UpdateDesktopCpuUseCase(IResourceCollection repository) : IUseCase
-{
-    public async Task ExecuteAsync(
-        string name,
-        int index,
-        string? model,
-        int? cores,
-        int? threads)
-    {
-        // ToDo pass in properties as inputs, construct the entity in the usecase, ensure optional inputs are nullable
-        // ToDo validate / normalize all inputs
-
-        name = Normalize.HardwareName(name);
-        ThrowIfInvalid.ResourceName(name);
-
-        var desktop = await repository.GetByNameAsync(name) as Desktop
-                      ?? throw new NotFoundException($"Desktop '{name}' not found.");
-
-        if (desktop.Cpus == null || index < 0 || index >= desktop.Cpus.Count)
-            throw new NotFoundException($"CPU index {index} not found on desktop '{name}'.");
-
-        var cpu = desktop.Cpus[index];
-        cpu.Model = model;
-        cpu.Cores = cores;
-        cpu.Threads = threads;
-
-        await repository.UpdateAsync(desktop);
-    }
-}

+ 0 - 32
RackPeek.Domain/Resources/Hardware/Desktops/Drives/AddDesktopDriveUseCase.cs

@@ -1,32 +0,0 @@
-using RackPeek.Domain.Helpers;
-using RackPeek.Domain.Persistence;
-using RackPeek.Domain.Resources.Models;
-
-namespace RackPeek.Domain.Resources.Hardware.Desktops.Drives;
-
-public class AddDesktopDriveUseCase(IResourceCollection repository) : IUseCase
-{
-    public async Task ExecuteAsync(
-        string name,
-        string? type,
-        int? size)
-    {
-        // ToDo pass in properties as inputs, construct the entity in the usecase, ensure optional inputs are nullable
-        // ToDo validate / normalize all inputs
-
-        name = Normalize.HardwareName(name);
-        ThrowIfInvalid.ResourceName(name);
-
-        var desktop = await repository.GetByNameAsync(name) as Desktop
-                      ?? throw new NotFoundException($"Desktop '{name}' not found.");
-
-        desktop.Drives ??= new List<Drive>();
-        desktop.Drives.Add(new Drive
-        {
-            Type = type,
-            Size = size
-        });
-
-        await repository.UpdateAsync(desktop);
-    }
-}

+ 0 - 24
RackPeek.Domain/Resources/Hardware/Desktops/Drives/RemoveDesktopDriveUseCase.cs

@@ -1,24 +0,0 @@
-using RackPeek.Domain.Helpers;
-using RackPeek.Domain.Persistence;
-using RackPeek.Domain.Resources.Models;
-
-namespace RackPeek.Domain.Resources.Hardware.Desktops.Drives;
-
-public class RemoveDesktopDriveUseCase(IResourceCollection repository) : IUseCase
-{
-    public async Task ExecuteAsync(string name, int index)
-    {
-        name = Normalize.HardwareName(name);
-        ThrowIfInvalid.ResourceName(name);
-
-        var desktop = await repository.GetByNameAsync(name) as Desktop
-                      ?? throw new NotFoundException($"Desktop '{name}' not found.");
-
-        if (desktop.Drives == null || index < 0 || index >= desktop.Drives.Count)
-            throw new NotFoundException($"Drive index {index} not found on desktop '{name}'.");
-
-        desktop.Drives.RemoveAt(index);
-
-        await repository.UpdateAsync(desktop);
-    }
-}

+ 0 - 29
RackPeek.Domain/Resources/Hardware/Desktops/Drives/UpdateDesktopDriveUseCase.cs

@@ -1,29 +0,0 @@
-using RackPeek.Domain.Helpers;
-using RackPeek.Domain.Persistence;
-using RackPeek.Domain.Resources.Models;
-
-namespace RackPeek.Domain.Resources.Hardware.Desktops.Drives;
-
-public class UpdateDesktopDriveUseCase(IResourceCollection repository) : IUseCase
-{
-    public async Task ExecuteAsync(string name, int index, string? type, int? size)
-    {
-        // ToDo pass in properties as inputs, construct the entity in the usecase, ensure optional inputs are nullable
-        // ToDo validate / normalize all inputs
-
-        name = Normalize.HardwareName(name);
-        ThrowIfInvalid.ResourceName(name);
-
-        var desktop = await repository.GetByNameAsync(name) as Desktop
-                      ?? throw new NotFoundException($"Desktop '{name}' not found.");
-
-        if (desktop.Drives == null || index < 0 || index >= desktop.Drives.Count)
-            throw new NotFoundException($"Drive index {index} not found on desktop '{name}'.");
-
-        var drive = desktop.Drives[index];
-        drive.Type = type;
-        drive.Size = size;
-
-        await repository.UpdateAsync(desktop);
-    }
-}

+ 0 - 24
RackPeek.Domain/Resources/Hardware/Laptops/Cpus/AddDesktopCpuUseCase.cs

@@ -1,24 +0,0 @@
-using RackPeek.Domain.Helpers;
-using RackPeek.Domain.Persistence;
-using RackPeek.Domain.Resources.Models;
-
-namespace RackPeek.Domain.Resources.Hardware.Laptops.Cpus;
-
-public class AddLaptopCpuUseCase(IResourceCollection repository) : IUseCase
-{
-    public async Task ExecuteAsync(string name, string? model, int? cores, int? threads)
-    {
-        // ToDo validate / normalize all inputs
-
-        name = Normalize.HardwareName(name);
-        ThrowIfInvalid.ResourceName(name);
-
-        var laptop = await repository.GetByNameAsync(name) as Laptop
-                     ?? throw new NotFoundException($"Laptop '{name}' not found.");
-
-        laptop.Cpus ??= new List<Cpu>();
-        laptop.Cpus.Add(new Cpu { Model = model, Cores = cores, Threads = threads });
-
-        await repository.UpdateAsync(laptop);
-    }
-}

+ 0 - 24
RackPeek.Domain/Resources/Hardware/Laptops/Cpus/RemoveDesktopCpuUseCase.cs

@@ -1,24 +0,0 @@
-using RackPeek.Domain.Helpers;
-using RackPeek.Domain.Persistence;
-using RackPeek.Domain.Resources.Models;
-
-namespace RackPeek.Domain.Resources.Hardware.Laptops.Cpus;
-
-public class RemoveLaptopCpuUseCase(IResourceCollection repository) : IUseCase
-{
-    public async Task ExecuteAsync(string name, int index)
-    {
-        name = Normalize.HardwareName(name);
-        ThrowIfInvalid.ResourceName(name);
-
-        var laptop = await repository.GetByNameAsync(name) as Laptop
-                     ?? throw new InvalidOperationException($"Laptop '{name}' not found.");
-
-        if (laptop.Cpus == null || index < 0 || index >= laptop.Cpus.Count)
-            throw new InvalidOperationException($"CPU index {index} not found on Laptop '{name}'.");
-
-        laptop.Cpus.RemoveAt(index);
-
-        await repository.UpdateAsync(laptop);
-    }
-}

+ 0 - 33
RackPeek.Domain/Resources/Hardware/Laptops/Cpus/UpdateDesktopCpuUseCase.cs

@@ -1,33 +0,0 @@
-using RackPeek.Domain.Helpers;
-using RackPeek.Domain.Persistence;
-using RackPeek.Domain.Resources.Models;
-
-namespace RackPeek.Domain.Resources.Hardware.Laptops.Cpus;
-
-public class UpdateLaptopCpuUseCase(IResourceCollection repository) : IUseCase
-{
-    public async Task ExecuteAsync(
-        string name,
-        int index,
-        string? model,
-        int? cores,
-        int? threads)
-    {
-        // ToDo pass in properties as inputs, construct the entity in the usecase, ensure optional inputs are nullable
-        // ToDo validate / normalize all inputs
-
-        name = Normalize.HardwareName(name);
-        ThrowIfInvalid.ResourceName(name);
-        var laptop = await repository.GetByNameAsync(name) as Laptop
-                     ?? throw new NotFoundException($"Laptop '{name}' not found.");
-
-        if (laptop.Cpus == null || index < 0 || index >= laptop.Cpus.Count)
-            throw new NotFoundException($"CPU index {index} not found on Laptop '{name}'.");
-
-        var cpu = laptop.Cpus[index];
-        cpu.Model = model;
-        cpu.Cores = cores;
-        cpu.Threads = threads;
-        await repository.UpdateAsync(laptop);
-    }
-}

+ 0 - 31
RackPeek.Domain/Resources/Hardware/Laptops/Drives/AddDesktopDriveUseCase.cs

@@ -1,31 +0,0 @@
-using RackPeek.Domain.Helpers;
-using RackPeek.Domain.Persistence;
-using RackPeek.Domain.Resources.Models;
-
-namespace RackPeek.Domain.Resources.Hardware.Laptops.Drives;
-
-public class AddLaptopDriveUseCase(IResourceCollection repository) : IUseCase
-{
-    public async Task ExecuteAsync(
-        string name,
-        string? type,
-        int? size)
-    {
-        // ToDo pass in properties as inputs, construct the entity in the usecase, ensure optional inputs are nullable
-        // ToDo validate / normalize all inputs
-
-        name = Normalize.HardwareName(name);
-        ThrowIfInvalid.ResourceName(name);
-
-        var laptop = await repository.GetByNameAsync(name) as Laptop
-                     ?? throw new NotFoundException($"Laptop '{name}' not found.");
-
-        laptop.Drives ??= new List<Drive>();
-        laptop.Drives.Add(new Drive
-        {
-            Type = type,
-            Size = size
-        });
-        await repository.UpdateAsync(laptop);
-    }
-}

+ 0 - 23
RackPeek.Domain/Resources/Hardware/Laptops/Drives/RemoveDesktopDriveUseCase.cs

@@ -1,23 +0,0 @@
-using RackPeek.Domain.Helpers;
-using RackPeek.Domain.Persistence;
-using RackPeek.Domain.Resources.Models;
-
-namespace RackPeek.Domain.Resources.Hardware.Laptops.Drives;
-
-public class RemoveLaptopDriveUseCase(IResourceCollection repository) : IUseCase
-{
-    public async Task ExecuteAsync(string name, int index)
-    {
-        name = Normalize.HardwareName(name);
-        ThrowIfInvalid.ResourceName(name);
-        var laptop = await repository.GetByNameAsync(name) as Laptop
-                     ?? throw new NotFoundException($"Laptop '{name}' not found.");
-
-        if (laptop.Drives == null || index < 0 || index >= laptop.Drives.Count)
-            throw new NotFoundException($"Drive index {index} not found on Laptop '{name}'.");
-
-        laptop.Drives.RemoveAt(index);
-
-        await repository.UpdateAsync(laptop);
-    }
-}

+ 0 - 29
RackPeek.Domain/Resources/Hardware/Laptops/Drives/UpdateDesktopDriveUseCase.cs

@@ -1,29 +0,0 @@
-using RackPeek.Domain.Helpers;
-using RackPeek.Domain.Persistence;
-using RackPeek.Domain.Resources.Models;
-
-namespace RackPeek.Domain.Resources.Hardware.Laptops.Drives;
-
-public class UpdateLaptopDriveUseCase(IResourceCollection repository) : IUseCase
-{
-    public async Task ExecuteAsync(string name, int index, string? type, int? size)
-    {
-        // ToDo pass in properties as inputs, construct the entity in the usecase, ensure optional inputs are nullable
-        // ToDo validate / normalize all inputs
-
-        name = Normalize.HardwareName(name);
-        ThrowIfInvalid.ResourceName(name);
-
-        var laptop = await repository.GetByNameAsync(name) as Laptop
-                     ?? throw new NotFoundException($"Laptop '{name}' not found.");
-
-        if (laptop.Drives == null || index < 0 || index >= laptop.Drives.Count)
-            throw new NotFoundException($"Drive index {index} not found on Laptop '{name}'.");
-
-        var drive = laptop.Drives[index];
-        drive.Type = type;
-        drive.Size = size;
-
-        await repository.UpdateAsync(laptop);
-    }
-}

+ 0 - 36
RackPeek.Domain/Resources/Hardware/Servers/Cpus/AddCpuUseCase.cs

@@ -1,36 +0,0 @@
-using RackPeek.Domain.Helpers;
-using RackPeek.Domain.Persistence;
-using RackPeek.Domain.Resources.Models;
-
-namespace RackPeek.Domain.Resources.Hardware.Servers.Cpus;
-
-public class AddCpuUseCase(IResourceCollection repository) : IUseCase
-{
-    public async Task ExecuteAsync(
-        string name,
-        string? model,
-        int? cores,
-        int? threads)
-    {
-        // ToDo pass in properties as inputs, construct the entity in the usecase
-        // ToDo validate / normalize all inputs
-
-        name = Normalize.HardwareName(name);
-        ThrowIfInvalid.ResourceName(name);
-
-        var hardware = await repository.GetByNameAsync(name);
-
-        if (hardware is not Server server) return;
-
-        server.Cpus ??= [];
-
-        server.Cpus.Add(new Cpu
-        {
-            Model = model,
-            Cores = cores,
-            Threads = threads
-        });
-
-        await repository.UpdateAsync(server);
-    }
-}

+ 0 - 28
RackPeek.Domain/Resources/Hardware/Servers/Cpus/RemoveCpuUseCase.cs

@@ -1,28 +0,0 @@
-using RackPeek.Domain.Helpers;
-using RackPeek.Domain.Persistence;
-using RackPeek.Domain.Resources.Models;
-
-namespace RackPeek.Domain.Resources.Hardware.Servers.Cpus;
-
-public class RemoveCpuUseCase(IResourceCollection repository) : IUseCase
-{
-    public async Task ExecuteAsync(
-        string name,
-        int index)
-    {
-        name = Normalize.HardwareName(name);
-        ThrowIfInvalid.ResourceName(name);
-
-        var hardware = await repository.GetByNameAsync(name);
-        if (hardware is not Server server) return;
-
-        server.Cpus ??= [];
-
-        if (index < 0 || index >= server.Cpus.Count)
-            throw new ArgumentOutOfRangeException(nameof(index), "CPU index out of range.");
-
-        server.Cpus.RemoveAt(index);
-
-        await repository.UpdateAsync(server);
-    }
-}

+ 0 - 38
RackPeek.Domain/Resources/Hardware/Servers/Cpus/UpdateCpuUseCase.cs

@@ -1,38 +0,0 @@
-using RackPeek.Domain.Helpers;
-using RackPeek.Domain.Persistence;
-using RackPeek.Domain.Resources.Models;
-
-namespace RackPeek.Domain.Resources.Hardware.Servers.Cpus;
-
-public class UpdateCpuUseCase(IResourceCollection repository) : IUseCase
-{
-    public async Task ExecuteAsync(
-        string name,
-        int index,
-        string? model,
-        int? cores,
-        int? threads)
-    {
-        // ToDo pass in properties as inputs, construct the entity in the usecase
-        // ToDo validate / normalize all inputs
-
-        name = Normalize.HardwareName(name);
-        ThrowIfInvalid.ResourceName(name);
-
-        var hardware = await repository.GetByNameAsync(name);
-
-        if (hardware is not Server server) return;
-
-        server.Cpus ??= [];
-
-        if (index < 0 || index >= server.Cpus.Count)
-            throw new ArgumentOutOfRangeException(nameof(index), "CPU index out of range.");
-
-        var cpu = server.Cpus[index];
-        cpu.Model = model;
-        cpu.Cores = cores;
-        cpu.Threads = threads;
-
-        await repository.UpdateAsync(server);
-    }
-}

+ 0 - 35
RackPeek.Domain/Resources/Hardware/Servers/Drives/AddDriveUseCase.cs

@@ -1,35 +0,0 @@
-using RackPeek.Domain.Helpers;
-using RackPeek.Domain.Persistence;
-using RackPeek.Domain.Resources.Models;
-
-namespace RackPeek.Domain.Resources.Hardware.Servers.Drives;
-
-public class AddDrivesUseCase(IResourceCollection repository) : IUseCase
-{
-    public async Task ExecuteAsync(
-        string name,
-        string? type,
-        int? size)
-    {
-        // ToDo pass in properties as inputs, construct the entity in the usecase, ensure optional inputs are nullable
-        // ToDo validate / normalize all inputs
-
-        name = Normalize.HardwareName(name);
-        ThrowIfInvalid.ResourceName(name);
-
-        var hardware = await repository.GetByNameAsync(name);
-
-        if (hardware is not Server server)
-            throw new NotFoundException($"Server '{name}' not found.");
-
-        server.Drives ??= [];
-
-        server.Drives.Add(new Drive
-        {
-            Type = type,
-            Size = size
-        });
-
-        await repository.UpdateAsync(server);
-    }
-}

+ 0 - 25
RackPeek.Domain/Resources/Hardware/Servers/Drives/RemoveDriveUseCase.cs

@@ -1,25 +0,0 @@
-using RackPeek.Domain.Helpers;
-using RackPeek.Domain.Persistence;
-using RackPeek.Domain.Resources.Models;
-
-namespace RackPeek.Domain.Resources.Hardware.Servers.Drives;
-
-public class RemoveDriveUseCase(IResourceCollection repository) : IUseCase
-{
-    public async Task ExecuteAsync(string name, int index)
-    {
-        name = Normalize.HardwareName(name);
-        ThrowIfInvalid.ResourceName(name);
-
-        var hardware = await repository.GetByNameAsync(name);
-        if (hardware is not Server server)
-            throw new NotFoundException($"Server '{name}' not found.");
-
-        server.Drives ??= [];
-        if (index < 0 || index >= server.Drives.Count)
-            throw new ArgumentOutOfRangeException(nameof(index), "Drive index out of range.");
-
-        server.Drives.RemoveAt(index);
-        await repository.UpdateAsync(server);
-    }
-}

+ 0 - 31
RackPeek.Domain/Resources/Hardware/Servers/Drives/UpdateDriveUseCase.cs

@@ -1,31 +0,0 @@
-using RackPeek.Domain.Helpers;
-using RackPeek.Domain.Persistence;
-using RackPeek.Domain.Resources.Models;
-
-namespace RackPeek.Domain.Resources.Hardware.Servers.Drives;
-
-public class UpdateDriveUseCase(IResourceCollection repository) : IUseCase
-{
-    public async Task ExecuteAsync(string name, int index, string? type, int? size)
-    {
-        // ToDo pass in properties as inputs, construct the entity in the usecase, ensure optional inputs are nullable
-        // ToDo validate / normalize all inputs
-
-        name = Normalize.HardwareName(name);
-        ThrowIfInvalid.ResourceName(name);
-
-        var hardware = await repository.GetByNameAsync(name);
-        if (hardware is not Server server)
-            throw new NotFoundException($"Server '{name}' not found.");
-
-
-        server.Drives ??= [];
-        if (index < 0 || index >= server.Drives.Count)
-            throw new ArgumentOutOfRangeException(nameof(index), "Drive index out of range.");
-
-        var drive = server.Drives[index];
-        drive.Type = type;
-        drive.Size = size;
-        await repository.UpdateAsync(server);
-    }
-}

+ 1 - 1
RackPeek.Domain/Resources/Models/Desktop.cs

@@ -1,6 +1,6 @@
 namespace RackPeek.Domain.Resources.Models;
 
-public class Desktop : Hardware
+public class Desktop : Hardware, ICpuResource, IDriveResource
 {
     public const string KindLabel = "Desktop";
     public List<Cpu>? Cpus { get; set; }

+ 1 - 1
RackPeek.Domain/Resources/Models/Laptop.cs

@@ -1,6 +1,6 @@
 namespace RackPeek.Domain.Resources.Models;
 
-public class Laptop : Hardware
+public class Laptop : Hardware, ICpuResource, IDriveResource
 {
     public const string KindLabel = "Laptop";
     public List<Cpu>? Cpus { get; set; }

+ 11 - 1
RackPeek.Domain/Resources/Models/Server.cs

@@ -1,6 +1,6 @@
 namespace RackPeek.Domain.Resources.Models;
 
-public class Server : Hardware
+public class Server : Hardware, ICpuResource, IDriveResource
 {
     public const string KindLabel = "Server";
     public List<Cpu>? Cpus { get; set; }
@@ -9,4 +9,14 @@ public class Server : Hardware
     public List<Nic>? Nics { get; set; }
     public List<Gpu>? Gpus { get; set; }
     public bool? Ipmi { get; set; }
+}
+
+public interface ICpuResource
+{
+    public List<Cpu>? Cpus { get; set; }
+}
+
+public interface IDriveResource
+{
+    public List<Drive>? Drives { get; set; }
 }

+ 1 - 1
RackPeek.Domain/Resources/SystemResources/SystemResource.cs

@@ -2,7 +2,7 @@ using RackPeek.Domain.Resources.Models;
 
 namespace RackPeek.Domain.Resources.SystemResources;
 
-public class SystemResource : Resource
+public class SystemResource : Resource, IDriveResource
 {
     public const string KindLabel = "System";
 

+ 0 - 33
RackPeek.Domain/Resources/SystemResources/UseCases/Drives/AddSystemDriveUseCase.cs

@@ -1,33 +0,0 @@
-using RackPeek.Domain.Helpers;
-using RackPeek.Domain.Persistence;
-using RackPeek.Domain.Resources.Models;
-
-namespace RackPeek.Domain.Resources.SystemResources.UseCases;
-
-public class AddSystemDriveUseCase(IResourceCollection repository) : IUseCase
-{
-    public async Task ExecuteAsync(string systemName, string driveType, int size)
-    {
-        // ToDo pass in properties as inputs, construct the entity in the usecase, ensure optional inputs are nullable
-        // ToDo validate / normalize all inputs
-
-        ThrowIfInvalid.ResourceName(systemName);
-
-        var driveTypeNormalized = Normalize.DriveType(driveType);
-        ThrowIfInvalid.DriveType(driveTypeNormalized);
-        ThrowIfInvalid.DriveSize(size);
-
-        var system = (await repository.GetByNameAsync(systemName)) as SystemResource
-                     ?? throw new NotFoundException($"System '{systemName}' not found.");
-
-        system.Drives ??= new List<Drive>();
-
-        system.Drives.Add(new Drive
-        {
-            Type = driveTypeNormalized,
-            Size = size
-        });
-
-        await repository.UpdateAsync(system);
-    }
-}

+ 0 - 22
RackPeek.Domain/Resources/SystemResources/UseCases/Drives/RemoveSystemDriveUseCase.cs

@@ -1,22 +0,0 @@
-using RackPeek.Domain.Helpers;
-using RackPeek.Domain.Persistence;
-
-namespace RackPeek.Domain.Resources.SystemResources.UseCases;
-
-public class RemoveSystemDriveUseCase(IResourceCollection repository) : IUseCase
-{
-    public async Task ExecuteAsync(string systemName, int index)
-    {
-        ThrowIfInvalid.ResourceName(systemName);
-
-        var system = await repository.GetByNameAsync(systemName) as SystemResource
-                     ?? throw new NotFoundException($"System '{systemName}' not found.");
-
-        if (system.Drives == null || index < 0 || index >= system.Drives.Count)
-            throw new NotFoundException($"Drive index {index} not found on system '{systemName}'.");
-
-        system.Drives.RemoveAt(index);
-
-        await repository.UpdateAsync(system);
-    }
-}

+ 0 - 31
RackPeek.Domain/Resources/SystemResources/UseCases/Drives/UpdateSystemDriveUseCase.cs

@@ -1,31 +0,0 @@
-using RackPeek.Domain.Helpers;
-using RackPeek.Domain.Persistence;
-
-namespace RackPeek.Domain.Resources.SystemResources.UseCases;
-
-public class UpdateSystemDriveUseCase(IResourceCollection repository) : IUseCase
-{
-    public async Task ExecuteAsync(string systemName, int index, string driveType, int size)
-    {
-        // ToDo pass in properties as inputs, construct the entity in the usecase, ensure optional inputs are nullable
-        // ToDo validate / normalize all inputs
-
-        ThrowIfInvalid.ResourceName(systemName);
-        var driveTypeNormalized = Normalize.DriveType(driveType);
-        ThrowIfInvalid.DriveType(driveTypeNormalized);
-        ThrowIfInvalid.DriveSize(size);
-
-        var system = await repository.GetByNameAsync(systemName) as SystemResource ??
-                     throw new NotFoundException($"System '{systemName}' not found.");
-
-        if (system.Drives == null || index < 0 || index >= system.Drives.Count)
-            throw new NotFoundException($"Drive index {index} not found on system '{systemName}'.");
-
-        var drive = system.Drives[index];
-
-        drive.Type = driveTypeNormalized;
-        drive.Size = size;
-
-        await repository.UpdateAsync(system);
-    }
-}

+ 12 - 0
RackPeek.Domain/ServiceCollectionExtensions.cs

@@ -8,6 +8,8 @@ using RackPeek.Domain.Resources.Models;
 using RackPeek.Domain.Resources.Services;
 using RackPeek.Domain.Resources.SystemResources;
 using RackPeek.Domain.UseCases;
+using RackPeek.Domain.UseCases.Cpus;
+using RackPeek.Domain.UseCases.Drives;
 using RackPeek.Domain.UseCases.Tags;
 
 namespace RackPeek.Domain;
@@ -57,6 +59,16 @@ public static class ServiceCollectionExtensions
         services.AddScoped(typeof(IGetResourceByNameUseCase<>), typeof(GetResourceByNameUseCase<>));
         services.AddScoped(typeof(IRenameResourceUseCase<>), typeof(RenameResourceUseCase<>));
 
+        services.AddScoped(typeof(IAddCpuUseCase<>), typeof(AddCpuUseCase<>));
+        services.AddScoped(typeof(IRemoveCpuUseCase<>), typeof(RemoveCpuUseCase<>));
+        services.AddScoped(typeof(IUpdateCpuUseCase<>), typeof(UpdateCpuUseCase<>));
+
+        
+        services.AddScoped(typeof(IAddDriveUseCase<>), typeof(AddDriveUseCase<>));
+        services.AddScoped(typeof(IRemoveDriveUseCase<>), typeof(RemoveDriveUseCase<>));
+        services.AddScoped(typeof(IUpdateDriveUseCase<>), typeof(UpdateDriveUseCase<>));
+
+        
         var usecases = Assembly.GetAssembly(typeof(IUseCase))
             ?.GetTypes()
             .Where(t =>

+ 49 - 0
RackPeek.Domain/UseCases/Cpus/AddCpuUseCase.cs

@@ -0,0 +1,49 @@
+using RackPeek.Domain.Helpers;
+using RackPeek.Domain.Persistence;
+using RackPeek.Domain.Resources;
+using RackPeek.Domain.Resources.Models;
+
+namespace RackPeek.Domain.UseCases.Cpus;
+
+public interface IAddCpuUseCase<T> : IResourceUseCase<T>
+    where T : Resource
+{
+    public Task ExecuteAsync(
+        string name,
+        string? model,
+        int? cores,
+        int? threads);
+}
+
+
+    
+public class AddCpuUseCase<T>(IResourceCollection repo) : IAddCpuUseCase<T> where T : Resource
+{
+    public async Task ExecuteAsync(
+        string name,
+        string? model,
+        int? cores,
+        int? threads)
+    {
+        // ToDo pass in properties as inputs, construct the entity in the usecase
+        // ToDo validate / normalize all inputs
+
+        name = Normalize.HardwareName(name);
+        ThrowIfInvalid.ResourceName(name);
+
+        var resource = await repo.GetByNameAsync(name);
+
+        if (resource is not ICpuResource cpuResource) return;
+
+        cpuResource.Cpus ??= [];
+
+        cpuResource.Cpus.Add(new Cpu
+        {
+            Model = model,
+            Cores = cores,
+            Threads = threads
+        });
+
+        await repo.UpdateAsync(resource);
+    }
+}

+ 39 - 0
RackPeek.Domain/UseCases/Cpus/RemoveCpuUseCase.cs

@@ -0,0 +1,39 @@
+using RackPeek.Domain.Helpers;
+using RackPeek.Domain.Persistence;
+using RackPeek.Domain.Resources;
+using RackPeek.Domain.Resources.Models;
+
+namespace RackPeek.Domain.UseCases.Cpus;
+
+public interface IRemoveCpuUseCase<T> : IResourceUseCase<T>
+    where T : Resource
+{
+    public Task ExecuteAsync(
+        string name,
+        int index);
+}
+
+
+    
+public class RemoveCpuUseCase<T>(IResourceCollection repo) : IRemoveCpuUseCase<T> where T : Resource
+{
+    public async Task ExecuteAsync(
+        string name,
+        int index)
+    {
+        name = Normalize.HardwareName(name);
+        ThrowIfInvalid.ResourceName(name);
+
+        var resource = await repo.GetByNameAsync(name);
+        if (resource is not ICpuResource cpuResource) return;
+
+        cpuResource.Cpus ??= [];
+
+        if (index < 0 || index >= cpuResource.Cpus.Count)
+            throw new ArgumentOutOfRangeException(nameof(index), "CPU index out of range.");
+
+        cpuResource.Cpus.RemoveAt(index);
+
+        await repo.UpdateAsync(resource);
+    }
+}

+ 52 - 0
RackPeek.Domain/UseCases/Cpus/UpdateCpuUseCase.cs

@@ -0,0 +1,52 @@
+using RackPeek.Domain.Helpers;
+using RackPeek.Domain.Persistence;
+using RackPeek.Domain.Resources;
+using RackPeek.Domain.Resources.Models;
+
+namespace RackPeek.Domain.UseCases.Cpus;
+
+public interface IUpdateCpuUseCase<T> : IResourceUseCase<T>
+    where T : Resource
+{
+    public Task ExecuteAsync(
+        string name,
+        int index,
+        string? model,
+        int? cores,
+        int? threads);
+}
+
+
+    
+public class UpdateCpuUseCase<T>(IResourceCollection repo) : IUpdateCpuUseCase<T> where T : Resource
+{
+    public async Task ExecuteAsync(
+        string name,
+        int index,
+        string? model,
+        int? cores,
+        int? threads)
+    {
+        // ToDo pass in properties as inputs, construct the entity in the usecase
+        // ToDo validate / normalize all inputs
+
+        name = Normalize.HardwareName(name);
+        ThrowIfInvalid.ResourceName(name);
+
+        var resource = await repo.GetByNameAsync(name);
+
+        if (resource is not ICpuResource cpuResource) return;
+
+        cpuResource.Cpus ??= [];
+
+        if (index < 0 || index >= cpuResource.Cpus.Count)
+            throw new ArgumentOutOfRangeException(nameof(index), "CPU index out of range.");
+
+        var cpu = cpuResource.Cpus[index];
+        cpu.Model = model;
+        cpu.Cores = cores;
+        cpu.Threads = threads;
+
+        await repo.UpdateAsync(resource);
+    }
+}

+ 46 - 0
RackPeek.Domain/UseCases/Drives/AddDriveUseCase.cs

@@ -0,0 +1,46 @@
+using RackPeek.Domain.Helpers;
+using RackPeek.Domain.Persistence;
+using RackPeek.Domain.Resources;
+using RackPeek.Domain.Resources.Models;
+
+namespace RackPeek.Domain.UseCases.Drives;
+
+public interface IAddDriveUseCase<T> : IResourceUseCase<T>
+    where T : Resource
+{
+    public Task ExecuteAsync(
+        string name,
+        string? type,
+        int? size);
+}
+
+public class AddDriveUseCase<T>(IResourceCollection repository): IAddDriveUseCase<T> where T : Resource
+{
+    public async Task ExecuteAsync(
+        string name,
+        string? type,
+        int? size)
+    {
+        // ToDo pass in properties as inputs, construct the entity in the usecase, ensure optional inputs are nullable
+        // ToDo validate / normalize all inputs
+
+        name = Normalize.HardwareName(name);
+        ThrowIfInvalid.ResourceName(name);
+
+        var resource = await repository.GetByNameAsync(name) ?? throw new NotFoundException($"Resource '{name}' not found.");
+
+        if (resource is not IDriveResource dr)
+        {
+            throw new NotFoundException($"Resource '{name}' not found.");
+        }
+        
+        dr.Drives ??= new List<Drive>();
+        dr.Drives.Add(new Drive
+        {
+            Type = type,
+            Size = size
+        });
+
+        await repository.UpdateAsync(resource);
+    }
+}

+ 37 - 0
RackPeek.Domain/UseCases/Drives/RemoveDriveUseCase.cs

@@ -0,0 +1,37 @@
+using RackPeek.Domain.Helpers;
+using RackPeek.Domain.Persistence;
+using RackPeek.Domain.Resources;
+using RackPeek.Domain.Resources.Models;
+
+namespace RackPeek.Domain.UseCases.Drives;
+
+public interface IRemoveDriveUseCase<T> : IResourceUseCase<T>
+    where T : Resource
+{
+    public Task ExecuteAsync(string name, int index);
+}
+
+
+    
+public class RemoveDriveUseCase<T>(IResourceCollection repository) : IRemoveDriveUseCase<T> where T : Resource
+{
+    public async Task ExecuteAsync(string name, int index)
+    {
+        name = Normalize.HardwareName(name);
+        ThrowIfInvalid.ResourceName(name);
+
+        var resource = await repository.GetByNameAsync(name) ?? throw new NotFoundException($"Resource '{name}' not found.");
+
+        if (resource is not IDriveResource dr)
+        {
+            throw new NotFoundException($"Resource '{name}' not found.");
+        }
+
+        if (dr.Drives == null || index < 0 || index >= dr.Drives.Count)
+            throw new NotFoundException($"Drive index {index} not found on '{name}'.");
+
+        dr.Drives.RemoveAt(index);
+
+        await repository.UpdateAsync(resource);
+    }
+}

+ 43 - 0
RackPeek.Domain/UseCases/Drives/UpdateDriveUseCase.cs

@@ -0,0 +1,43 @@
+using RackPeek.Domain.Helpers;
+using RackPeek.Domain.Persistence;
+using RackPeek.Domain.Resources;
+using RackPeek.Domain.Resources.Models;
+
+namespace RackPeek.Domain.UseCases.Drives;
+
+public interface IUpdateDriveUseCase<T> : IResourceUseCase<T>
+    where T : Resource
+{
+    public Task ExecuteAsync(string name, int index, string? type, int? size);
+}
+
+
+
+public class UpdateDriveUseCase<T>(IResourceCollection repository) : IUpdateDriveUseCase<T> where T : Resource
+{
+    public async Task ExecuteAsync(string name, int index, string? type, int? size)
+    {
+        // ToDo pass in properties as inputs, construct the entity in the usecase, ensure optional inputs are nullable
+        // ToDo validate / normalize all inputs
+
+        name = Normalize.HardwareName(name);
+        ThrowIfInvalid.ResourceName(name);
+
+        var resource = await repository.GetByNameAsync(name) ?? throw new NotFoundException($"Resource '{name}' not found.");
+
+        if (resource is not IDriveResource dr)
+        {
+            throw new NotFoundException($"Resource '{name}' not found.");
+        }
+
+
+        if (dr.Drives == null || index < 0 || index >= dr.Drives.Count)
+            throw new NotFoundException($"Drive index {index} not found on '{name}'.");
+
+        var drive = dr.Drives[index];
+        drive.Type = type;
+        drive.Size = size;
+
+        await repository.UpdateAsync(resource);
+    }
+}

+ 1 - 0
RackPeek.Web.Viewer/Program.cs

@@ -8,6 +8,7 @@ using RackPeek.Domain.Resources;
 using RackPeek.Domain.Resources.Hardware;
 using RackPeek.Domain.Resources.Services;
 using RackPeek.Domain.Resources.SystemResources;
+using Shared.Rcl;
 
 namespace RackPeek.Web.Viewer;
 

+ 0 - 1
RackPeek.Web/Program.cs

@@ -8,7 +8,6 @@ using RackPeek.Domain.Resources.Hardware;
 using RackPeek.Domain.Resources.Services;
 using RackPeek.Domain.Resources.SystemResources;
 using RackPeek.Web.Components;
-using RackPeek.Yaml;
 using Shared.Rcl;
 
 namespace RackPeek.Web;

+ 1 - 0
RackPeek/Program.cs

@@ -2,6 +2,7 @@
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.Logging;
 using RackPeek.Spectre;
+using Shared.Rcl;
 using Spectre.Console.Cli;
 
 namespace RackPeek;

+ 1 - 1
RackPeek/RackPeek.csproj

@@ -5,7 +5,7 @@
         <TargetFramework>net10.0</TargetFramework>
         <ImplicitUsings>enable</ImplicitUsings>
         <Nullable>enable</Nullable>
-        <AssemblyVersion>v0.0.11</AssemblyVersion>
+        <AssemblyVersion>0.0.11</AssemblyVersion>
     </PropertyGroup>
 
     <ItemGroup>

+ 2 - 0
Shared.Rcl/AnsiToHtml.cs

@@ -1,5 +1,7 @@
 using System.Text.RegularExpressions;
 
+namespace Shared.Rcl;
+
 public static class AnsiStripper
 {
     private static readonly Regex CsiRegex =

+ 26 - 31
Shared.Rcl/CliBootstrap.cs

@@ -1,44 +1,39 @@
 using System.ComponentModel.DataAnnotations;
 using Microsoft.Extensions.Configuration;
 using Microsoft.Extensions.DependencyInjection;
-using RackPeek.Commands;
-using RackPeek.Commands.AccessPoints;
-using RackPeek.Commands.Desktops;
-using RackPeek.Commands.Desktops.Cpus;
-using RackPeek.Commands.Desktops.Drive;
-using RackPeek.Commands.Desktops.Gpus;
-using RackPeek.Commands.Desktops.Nics;
-using RackPeek.Commands.Firewalls;
-using RackPeek.Commands.Firewalls.Ports;
-using RackPeek.Commands.Laptops;
-using RackPeek.Commands.Laptops.Cpus;
-using RackPeek.Commands.Laptops.Drive;
-using RackPeek.Commands.Laptops.Gpus;
-using RackPeek.Commands.Routers;
-using RackPeek.Commands.Routers.Ports;
-using RackPeek.Commands.Servers;
-using RackPeek.Commands.Servers.Cpus;
-using RackPeek.Commands.Servers.Drives;
-using RackPeek.Commands.Servers.Gpus;
-using RackPeek.Commands.Servers.Nics;
-using RackPeek.Commands.Services;
-using RackPeek.Commands.Switches;
-using RackPeek.Commands.Switches.Ports;
-using RackPeek.Commands.Systems;
-using RackPeek.Commands.Ups;
 using RackPeek.Domain;
 using RackPeek.Domain.Helpers;
 using RackPeek.Domain.Persistence;
 using RackPeek.Domain.Persistence.Yaml;
-using RackPeek.Domain.Resources;
-using RackPeek.Domain.Resources.Hardware;
-using RackPeek.Domain.Resources.Services;
-using RackPeek.Domain.Resources.SystemResources;
-using RackPeek.Yaml;
+using Shared.Rcl.Commands;
+using Shared.Rcl.Commands.AccessPoints;
+using Shared.Rcl.Commands.Desktops;
+using Shared.Rcl.Commands.Desktops.Cpus;
+using Shared.Rcl.Commands.Desktops.Drive;
+using Shared.Rcl.Commands.Desktops.Gpus;
+using Shared.Rcl.Commands.Desktops.Nics;
+using Shared.Rcl.Commands.Firewalls;
+using Shared.Rcl.Commands.Firewalls.Ports;
+using Shared.Rcl.Commands.Laptops;
+using Shared.Rcl.Commands.Laptops.Cpus;
+using Shared.Rcl.Commands.Laptops.Drive;
+using Shared.Rcl.Commands.Laptops.Gpus;
+using Shared.Rcl.Commands.Routers;
+using Shared.Rcl.Commands.Routers.Ports;
+using Shared.Rcl.Commands.Servers;
+using Shared.Rcl.Commands.Servers.Cpus;
+using Shared.Rcl.Commands.Servers.Drives;
+using Shared.Rcl.Commands.Servers.Gpus;
+using Shared.Rcl.Commands.Servers.Nics;
+using Shared.Rcl.Commands.Services;
+using Shared.Rcl.Commands.Switches;
+using Shared.Rcl.Commands.Switches.Ports;
+using Shared.Rcl.Commands.Systems;
+using Shared.Rcl.Commands.Ups;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek;
+namespace Shared.Rcl;
 
 public static class CliBootstrap
 {

+ 1 - 1
Shared.Rcl/Commands/AccessPoints/AccessCommands.cs

@@ -1,7 +1,7 @@
 using System.ComponentModel;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.AccessPoints;
+namespace Shared.Rcl.Commands.AccessPoints;
 
 public class AccessPointNameSettings : CommandSettings
 {

+ 1 - 2
Shared.Rcl/Commands/AccessPoints/AccessPointAddCommand.cs

@@ -1,12 +1,11 @@
 using System.ComponentModel;
 using Microsoft.Extensions.DependencyInjection;
-using RackPeek.Domain.Resources.Hardware.AccessPoints;
 using RackPeek.Domain.Resources.Models;
 using RackPeek.Domain.UseCases;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.AccessPoints;
+namespace Shared.Rcl.Commands.AccessPoints;
 
 public class AccessPointAddSettings : CommandSettings
 {

+ 1 - 2
Shared.Rcl/Commands/AccessPoints/AccessPointDeleteCommand.cs

@@ -1,11 +1,10 @@
 using Microsoft.Extensions.DependencyInjection;
-using RackPeek.Domain.Resources.Hardware.AccessPoints;
 using RackPeek.Domain.Resources.Models;
 using RackPeek.Domain.UseCases;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.AccessPoints;
+namespace Shared.Rcl.Commands.AccessPoints;
 
 public class AccessPointDeleteCommand(
     IServiceProvider serviceProvider

+ 1 - 2
Shared.Rcl/Commands/AccessPoints/AccessPointDescribeCommand.cs

@@ -1,11 +1,10 @@
 using Microsoft.Extensions.DependencyInjection;
-using RackPeek.Domain.Resources.Hardware.AccessPoints;
 using RackPeek.Domain.Resources.Models;
 using RackPeek.Domain.UseCases;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.AccessPoints;
+namespace Shared.Rcl.Commands.AccessPoints;
 
 public class AccessPointDescribeCommand(
     IServiceProvider serviceProvider

+ 1 - 2
Shared.Rcl/Commands/AccessPoints/AccessPointGetByNameCommand.cs

@@ -1,11 +1,10 @@
 using Microsoft.Extensions.DependencyInjection;
-using RackPeek.Domain.Resources.Hardware.AccessPoints;
 using RackPeek.Domain.Resources.Models;
 using RackPeek.Domain.UseCases;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.AccessPoints;
+namespace Shared.Rcl.Commands.AccessPoints;
 
 public class AccessPointGetByNameCommand(
     IServiceProvider serviceProvider

+ 1 - 1
Shared.Rcl/Commands/AccessPoints/AccessPointGetCommand.cs

@@ -3,7 +3,7 @@ using RackPeek.Domain.Resources.Hardware.AccessPoints;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.AccessPoints;
+namespace Shared.Rcl.Commands.AccessPoints;
 
 public class AccessPointGetCommand(
     IServiceProvider serviceProvider

+ 1 - 1
Shared.Rcl/Commands/AccessPoints/AccessPointReportCommand.cs

@@ -4,7 +4,7 @@ using RackPeek.Domain.Resources.Hardware.AccessPoints;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.AccessPoints;
+namespace Shared.Rcl.Commands.AccessPoints;
 
 public class AccessPointReportCommand(
     ILogger<AccessPointReportCommand> logger,

+ 2 - 2
Shared.Rcl/Commands/AccessPoints/AccessPointSetCommand.cs

@@ -1,11 +1,11 @@
 using System.ComponentModel;
 using Microsoft.Extensions.DependencyInjection;
-using RackPeek.Commands.Servers;
 using RackPeek.Domain.Resources.Hardware.AccessPoints;
+using Shared.Rcl.Commands.Servers;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.AccessPoints;
+namespace Shared.Rcl.Commands.AccessPoints;
 
 public class AccessPointSetSettings : ServerNameSettings
 {

+ 4 - 3
Shared.Rcl/Commands/Desktops/Cpus/DesktopCpuAddCommand.cs

@@ -1,9 +1,10 @@
 using Microsoft.Extensions.DependencyInjection;
-using RackPeek.Domain.Resources.Hardware.Desktops.Cpus;
+using RackPeek.Domain.Resources.Models;
+using RackPeek.Domain.UseCases.Cpus;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Desktops.Cpus;
+namespace Shared.Rcl.Commands.Desktops.Cpus;
 
 public class DesktopCpuAddCommand(IServiceProvider provider)
     : AsyncCommand<DesktopCpuAddSettings>
@@ -14,7 +15,7 @@ public class DesktopCpuAddCommand(IServiceProvider provider)
         CancellationToken cancellationToken)
     {
         using var scope = provider.CreateScope();
-        var useCase = scope.ServiceProvider.GetRequiredService<AddDesktopCpuUseCase>();
+        var useCase = scope.ServiceProvider.GetRequiredService<IAddCpuUseCase<Desktop>>();
 
         await useCase.ExecuteAsync(settings.DesktopName, settings.Model, settings.Cores, settings.Threads);
 

+ 1 - 1
Shared.Rcl/Commands/Desktops/Cpus/DesktopCpuAddSettings.cs

@@ -1,7 +1,7 @@
 using System.ComponentModel;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Desktops.Cpus;
+namespace Shared.Rcl.Commands.Desktops.Cpus;
 
 public class DesktopCpuAddSettings : CommandSettings
 {

+ 4 - 3
Shared.Rcl/Commands/Desktops/Cpus/DesktopCpuRemoveCommand.cs

@@ -1,9 +1,10 @@
 using Microsoft.Extensions.DependencyInjection;
-using RackPeek.Domain.Resources.Hardware.Desktops.Cpus;
+using RackPeek.Domain.Resources.Models;
+using RackPeek.Domain.UseCases.Cpus;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Desktops.Cpus;
+namespace Shared.Rcl.Commands.Desktops.Cpus;
 
 public class DesktopCpuRemoveCommand(IServiceProvider provider)
     : AsyncCommand<DesktopCpuRemoveSettings>
@@ -14,7 +15,7 @@ public class DesktopCpuRemoveCommand(IServiceProvider provider)
         CancellationToken cancellationToken)
     {
         using var scope = provider.CreateScope();
-        var useCase = scope.ServiceProvider.GetRequiredService<RemoveDesktopCpuUseCase>();
+        var useCase = scope.ServiceProvider.GetRequiredService<IRemoveCpuUseCase<Desktop>>();
 
         await useCase.ExecuteAsync(settings.DesktopName, settings.Index);
 

+ 1 - 1
Shared.Rcl/Commands/Desktops/Cpus/DesktopCpuRemoveSettings.cs

@@ -1,7 +1,7 @@
 using System.ComponentModel;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Desktops.Cpus;
+namespace Shared.Rcl.Commands.Desktops.Cpus;
 
 public class DesktopCpuRemoveSettings : CommandSettings
 {

+ 4 - 3
Shared.Rcl/Commands/Desktops/Cpus/DesktopCpuSetCommand.cs

@@ -1,9 +1,10 @@
 using Microsoft.Extensions.DependencyInjection;
-using RackPeek.Domain.Resources.Hardware.Desktops.Cpus;
+using RackPeek.Domain.Resources.Models;
+using RackPeek.Domain.UseCases.Cpus;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Desktops.Cpus;
+namespace Shared.Rcl.Commands.Desktops.Cpus;
 
 public class DesktopCpuSetCommand(IServiceProvider provider)
     : AsyncCommand<DesktopCpuSetSettings>
@@ -14,7 +15,7 @@ public class DesktopCpuSetCommand(IServiceProvider provider)
         CancellationToken cancellationToken)
     {
         using var scope = provider.CreateScope();
-        var useCase = scope.ServiceProvider.GetRequiredService<UpdateDesktopCpuUseCase>();
+        var useCase = scope.ServiceProvider.GetRequiredService<IUpdateCpuUseCase<Desktop>>();
 
         await useCase.ExecuteAsync(settings.DesktopName, settings.Index, settings.Model, settings.Cores,
             settings.Threads);

+ 1 - 1
Shared.Rcl/Commands/Desktops/Cpus/DesktopCpuSetSettings.cs

@@ -1,7 +1,7 @@
 using System.ComponentModel;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Desktops.Cpus;
+namespace Shared.Rcl.Commands.Desktops.Cpus;
 
 public class DesktopCpuSetSettings : CommandSettings
 {

+ 1 - 2
Shared.Rcl/Commands/Desktops/DesktopAddCommand.cs

@@ -1,11 +1,10 @@
 using Microsoft.Extensions.DependencyInjection;
-using RackPeek.Domain.Resources.Hardware.Desktops;
 using RackPeek.Domain.Resources.Models;
 using RackPeek.Domain.UseCases;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Desktops;
+namespace Shared.Rcl.Commands.Desktops;
 
 public class DesktopAddCommand(IServiceProvider provider)
     : AsyncCommand<DesktopNameSettings>

+ 1 - 1
Shared.Rcl/Commands/Desktops/DesktopCommands.cs

@@ -1,6 +1,6 @@
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Desktops;
+namespace Shared.Rcl.Commands.Desktops;
 
 public class DesktopNameSettings : CommandSettings
 {

+ 1 - 2
Shared.Rcl/Commands/Desktops/DesktopDeleteCommand.cs

@@ -1,11 +1,10 @@
 using Microsoft.Extensions.DependencyInjection;
-using RackPeek.Domain.Resources.Hardware.Desktops;
 using RackPeek.Domain.Resources.Models;
 using RackPeek.Domain.UseCases;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Desktops;
+namespace Shared.Rcl.Commands.Desktops;
 
 public class DesktopDeleteCommand(IServiceProvider provider)
     : AsyncCommand<DesktopNameSettings>

+ 1 - 1
Shared.Rcl/Commands/Desktops/DesktopDescribeCommand.cs

@@ -3,7 +3,7 @@ using RackPeek.Domain.Resources.Hardware.Desktops;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Desktops;
+namespace Shared.Rcl.Commands.Desktops;
 
 public class DesktopDescribeCommand(IServiceProvider provider)
     : AsyncCommand<DesktopNameSettings>

+ 1 - 2
Shared.Rcl/Commands/Desktops/DesktopGetByNameCommand.cs

@@ -1,11 +1,10 @@
 using Microsoft.Extensions.DependencyInjection;
-using RackPeek.Domain.Resources.Hardware.Desktops;
 using RackPeek.Domain.Resources.Models;
 using RackPeek.Domain.UseCases;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Desktops;
+namespace Shared.Rcl.Commands.Desktops;
 
 public class DesktopGetByNameCommand(IServiceProvider provider)
     : AsyncCommand<DesktopNameSettings>

+ 1 - 2
Shared.Rcl/Commands/Desktops/DesktopGetCommand.cs

@@ -1,11 +1,10 @@
 using Microsoft.Extensions.DependencyInjection;
-using RackPeek.Domain.Resources.Hardware.Desktops;
 using RackPeek.Domain.Resources.Models;
 using RackPeek.Domain.UseCases;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Desktops;
+namespace Shared.Rcl.Commands.Desktops;
 
 public class DesktopGetCommand(IServiceProvider provider)
     : AsyncCommand

+ 1 - 1
Shared.Rcl/Commands/Desktops/DesktopReportCommand.cs

@@ -4,7 +4,7 @@ using RackPeek.Domain.Resources.Hardware.Desktops;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Desktops;
+namespace Shared.Rcl.Commands.Desktops;
 
 public class DesktopReportCommand(
     ILogger<DesktopReportCommand> logger,

+ 1 - 1
Shared.Rcl/Commands/Desktops/DesktopSetCommand.cs

@@ -3,7 +3,7 @@ using RackPeek.Domain.Resources.Hardware.Desktops;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Desktops;
+namespace Shared.Rcl.Commands.Desktops;
 
 public class DesktopSetSettings : DesktopNameSettings
 {

+ 1 - 1
Shared.Rcl/Commands/Desktops/DesktopTreeCommand.cs

@@ -2,7 +2,7 @@ using RackPeek.Domain.Resources.Hardware;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Desktops;
+namespace Shared.Rcl.Commands.Desktops;
 
 public sealed class DesktopTreeCommand(GetHardwareSystemTreeUseCase useCase)
     : AsyncCommand<DesktopNameSettings>

+ 4 - 3
Shared.Rcl/Commands/Desktops/Drive/DesktopDriveAddCommand.cs

@@ -1,9 +1,10 @@
 using Microsoft.Extensions.DependencyInjection;
-using RackPeek.Domain.Resources.Hardware.Desktops.Drives;
+using RackPeek.Domain.Resources.Models;
+using RackPeek.Domain.UseCases.Drives;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Desktops.Drive;
+namespace Shared.Rcl.Commands.Desktops.Drive;
 
 public class DesktopDriveAddCommand(IServiceProvider provider)
     : AsyncCommand<DesktopDriveAddSettings>
@@ -14,7 +15,7 @@ public class DesktopDriveAddCommand(IServiceProvider provider)
         CancellationToken cancellationToken)
     {
         using var scope = provider.CreateScope();
-        var useCase = scope.ServiceProvider.GetRequiredService<AddDesktopDriveUseCase>();
+        var useCase = scope.ServiceProvider.GetRequiredService<IAddDriveUseCase<Desktop>>();
 
         await useCase.ExecuteAsync(settings.DesktopName, settings.Type, settings.Size);
 

+ 1 - 1
Shared.Rcl/Commands/Desktops/Drive/DesktopDriveAddSettings.cs

@@ -1,7 +1,7 @@
 using System.ComponentModel;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Desktops.Drive;
+namespace Shared.Rcl.Commands.Desktops.Drive;
 
 public class DesktopDriveAddSettings : CommandSettings
 {

+ 4 - 3
Shared.Rcl/Commands/Desktops/Drive/DesktopDriveRemoveCommand.cs

@@ -1,9 +1,10 @@
 using Microsoft.Extensions.DependencyInjection;
-using RackPeek.Domain.Resources.Hardware.Desktops.Drives;
+using RackPeek.Domain.Resources.Models;
+using RackPeek.Domain.UseCases.Drives;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Desktops.Drive;
+namespace Shared.Rcl.Commands.Desktops.Drive;
 
 public class DesktopDriveRemoveCommand(IServiceProvider provider)
     : AsyncCommand<DesktopDriveRemoveSettings>
@@ -14,7 +15,7 @@ public class DesktopDriveRemoveCommand(IServiceProvider provider)
         CancellationToken cancellationToken)
     {
         using var scope = provider.CreateScope();
-        var useCase = scope.ServiceProvider.GetRequiredService<RemoveDesktopDriveUseCase>();
+        var useCase = scope.ServiceProvider.GetRequiredService<IRemoveDriveUseCase<Desktop>>();
 
         await useCase.ExecuteAsync(settings.DesktopName, settings.Index);
 

+ 1 - 1
Shared.Rcl/Commands/Desktops/Drive/DesktopDriveRemoveSettings.cs

@@ -1,7 +1,7 @@
 using System.ComponentModel;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Desktops.Drive;
+namespace Shared.Rcl.Commands.Desktops.Drive;
 
 public class DesktopDriveRemoveSettings : CommandSettings
 {

+ 4 - 3
Shared.Rcl/Commands/Desktops/Drive/DesktopDriveSetCommand.cs

@@ -1,9 +1,10 @@
 using Microsoft.Extensions.DependencyInjection;
-using RackPeek.Domain.Resources.Hardware.Desktops.Drives;
+using RackPeek.Domain.Resources.Models;
+using RackPeek.Domain.UseCases.Drives;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Desktops.Drive;
+namespace Shared.Rcl.Commands.Desktops.Drive;
 
 public class DesktopDriveSetCommand(IServiceProvider provider)
     : AsyncCommand<DesktopDriveSetSettings>
@@ -14,7 +15,7 @@ public class DesktopDriveSetCommand(IServiceProvider provider)
         CancellationToken cancellationToken)
     {
         using var scope = provider.CreateScope();
-        var useCase = scope.ServiceProvider.GetRequiredService<UpdateDesktopDriveUseCase>();
+        var useCase = scope.ServiceProvider.GetRequiredService<IUpdateDriveUseCase<Desktop>>();
 
         await useCase.ExecuteAsync(settings.DesktopName, settings.Index, settings.Type, settings.Size);
 

+ 1 - 1
Shared.Rcl/Commands/Desktops/Drive/DesktopDriveSetSettings.cs

@@ -1,7 +1,7 @@
 using System.ComponentModel;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Desktops.Drive;
+namespace Shared.Rcl.Commands.Desktops.Drive;
 
 public class DesktopDriveSetSettings : CommandSettings
 {

+ 1 - 1
Shared.Rcl/Commands/Desktops/Gpus/DesktopGpuAddCommand.cs

@@ -3,7 +3,7 @@ using RackPeek.Domain.Resources.Hardware.Desktops.Gpus;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Desktops.Gpus;
+namespace Shared.Rcl.Commands.Desktops.Gpus;
 
 public class DesktopGpuAddCommand(IServiceProvider provider)
     : AsyncCommand<DesktopGpuAddSettings>

+ 1 - 1
Shared.Rcl/Commands/Desktops/Gpus/DesktopGpuAddSettings.cs

@@ -1,7 +1,7 @@
 using System.ComponentModel;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Desktops.Gpus;
+namespace Shared.Rcl.Commands.Desktops.Gpus;
 
 public class DesktopGpuAddSettings : CommandSettings
 {

+ 1 - 1
Shared.Rcl/Commands/Desktops/Gpus/DesktopGpuRemoveCommand.cs

@@ -3,7 +3,7 @@ using RackPeek.Domain.Resources.Hardware.Desktops.Gpus;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Desktops.Gpus;
+namespace Shared.Rcl.Commands.Desktops.Gpus;
 
 public class DesktopGpuRemoveCommand(IServiceProvider provider)
     : AsyncCommand<DesktopGpuRemoveSettings>

+ 1 - 1
Shared.Rcl/Commands/Desktops/Gpus/DesktopGpuRemoveSettings.cs

@@ -1,7 +1,7 @@
 using System.ComponentModel;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Desktops.Gpus;
+namespace Shared.Rcl.Commands.Desktops.Gpus;
 
 public class DesktopGpuRemoveSettings : CommandSettings
 {

+ 1 - 1
Shared.Rcl/Commands/Desktops/Gpus/DesktopGpuSetCommand.cs

@@ -3,7 +3,7 @@ using RackPeek.Domain.Resources.Hardware.Desktops.Gpus;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Desktops.Gpus;
+namespace Shared.Rcl.Commands.Desktops.Gpus;
 
 public class DesktopGpuSetCommand(IServiceProvider provider)
     : AsyncCommand<DesktopGpuSetSettings>

+ 1 - 1
Shared.Rcl/Commands/Desktops/Gpus/DesktopGpuSetSettings.cs

@@ -1,7 +1,7 @@
 using System.ComponentModel;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Desktops.Gpus;
+namespace Shared.Rcl.Commands.Desktops.Gpus;
 
 public class DesktopGpuSetSettings : CommandSettings
 {

+ 1 - 1
Shared.Rcl/Commands/Desktops/Nics/DesktopNicAddCommand.cs

@@ -3,7 +3,7 @@ using RackPeek.Domain.Resources.Hardware.Desktops.Nics;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Desktops.Nics;
+namespace Shared.Rcl.Commands.Desktops.Nics;
 
 public class DesktopNicAddCommand(IServiceProvider provider)
     : AsyncCommand<DesktopNicAddSettings>

+ 1 - 1
Shared.Rcl/Commands/Desktops/Nics/DesktopNicAddSettings.cs

@@ -1,7 +1,7 @@
 using System.ComponentModel;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Desktops.Nics;
+namespace Shared.Rcl.Commands.Desktops.Nics;
 
 public class DesktopNicAddSettings : CommandSettings
 {

+ 1 - 1
Shared.Rcl/Commands/Desktops/Nics/DesktopNicRemoveCommand.cs

@@ -3,7 +3,7 @@ using RackPeek.Domain.Resources.Hardware.Desktops.Nics;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Desktops.Nics;
+namespace Shared.Rcl.Commands.Desktops.Nics;
 
 public class DesktopNicRemoveCommand(IServiceProvider provider)
     : AsyncCommand<DesktopNicRemoveSettings>

+ 1 - 1
Shared.Rcl/Commands/Desktops/Nics/DesktopNicRemoveSettings.cs

@@ -1,7 +1,7 @@
 using System.ComponentModel;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Desktops.Nics;
+namespace Shared.Rcl.Commands.Desktops.Nics;
 
 public class DesktopNicRemoveSettings : CommandSettings
 {

+ 1 - 1
Shared.Rcl/Commands/Desktops/Nics/DesktopNicSetCommand.cs

@@ -3,7 +3,7 @@ using RackPeek.Domain.Resources.Hardware.Desktops.Nics;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Desktops.Nics;
+namespace Shared.Rcl.Commands.Desktops.Nics;
 
 public class DesktopNicSetCommand(IServiceProvider provider)
     : AsyncCommand<DesktopNicSetSettings>

+ 1 - 1
Shared.Rcl/Commands/Desktops/Nics/DesktopNicSetSettings.cs

@@ -1,7 +1,7 @@
 using System.ComponentModel;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Desktops.Nics;
+namespace Shared.Rcl.Commands.Desktops.Nics;
 
 public class DesktopNicSetSettings : CommandSettings
 {

+ 1 - 2
Shared.Rcl/Commands/Firewalls/FirewallAddCommand.cs

@@ -1,11 +1,10 @@
 using Microsoft.Extensions.DependencyInjection;
-using RackPeek.Domain.Resources.Hardware.Firewalls;
 using RackPeek.Domain.Resources.Models;
 using RackPeek.Domain.UseCases;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Firewalls;
+namespace Shared.Rcl.Commands.Firewalls;
 
 public class FirewallAddSettings : CommandSettings
 {

+ 1 - 1
Shared.Rcl/Commands/Firewalls/FirewallCommands.cs

@@ -1,6 +1,6 @@
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Firewalls;
+namespace Shared.Rcl.Commands.Firewalls;
 
 public class FirewallNameSettings : CommandSettings
 {

+ 1 - 2
Shared.Rcl/Commands/Firewalls/FirewallDeleteCommand.cs

@@ -1,11 +1,10 @@
 using Microsoft.Extensions.DependencyInjection;
-using RackPeek.Domain.Resources.Hardware.Firewalls;
 using RackPeek.Domain.Resources.Models;
 using RackPeek.Domain.UseCases;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Firewalls;
+namespace Shared.Rcl.Commands.Firewalls;
 
 public class FirewallDeleteCommand(
     IServiceProvider serviceProvider

+ 1 - 1
Shared.Rcl/Commands/Firewalls/FirewallDescribeCommand.cs

@@ -3,7 +3,7 @@ using RackPeek.Domain.Resources.Hardware.Firewalls;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Firewalls;
+namespace Shared.Rcl.Commands.Firewalls;
 
 public class FirewallDescribeCommand(
     IServiceProvider serviceProvider

+ 1 - 1
Shared.Rcl/Commands/Firewalls/FirewallGetByNameCommand.cs

@@ -3,7 +3,7 @@ using RackPeek.Domain.Resources.Hardware.Firewalls;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Firewalls;
+namespace Shared.Rcl.Commands.Firewalls;
 
 public class FirewallGetByNameCommand(
     IServiceProvider serviceProvider

+ 1 - 1
Shared.Rcl/Commands/Firewalls/FirewallGetCommand.cs

@@ -3,7 +3,7 @@ using RackPeek.Domain.Resources.Hardware.Firewalls;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Firewalls;
+namespace Shared.Rcl.Commands.Firewalls;
 
 public class FirewallGetCommand(
     IServiceProvider serviceProvider

+ 1 - 1
Shared.Rcl/Commands/Firewalls/FirewallReportCommand.cs

@@ -4,7 +4,7 @@ using RackPeek.Domain.Resources.Hardware.Firewalls;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Firewalls;
+namespace Shared.Rcl.Commands.Firewalls;
 
 public class FirewallReportCommand(
     ILogger<FirewallReportCommand> logger,

+ 2 - 2
Shared.Rcl/Commands/Firewalls/FirewallSetCommand.cs

@@ -1,10 +1,10 @@
 using Microsoft.Extensions.DependencyInjection;
-using RackPeek.Commands.Servers;
 using RackPeek.Domain.Resources.Hardware.Firewalls;
+using Shared.Rcl.Commands.Servers;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Firewalls;
+namespace Shared.Rcl.Commands.Firewalls;
 
 public class FirewallSetSettings : ServerNameSettings
 {

+ 2 - 3
Shared.Rcl/Commands/Firewalls/Ports/FirewallPortAddCommand.cs

@@ -1,10 +1,9 @@
-using Spectre.Console.Cli;
-using System.ComponentModel;
 using Microsoft.Extensions.DependencyInjection;
 using RackPeek.Domain.Resources.Hardware.Firewalls.Ports;
 using Spectre.Console;
+using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Firewalls.Ports;
+namespace Shared.Rcl.Commands.Firewalls.Ports;
 
 public class FirewallPortAddSettings : FirewallNameSettings
 {

+ 2 - 3
Shared.Rcl/Commands/Firewalls/Ports/FirewallPortRemoveCommand.cs

@@ -1,10 +1,9 @@
-using Spectre.Console.Cli;
-using System.ComponentModel;
 using Microsoft.Extensions.DependencyInjection;
 using RackPeek.Domain.Resources.Hardware.Firewalls.Ports;
 using Spectre.Console;
+using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Firewalls.Ports;
+namespace Shared.Rcl.Commands.Firewalls.Ports;
 
 public class FirewallPortRemoveSettings : FirewallNameSettings
 {

+ 2 - 3
Shared.Rcl/Commands/Firewalls/Ports/FirewallPortUpdateCommand.cs

@@ -1,10 +1,9 @@
-using Spectre.Console.Cli;
-using System.ComponentModel;
 using Microsoft.Extensions.DependencyInjection;
 using RackPeek.Domain.Resources.Hardware.Firewalls.Ports;
 using Spectre.Console;
+using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Firewalls.Ports;
+namespace Shared.Rcl.Commands.Firewalls.Ports;
 
 public class FirewallPortUpdateSettings : FirewallNameSettings
 {

+ 1 - 1
Shared.Rcl/Commands/GetTotalSummaryCommand.cs

@@ -5,7 +5,7 @@ using RackPeek.Domain.Resources.SystemResources.UseCases;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands;
+namespace Shared.Rcl.Commands;
 
 public class GetTotalSummaryCommand(IServiceProvider provider) : AsyncCommand
 {

+ 4 - 3
Shared.Rcl/Commands/Laptops/Cpus/LaptopCpuAddCommand.cs

@@ -1,9 +1,10 @@
 using Microsoft.Extensions.DependencyInjection;
-using RackPeek.Domain.Resources.Hardware.Laptops.Cpus;
+using RackPeek.Domain.Resources.Models;
+using RackPeek.Domain.UseCases.Cpus;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Laptops.Cpus;
+namespace Shared.Rcl.Commands.Laptops.Cpus;
 
 public class LaptopCpuAddCommand(IServiceProvider provider)
     : AsyncCommand<LaptopCpuAddSettings>
@@ -14,7 +15,7 @@ public class LaptopCpuAddCommand(IServiceProvider provider)
         CancellationToken cancellationToken)
     {
         using var scope = provider.CreateScope();
-        var useCase = scope.ServiceProvider.GetRequiredService<AddLaptopCpuUseCase>();
+        var useCase = scope.ServiceProvider.GetRequiredService<IAddCpuUseCase<Laptop>>();
 
         await useCase.ExecuteAsync(settings.LaptopName, settings.Model, settings.Cores, settings.Threads);
 

+ 1 - 1
Shared.Rcl/Commands/Laptops/Cpus/LaptopCpuAddSettings.cs

@@ -1,7 +1,7 @@
 using System.ComponentModel;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Laptops.Cpus;
+namespace Shared.Rcl.Commands.Laptops.Cpus;
 
 public class LaptopCpuAddSettings : CommandSettings
 {

+ 4 - 3
Shared.Rcl/Commands/Laptops/Cpus/LaptopCpuRemoveCommand.cs

@@ -1,9 +1,10 @@
 using Microsoft.Extensions.DependencyInjection;
-using RackPeek.Domain.Resources.Hardware.Laptops.Cpus;
+using RackPeek.Domain.Resources.Models;
+using RackPeek.Domain.UseCases.Cpus;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Laptops.Cpus;
+namespace Shared.Rcl.Commands.Laptops.Cpus;
 
 public class LaptopCpuRemoveCommand(IServiceProvider provider)
     : AsyncCommand<LaptopCpuRemoveSettings>
@@ -14,7 +15,7 @@ public class LaptopCpuRemoveCommand(IServiceProvider provider)
         CancellationToken cancellationToken)
     {
         using var scope = provider.CreateScope();
-        var useCase = scope.ServiceProvider.GetRequiredService<RemoveLaptopCpuUseCase>();
+        var useCase = scope.ServiceProvider.GetRequiredService<IRemoveCpuUseCase<Laptop>>();
 
         await useCase.ExecuteAsync(settings.LaptopName, settings.Index);
 

+ 1 - 1
Shared.Rcl/Commands/Laptops/Cpus/LaptopCpuRemoveSettings.cs

@@ -1,7 +1,7 @@
 using System.ComponentModel;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Laptops.Cpus;
+namespace Shared.Rcl.Commands.Laptops.Cpus;
 
 public class LaptopCpuRemoveSettings : CommandSettings
 {

+ 4 - 3
Shared.Rcl/Commands/Laptops/Cpus/LaptopCpuSetCommand.cs

@@ -1,9 +1,10 @@
 using Microsoft.Extensions.DependencyInjection;
-using RackPeek.Domain.Resources.Hardware.Laptops.Cpus;
+using RackPeek.Domain.Resources.Models;
+using RackPeek.Domain.UseCases.Cpus;
 using Spectre.Console;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Laptops.Cpus;
+namespace Shared.Rcl.Commands.Laptops.Cpus;
 
 public class LaptopCpuSetCommand(IServiceProvider provider)
     : AsyncCommand<LaptopCpuSetSettings>
@@ -14,7 +15,7 @@ public class LaptopCpuSetCommand(IServiceProvider provider)
         CancellationToken cancellationToken)
     {
         using var scope = provider.CreateScope();
-        var useCase = scope.ServiceProvider.GetRequiredService<UpdateLaptopCpuUseCase>();
+        var useCase = scope.ServiceProvider.GetRequiredService<IUpdateCpuUseCase<Laptop>>();
 
         await useCase.ExecuteAsync(settings.LaptopName, settings.Index, settings.Model, settings.Cores,
             settings.Threads);

+ 1 - 1
Shared.Rcl/Commands/Laptops/Cpus/LaptopCpuSetSettings.cs

@@ -1,7 +1,7 @@
 using System.ComponentModel;
 using Spectre.Console.Cli;
 
-namespace RackPeek.Commands.Laptops.Cpus;
+namespace Shared.Rcl.Commands.Laptops.Cpus;
 
 public class LaptopCpuSetSettings : CommandSettings
 {

Некоторые файлы не были показаны из-за большого количества измененных файлов