nix: cleanup
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: Ia88656a1d6bb152398a5c4ce83d40a3e6a6a6964
This commit is contained in:
parent
794e4a8e61
commit
62f8cdf4de
13 changed files with 514 additions and 529 deletions
|
|
@ -1,12 +1,14 @@
|
|||
{
|
||||
pkgs,
|
||||
fc-packages,
|
||||
nixosModule,
|
||||
}:
|
||||
{pkgs, self}:
|
||||
pkgs.testers.nixosTest {
|
||||
name = "fc-basic-api";
|
||||
|
||||
nodes.machine = import ./common.nix {inherit pkgs fc-packages nixosModule;};
|
||||
nodes.machine = {
|
||||
imports = [
|
||||
self.nixosModules.fc-ci
|
||||
../vm-common.nix
|
||||
];
|
||||
_module.args.self = self;
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
import hashlib
|
||||
|
|
@ -22,7 +24,7 @@ pkgs.testers.nixosTest {
|
|||
# Wait for the server to start listening
|
||||
machine.wait_until_succeeds("curl -sf http://127.0.0.1:3000/health", timeout=30)
|
||||
|
||||
# ---- Seed an API key for write operations ----
|
||||
## Seed an API key for write operations
|
||||
# Token: fc_testkey123 -> SHA-256 hash inserted into api_keys table
|
||||
api_token = "fc_testkey123"
|
||||
api_hash = hashlib.sha256(api_token.encode()).hexdigest()
|
||||
|
|
@ -31,7 +33,7 @@ pkgs.testers.nixosTest {
|
|||
)
|
||||
auth_header = f"-H 'Authorization: Bearer {api_token}'"
|
||||
|
||||
# ---- Health endpoint ----
|
||||
# Health endpoint
|
||||
with subtest("Health endpoint returns OK"):
|
||||
result = machine.succeed("curl -sf http://127.0.0.1:3000/health | jq -r .status")
|
||||
assert result.strip() == "ok", f"Expected 'ok', got '{result.strip()}'"
|
||||
|
|
@ -40,13 +42,13 @@ pkgs.testers.nixosTest {
|
|||
result = machine.succeed("curl -sf http://127.0.0.1:3000/health | jq -r .database")
|
||||
assert result.strip() == "true", f"Expected 'true', got '{result.strip()}'"
|
||||
|
||||
# ---- Cache endpoint: nix-cache-info ----
|
||||
# Cache endpoint: nix-cache-info
|
||||
with subtest("Cache info endpoint returns correct data"):
|
||||
result = machine.succeed("curl -sf http://127.0.0.1:3000/nix-cache/nix-cache-info")
|
||||
assert "StoreDir: /nix/store" in result, f"Missing StoreDir in: {result}"
|
||||
assert "WantMassQuery: 1" in result, f"Missing WantMassQuery in: {result}"
|
||||
|
||||
# ---- Cache endpoint: invalid hash rejection ----
|
||||
# Cache endpoint: invalid hash rejection
|
||||
with subtest("Cache rejects short hash"):
|
||||
machine.succeed("curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:3000/nix-cache/tooshort.narinfo | grep -q 404")
|
||||
|
||||
|
|
@ -59,14 +61,14 @@ pkgs.testers.nixosTest {
|
|||
with subtest("Cache returns 404 for valid but nonexistent hash"):
|
||||
machine.succeed("curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:3000/nix-cache/abcdefghijklmnopqrstuvwxyz012345.narinfo | grep -q 404")
|
||||
|
||||
# ---- NAR endpoints: invalid hash rejection ----
|
||||
# NAR endpoints: invalid hash rejection
|
||||
with subtest("NAR zst rejects invalid hash"):
|
||||
machine.succeed("curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:3000/nix-cache/nar/INVALID.nar.zst | grep -q 404")
|
||||
|
||||
with subtest("NAR plain rejects invalid hash"):
|
||||
machine.succeed("curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:3000/nix-cache/nar/INVALID.nar | grep -q 404")
|
||||
|
||||
# ---- Search endpoint: length validation ----
|
||||
# Search endpoint: length validation
|
||||
with subtest("Search rejects empty query"):
|
||||
result = machine.succeed("curl -sf 'http://127.0.0.1:3000/api/v1/search?q=' | jq '.projects | length'")
|
||||
assert result.strip() == "0", f"Expected 0 projects, got {result.strip()}"
|
||||
|
|
@ -76,12 +78,12 @@ pkgs.testers.nixosTest {
|
|||
result = machine.succeed(f"curl -sf 'http://127.0.0.1:3000/api/v1/search?q={long_q}' | jq '.projects | length'")
|
||||
assert result.strip() == "0", f"Expected 0 projects for long query, got {result.strip()}"
|
||||
|
||||
# ---- Error response format ----
|
||||
# Error response format
|
||||
with subtest("404 error response includes error_code field"):
|
||||
json_result = machine.succeed("curl -s http://127.0.0.1:3000/api/v1/projects/00000000-0000-0000-0000-000000000000 | jq -r .error_code")
|
||||
assert json_result.strip() == "NOT_FOUND", f"Expected NOT_FOUND, got {json_result.strip()}"
|
||||
|
||||
# ---- Empty page states (before any data is created) ----
|
||||
# Empty page states (before any data is created)
|
||||
with subtest("Empty evaluations page has proper empty state"):
|
||||
body = machine.succeed("curl -sf http://127.0.0.1:3000/evaluations")
|
||||
assert "Page 1 of 0" not in body, \
|
||||
|
|
@ -107,7 +109,7 @@ pkgs.testers.nixosTest {
|
|||
assert "table-wrap" in body, \
|
||||
"Projects page should wrap tables in .table-wrap class"
|
||||
|
||||
# ---- API CRUD: create and list projects ----
|
||||
# API CRUD: create and list projects
|
||||
with subtest("Create a project via API"):
|
||||
result = machine.succeed(
|
||||
"curl -sf -X POST http://127.0.0.1:3000/api/v1/projects "
|
||||
|
|
@ -123,7 +125,7 @@ pkgs.testers.nixosTest {
|
|||
result = machine.succeed("curl -sf http://127.0.0.1:3000/api/v1/projects | jq '.items[0].name'")
|
||||
assert "test-project" in result, f"Expected test-project in: {result}"
|
||||
|
||||
# ---- Builds list with filters ----
|
||||
# Builds list with filters
|
||||
with subtest("Builds list with system filter returns 200"):
|
||||
machine.succeed("curl -sf 'http://127.0.0.1:3000/api/v1/builds?system=x86_64-linux' | jq '.items'")
|
||||
|
||||
|
|
@ -133,14 +135,14 @@ pkgs.testers.nixosTest {
|
|||
with subtest("Builds list with combined filters returns 200"):
|
||||
machine.succeed("curl -sf 'http://127.0.0.1:3000/api/v1/builds?system=x86_64-linux&status=pending&job_name=test' | jq '.items'")
|
||||
|
||||
# ---- Metrics endpoint ----
|
||||
# Metrics endpoint
|
||||
with subtest("Metrics endpoint returns prometheus format"):
|
||||
result = machine.succeed("curl -sf http://127.0.0.1:3000/metrics")
|
||||
assert "fc_builds_total" in result, "Missing fc_builds_total in metrics"
|
||||
assert "fc_projects_total" in result, "Missing fc_projects_total in metrics"
|
||||
assert "fc_evaluations_total" in result, "Missing fc_evaluations_total in metrics"
|
||||
|
||||
# ---- CORS: default restrictive (no Access-Control-Allow-Origin for cross-origin) ----
|
||||
# CORS: default restrictive (no Access-Control-Allow-Origin for cross-origin)
|
||||
with subtest("Default CORS does not allow arbitrary origins"):
|
||||
result = machine.succeed(
|
||||
"curl -s -D - "
|
||||
|
|
@ -153,7 +155,7 @@ pkgs.testers.nixosTest {
|
|||
assert "access-control-allow-origin: http://evil.example.com" not in result.lower(), \
|
||||
f"CORS should not allow arbitrary origins: {result}"
|
||||
|
||||
# ---- Systemd hardening ----
|
||||
# Systemd hardening
|
||||
with subtest("fc-server runs as fc user"):
|
||||
result = machine.succeed("systemctl show fc-server --property=User --value")
|
||||
assert result.strip() == "fc", f"Expected fc user, got '{result.strip()}'"
|
||||
|
|
@ -168,7 +170,7 @@ pkgs.testers.nixosTest {
|
|||
with subtest("Log directory exists"):
|
||||
machine.succeed("test -d /var/lib/fc/logs || mkdir -p /var/lib/fc/logs")
|
||||
|
||||
# ---- Stats endpoint ----
|
||||
# Stats endpoint
|
||||
with subtest("Build stats endpoint returns data"):
|
||||
result = machine.succeed("curl -sf http://127.0.0.1:3000/api/v1/builds/stats | jq '.total_builds'")
|
||||
# Should be a number (possibly 0)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue