ServiceSubnetsUseCase.cs 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. using RackPeek.Domain.Persistence;
  2. using RackPeek.Domain.Resources.Services.Networking;
  3. namespace RackPeek.Domain.Resources.Services.UseCases;
  4. public class ServiceSubnetsUseCase(IResourceCollection repo) : IUseCase
  5. {
  6. public async Task<ServiceSubnetsResult> ExecuteAsync(string? cidr, int? prefix, CancellationToken token)
  7. {
  8. var services = await repo.GetAllOfTypeAsync<Service>();
  9. // If CIDR is provided → filter mode
  10. if (cidr is not null)
  11. {
  12. Cidr parsed;
  13. try
  14. {
  15. parsed = Cidr.Parse(cidr);
  16. }
  17. catch
  18. {
  19. return ServiceSubnetsResult.InvalidCidr(cidr);
  20. }
  21. var matches = services
  22. .Where(s => s.Network?.Ip != null)
  23. .Where(s => parsed.Contains(IpHelper.ToUInt32(s.Network!.Ip!)))
  24. .Select(s => new ServiceSummary(
  25. s.Name,
  26. s.Network!.Ip!,
  27. s.RunsOn))
  28. .ToList();
  29. return ServiceSubnetsResult.FromServices(matches, parsed.ToString());
  30. }
  31. // No CIDR → subnet discovery mode
  32. var effectivePrefix = prefix ?? 24;
  33. var mask = IpHelper.MaskFromPrefix(effectivePrefix);
  34. var groups = services
  35. .Where(s => s.Network?.Ip != null)
  36. .Select(s => IpHelper.ToUInt32(s.Network!.Ip!))
  37. .GroupBy(ip => ip & mask)
  38. .Select(g => new SubnetSummary(
  39. $"{IpHelper.ToIp(g.Key)}/{effectivePrefix}",
  40. g.Count()))
  41. .OrderBy(s => s.Cidr)
  42. .ToList();
  43. return ServiceSubnetsResult.FromSubnets(groups);
  44. }
  45. }
  46. public record SubnetSummary(string Cidr, int Count);
  47. public record ServiceSummary(string Name, string Ip, List<string>? RunsOn);
  48. public class ServiceSubnetsResult
  49. {
  50. public bool IsInvalidCidr { get; private set; }
  51. public string? InvalidCidrValue { get; private set; }
  52. public string? FilteredCidr { get; private set; }
  53. public List<SubnetSummary> Subnets { get; private set; } = new();
  54. public List<ServiceSummary> Services { get; private set; } = new();
  55. public static ServiceSubnetsResult InvalidCidr(string cidr)
  56. {
  57. return new ServiceSubnetsResult { IsInvalidCidr = true, InvalidCidrValue = cidr };
  58. }
  59. public static ServiceSubnetsResult FromSubnets(List<SubnetSummary> subnets)
  60. {
  61. return new ServiceSubnetsResult { Subnets = subnets };
  62. }
  63. public static ServiceSubnetsResult FromServices(List<ServiceSummary> services, string cidr)
  64. {
  65. return new ServiceSubnetsResult { Services = services, FilteredCidr = cidr };
  66. }
  67. }