138 lines
6.4 KiB
PHP
138 lines
6.4 KiB
PHP
<?php
|
|
/**
|
|
* MUA — Mikes Unraid Agent
|
|
* Selftest-Script
|
|
*
|
|
* Testet den MCP-Server lokal (ohne HTTP).
|
|
* Aufruf: php /usr/local/plugins/mua/mcp/selftest.php
|
|
*/
|
|
|
|
require_once __DIR__ . '/helpers.php';
|
|
require_once __DIR__ . '/tools.php';
|
|
|
|
$passed = 0;
|
|
$failed = 0;
|
|
$results = [];
|
|
|
|
function check(string $name, bool $condition, string $detail = ''): void {
|
|
global $passed, $failed, $results;
|
|
if ($condition) {
|
|
$passed++;
|
|
$results[] = ["PASS" => $name, "detail" => $detail];
|
|
echo " ✓ $name" . ($detail ? " ($detail)" : '') . "\n";
|
|
} else {
|
|
$failed++;
|
|
$results[] = ["FAIL" => $name, "detail" => $detail];
|
|
echo " ✗ $name" . ($detail ? " ($detail)" : '') . "\n";
|
|
}
|
|
}
|
|
|
|
echo "=== MUA Selftest ===\n\n";
|
|
|
|
// ── 1. Tools-Definition ──────────────────────────────────────────────────
|
|
echo "[1] Tools-Definition\n";
|
|
$tools = mua_tools();
|
|
check('21 Tools definiert', count($tools) === 21, count($tools) . ' Tools');
|
|
|
|
$names = array_column($tools, 'name');
|
|
$expected = [
|
|
'unraid_docker_list', 'unraid_docker_inspect', 'unraid_docker_logs',
|
|
'unraid_docker_analyze_logs', 'unraid_docker_processes', 'unraid_docker_stats',
|
|
'unraid_docker_info', 'unraid_docker_start', 'unraid_docker_stop',
|
|
'unraid_docker_restart', 'unraid_docker_create', 'unraid_docker_modify',
|
|
'unraid_docker_update', 'unraid_docker_rebuild',
|
|
'unraid_network_inventory', 'unraid_network_list', 'unraid_network_inspect',
|
|
'unraid_network_host_state', 'unraid_network_audit_tcp', 'unraid_network_lan_probe',
|
|
'unraid_system_connection_test',
|
|
];
|
|
$missing = array_diff($expected, $names);
|
|
check('Alle erwarteten Tools vorhanden', empty($missing), empty($missing) ? '' : 'Fehlt: ' . implode(', ', $missing));
|
|
|
|
// ── 2. Docker-Verbindung ─────────────────────────────────────────────────
|
|
echo "\n[2] Docker-Verbindung\n";
|
|
try {
|
|
$info = docker_exec("info --format '{{.ServerVersion}}'");
|
|
check('Docker erreichbar', $info !== '', 'Version: ' . trim($info));
|
|
} catch (Exception $e) {
|
|
check('Docker erreichbar', false, $e->getMessage());
|
|
}
|
|
|
|
// ── 3. Container-Liste ───────────────────────────────────────────────────
|
|
echo "\n[3] Container-Liste\n";
|
|
try {
|
|
$summary = container_runtime_summary();
|
|
$decoded = json_decode($summary, true);
|
|
check('container_runtime_summary() funktioniert', is_array($decoded) && isset($decoded['container_count']));
|
|
check('Container-Count > 0', ($decoded['container_count'] ?? 0) > 0, $decoded['container_count'] . ' Container');
|
|
} catch (Exception $e) {
|
|
check('container_runtime_summary() funktioniert', false, $e->getMessage());
|
|
}
|
|
|
|
// ── 3b. Kompakte Inspect-Ausgabe ─────────────────────────────────────────
|
|
$fixture = json_encode([[
|
|
'Id' => str_repeat('a', 64),
|
|
'Name' => '/test',
|
|
'State' => ['Status' => 'running', 'Running' => true, 'Pid' => 42, 'ExitCode' => 0],
|
|
'Config' => ['Image' => 'example:latest', 'Env' => ['SECRET=value']],
|
|
'HostConfig' => ['NetworkMode' => 'bridge'],
|
|
'NetworkSettings' => ['Ports' => []],
|
|
'Mounts' => [['Type' => 'bind', 'Source' => '/secret', 'Destination' => '/data']],
|
|
'RestartCount' => 0,
|
|
'Created' => 'now',
|
|
]]);
|
|
$summaryInspect = json_decode(compact_container_inspect($fixture), true);
|
|
$fullInspect = json_decode(compact_container_inspect($fixture, 'full'), true);
|
|
check('Inspect summary laesst Env aus', !isset($summaryInspect['Env']) && !isset($summaryInspect['Mounts']));
|
|
check('Inspect full enthaelt Env und Mounts', isset($fullInspect['Env']) && isset($fullInspect['Mounts']));
|
|
check('Inspect full maskiert Secrets', ($fullInspect['Env'][0] ?? '') === 'SECRET=<redacted>');
|
|
|
|
// ── 4. Netzwerk-Inventur ─────────────────────────────────────────────────
|
|
echo "\n[4] Netzwerk-Inventur\n";
|
|
try {
|
|
$inventory = compact_network_inventory([]);
|
|
$decoded = json_decode($inventory, true);
|
|
check('compact_network_inventory() funktioniert', is_array($decoded) && isset($decoded['network_count']));
|
|
check('Netzwerk-Count > 0', ($decoded['network_count'] ?? 0) > 0, $decoded['network_count'] . ' Netzwerke');
|
|
} catch (Exception $e) {
|
|
check('compact_network_inventory() funktioniert', false, $e->getMessage());
|
|
}
|
|
|
|
// ── 5. Host-Adressen ─────────────────────────────────────────────────────
|
|
echo "\n[5] Host-Adressen\n";
|
|
try {
|
|
$raw = run_local('test', "ip -j address show");
|
|
$addrs = host_addresses($raw);
|
|
check('IPv4-Adresse gefunden', $addrs['ipv4'] !== '', $addrs['ipv4']);
|
|
check('IPv6-Adresse gefunden', $addrs['ipv6'] !== '', $addrs['ipv6']);
|
|
} catch (Exception $e) {
|
|
check('Host-Adressen', false, $e->getMessage());
|
|
}
|
|
|
|
// ── 6. Validate-Name ─────────────────────────────────────────────────────
|
|
echo "\n[6] Validate-Name\n";
|
|
try {
|
|
validate_name('test-container', 'container');
|
|
check('Gültiger Name akzeptiert', true);
|
|
} catch (Exception $e) {
|
|
check('Gültiger Name akzeptiert', false, $e->getMessage());
|
|
}
|
|
try {
|
|
validate_name('bad;name', 'container');
|
|
check('Ungültiger Name abgelehnt', false, 'Sollte Exception werfen');
|
|
} catch (Exception $e) {
|
|
check('Ungültiger Name abgelehnt', true);
|
|
}
|
|
|
|
// ── 7. PHP-Helper vorhanden ──────────────────────────────────────────────
|
|
echo "\n[7] PHP-Helper\n";
|
|
$helper = '/usr/local/bin/unraid-docker-mcp-helper.php';
|
|
check('PHP-Helper vorhanden', file_exists($helper), $helper);
|
|
|
|
// ── Zusammenfassung ──────────────────────────────────────────────────────
|
|
echo "\n=== Zusammenfassung ===\n";
|
|
echo " Bestanden: $passed\n";
|
|
echo " Fehlgeschlagen: $failed\n";
|
|
echo " Gesamt: " . ($passed + $failed) . "\n";
|
|
|
|
exit($failed > 0 ? 1 : 0);
|