InventoryEndpointStartupTests.cs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. using System.Net.Http.Json;
  2. using RackPeek.Domain.Api;
  3. using Xunit.Abstractions;
  4. namespace Tests.Api;
  5. /// <summary>
  6. /// The inventory API is reached without a browser — by scripts, by CI, and by
  7. /// <c>rpk discover --push</c> on a timer. It therefore has to work on a server that
  8. /// nobody has opened a page on yet.
  9. /// </summary>
  10. public class InventoryEndpointStartupTests(ITestOutputHelper output) : ApiTestBase(output) {
  11. private const string _existingConfig = """
  12. version: 3
  13. resources:
  14. - kind: Server
  15. name: hand-written-server
  16. notes: documented by hand years ago
  17. connections: []
  18. """;
  19. [Fact]
  20. public async Task The_first_request_after_a_restart_does_not_destroy_the_existing_inventory() {
  21. var configPath = Path.Combine(TempDir, "config.yaml");
  22. await File.WriteAllTextAsync(configPath, _existingConfig);
  23. // The very first thing to touch this server is an API call, with no Blazor
  24. // circuit having ever initialised and therefore no implicit load.
  25. HttpClient client = CreateClient(true);
  26. HttpResponseMessage response = await client.PostAsJsonAsync("/api/inventory", new {
  27. yaml = """
  28. version: 3
  29. resources:
  30. - kind: Server
  31. name: newly-discovered-box
  32. """,
  33. mode = "Merge"
  34. });
  35. response.EnsureSuccessStatusCode();
  36. var stored = await File.ReadAllTextAsync(configPath);
  37. Assert.Contains("hand-written-server", stored);
  38. Assert.Contains("documented by hand years ago", stored);
  39. Assert.Contains("newly-discovered-box", stored);
  40. }
  41. [Fact]
  42. public async Task An_existing_resource_is_updated_rather_than_re_added_on_a_cold_server() {
  43. await File.WriteAllTextAsync(Path.Combine(TempDir, "config.yaml"), _existingConfig);
  44. HttpClient client = CreateClient(true);
  45. HttpResponseMessage response = await client.PostAsJsonAsync("/api/inventory", new {
  46. yaml = """
  47. version: 3
  48. resources:
  49. - kind: Server
  50. name: hand-written-server
  51. notes: updated
  52. """,
  53. mode = "Merge"
  54. });
  55. ImportYamlResponse? result = await response.Content.ReadFromJsonAsync<ImportYamlResponse>();
  56. Assert.Empty(result!.Added);
  57. Assert.Equal(["hand-written-server"], result.Updated);
  58. }
  59. [Fact]
  60. public async Task An_unreadable_config_does_not_stop_the_server_starting() {
  61. // The web UI is how someone fixes a broken config, so it has to come up.
  62. await File.WriteAllTextAsync(
  63. Path.Combine(TempDir, "config.yaml"),
  64. "version: 3\nresources:\n - kind: Server\n name: [unterminated\n");
  65. HttpClient client = CreateClient();
  66. HttpResponseMessage response = await client.GetAsync("/health");
  67. response.EnsureSuccessStatusCode();
  68. Assert.Equal("rackpeek", await response.Content.ReadAsStringAsync());
  69. }
  70. }