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

Added validation / error handling

Tim Jones 2 месяцев назад
Родитель
Сommit
491cdeae2f
32 измененных файлов с 1580 добавлено и 1306 удалено
  1. BIN
      .DS_Store
  2. 14 0
      RackPeek.Domain/Helpers/ConflictException.cs
  3. 9 0
      RackPeek.Domain/Helpers/Normalize.cs
  4. 14 0
      RackPeek.Domain/Helpers/NotFoundException.cs
  5. 117 0
      RackPeek.Domain/Helpers/ThrowIfInvalid.cs
  6. 4 1
      RackPeek.Domain/Resources/Hardware/Servers/AddServerUseCase.cs
  7. 7 2
      RackPeek.Domain/Resources/Hardware/Servers/DeleteServerUseCase.cs
  8. 3 0
      RackPeek.Domain/Resources/Hardware/Servers/DescribeServerUseCase.cs
  9. 2 0
      RackPeek.Domain/Resources/Hardware/Servers/GetServerUseCase.cs
  10. 4 1
      RackPeek.Domain/Resources/Hardware/Servers/Gpus/AddGpuUseCase.cs
  11. 10 2
      RackPeek.Domain/Resources/Hardware/Servers/Nics/AddNicUseCase.cs
  12. 5 2
      RackPeek.Domain/Resources/Hardware/Servers/Nics/RemoveNicUseCase.cs
  13. 12 3
      RackPeek.Domain/Resources/Hardware/Servers/Nics/UpdateNicUseCase.cs
  14. 5 1
      RackPeek.Domain/Resources/Hardware/Servers/UpdateServerUseCase.cs
  15. 28 0
      RackPeek/CliBootstrap.cs
  16. 594 584
      RackPeek/config/Services.yaml
  17. 207 183
      RackPeek/config/Systems.yaml
  18. 30 30
      RackPeek/config/accesspoints.yaml
  19. 21 20
      RackPeek/config/desktops.yaml
  20. 13 13
      RackPeek/config/firewalls.yaml
  21. 16 16
      RackPeek/config/laptops.yaml
  22. 13 13
      RackPeek/config/routers.yaml
  23. 396 396
      RackPeek/config/servers.yaml
  24. 13 13
      RackPeek/config/switches.yaml
  25. 5 5
      RackPeek/config/ups.yaml
  26. 9 6
      Tests/HardwareResources/AddGpuUseCaseTests.cs
  27. 9 5
      Tests/HardwareResources/AddNicUseCaseTests.cs
  28. 2 2
      Tests/HardwareResources/AddServerUseCaseTests.cs
  29. 2 1
      Tests/HardwareResources/DeleteServerUseCaseTests.cs
  30. 7 3
      Tests/HardwareResources/RemoveNicUseCaseTests.cs
  31. 7 3
      Tests/HardwareResources/UpdateNicUseCaseTests.cs
  32. 2 1
      Tests/HardwareResources/UpdateServerUseCaseTests.cs

+ 14 - 0
RackPeek.Domain/Helpers/ConflictException.cs

@@ -0,0 +1,14 @@
+namespace RackPeek.Domain.Helpers;
+
+public sealed class ConflictException : Exception
+{
+    public ConflictException(string message)
+        : base(message)
+    {
+    }
+
+    public ConflictException(string message, Exception innerException)
+        : base(message, innerException)
+    {
+    }
+}

+ 9 - 0
RackPeek.Domain/Helpers/Normalize.cs

@@ -0,0 +1,9 @@
+namespace RackPeek.Domain.Helpers;
+
+public static class Normalize
+{
+    public static string NicType(string value)
+    {
+        return value.Trim().ToLowerInvariant();
+    }
+}

+ 14 - 0
RackPeek.Domain/Helpers/NotFoundException.cs

@@ -0,0 +1,14 @@
+namespace RackPeek.Domain.Helpers;
+
+public sealed class NotFoundException : Exception
+{
+    public NotFoundException(string message)
+        : base(message)
+    {
+    }
+
+    public NotFoundException(string message, Exception innerException)
+        : base(message, innerException)
+    {
+    }
+}

+ 117 - 0
RackPeek.Domain/Helpers/ThrowIfInvalid.cs

@@ -0,0 +1,117 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace RackPeek.Domain.Helpers;
+
+public static class ThrowIfInvalid
+{
+    public static void ResourceName(string name)
+    {
+        if (string.IsNullOrWhiteSpace(name))
+            throw new ValidationException("Name is required.");
+
+        if (name.Length > 50)
+            throw new ValidationException("Name is too long.");
+    }
+
+    public static void RamGb(int? value)
+    {
+        if (value is null)
+            throw new ValidationException("RAM value must be specified.");
+
+        if (value < 0)
+            throw new ValidationException("RAM value must be a non negative number of gigabytes.");
+    }
+
+
+    #region Nics
+
+    public static readonly string[] ValidNicTypes =
+    {
+        // Copper Ethernet
+        "rj45",
+
+        // SFP family
+        "sfp", // 1G
+        "sfp+", // 10G
+        "sfp28", // 25G
+        "sfp56", // 50G
+
+        // QSFP family
+        "qsfp+", // 40G
+        "qsfp28", // 100G
+        "qsfp56", // 200G
+        "qsfp-dd", // 400G (QSFP Double Density)
+
+        // OSFP (400G+)
+        "osfp",
+
+        // Legacy / niche but still seen
+        "xfp",
+        "cx4",
+
+        // Management / special-purpose
+        "mgmt" // Dedicated management NIC (IPMI/BMC)
+    };
+
+    public static void NicType(string nicType)
+    {
+        if (string.IsNullOrWhiteSpace(nicType))
+            throw new ValidationException("NIC type is required.");
+
+        var normalized = nicType.Trim().ToLowerInvariant();
+
+        if (ValidNicTypes.Contains(normalized))
+            return;
+
+        var suggestions = GetNicTypeSuggestions(normalized).ToList();
+
+        var message = suggestions.Any()
+            ? $"NIC type '{nicType}' is not valid. Did you mean: {string.Join(", ", suggestions)}?"
+            : $"NIC type '{nicType}' is not valid. Valid NIC types include rj45, sfp, sfp+, qsfp+ etc";
+
+        throw new ValidationException(message);
+    }
+
+    private static IEnumerable<string> GetNicTypeSuggestions(string input)
+    {
+        return ValidNicTypes
+            .Select(type => new
+            {
+                Type = type,
+                Score = SimilarityScore(input, type)
+            })
+            .Where(x => x.Score >= 0.5)
+            .OrderByDescending(x => x.Score)
+            .Take(3)
+            .Select(x => x.Type);
+    }
+
+    private static double SimilarityScore(string a, string b)
+    {
+        if (a == b)
+            return 1.0;
+
+        if (b.StartsWith(a) || a.StartsWith(b))
+            return 0.9;
+
+        var commonChars = a.Intersect(b).Count();
+        return (double)commonChars / Math.Max(a.Length, b.Length);
+    }
+
+    public static void NicSpeed(int speed)
+    {
+        if (speed < 0)
+            throw new ValidationException(
+                "NIC speed must be a non negative number of gigabits per second.");
+    }
+
+
+    public static void NicPorts(int ports)
+    {
+        if (ports < 0)
+            throw new ValidationException(
+                "NIC port count must be a non negative integer.");
+    }
+
+    #endregion
+}

+ 4 - 1
RackPeek.Domain/Resources/Hardware/Servers/AddServerUseCase.cs

@@ -1,3 +1,4 @@
+using RackPeek.Domain.Helpers;
 using RackPeek.Domain.Resources.Hardware.Models;
 
 namespace RackPeek.Domain.Resources.Hardware.Servers;
@@ -6,10 +7,12 @@ public class AddServerUseCase(IHardwareRepository repository) : IUseCase
 {
     public async Task ExecuteAsync(string name)
     {
+        ThrowIfInvalid.ResourceName(name);
+
         // basic guard rails
         var existing = await repository.GetByNameAsync(name);
         if (existing != null)
-            throw new InvalidOperationException($"Server '{name}' already exists.");
+            throw new ConflictException($"Resource: '{name}' already exists.");
 
         var server = new Server
         {

+ 7 - 2
RackPeek.Domain/Resources/Hardware/Servers/DeleteServerUseCase.cs

@@ -1,12 +1,17 @@
+using RackPeek.Domain.Helpers;
+using RackPeek.Domain.Resources.Hardware.Models;
+
 namespace RackPeek.Domain.Resources.Hardware.Servers;
 
 public class DeleteServerUseCase(IHardwareRepository repository) : IUseCase
 {
     public async Task ExecuteAsync(string name)
     {
-        var hardware = await repository.GetByNameAsync(name);
+        ThrowIfInvalid.ResourceName(name);
+
+        var hardware = await repository.GetByNameAsync(name) as Server;
         if (hardware == null)
-            throw new InvalidOperationException($"Server '{name}' not found.");
+            throw new NotFoundException($"Server '{name}' not found.");
 
         await repository.DeleteAsync(name);
     }

+ 3 - 0
RackPeek.Domain/Resources/Hardware/Servers/DescribeServerUseCase.cs

@@ -1,3 +1,4 @@
+using RackPeek.Domain.Helpers;
 using RackPeek.Domain.Resources.Hardware.Models;
 
 namespace RackPeek.Domain.Resources.Hardware.Servers;
@@ -17,6 +18,8 @@ public class DescribeServerUseCase(IHardwareRepository repository) : IUseCase
 {
     public async Task<ServerDescription?> ExecuteAsync(string name)
     {
+        ThrowIfInvalid.ResourceName(name);
+
         var server = await repository.GetByNameAsync(name) as Server;
         if (server == null)
             return null;

+ 2 - 0
RackPeek.Domain/Resources/Hardware/Servers/GetServerUseCase.cs

@@ -1,3 +1,4 @@
+using RackPeek.Domain.Helpers;
 using RackPeek.Domain.Resources.Hardware.Models;
 
 namespace RackPeek.Domain.Resources.Hardware.Servers;
@@ -6,6 +7,7 @@ public class GetServerUseCase(IHardwareRepository repository) : IUseCase
 {
     public async Task<Server?> ExecuteAsync(string name)
     {
+        ThrowIfInvalid.ResourceName(name);
         var hardware = await repository.GetByNameAsync(name);
         return hardware as Server;
     }

+ 4 - 1
RackPeek.Domain/Resources/Hardware/Servers/Gpus/AddGpuUseCase.cs

@@ -1,3 +1,4 @@
+using RackPeek.Domain.Helpers;
 using RackPeek.Domain.Resources.Hardware.Models;
 
 namespace RackPeek.Domain.Resources.Hardware.Servers.Gpus;
@@ -9,10 +10,12 @@ public class AddGpuUseCase(IHardwareRepository repository) : IUseCase
         string model,
         int vram)
     {
+        ThrowIfInvalid.ResourceName(serverName);
+
         var hardware = await repository.GetByNameAsync(serverName);
 
         if (hardware is not Server server)
-            return;
+            throw new NotFoundException($"Server '{serverName}' not found.");
 
         server.Gpus ??= [];
 

+ 10 - 2
RackPeek.Domain/Resources/Hardware/Servers/Nics/AddNicUseCase.cs

@@ -1,3 +1,4 @@
+using RackPeek.Domain.Helpers;
 using RackPeek.Domain.Resources.Hardware.Models;
 
 namespace RackPeek.Domain.Resources.Hardware.Servers.Nics;
@@ -10,16 +11,23 @@ public class AddNicUseCase(IHardwareRepository repository) : IUseCase
         int speed,
         int ports)
     {
+        ThrowIfInvalid.ResourceName(serverName);
+        ThrowIfInvalid.NicSpeed(speed);
+        ThrowIfInvalid.NicPorts(ports);
+
+        var nicType = Normalize.NicType(type);
+        ThrowIfInvalid.NicType(nicType);
+
         var hardware = await repository.GetByNameAsync(serverName);
 
         if (hardware is not Server server)
-            return;
+            throw new NotFoundException($"Server: '{serverName}' not found.");
 
         server.Nics ??= [];
 
         server.Nics.Add(new Nic
         {
-            Type = type,
+            Type = nicType,
             Speed = speed,
             Ports = ports
         });

+ 5 - 2
RackPeek.Domain/Resources/Hardware/Servers/Nics/RemoveNicUseCase.cs

@@ -1,3 +1,5 @@
+using System.ComponentModel.DataAnnotations;
+using RackPeek.Domain.Helpers;
 using RackPeek.Domain.Resources.Hardware.Models;
 
 namespace RackPeek.Domain.Resources.Hardware.Servers.Nics;
@@ -6,15 +8,16 @@ public class RemoveNicUseCase(IHardwareRepository repository) : IUseCase
 {
     public async Task ExecuteAsync(string serverName, int index)
     {
+        ThrowIfInvalid.ResourceName(serverName);
         var hardware = await repository.GetByNameAsync(serverName);
 
         if (hardware is not Server server)
-            return;
+            throw new NotFoundException($"Server: '{serverName}' not found.");
 
         server.Nics ??= [];
 
         if (index < 0 || index >= server.Nics.Count)
-            throw new ArgumentOutOfRangeException(nameof(index), "NIC index out of range.");
+            throw new ValidationException("NIC index out of range.");
 
         server.Nics.RemoveAt(index);
 

+ 12 - 3
RackPeek.Domain/Resources/Hardware/Servers/Nics/UpdateNicUseCase.cs

@@ -1,3 +1,5 @@
+using System.ComponentModel.DataAnnotations;
+using RackPeek.Domain.Helpers;
 using RackPeek.Domain.Resources.Hardware.Models;
 
 namespace RackPeek.Domain.Resources.Hardware.Servers.Nics;
@@ -11,18 +13,25 @@ public class UpdateNicUseCase(IHardwareRepository repository) : IUseCase
         int speed,
         int ports)
     {
+        ThrowIfInvalid.ResourceName(serverName);
+        ThrowIfInvalid.NicSpeed(speed);
+        ThrowIfInvalid.NicPorts(ports);
+
+        var nicType = Normalize.NicType(type);
+        ThrowIfInvalid.NicType(nicType);
+
         var hardware = await repository.GetByNameAsync(serverName);
 
         if (hardware is not Server server)
-            return;
+            throw new NotFoundException($"Server: '{serverName}' not found.");
 
         server.Nics ??= [];
 
         if (index < 0 || index >= server.Nics.Count)
-            throw new ArgumentOutOfRangeException(nameof(index), "NIC index out of range.");
+            throw new ValidationException("NIC index out of range.");
 
         var nic = server.Nics[index];
-        nic.Type = type;
+        nic.Type = nicType;
         nic.Speed = speed;
         nic.Ports = ports;
 

+ 5 - 1
RackPeek.Domain/Resources/Hardware/Servers/UpdateServerUseCase.cs

@@ -1,3 +1,4 @@
+using RackPeek.Domain.Helpers;
 using RackPeek.Domain.Resources.Hardware.Models;
 
 namespace RackPeek.Domain.Resources.Hardware.Servers;
@@ -10,13 +11,16 @@ public class UpdateServerUseCase(IHardwareRepository repository) : IUseCase
         bool? ipmi = null
     )
     {
+        ThrowIfInvalid.ResourceName(name);
+
         var server = await repository.GetByNameAsync(name) as Server;
         if (server == null)
-            throw new InvalidOperationException($"Server '{name}' not found.");
+            throw new NotFoundException($"Server '{name}' not found.");
 
         // ---- RAM ----
         if (ramGb.HasValue)
         {
+            ThrowIfInvalid.RamGb(ramGb);
             server.Ram ??= new Ram();
             server.Ram.Size = ramGb.Value;
         }

+ 28 - 0
RackPeek/CliBootstrap.cs

@@ -1,3 +1,4 @@
+using System.ComponentModel.DataAnnotations;
 using Microsoft.Extensions.Configuration;
 using Microsoft.Extensions.DependencyInjection;
 using RackPeek.Commands;
@@ -22,10 +23,12 @@ using RackPeek.Commands.Switches;
 using RackPeek.Commands.Systems;
 using RackPeek.Commands.Ups;
 using RackPeek.Domain;
+using RackPeek.Domain.Helpers;
 using RackPeek.Domain.Resources.Hardware;
 using RackPeek.Domain.Resources.Services;
 using RackPeek.Domain.Resources.SystemResources;
 using RackPeek.Yaml;
+using Spectre.Console;
 using Spectre.Console.Cli;
 
 namespace RackPeek;
@@ -77,6 +80,8 @@ public static class CliBootstrap
             config.SetApplicationName("rpk");
             config.ValidateExamples();
 
+            config.SetExceptionHandler(HandleException);
+
             // Global summary
             config.AddCommand<GetTotalSummaryCommand>("summary")
                 .WithDescription("Show a summarized report of all resources in the system.");
@@ -515,4 +520,27 @@ public static class CliBootstrap
             });
         });
     }
+
+    private static int HandleException(Exception ex, ITypeResolver? arg2)
+    {
+        switch (ex)
+        {
+            case ValidationException ve:
+                AnsiConsole.MarkupLine($"[yellow]Validation error:[/] {ve.Message}");
+                return 2;
+
+            case ConflictException ce:
+                AnsiConsole.MarkupLine($"[red]Conflict:[/] {ce.Message}");
+                return 3;
+
+            case NotFoundException ne:
+                AnsiConsole.MarkupLine($"[red]Not found:[/] {ne.Message}");
+                return 4;
+
+            default:
+                AnsiConsole.MarkupLine("[red]Unexpected error occurred.[/]");
+                AnsiConsole.WriteException(ex, ExceptionFormats.ShortenEverything);
+                return 99;
+        }
+    }
 }

+ 594 - 584
RackPeek/config/Services.yaml

@@ -1,585 +1,595 @@
 resources:
-  - kind: Service
-    name: immich
-    network:
-      ip: 192.168.0.4
-      port: 8080
-      protocol: TCP
-      url: http://immich.lan:8080
-    runsOn: proxmox-host
-
-  - kind: Service
-    name: jellyfin
-    network:
-      ip: 192.168.0.10
-      port: 8096
-      protocol: TCP
-      url: http://jellyfin.lan:8096
-    runsOn: docker-host
-
-  - kind: Service
-    name: plex
-    network:
-      ip: 192.168.0.11
-      port: 32400
-      protocol: TCP
-      url: http://plex.lan:32400
-    runsOn: proxmox-host
-
-  - kind: Service
-    name: home-assistant
-    network:
-      ip: 192.168.1.20
-      port: 8123
-      protocol: TCP
-      url: http://ha.lan:8123
-    runsOn: k8s-node-1
-
-  - kind: Service
-    name: pihole
-    network:
-      ip: 192.168.1.2
-      port: 53
-      protocol: UDP
-      url: http://pihole.lan/admin
-    runsOn: baremetal-rpi4
-
-  - kind: Service
-    name: unifi-controller
-    network:
-      ip: 192.168.1.5
-      port: 8443
-      protocol: TCP
-      url: https://unifi.lan:8443
-    runsOn: vm-cluster-1
-
-  - kind: Service
-    name: syncthing
-    network:
-      ip: 10.0.0.15
-      port: 8384
-      protocol: TCP
-      url: http://sync.internal:8384
-    runsOn: docker-host
-
-  - kind: Service
-    name: grafana
-    network:
-      ip: 10.0.0.20
-      port: 3000
-      protocol: TCP
-      url: http://grafana.internal:3000
-    runsOn: monitoring-node
-
-  - kind: Service
-    name: prometheus
-    network:
-      ip: 10.0.0.21
-      port: 9090
-      protocol: TCP
-      url: http://prometheus.internal:9090
-    runsOn: monitoring-node
-
-  - kind: Service
-    name: loki
-    network:
-      ip: 10.0.0.22
-      port: 3100
-      protocol: TCP
-      url: http://loki.internal:3100
-    runsOn: monitoring-node
-
-  - kind: Service
-    name: minio
-    network:
-      ip: 172.16.0.10
-      port: 9000
-      protocol: TCP
-      url: http://minio.storage:9000
-    runsOn: storage-node-1
-
-  - kind: Service
-    name: nextcloud
-    network:
-      ip: 172.16.0.11
-      port: 443
-      protocol: TCP
-      url: https://nextcloud.storage
-    runsOn: storage-node-2
-
-  - kind: Service
-    name: vaultwarden
-    network:
-      ip: 192.168.0.30
-      port: 8081
-      protocol: TCP
-      url: http://vault.lan:8081
-    runsOn: docker-host
-
-  - kind: Service
-    name: traefik
-    network:
-      ip: 192.168.0.2
-      port: 80
-      protocol: TCP
-      url: http://traefik.lan
-    runsOn: k8s-node-1
-
-  - kind: Service
-    name: nginx-reverse-proxy
-    network:
-      ip: 192.168.0.3
-      port: 443
-      protocol: TCP
-      url: https://proxy.lan
-    runsOn: docker-host
-
-  - kind: Service
-    name: qbittorrent
-    network:
-      ip: 192.168.0.40
-      port: 8080
-      protocol: TCP
-      url: http://torrent.lan:8080
-    runsOn: proxmox-host
-
-  - kind: Service
-    name: radarr
-    network:
-      ip: 192.168.0.41
-      port: 7878
-      protocol: TCP
-      url: http://radarr.lan:7878
-    runsOn: docker-host
-
-  - kind: Service
-    name: sonarr
-    network:
-      ip: 192.168.0.42
-      port: 8989
-      protocol: TCP
-      url: http://sonarr.lan:8989
-    runsOn: docker-host
-
-  - kind: Service
-    name: prowlarr
-    network:
-      ip: 192.168.0.43
-      port: 9696
-      protocol: TCP
-      url: http://prowlarr.lan:9696
-    runsOn: docker-host
-
-  - kind: Service
-    name: sabnzbd
-    network:
-      ip: 192.168.0.44
-      port: 8085
-      protocol: TCP
-      url: http://sabnzbd.lan:8085
-    runsOn: docker-host
-
-  - kind: Service
-    name: frigate
-    network:
-      ip: 192.168.1.30
-      port: 5000
-      protocol: TCP
-      url: http://frigate.lan:5000
-    runsOn: k8s-node-2
-
-  - kind: Service
-    name: mosquitto-mqtt
-    network:
-      ip: 192.168.1.31
-      port: 1883
-      protocol: TCP
-      url: mqtt://mqtt.lan:1883
-    runsOn: docker-host
-
-  - kind: Service
-    name: zigbee2mqtt
-    network:
-      ip: 192.168.1.32
-      port: 8080
-      protocol: TCP
-      url: http://z2m.lan:8080
-    runsOn: docker-host
-
-  - kind: Service
-    name: postgres-main
-    network:
-      ip: 10.0.1.10
-      port: 5432
-      protocol: TCP
-      url: postgres://db.internal:5432
-    runsOn: db-node-1
-
-  - kind: Service
-    name: mariadb
-    network:
-      ip: 10.0.1.11
-      port: 3306
-      protocol: TCP
-      url: mysql://mariadb.internal:3306
-    runsOn: db-node-2
-
-  - kind: Service
-    name: redis-cache
-    network:
-      ip: 10.0.1.12
-      port: 6379
-      protocol: TCP
-      url: redis://redis.internal:6379
-    runsOn: cache-node
-
-  - kind: Service
-    name: elasticsearch
-    network:
-      ip: 10.0.2.10
-      port: 9200
-      protocol: TCP
-      url: http://es.internal:9200
-    runsOn: search-node
-
-  - kind: Service
-    name: kibana
-    network:
-      ip: 10.0.2.11
-      port: 5601
-      protocol: TCP
-      url: http://kibana.internal:5601
-    runsOn: search-node
-
-  - kind: Service
-    name: uptime-kuma
-    network:
-      ip: 192.168.0.50
-      port: 3001
-      protocol: TCP
-      url: http://uptime.lan:3001
-    runsOn: docker-host
-
-  - kind: Service
-    name: wireguard-vpn
-    network:
-      ip: 192.168.1.100
-      port: 51820
-      protocol: UDP
-      url: wg://vpn.lan
-    runsOn: baremetal-rpi4
-
-  - kind: Service
-    name: openvpn
-    network:
-      ip: 192.168.1.101
-      port: 1194
-      protocol: UDP
-      url: ovpn://openvpn.lan
-    runsOn: vm-cluster-2
-
-  - kind: Service
-    name: adguard-home
-    network:
-      ip: 192.168.1.3
-      port: 3000
-      protocol: TCP
-      url: http://adguard.lan:3000
-    runsOn: docker-host
-
-  - kind: Service
-    name: gitlab
-    network:
-      ip: 10.0.3.10
-      port: 443
-      protocol: TCP
-      url: https://gitlab.internal
-    runsOn: dev-node-1
-
-  - kind: Service
-    name: gitea
-    network:
-      ip: 10.0.3.11
-      port: 3000
-      protocol: TCP
-      url: http://gitea.internal:3000
-    runsOn: dev-node-2
-
-  - kind: Service
-    name: drone-ci
-    network:
-      ip: 10.0.3.12
-      port: 8080
-      protocol: TCP
-      url: http://drone.internal:8080
-    runsOn: dev-node-2
-
-  - kind: Service
-    name: harbor-registry
-    network:
-      ip: 10.0.3.13
-      port: 5000
-      protocol: TCP
-      url: http://harbor.internal:5000
-    runsOn: dev-node-3
-
-  - kind: Service
-    name: kubernetes-api
-    network:
-      ip: 10.0.4.1
-      port: 6443
-      protocol: TCP
-      url: https://k8s-api.internal:6443
-    runsOn: k8s-control-plane
-
-  - kind: Service
-    name: longhorn-ui
-    network:
-      ip: 10.0.4.20
-      port: 9500
-      protocol: TCP
-      url: http://longhorn.internal:9500
-    runsOn: k8s-node-3
-
-  - kind: Service
-    name: rook-ceph-dashboard
-    network:
-      ip: 10.0.4.21
-      port: 8443
-      protocol: TCP
-      url: https://ceph.internal:8443
-    runsOn: k8s-node-3
-
-  - kind: Service
-    name: samba-fileserver
-    network:
-      ip: 192.168.0.60
-      port: 445
-      protocol: TCP
-      url: smb://fileserver.lan
-    runsOn: storage-node-1
-
-  - kind: Service
-    name: nfs-server
-    network:
-      ip: 192.168.0.61
-      port: 2049
-      protocol: TCP
-      url: nfs://nfs.lan
-    runsOn: dell-c6400-node01
-
-  - kind: Service
-    name: iscsi-target
-    network:
-      ip: 172.16.1.10
-      port: 3260
-      protocol: TCP
-      url: iscsi://iscsi.storage
-    runsOn: storage-node-3
-
-  - kind: Service
-    name: calibre-web
-    network:
-      ip: 192.168.0.70
-      port: 8083
-      protocol: TCP
-      url: http://books.lan:8083
-    runsOn: docker-host
-
-  - kind: Service
-    name: paperless-ngx
-    network:
-      ip: 192.168.0.71
-      port: 8000
-      protocol: TCP
-      url: http://docs.lan:8000
-    runsOn: dell-c6400-node01
-
-  - kind: Service
-    name: openldap
-    network:
-      ip: 10.0.5.10
-      port: 389
-      protocol: TCP
-      url: ldap://ldap.internal:389
-    runsOn: dell-c6400-node01
-
-  - kind: Service
-    name: keycloak
-    network:
-      ip: 10.0.5.11
-      port: 8080
-      protocol: TCP
-      url: http://keycloak.internal:8080
-    runsOn: dell-c6400-node01
-
-  - kind: Service
-    name: ntp-server
-    network:
-      ip: 192.168.1.50
-      port: 123
-      protocol: UDP
-      url: ntp://ntp.lan
-    runsOn: baremetal-rpi3
-
-  - kind: Service
-    name: syslog-server
-    network:
-      ip: 10.0.6.10
-      port: 514
-      protocol: UDP
-      url: syslog://syslog.internal
-    runsOn: monitoring-node
-
-  - kind: Service
-    name: dhcp-server
-    network:
-      ip: 192.168.1.1
-      port: 67
-      protocol: UDP
-      url: dhcp://dhcp.lan
-    runsOn: router-appliance
-
-  - kind: Service
-    name: bind-dns
-    network:
-      ip: 10.0.7.10
-      port: 53
-      protocol: UDP
-      url: dns://dns.internal
-    runsOn: infra-node
-
-  - kind: Service
-    name: vault
-    network:
-      ip: 10.0.7.11
-      port: 8200
-      protocol: TCP
-      url: http://vault.internal:8200
-    runsOn: infra-node
-
-  - kind: Service
-    name: consul
-    network:
-      ip: 10.0.7.12
-      port: 8500
-      protocol: TCP
-      url: http://consul.internal:8500
-    runsOn: infra-node
-
-  - kind: Service
-    name: nomad
-    network:
-      ip: 10.0.7.13
-      port: 4646
-      protocol: TCP
-      url: http://nomad.internal:4646
-    runsOn: infra-node
-
-  - kind: Service
-    name: openhab
-    network:
-      ip: 192.168.1.40
-      port: 8080
-      protocol: TCP
-      url: http://openhab.lan:8080
-    runsOn: k8s-node-2
-
-  - kind: Service
-    name: mqtt-explorer
-    network:
-      ip: 192.168.1.41
-      port: 4000
-      protocol: TCP
-      url: http://mqtt-explorer.lan:4000
-    runsOn: docker-host
-
-  - kind: Service
-    name: influxdb
-    network:
-      ip: 10.0.8.10
-      port: 8086
-      protocol: TCP
-      url: http://influx.internal:8086
-    runsOn: monitoring-node
-
-  - kind: Service
-    name: telegraf
-    network:
-      ip: 10.0.8.11
-      port: 8125
-      protocol: UDP
-      url: statsd://telegraf.internal
-    runsOn: monitoring-node
-
-  - kind: Service
-    name: speedtest-tracker
-    network:
-      ip: 192.168.0.80
-      port: 8080
-      protocol: TCP
-      url: http://speedtest.lan:8080
-    runsOn: docker-host
-
-  - kind: Service
-    name: navidrome
-    network:
-      ip: 192.168.0.81
-      port: 4533
-      protocol: TCP
-      url: http://music.lan:4533
-    runsOn: docker-host
-
-  - kind: Service
-    name: photoprism
-    network:
-      ip: 192.168.0.82
-      port: 2342
-      protocol: TCP
-      url: http://photos.lan:2342
-    runsOn: docker-host
-
-  - kind: Service
-    name: dnsdist
-    network:
-      ip: 10.0.9.10
-      port: 53
-      protocol: UDP
-      url: dns://dnsdist.internal
-    runsOn: infra-node
-
-  - kind: Service
-    name: powerdns
-    network:
-      ip: 10.0.9.11
-      port: 8081
-      protocol: TCP
-      url: http://pdns.internal:8081
-    runsOn: infra-node
-
-  - kind: Service
-    name: openproject
-    network:
-      ip: 10.0.10.10
-      port: 8080
-      protocol: TCP
-      url: http://openproject.internal:8080
-    runsOn: dev-node-3
-
-  - kind: Service
-    name: mattermost
-    network:
-      ip: 10.0.10.11
-      port: 8065
-      protocol: TCP
-      url: http://chat.internal:8065
-    runsOn: dev-node-3
-
-  - kind: Service
-    name: rocket-chat
-    network:
-      ip: 10.0.10.12
-      port: 3000
-      protocol: TCP
-      url: http://rocket.internal:3000
-    runsOn: dev-node-3
+- kind: Service
+  network:
+    ip: 192.168.0.4
+    port: 8080
+    protocol: TCP
+    url: http://immich.lan:8080
+  runsOn: proxmox-host
+  name: immich
+  tags: 
+- kind: Service
+  network:
+    ip: 192.168.0.10
+    port: 8096
+    protocol: TCP
+    url: http://jellyfin.lan:8096
+  runsOn: docker-host
+  name: jellyfin
+  tags: 
+- kind: Service
+  network:
+    ip: 192.168.0.11
+    port: 32400
+    protocol: TCP
+    url: http://plex.lan:32400
+  runsOn: proxmox-host
+  name: plex
+  tags: 
+- kind: Service
+  network:
+    ip: 192.168.1.20
+    port: 8123
+    protocol: TCP
+    url: http://ha.lan:8123
+  runsOn: k8s-node-1
+  name: home-assistant
+  tags: 
+- kind: Service
+  network:
+    ip: 192.168.1.2
+    port: 53
+    protocol: UDP
+    url: http://pihole.lan/admin
+  runsOn: baremetal-rpi4
+  name: pihole
+  tags: 
+- kind: Service
+  network:
+    ip: 192.168.1.5
+    port: 8443
+    protocol: TCP
+    url: https://unifi.lan:8443
+  runsOn: vm-cluster-1
+  name: unifi-controller
+  tags: 
+- kind: Service
+  network:
+    ip: 10.0.0.15
+    port: 8384
+    protocol: TCP
+    url: http://sync.internal:8384
+  runsOn: docker-host
+  name: syncthing
+  tags: 
+- kind: Service
+  network:
+    ip: 10.0.0.20
+    port: 3000
+    protocol: TCP
+    url: http://grafana.internal:3000
+  runsOn: monitoring-node
+  name: grafana
+  tags: 
+- kind: Service
+  network:
+    ip: 10.0.0.21
+    port: 9090
+    protocol: TCP
+    url: http://prometheus.internal:9090
+  runsOn: monitoring-node
+  name: prometheus
+  tags: 
+- kind: Service
+  network:
+    ip: 10.0.0.22
+    port: 3100
+    protocol: TCP
+    url: http://loki.internal:3100
+  runsOn: monitoring-node
+  name: loki
+  tags: 
+- kind: Service
+  network:
+    ip: 172.16.0.10
+    port: 9000
+    protocol: TCP
+    url: http://minio.storage:9000
+  runsOn: storage-node-1
+  name: minio
+  tags: 
+- kind: Service
+  network:
+    ip: 172.16.0.11
+    port: 443
+    protocol: TCP
+    url: https://nextcloud.storage
+  runsOn: storage-node-2
+  name: nextcloud
+  tags: 
+- kind: Service
+  network:
+    ip: 192.168.0.30
+    port: 8081
+    protocol: TCP
+    url: http://vault.lan:8081
+  runsOn: docker-host
+  name: vaultwarden
+  tags: 
+- kind: Service
+  network:
+    ip: 192.168.0.2
+    port: 80
+    protocol: TCP
+    url: http://traefik.lan
+  runsOn: k8s-node-1
+  name: traefik
+  tags: 
+- kind: Service
+  network:
+    ip: 192.168.0.3
+    port: 443
+    protocol: TCP
+    url: https://proxy.lan
+  runsOn: docker-host
+  name: nginx-reverse-proxy
+  tags: 
+- kind: Service
+  network:
+    ip: 192.168.0.40
+    port: 8080
+    protocol: TCP
+    url: http://torrent.lan:8080
+  runsOn: proxmox-host
+  name: qbittorrent
+  tags: 
+- kind: Service
+  network:
+    ip: 192.168.0.41
+    port: 7878
+    protocol: TCP
+    url: http://radarr.lan:7878
+  runsOn: docker-host
+  name: radarr
+  tags: 
+- kind: Service
+  network:
+    ip: 192.168.0.42
+    port: 8989
+    protocol: TCP
+    url: http://sonarr.lan:8989
+  runsOn: docker-host
+  name: sonarr
+  tags: 
+- kind: Service
+  network:
+    ip: 192.168.0.43
+    port: 9696
+    protocol: TCP
+    url: http://prowlarr.lan:9696
+  runsOn: docker-host
+  name: prowlarr
+  tags: 
+- kind: Service
+  network:
+    ip: 192.168.0.44
+    port: 8085
+    protocol: TCP
+    url: http://sabnzbd.lan:8085
+  runsOn: docker-host
+  name: sabnzbd
+  tags: 
+- kind: Service
+  network:
+    ip: 192.168.1.30
+    port: 5000
+    protocol: TCP
+    url: http://frigate.lan:5000
+  runsOn: k8s-node-2
+  name: frigate
+  tags: 
+- kind: Service
+  network:
+    ip: 192.168.1.31
+    port: 1883
+    protocol: TCP
+    url: mqtt://mqtt.lan:1883
+  runsOn: docker-host
+  name: mosquitto-mqtt
+  tags: 
+- kind: Service
+  network:
+    ip: 192.168.1.32
+    port: 8080
+    protocol: TCP
+    url: http://z2m.lan:8080
+  runsOn: docker-host
+  name: zigbee2mqtt
+  tags: 
+- kind: Service
+  network:
+    ip: 10.0.1.10
+    port: 5432
+    protocol: TCP
+    url: postgres://db.internal:5432
+  runsOn: db-node-1
+  name: postgres-main
+  tags: 
+- kind: Service
+  network:
+    ip: 10.0.1.11
+    port: 3306
+    protocol: TCP
+    url: mysql://mariadb.internal:3306
+  runsOn: db-node-2
+  name: mariadb
+  tags: 
+- kind: Service
+  network:
+    ip: 10.0.1.12
+    port: 6379
+    protocol: TCP
+    url: redis://redis.internal:6379
+  runsOn: cache-node
+  name: redis-cache
+  tags: 
+- kind: Service
+  network:
+    ip: 10.0.2.10
+    port: 9200
+    protocol: TCP
+    url: http://es.internal:9200
+  runsOn: search-node
+  name: elasticsearch
+  tags: 
+- kind: Service
+  network:
+    ip: 10.0.2.11
+    port: 5601
+    protocol: TCP
+    url: http://kibana.internal:5601
+  runsOn: search-node
+  name: kibana
+  tags: 
+- kind: Service
+  network:
+    ip: 192.168.0.50
+    port: 3001
+    protocol: TCP
+    url: http://uptime.lan:3001
+  runsOn: docker-host
+  name: uptime-kuma
+  tags: 
+- kind: Service
+  network:
+    ip: 192.168.1.100
+    port: 51820
+    protocol: UDP
+    url: wg://vpn.lan
+  runsOn: baremetal-rpi4
+  name: wireguard-vpn
+  tags: 
+- kind: Service
+  network:
+    ip: 192.168.1.101
+    port: 1194
+    protocol: UDP
+    url: ovpn://openvpn.lan
+  runsOn: vm-cluster-2
+  name: openvpn
+  tags: 
+- kind: Service
+  network:
+    ip: 192.168.1.3
+    port: 3000
+    protocol: TCP
+    url: http://adguard.lan:3000
+  runsOn: docker-host
+  name: adguard-home
+  tags: 
+- kind: Service
+  network:
+    ip: 10.0.3.10
+    port: 443
+    protocol: TCP
+    url: https://gitlab.internal
+  runsOn: dev-node-1
+  name: gitlab
+  tags: 
+- kind: Service
+  network:
+    ip: 10.0.3.11
+    port: 3000
+    protocol: TCP
+    url: http://gitea.internal:3000
+  runsOn: dev-node-2
+  name: gitea
+  tags: 
+- kind: Service
+  network:
+    ip: 10.0.3.12
+    port: 8080
+    protocol: TCP
+    url: http://drone.internal:8080
+  runsOn: dev-node-2
+  name: drone-ci
+  tags: 
+- kind: Service
+  network:
+    ip: 10.0.3.13
+    port: 5000
+    protocol: TCP
+    url: http://harbor.internal:5000
+  runsOn: dev-node-3
+  name: harbor-registry
+  tags: 
+- kind: Service
+  network:
+    ip: 10.0.4.1
+    port: 6443
+    protocol: TCP
+    url: https://k8s-api.internal:6443
+  runsOn: k8s-control-plane
+  name: kubernetes-api
+  tags: 
+- kind: Service
+  network:
+    ip: 10.0.4.20
+    port: 9500
+    protocol: TCP
+    url: http://longhorn.internal:9500
+  runsOn: k8s-node-3
+  name: longhorn-ui
+  tags: 
+- kind: Service
+  network:
+    ip: 10.0.4.21
+    port: 8443
+    protocol: TCP
+    url: https://ceph.internal:8443
+  runsOn: k8s-node-3
+  name: rook-ceph-dashboard
+  tags: 
+- kind: Service
+  network:
+    ip: 192.168.0.60
+    port: 445
+    protocol: TCP
+    url: smb://fileserver.lan
+  runsOn: storage-node-1
+  name: samba-fileserver
+  tags: 
+- kind: Service
+  network:
+    ip: 192.168.0.61
+    port: 2049
+    protocol: TCP
+    url: nfs://nfs.lan
+  runsOn: dell-c6400-node01
+  name: nfs-server
+  tags: 
+- kind: Service
+  network:
+    ip: 172.16.1.10
+    port: 3260
+    protocol: TCP
+    url: iscsi://iscsi.storage
+  runsOn: storage-node-3
+  name: iscsi-target
+  tags: 
+- kind: Service
+  network:
+    ip: 192.168.0.70
+    port: 8083
+    protocol: TCP
+    url: http://books.lan:8083
+  runsOn: docker-host
+  name: calibre-web
+  tags: 
+- kind: Service
+  network:
+    ip: 192.168.0.71
+    port: 8000
+    protocol: TCP
+    url: http://docs.lan:8000
+  runsOn: dell-c6400-node01
+  name: paperless-ngx
+  tags: 
+- kind: Service
+  network:
+    ip: 10.0.5.10
+    port: 389
+    protocol: TCP
+    url: ldap://ldap.internal:389
+  runsOn: dell-c6400-node01
+  name: openldap
+  tags: 
+- kind: Service
+  network:
+    ip: 10.0.5.11
+    port: 8080
+    protocol: TCP
+    url: http://keycloak.internal:8080
+  runsOn: dell-c6400-node01
+  name: keycloak
+  tags: 
+- kind: Service
+  network:
+    ip: 192.168.1.50
+    port: 123
+    protocol: UDP
+    url: ntp://ntp.lan
+  runsOn: baremetal-rpi3
+  name: ntp-server
+  tags: 
+- kind: Service
+  network:
+    ip: 10.0.6.10
+    port: 514
+    protocol: UDP
+    url: syslog://syslog.internal
+  runsOn: monitoring-node
+  name: syslog-server
+  tags: 
+- kind: Service
+  network:
+    ip: 192.168.1.1
+    port: 67
+    protocol: UDP
+    url: dhcp://dhcp.lan
+  runsOn: router-appliance
+  name: dhcp-server
+  tags: 
+- kind: Service
+  network:
+    ip: 10.0.7.10
+    port: 53
+    protocol: UDP
+    url: dns://dns.internal
+  runsOn: infra-node
+  name: bind-dns
+  tags: 
+- kind: Service
+  network:
+    ip: 10.0.7.11
+    port: 8200
+    protocol: TCP
+    url: http://vault.internal:8200
+  runsOn: infra-node
+  name: vault
+  tags: 
+- kind: Service
+  network:
+    ip: 10.0.7.12
+    port: 8500
+    protocol: TCP
+    url: http://consul.internal:8500
+  runsOn: infra-node
+  name: consul
+  tags: 
+- kind: Service
+  network:
+    ip: 10.0.7.13
+    port: 4646
+    protocol: TCP
+    url: http://nomad.internal:4646
+  runsOn: infra-node
+  name: nomad
+  tags: 
+- kind: Service
+  network:
+    ip: 192.168.1.40
+    port: 8080
+    protocol: TCP
+    url: http://openhab.lan:8080
+  runsOn: k8s-node-2
+  name: openhab
+  tags: 
+- kind: Service
+  network:
+    ip: 192.168.1.41
+    port: 4000
+    protocol: TCP
+    url: http://mqtt-explorer.lan:4000
+  runsOn: docker-host
+  name: mqtt-explorer
+  tags: 
+- kind: Service
+  network:
+    ip: 10.0.8.10
+    port: 8086
+    protocol: TCP
+    url: http://influx.internal:8086
+  runsOn: monitoring-node
+  name: influxdb
+  tags: 
+- kind: Service
+  network:
+    ip: 10.0.8.11
+    port: 8125
+    protocol: UDP
+    url: statsd://telegraf.internal
+  runsOn: monitoring-node
+  name: telegraf
+  tags: 
+- kind: Service
+  network:
+    ip: 192.168.0.80
+    port: 8080
+    protocol: TCP
+    url: http://speedtest.lan:8080
+  runsOn: docker-host
+  name: speedtest-tracker
+  tags: 
+- kind: Service
+  network:
+    ip: 192.168.0.81
+    port: 4533
+    protocol: TCP
+    url: http://music.lan:4533
+  runsOn: docker-host
+  name: navidrome
+  tags: 
+- kind: Service
+  network:
+    ip: 192.168.0.82
+    port: 2342
+    protocol: TCP
+    url: http://photos.lan:2342
+  runsOn: docker-host
+  name: photoprism
+  tags: 
+- kind: Service
+  network:
+    ip: 10.0.9.10
+    port: 53
+    protocol: UDP
+    url: dns://dnsdist.internal
+  runsOn: infra-node
+  name: dnsdist
+  tags: 
+- kind: Service
+  network:
+    ip: 10.0.9.11
+    port: 8081
+    protocol: TCP
+    url: http://pdns.internal:8081
+  runsOn: infra-node
+  name: powerdns
+  tags: 
+- kind: Service
+  network:
+    ip: 10.0.10.10
+    port: 8080
+    protocol: TCP
+    url: http://openproject.internal:8080
+  runsOn: dev-node-3
+  name: openproject
+  tags: 
+- kind: Service
+  network:
+    ip: 10.0.10.11
+    port: 8065
+    protocol: TCP
+    url: http://chat.internal:8065
+  runsOn: dev-node-3
+  name: mattermost
+  tags: 
+- kind: Service
+  network:
+    ip: 10.0.10.12
+    port: 3000
+    protocol: TCP
+    url: http://rocket.internal:3000
+  runsOn: dev-node-3
+  name: rocket-chat
+  tags: 
+- kind: Server
+  cpus: 
+  ram: 
+  drives: 
+  nics: 
+  gpus: 
+  ipmi: 
+  name: node01
+  tags: 

+ 207 - 183
RackPeek/config/Systems.yaml

@@ -1,184 +1,208 @@
 resources:
-  - kind: System
-    type: Hypervisor
-    name: proxmox-host
-    os: proxmox
-    cores: 16
-    ram: 64gb
-    runsOn: dell-c6400-node01
-
-  - kind: System
-    type: ContainerHost
-    name: docker-host
-    os: ubuntu
-    cores: 12
-    ram: 32gb
-    runsOn: dell-c6400-node01
-
-  - kind: System
-    type: KubernetesNode
-    name: k8s-node-1
-    os: ubuntu
-    cores: 8
-    ram: 32gb
-    runsOn: dell-c6400-node01
-
-  - kind: System
-    type: KubernetesNode
-    name: k8s-node-2
-    os: ubuntu
-    cores: 8
-    ram: 32gb
-    runsOn: dell-c6400-node01
-
-  - kind: System
-    type: KubernetesNode
-    name: k8s-node-3
-    os: ubuntu
-    cores: 8
-    ram: 32gb
-    runsOn: dell-c6400-node01
-
-  - kind: System
-    type: KubernetesControlPlane
-    name: k8s-control-plane
-    os: ubuntu
-    cores: 4
-    ram: 16gb
-    runsOn: dell-c6400-node01
-
-  - kind: System
-    type: Monitoring
-    name: monitoring-node
-    os: ubuntu
-    cores: 8
-    ram: 32gb
-    runsOn: dell-c6400-node01
-
-  - kind: System
-    type: Storage
-    name: storage-node-1
-    os: truenas
-    cores: 8
-    ram: 64gb
-    runsOn: dell-c6400-node01
-
-  - kind: System
-    type: Storage
-    name: storage-node-2
-    os: truenas
-    cores: 8
-    ram: 64gb
-    runsOn: dell-c6400-node01
-
-  - kind: System
-    type: Storage
-    name: storage-node-3
-    os: truenas
-    cores: 8
-    ram: 64gb
-    runsOn: dell-c6400-node01
-
-  - kind: System
-    type: Database
-    name: db-node-1
-    os: ubuntu
-    cores: 8
-    ram: 32gb
-    runsOn: dell-c6400-node01
-
-  - kind: System
-    type: Database
-    name: db-node-2
-    os: ubuntu
-    cores: 8
-    ram: 32gb
-    runsOn: dell-c6400-node01
-
-  - kind: System
-    type: Cache
-    name: cache-node
-    os: ubuntu
-    cores: 4
-    ram: 16gb
-    runsOn: dell-c6400-node01
-
-  - kind: System
-    type: Search
-    name: search-node
-    os: ubuntu
-    cores: 8
-    ram: 32gb
-    runsOn: dell-c6400-node01
-
-  - kind: System
-    type: Development
-    name: dev-node-1
-    os: ubuntu
-    cores: 4
-    ram: 16gb
-    runsOn: dell-c6400-node01
-
-  - kind: System
-    type: Development
-    name: dev-node-2
-    os: ubuntu
-    cores: 4
-    ram: 16gb
-    runsOn: dell-c6400-node01
-
-  - kind: System
-    type: Development
-    name: dev-node-3
-    os: ubuntu
-    cores: 6
-    ram: 24gb
-    runsOn: dell-c6400-node01
-
-  - kind: System
-    type: VirtualMachineCluster
-    name: vm-cluster-1
-    os: proxmox
-    cores: 12
-    ram: 48gb
-    runsOn: dell-c6400-node01
-
-  - kind: System
-    type: VirtualMachineCluster
-    name: vm-cluster-2
-    os: proxmox
-    cores: 12
-    ram: 48gb
-    runsOn: dell-c6400-node01
-
-  - kind: System
-    type: BareMetal
-    name: baremetal-rpi4
-    os: raspbian
-    cores: 4
-    ram: 8gb
-    runsOn: rack-edge
-
-  - kind: System
-    type: BareMetal
-    name: baremetal-rpi3
-    os: raspbian
-    cores: 4
-    ram: 4gb
-    runsOn: rack-edge
-
-  - kind: System
-    type: Infrastructure
-    name: infra-node
-    os: ubuntu
-    cores: 4
-    ram: 16gb
-    runsOn: dell-c6400-node01
-
-  - kind: System
-    type: NetworkAppliance
-    name: router-appliance
-    os: openwrt
-    cores: 2
-    ram: 2gb
-    runsOn: network-rack
+- kind: System
+  type: Hypervisor
+  os: proxmox
+  cores: 16
+  ram: 64
+  drives: 
+  runsOn: dell-c6400-node01
+  name: proxmox-host
+  tags: 
+- kind: System
+  type: ContainerHost
+  os: ubuntu
+  cores: 12
+  ram: 32
+  drives: 
+  runsOn: dell-c6400-node01
+  name: docker-host
+  tags: 
+- kind: System
+  type: KubernetesNode
+  os: ubuntu
+  cores: 8
+  ram: 32
+  drives: 
+  runsOn: dell-c6400-node01
+  name: k8s-node-1
+  tags: 
+- kind: System
+  type: KubernetesNode
+  os: ubuntu
+  cores: 8
+  ram: 32
+  drives: 
+  runsOn: dell-c6400-node01
+  name: k8s-node-2
+  tags: 
+- kind: System
+  type: KubernetesNode
+  os: ubuntu
+  cores: 8
+  ram: 32
+  drives: 
+  runsOn: dell-c6400-node01
+  name: k8s-node-3
+  tags: 
+- kind: System
+  type: KubernetesControlPlane
+  os: ubuntu
+  cores: 4
+  ram: 16
+  drives: 
+  runsOn: dell-c6400-node01
+  name: k8s-control-plane
+  tags: 
+- kind: System
+  type: Monitoring
+  os: ubuntu
+  cores: 8
+  ram: 32
+  drives: 
+  runsOn: dell-c6400-node01
+  name: monitoring-node
+  tags: 
+- kind: System
+  type: Storage
+  os: truenas
+  cores: 8
+  ram: 64
+  drives: 
+  runsOn: dell-c6400-node01
+  name: storage-node-1
+  tags: 
+- kind: System
+  type: Storage
+  os: truenas
+  cores: 8
+  ram: 64
+  drives: 
+  runsOn: dell-c6400-node01
+  name: storage-node-2
+  tags: 
+- kind: System
+  type: Storage
+  os: truenas
+  cores: 8
+  ram: 64
+  drives: 
+  runsOn: dell-c6400-node01
+  name: storage-node-3
+  tags: 
+- kind: System
+  type: Database
+  os: ubuntu
+  cores: 8
+  ram: 32
+  drives: 
+  runsOn: dell-c6400-node01
+  name: db-node-1
+  tags: 
+- kind: System
+  type: Database
+  os: ubuntu
+  cores: 8
+  ram: 32
+  drives: 
+  runsOn: dell-c6400-node01
+  name: db-node-2
+  tags: 
+- kind: System
+  type: Cache
+  os: ubuntu
+  cores: 4
+  ram: 16
+  drives: 
+  runsOn: dell-c6400-node01
+  name: cache-node
+  tags: 
+- kind: System
+  type: Search
+  os: ubuntu
+  cores: 8
+  ram: 32
+  drives: 
+  runsOn: dell-c6400-node01
+  name: search-node
+  tags: 
+- kind: System
+  type: Development
+  os: ubuntu
+  cores: 4
+  ram: 16
+  drives: 
+  runsOn: dell-c6400-node01
+  name: dev-node-1
+  tags: 
+- kind: System
+  type: Development
+  os: ubuntu
+  cores: 4
+  ram: 16
+  drives: 
+  runsOn: dell-c6400-node01
+  name: dev-node-2
+  tags: 
+- kind: System
+  type: Development
+  os: ubuntu
+  cores: 6
+  ram: 24
+  drives: 
+  runsOn: dell-c6400-node01
+  name: dev-node-3
+  tags: 
+- kind: System
+  type: VirtualMachineCluster
+  os: proxmox
+  cores: 12
+  ram: 48
+  drives: 
+  runsOn: dell-c6400-node01
+  name: vm-cluster-1
+  tags: 
+- kind: System
+  type: VirtualMachineCluster
+  os: proxmox
+  cores: 12
+  ram: 48
+  drives: 
+  runsOn: dell-c6400-node01
+  name: vm-cluster-2
+  tags: 
+- kind: System
+  type: BareMetal
+  os: raspbian
+  cores: 4
+  ram: 8
+  drives: 
+  runsOn: rack-edge
+  name: baremetal-rpi4
+  tags: 
+- kind: System
+  type: BareMetal
+  os: raspbian
+  cores: 4
+  ram: 4
+  drives: 
+  runsOn: rack-edge
+  name: baremetal-rpi3
+  tags: 
+- kind: System
+  type: Infrastructure
+  os: ubuntu
+  cores: 4
+  ram: 16
+  drives: 
+  runsOn: dell-c6400-node01
+  name: infra-node
+  tags: 
+- kind: System
+  type: NetworkAppliance
+  os: openwrt
+  cores: 2
+  ram: 2
+  drives: 
+  runsOn: network-rack
+  name: router-appliance
+  tags: 

+ 30 - 30
RackPeek/config/accesspoints.yaml

@@ -1,31 +1,31 @@
 resources:
-  - kind: AccessPoint
-    model: Unifi-Ap-Pro
-    speed: 1
-    name: lounge-ap
-    tags:
-  - kind: AccessPoint
-    model: Unifi-U6-Lite
-    speed: 1
-    name: office-ap
-    tags:
-  - kind: AccessPoint
-    model: TP-Link-EAP245
-    speed: 1
-    name: garage-ap
-    tags:
-  - kind: AccessPoint
-    model: Aruba-AP-515
-    speed: 2.5
-    name: upstairs-ap
-    tags:
-  - kind: AccessPoint
-    model: Unifi-U6-Mesh
-    speed: 1
-    name: guest-ap
-    tags:
-  - kind: AccessPoint
-    model: Cisco-Aironet-1832i
-    speed: 1
-    name: warehouse-ap
-    tags: 
+- kind: AccessPoint
+  model: Unifi-Ap-Pro
+  speed: 1
+  name: lounge-ap
+  tags: 
+- kind: AccessPoint
+  model: Unifi-U6-Lite
+  speed: 1
+  name: office-ap
+  tags: 
+- kind: AccessPoint
+  model: TP-Link-EAP245
+  speed: 1
+  name: garage-ap
+  tags: 
+- kind: AccessPoint
+  model: Aruba-AP-515
+  speed: 2.5
+  name: upstairs-ap
+  tags: 
+- kind: AccessPoint
+  model: Unifi-U6-Mesh
+  speed: 1
+  name: guest-ap
+  tags: 
+- kind: AccessPoint
+  model: Cisco-Aironet-1832i
+  speed: 1
+  name: warehouse-ap
+  tags: 

+ 21 - 20
RackPeek/config/desktops.yaml

@@ -1,21 +1,22 @@
 resources:
-  - kind: Desktop
-    cpus:
-      - model: Intel(R) Core(TM) i5-9500
-        cores: 6
-        threads: 6
-    ram:
-      size: 16
-      mts: 2666
-    drives:
-      - type: ssd
-        size: 512
-    nics:
-      - type: rj45
-        speed: 1
-        ports: 1
-    gpus:
-      - model: RTX 3080
-        vram: 12
-    name: dell-optiplex
-    tags: 
+- kind: Desktop
+  cpus:
+  - model: Intel(R) Core(TM) i5-9500
+    cores: 6
+    threads: 6
+  ram:
+    size: 16
+    mts: 2666
+  drives:
+  - type: ssd
+    size: 512
+  nics:
+  - type: rj45
+    speed: 1
+    ports: 1
+  gpus:
+  - model: RTX 3080
+    vram: 12
+  model: 
+  name: dell-optiplex
+  tags: 

+ 13 - 13
RackPeek/config/firewalls.yaml

@@ -1,14 +1,14 @@
 resources:
-  - kind: Firewall
-    model: pfSense-1100
-    managed: true
-    poe: true
-    ports:
-      - type: rj45
-        speed: 1
-        count: 8
-      - type: sfp
-        speed: 10
-        count: 2
-    name: pfsense
-    tags: 
+- kind: Firewall
+  model: pfSense-1100
+  managed: true
+  poe: true
+  ports:
+  - type: rj45
+    speed: 1
+    count: 8
+  - type: sfp
+    speed: 10
+    count: 2
+  name: pfsense
+  tags: 

+ 16 - 16
RackPeek/config/laptops.yaml

@@ -1,17 +1,17 @@
 resources:
-  - kind: Laptop
-    cpus:
-      - model: Intel(R) Core(TM) i7-10510U
-        cores: 4
-        threads: 8
-    ram:
-      size: 16
-      mts: 2666
-    drives:
-      - type: ssd
-        size: 1024
-    gpus:
-      - model: RTX 3080
-        vram: 12
-    name: thinkpad-x1
-    tags: 
+- kind: Laptop
+  cpus:
+  - model: Intel(R) Core(TM) i7-10510U
+    cores: 4
+    threads: 8
+  ram:
+    size: 16
+    mts: 2666
+  drives:
+  - type: ssd
+    size: 1024
+  gpus:
+  - model: RTX 3080
+    vram: 12
+  name: thinkpad-x1
+  tags: 

+ 13 - 13
RackPeek/config/routers.yaml

@@ -1,14 +1,14 @@
 resources:
-  - kind: Router
-    model: ER-4
-    managed: true
-    poe: true
-    ports:
-      - type: rj45
-        speed: 1
-        count: 8
-      - type: sfp
-        speed: 10
-        count: 2
-    name: ubiquiti-edge-router
-    tags: 
+- kind: Router
+  model: ER-4
+  managed: true
+  poe: true
+  ports:
+  - type: rj45
+    speed: 1
+    count: 8
+  - type: sfp
+    speed: 10
+    count: 2
+  name: ubiquiti-edge-router
+  tags: 

+ 396 - 396
RackPeek/config/servers.yaml

@@ -1,397 +1,397 @@
 resources:
-  - kind: Server
-    cpus:
-      - model: Intel(R) Xeon(R) Silver 4110
-        cores: 8
-        threads: 16
-    ram:
-      size: 64
-      mts: 2400
-    drives:
-      - type: ssd
-        size: 480
-      - type: ssd
-        size: 480
-    nics:
-      - type: rj45
-        speed: 1
-        ports: 2
-      - type: sfp+
-        speed: 10
-        ports: 2
-    gpus:
-    ipmi: true
-    name: dell-c6400-node01
-    tags:
-  - kind: Server
-    cpus:
-      - model: Intel(R) Xeon(R) Silver 4110
-        cores: 8
-        threads: 16
-    ram:
-      size: 128
-      mts: 2400
-    drives:
-      - type: ssd
-        size: 960
-    nics:
-      - type: rj45
-        speed: 1
-        ports: 2
-      - type: sfp+
-        speed: 10
-        ports: 2
-    gpus:
-    ipmi: true
-    name: dell-c6400-node02
-    tags:
-  - kind: Server
-    cpus:
-      - model: Intel(R) Xeon(R) Silver 4110
-        cores: 8
-        threads: 16
-    ram:
-      size: 64
-      mts: 2400
-    drives:
-      - type: ssd
-        size: 480
-      - type: ssd
-        size: 480
-    nics:
-      - type: rj45
-        speed: 1
-        ports: 2
-      - type: sfp+
-        speed: 10
-        ports: 2
-    gpus:
-    ipmi: true
-    name: dell-c6400-node03
-    tags:
-  - kind: Server
-    cpus:
-      - model: Intel(R) Xeon(R) Silver 4110
-        cores: 8
-        threads: 16
-    ram:
-      size: 128
-      mts: 2400
-    drives:
-      - type: ssd
-        size: 960
-    nics:
-      - type: rj45
-        speed: 1
-        ports: 2
-      - type: sfp+
-        speed: 10
-        ports: 2
-    gpus:
-    ipmi: true
-    name: dell-c6400-node04
-    tags:
-  - kind: Server
-    cpus:
-      - model: Intel(R) Xeon(R) E5-2620 v4
-        cores: 8
-        threads: 16
-    ram:
-      size: 64
-      mts: 2133
-    drives:
-      - type: hdd
-        size: 8192
-      - type: hdd
-        size: 8192
-      - type: hdd
-        size: 8192
-      - type: hdd
-        size: 8192
-      - type: ssd
-        size: 120
-    nics:
-      - type: rj45
-        speed: 1
-        ports: 1
-      - type: sfp+
-        speed: 10
-        ports: 1
-    gpus:
-    ipmi: true
-    name: truenas-storage01
-    tags:
-  - kind: Server
-    cpus:
-      - model: Intel(R) Core(TM) i5-8500
-        cores: 6
-        threads: 6
-    ram:
-      size: 32
-      mts: 2666
-    drives:
-      - type: ssd
-        size: 512
-    nics:
-      - type: rj45
-        speed: 1
-        ports: 4
-    gpus:
-    ipmi: false
-    name: proxmox-edge01
-    tags:
-  - kind: Server
-    cpus:
-      - model: Intel(R) Celeron(R) J4125
-        cores: 4
-        threads: 4
-    ram:
-      size: 8
-      mts: 2400
-    drives:
-      - type: ssd
-        size: 64
-    nics:
-      - type: rj45
-        speed: 1
-        ports: 4
-    gpus:
-    ipmi: false
-    name: opnsense-fw01
-    tags:
-  - kind: Server
-    cpus:
-      - model: Intel(R) Xeon(R) E3-1270 v6
-        cores: 4
-        threads: 8
-    ram:
-      size: 16
-      mts: 2400
-    drives:
-      - type: ssd
-        size: 256
-    nics:
-      - type: rj45
-        speed: 1
-        ports: 1
-    gpus:
-    ipmi: true
-    name: mgmt-bastion01
-    tags:
-  - kind: Server
-    cpus:
-      - model: Intel(R) Xeon(R) E5-2630 v4
-        cores: 10
-        threads: 20
-    ram:
-      size: 64
-      mts: 2133
-    drives:
-      - type: hdd
-        size: 6144
-      - type: hdd
-        size: 6144
-      - type: hdd
-        size: 6144
-      - type: hdd
-        size: 6144
-      - type: ssd
-        size: 240
-    nics:
-      - type: rj45
-        speed: 1
-        ports: 2
-      - type: sfp+
-        speed: 10
-        ports: 1
-    gpus:
-    ipmi: true
-    name: truenas-backup01
-    tags:
-  - kind: Server
-    cpus:
-      - model: Intel(R) Xeon(R) Silver 4214
-        cores: 12
-        threads: 24
-    ram:
-      size: 128
-      mts: 2666
-    drives:
-      - type: ssd
-        size: 1024
-    nics:
-      - type: sfp+
-        speed: 10
-        ports: 2
-    gpus:
-      - model: NVIDIA Tesla P40
-        vram: 24
-      - model: NVIDIA Tesla P40
-        vram: 24
-      - model: NVIDIA Tesla P4
-        vram: 8
-    ipmi: true
-    name: compute-gpu01
-    tags:
-  - kind: Server
-    cpus:
-      - model: Intel(R) Xeon(R) E3-1240 v5
-        cores: 4
-        threads: 8
-    ram:
-      size: 32
-      mts: 2133
-    drives:
-      - type: ssd
-        size: 512
-    nics:
-      - type: rj45
-        speed: 1
-        ports: 2
-    gpus:
-    ipmi: true
-    name: proxmox-lab01
-    tags:
-  - kind: Server
-    cpus:
-      - model: Intel(R) Xeon(R) E-2224
-        cores: 4
-        threads: 4
-    ram:
-      size: 16
-      mts: 2666
-    drives:
-      - type: ssd
-        size: 256
-    nics:
-      - type: rj45
-        speed: 1
-        ports: 2
-    gpus:
-    ipmi: true
-    name: k8s-control01
-    tags:
-  - kind: Server
-    cpus:
-      - model: Intel(R) Xeon(R) E-2224
-        cores: 4
-        threads: 4
-    ram:
-      size: 16
-      mts: 2666
-    drives:
-      - type: ssd
-        size: 256
-    nics:
-      - type: rj45
-        speed: 1
-        ports: 2
-    gpus:
-    ipmi: true
-    name: k8s-control02
-    tags:
-  - kind: Server
-    cpus:
-      - model: Intel(R) Xeon(R) Silver 4108
-        cores: 8
-        threads: 16
-    ram:
-      size: 64
-      mts: 2400
-    drives:
-      - type: ssd
-        size: 1024
-      - type: ssd
-        size: 1024
-    nics:
-      - type: sfp+
-        speed: 10
-        ports: 1
-    gpus:
-    ipmi: true
-    name: elk-logging01
-    tags:
-  - kind: Server
-    cpus:
-      - model: Intel(R) Core(TM) i3-8100
-        cores: 4
-        threads: 4
-    ram:
-      size: 16
-      mts: 2400
-    drives:
-      - type: ssd
-        size: 256
-    nics:
-      - type: rj45
-        speed: 1
-        ports: 2
-    gpus:
-    ipmi: false
-    name: edge-node01
-    tags:
-  - kind: Server
-    cpus:
-      - model: Intel(R) Xeon(R) E5-1650 v3
-        cores: 6
-        threads: 12
-    ram:
-      size: 64
-      mts: 2133
-    drives:
-      - type: ssd
-        size: 480
-      - type: hdd
-        size: 4096
-    nics:
-      - type: rj45
-        speed: 1
-        ports: 4
-    gpus:
-    ipmi: true
-    name: backup-proxmox01
-    tags:
-  - kind: Server
-    cpus:
-      - model: Intel(R) Core(TM) i7-8700
-        cores: 6
-        threads: 12
-    ram:
-      size: 32
-      mts: 2666
-    drives:
-      - type: ssd
-        size: 512
-    nics:
-      - type: rj45
-        speed: 1
-        ports: 1
-    gpus:
-    ipmi: false
-    name: lab-general01
-    tags:
-  - kind: Server
-    cpus:
-      - model: Intel(R) Xeon(R) E5-2650 v3
-        cores: 10
-        threads: 20
-    ram:
-      size: 128
-      mts: 2133
-    drives:
-      - type: hdd
-        size: 4096
-      - type: hdd
-        size: 4096
-      - type: hdd
-        size: 4096
-      - type: hdd
-        size: 4096
-    nics:
-      - type: sfp+
-        speed: 10
-        ports: 2
-    gpus:
-    ipmi: true
-    name: dell-r730-archive01
-    tags: 
+- kind: Server
+  cpus:
+  - model: Intel(R) Xeon(R) Silver 4110
+    cores: 8
+    threads: 16
+  ram:
+    size: 64
+    mts: 2400
+  drives:
+  - type: ssd
+    size: 480
+  - type: ssd
+    size: 480
+  nics:
+  - type: rj45
+    speed: 1
+    ports: 2
+  - type: sfp+
+    speed: 10
+    ports: 2
+  gpus: 
+  ipmi: true
+  name: dell-c6400-node01
+  tags: 
+- kind: Server
+  cpus:
+  - model: Intel(R) Xeon(R) Silver 4110
+    cores: 8
+    threads: 16
+  ram:
+    size: 128
+    mts: 2400
+  drives:
+  - type: ssd
+    size: 960
+  nics:
+  - type: rj45
+    speed: 1
+    ports: 2
+  - type: sfp+
+    speed: 10
+    ports: 2
+  gpus: 
+  ipmi: true
+  name: dell-c6400-node02
+  tags: 
+- kind: Server
+  cpus:
+  - model: Intel(R) Xeon(R) Silver 4110
+    cores: 8
+    threads: 16
+  ram:
+    size: 64
+    mts: 2400
+  drives:
+  - type: ssd
+    size: 480
+  - type: ssd
+    size: 480
+  nics:
+  - type: rj45
+    speed: 1
+    ports: 2
+  - type: sfp+
+    speed: 10
+    ports: 2
+  gpus: 
+  ipmi: true
+  name: dell-c6400-node03
+  tags: 
+- kind: Server
+  cpus:
+  - model: Intel(R) Xeon(R) Silver 4110
+    cores: 8
+    threads: 16
+  ram:
+    size: 128
+    mts: 2400
+  drives:
+  - type: ssd
+    size: 960
+  nics:
+  - type: rj45
+    speed: 1
+    ports: 2
+  - type: sfp+
+    speed: 10
+    ports: 2
+  gpus: 
+  ipmi: true
+  name: dell-c6400-node04
+  tags: 
+- kind: Server
+  cpus:
+  - model: Intel(R) Xeon(R) E5-2620 v4
+    cores: 8
+    threads: 16
+  ram:
+    size: 64
+    mts: 2133
+  drives:
+  - type: hdd
+    size: 8192
+  - type: hdd
+    size: 8192
+  - type: hdd
+    size: 8192
+  - type: hdd
+    size: 8192
+  - type: ssd
+    size: 120
+  nics:
+  - type: rj45
+    speed: 1
+    ports: 1
+  - type: sfp+
+    speed: 10
+    ports: 1
+  gpus: 
+  ipmi: true
+  name: truenas-storage01
+  tags: 
+- kind: Server
+  cpus:
+  - model: Intel(R) Core(TM) i5-8500
+    cores: 6
+    threads: 6
+  ram:
+    size: 32
+    mts: 2666
+  drives:
+  - type: ssd
+    size: 512
+  nics:
+  - type: rj45
+    speed: 1
+    ports: 4
+  gpus: 
+  ipmi: false
+  name: proxmox-edge01
+  tags: 
+- kind: Server
+  cpus:
+  - model: Intel(R) Celeron(R) J4125
+    cores: 4
+    threads: 4
+  ram:
+    size: 8
+    mts: 2400
+  drives:
+  - type: ssd
+    size: 64
+  nics:
+  - type: rj45
+    speed: 1
+    ports: 4
+  gpus: 
+  ipmi: false
+  name: opnsense-fw01
+  tags: 
+- kind: Server
+  cpus:
+  - model: Intel(R) Xeon(R) E3-1270 v6
+    cores: 4
+    threads: 8
+  ram:
+    size: 16
+    mts: 2400
+  drives:
+  - type: ssd
+    size: 256
+  nics:
+  - type: rj45
+    speed: 1
+    ports: 1
+  gpus: 
+  ipmi: true
+  name: mgmt-bastion01
+  tags: 
+- kind: Server
+  cpus:
+  - model: Intel(R) Xeon(R) E5-2630 v4
+    cores: 10
+    threads: 20
+  ram:
+    size: 64
+    mts: 2133
+  drives:
+  - type: hdd
+    size: 6144
+  - type: hdd
+    size: 6144
+  - type: hdd
+    size: 6144
+  - type: hdd
+    size: 6144
+  - type: ssd
+    size: 240
+  nics:
+  - type: rj45
+    speed: 1
+    ports: 2
+  - type: sfp+
+    speed: 10
+    ports: 1
+  gpus: 
+  ipmi: true
+  name: truenas-backup01
+  tags: 
+- kind: Server
+  cpus:
+  - model: Intel(R) Xeon(R) Silver 4214
+    cores: 12
+    threads: 24
+  ram:
+    size: 128
+    mts: 2666
+  drives:
+  - type: ssd
+    size: 1024
+  nics:
+  - type: sfp+
+    speed: 10
+    ports: 2
+  gpus:
+  - model: NVIDIA Tesla P40
+    vram: 24
+  - model: NVIDIA Tesla P40
+    vram: 24
+  - model: NVIDIA Tesla P4
+    vram: 8
+  ipmi: true
+  name: compute-gpu01
+  tags: 
+- kind: Server
+  cpus:
+  - model: Intel(R) Xeon(R) E3-1240 v5
+    cores: 4
+    threads: 8
+  ram:
+    size: 32
+    mts: 2133
+  drives:
+  - type: ssd
+    size: 512
+  nics:
+  - type: rj45
+    speed: 1
+    ports: 2
+  gpus: 
+  ipmi: true
+  name: proxmox-lab01
+  tags: 
+- kind: Server
+  cpus:
+  - model: Intel(R) Xeon(R) E-2224
+    cores: 4
+    threads: 4
+  ram:
+    size: 16
+    mts: 2666
+  drives:
+  - type: ssd
+    size: 256
+  nics:
+  - type: rj45
+    speed: 1
+    ports: 2
+  gpus: 
+  ipmi: true
+  name: k8s-control01
+  tags: 
+- kind: Server
+  cpus:
+  - model: Intel(R) Xeon(R) E-2224
+    cores: 4
+    threads: 4
+  ram:
+    size: 16
+    mts: 2666
+  drives:
+  - type: ssd
+    size: 256
+  nics:
+  - type: rj45
+    speed: 1
+    ports: 2
+  gpus: 
+  ipmi: true
+  name: k8s-control02
+  tags: 
+- kind: Server
+  cpus:
+  - model: Intel(R) Xeon(R) Silver 4108
+    cores: 8
+    threads: 16
+  ram:
+    size: 64
+    mts: 2400
+  drives:
+  - type: ssd
+    size: 1024
+  - type: ssd
+    size: 1024
+  nics:
+  - type: sfp+
+    speed: 10
+    ports: 1
+  gpus: 
+  ipmi: true
+  name: elk-logging01
+  tags: 
+- kind: Server
+  cpus:
+  - model: Intel(R) Core(TM) i3-8100
+    cores: 4
+    threads: 4
+  ram:
+    size: 16
+    mts: 2400
+  drives:
+  - type: ssd
+    size: 256
+  nics:
+  - type: rj45
+    speed: 1
+    ports: 2
+  gpus: 
+  ipmi: false
+  name: edge-node01
+  tags: 
+- kind: Server
+  cpus:
+  - model: Intel(R) Xeon(R) E5-1650 v3
+    cores: 6
+    threads: 12
+  ram:
+    size: 64
+    mts: 2133
+  drives:
+  - type: ssd
+    size: 480
+  - type: hdd
+    size: 4096
+  nics:
+  - type: rj45
+    speed: 1
+    ports: 4
+  gpus: 
+  ipmi: true
+  name: backup-proxmox01
+  tags: 
+- kind: Server
+  cpus:
+  - model: Intel(R) Core(TM) i7-8700
+    cores: 6
+    threads: 12
+  ram:
+    size: 32
+    mts: 2666
+  drives:
+  - type: ssd
+    size: 512
+  nics:
+  - type: rj45
+    speed: 1
+    ports: 1
+  gpus: 
+  ipmi: false
+  name: lab-general01
+  tags: 
+- kind: Server
+  cpus:
+  - model: Intel(R) Xeon(R) E5-2650 v3
+    cores: 10
+    threads: 20
+  ram:
+    size: 128
+    mts: 2133
+  drives:
+  - type: hdd
+    size: 4096
+  - type: hdd
+    size: 4096
+  - type: hdd
+    size: 4096
+  - type: hdd
+    size: 4096
+  nics:
+  - type: sfp+
+    speed: 10
+    ports: 2
+  gpus: 
+  ipmi: true
+  name: dell-r730-archive01
+  tags: 

+ 13 - 13
RackPeek/config/switches.yaml

@@ -1,14 +1,14 @@
 resources:
-  - kind: Switch
-    model: GS324
-    managed: true
-    poe: true
-    ports:
-      - type: rj45
-        speed: 1
-        count: 8
-      - type: sfp
-        speed: 10
-        count: 2
-    name: netgear-s24
-    tags: 
+- kind: Switch
+  model: GS324
+  managed: true
+  poe: true
+  ports:
+  - type: rj45
+    speed: 1
+    count: 8
+  - type: sfp
+    speed: 10
+    count: 2
+  name: netgear-s24
+  tags: 

+ 5 - 5
RackPeek/config/ups.yaml

@@ -1,6 +1,6 @@
 resources:
-  - kind: Ups
-    model: Volta
-    va: 2200
-    name: rack-ups
-    tags: 
+- kind: Ups
+  model: Volta
+  va: 2200
+  name: rack-ups
+  tags: 

+ 9 - 6
Tests/HardwareResources/AddGpuUseCaseTests.cs

@@ -1,4 +1,5 @@
 using NSubstitute;
+using RackPeek.Domain.Helpers;
 using RackPeek.Domain.Resources.Hardware;
 using RackPeek.Domain.Resources.Hardware.Models;
 using RackPeek.Domain.Resources.Hardware.Servers.Gpus;
@@ -76,7 +77,7 @@ public class AddGpuUseCaseTests
     }
 
     [Fact]
-    public async Task ExecuteAsync_Does_nothing_when_server_does_not_exist()
+    public async Task ExecuteAsync_throws_when_server_does_not_exist()
     {
         // Arrange
         var repo = Substitute.For<IHardwareRepository>();
@@ -86,13 +87,15 @@ public class AddGpuUseCaseTests
         var sut = new AddGpuUseCase(repo);
 
         // Act
-        await sut.ExecuteAsync(
-            "node01",
-            "RTX 4090",
-            24
+        var ex = await Assert.ThrowsAsync<NotFoundException>(async () =>
+                await sut.ExecuteAsync(
+                    "node01",
+                    "RTX 4090",
+                    24
+                )
         );
 
         // Assert
-        await repo.DidNotReceive().UpdateAsync(Arg.Any<Server>());
+        await repo.DidNotReceive().AddAsync(Arg.Any<Server>());
     }
 }

+ 9 - 5
Tests/HardwareResources/AddNicUseCaseTests.cs

@@ -1,4 +1,5 @@
 using NSubstitute;
+using RackPeek.Domain.Helpers;
 using RackPeek.Domain.Resources.Hardware;
 using RackPeek.Domain.Resources.Hardware.Models;
 using RackPeek.Domain.Resources.Hardware.Servers.Nics;
@@ -21,16 +22,16 @@ public class AddNicUseCaseTests
 
         var sut = new AddNicUseCase(repo);
 
-        await sut.ExecuteAsync("node01", "10GBase-T", 10000, 2);
+        await sut.ExecuteAsync("node01", "rj45", 10000, 2);
 
         Assert.Single(server.Nics);
-        Assert.Equal("10GBase-T", server.Nics[0].Type);
+        Assert.Equal("rj45", server.Nics[0].Type);
         Assert.Equal(10000, server.Nics[0].Speed!.Value);
         Assert.Equal(2, server.Nics[0].Ports!.Value);
 
         await repo.Received(1).UpdateAsync(Arg.Is<Server>(s =>
             s.Nics.Count == 1 &&
-            s.Nics[0].Type == "10GBase-T"
+            s.Nics[0].Type == "rj45"
         ));
     }
 
@@ -53,7 +54,7 @@ public class AddNicUseCaseTests
     }
 
     [Fact]
-    public async Task ExecuteAsync_Does_nothing_when_server_not_found()
+    public async Task ExecuteAsync_throws_when_server_not_found()
     {
         var repo = Substitute.For<IHardwareRepository>();
 
@@ -62,8 +63,11 @@ public class AddNicUseCaseTests
 
         var sut = new AddNicUseCase(repo);
 
-        await sut.ExecuteAsync("node01", "SFP+", 10000, 1);
+        var ex = await Assert.ThrowsAsync<NotFoundException>(async () =>
+            await sut.ExecuteAsync("node01", "SFP+", 10000, 1)
+        );
 
+        // Assert
         await repo.DidNotReceive().UpdateAsync(Arg.Any<Server>());
     }
 }

+ 2 - 2
Tests/HardwareResources/AddServerUseCaseTests.cs

@@ -1,4 +1,5 @@
 using NSubstitute;
+using RackPeek.Domain.Helpers;
 using RackPeek.Domain.Resources.Hardware;
 using RackPeek.Domain.Resources.Hardware.Models;
 using RackPeek.Domain.Resources.Hardware.Servers;
@@ -37,14 +38,13 @@ public class AddServerUseCaseTests
         var sut = new AddServerUseCase(repo);
 
         // Act
-        var ex = await Assert.ThrowsAsync<InvalidOperationException>(async () =>
+        var ex = await Assert.ThrowsAsync<ConflictException>(async () =>
             await sut.ExecuteAsync(
                 "node01"
             )
         );
 
         // Assert
-        Assert.Equal("Server 'node01' already exists.", ex.Message);
         await repo.DidNotReceive().AddAsync(Arg.Any<Server>());
     }
 }

+ 2 - 1
Tests/HardwareResources/DeleteServerUseCaseTests.cs

@@ -1,4 +1,5 @@
 using NSubstitute;
+using RackPeek.Domain.Helpers;
 using RackPeek.Domain.Resources.Hardware;
 using RackPeek.Domain.Resources.Hardware.Models;
 using RackPeek.Domain.Resources.Hardware.Servers;
@@ -33,7 +34,7 @@ public class DeleteServerUseCaseTests
         var sut = new DeleteServerUseCase(repo);
 
         // Act
-        var ex = await Assert.ThrowsAsync<InvalidOperationException>(() =>
+        var ex = await Assert.ThrowsAsync<NotFoundException>(() =>
             sut.ExecuteAsync("node01")
         );
 

+ 7 - 3
Tests/HardwareResources/RemoveNicUseCaseTests.cs

@@ -1,4 +1,6 @@
+using System.ComponentModel.DataAnnotations;
 using NSubstitute;
+using RackPeek.Domain.Helpers;
 using RackPeek.Domain.Resources.Hardware;
 using RackPeek.Domain.Resources.Hardware.Models;
 using RackPeek.Domain.Resources.Hardware.Servers.Nics;
@@ -47,14 +49,14 @@ public class RemoveNicUseCaseTests
 
         var sut = new RemoveNicUseCase(repo);
 
-        await Assert.ThrowsAsync<ArgumentOutOfRangeException>(() =>
+        await Assert.ThrowsAsync<ValidationException>(() =>
             sut.ExecuteAsync("node01", 1));
 
         await repo.DidNotReceive().UpdateAsync(Arg.Any<Server>());
     }
 
     [Fact]
-    public async Task ExecuteAsync_Does_nothing_when_server_not_found()
+    public async Task ExecuteAsync_throws_when_server_not_found()
     {
         var repo = Substitute.For<IHardwareRepository>();
 
@@ -63,7 +65,9 @@ public class RemoveNicUseCaseTests
 
         var sut = new RemoveNicUseCase(repo);
 
-        await sut.ExecuteAsync("node01", 0);
+        var ex = await Assert.ThrowsAsync<NotFoundException>(() =>
+            sut.ExecuteAsync("node01", 0)
+        );
 
         await repo.DidNotReceive().UpdateAsync(Arg.Any<Server>());
     }

+ 7 - 3
Tests/HardwareResources/UpdateNicUseCaseTests.cs

@@ -1,4 +1,6 @@
+using System.ComponentModel.DataAnnotations;
 using NSubstitute;
+using RackPeek.Domain.Helpers;
 using RackPeek.Domain.Resources.Hardware;
 using RackPeek.Domain.Resources.Hardware.Models;
 using RackPeek.Domain.Resources.Hardware.Servers.Nics;
@@ -26,7 +28,7 @@ public class UpdateNicUseCaseTests
 
         await sut.ExecuteAsync("node01", 0, "SFP+", 10000, 1);
 
-        Assert.Equal("SFP+", server.Nics[0].Type);
+        Assert.Equal("sfp+", server.Nics[0].Type);
         Assert.Equal(10000, server.Nics[0].Speed!.Value);
         Assert.Equal(1, server.Nics[0].Ports!.Value);
 
@@ -47,7 +49,7 @@ public class UpdateNicUseCaseTests
 
         var sut = new UpdateNicUseCase(repo);
 
-        await Assert.ThrowsAsync<ArgumentOutOfRangeException>(() =>
+        await Assert.ThrowsAsync<ValidationException>(() =>
             sut.ExecuteAsync("node01", 1, "SFP+", 10000, 1));
 
         await repo.DidNotReceive().UpdateAsync(Arg.Any<Server>());
@@ -63,7 +65,9 @@ public class UpdateNicUseCaseTests
 
         var sut = new UpdateNicUseCase(repo);
 
-        await sut.ExecuteAsync("node01", 0, "SFP+", 10000, 1);
+        var ex = await Assert.ThrowsAsync<NotFoundException>(() =>
+            sut.ExecuteAsync("node01", 0, "SFP+", 10000, 1)
+        );
 
         await repo.DidNotReceive().UpdateAsync(Arg.Any<Server>());
     }

+ 2 - 1
Tests/HardwareResources/UpdateServerUseCaseTests.cs

@@ -1,4 +1,5 @@
 using NSubstitute;
+using RackPeek.Domain.Helpers;
 using RackPeek.Domain.Resources.Hardware;
 using RackPeek.Domain.Resources.Hardware.Models;
 using RackPeek.Domain.Resources.Hardware.Servers;
@@ -50,7 +51,7 @@ public class UpdateServerUseCaseTests
         var sut = new UpdateServerUseCase(repo);
 
         // Act
-        var ex = await Assert.ThrowsAsync<InvalidOperationException>(() =>
+        var ex = await Assert.ThrowsAsync<NotFoundException>(() =>
             sut.ExecuteAsync("node01", 64)
         );