Files
Varaverk/Plugin/unraid/api/api_test.php
T
Gmer4LfeandClaude Sonnet 4.6 b093cae70d schema: re-introspect Unraid API against 7.3
7.3 findings (all existing queries confirmed working — no breaking changes):
- ArrayParity/ArrayCache no longer exist as named types; everything is ArrayDisk
- InfoOs gained: kernel, arch, fqdn, build, codename, platform, serial, uefi
- InfoCpu gained: manufacturer, model, speed, speedmin/max, processors, socket, topology
- ArrayDisk gained: idx, numReads/Writes/Errors, warning/critical temps, color, fsType
- MemoryUtilization gained: free, active, buffcache, swapFree, percentSwapTotal

Changes:
- Add kernel to master GQL query (useful for display)
- Update schema comments to reflect 7.3 reality
- Remove ArrayParity/ArrayCache from api_test.php introspection (now null types)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 19:34:36 -04:00

120 lines
4.7 KiB
PHP

<?php
// Diagnostic endpoint — tests the Unraid GraphQL API and returns raw results.
// Hit from browser: /plugins/varaverk/api/api_test.php
header('Content-Type: application/json');
require_once dirname(__DIR__) . '/include/config.php';
$hostId = vv_detect_host();
$vars = vv_conf_vars();
$key = $vars[strtoupper($hostId) . '_UNRAID_API_KEY'] ?? '';
$result = [
'host' => $hostId,
'key_present' => $key !== '',
'key_prefix' => $key ? substr($key, 0, 8) . '...' : null,
'curl_available' => function_exists('curl_init'),
'allow_url_fopen'=> (bool)ini_get('allow_url_fopen'),
'debug_log' => null,
'probe' => null,
'probe_raw' => null,
];
// Show last debug log if present
$debugFile = '/tmp/vv_api_debug.json';
if (file_exists($debugFile)) {
$result['debug_log'] = json_decode(file_get_contents($debugFile), true);
}
// Run a minimal probe query
if ($key) {
$url = 'http://localhost/graphql';
$body = json_encode(['query' => '{ info { os { hostname } } }']);
if (function_exists('curl_init')) {
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json', "x-api-key: {$key}"],
CURLOPT_POSTFIELDS => $body,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 5,
CURLOPT_CONNECTTIMEOUT => 3,
]);
$raw = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curlErr = curl_error($ch);
curl_close($ch);
} else {
$ctx = stream_context_create(['http' => [
'method' => 'POST',
'header' => "Content-Type: application/json\r\nx-api-key: {$key}",
'content' => $body,
'timeout' => 5,
'ignore_errors' => true,
]]);
$raw = @file_get_contents($url, false, $ctx);
$httpCode = $raw !== false ? 200 : 0;
$curlErr = '';
}
$result['probe'] = [
'url' => $url,
'http_code' => $httpCode,
'curl_err' => $curlErr ?: null,
'decoded' => json_decode((string)$raw, true),
];
$result['probe_raw'] = substr((string)$raw, 0, 1000);
// ── Schema introspection — discover actual field names ────────────────────────
if ($key) {
// ArrayParity and ArrayCache were separate named types in 7.2.5 — removed in 7.3 (now same as ArrayDisk)
$types = ['InfoOs','InfoCpu','InfoMemory','ArrayDisk','VmDomain'];
$introspectGql = '{ ' . implode(' ', array_map(fn($t) =>
"{$t}: __type(name: \"{$t}\") { fields { name type { name kind ofType { name kind } } } }",
$types
)) . ' }';
$body2 = json_encode(['query' => $introspectGql]);
$ch2 = curl_init('http://localhost/graphql');
curl_setopt_array($ch2, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json', "x-api-key: {$key}"],
CURLOPT_POSTFIELDS => $body2,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 8,
]);
$raw2 = curl_exec($ch2);
curl_close($ch2);
$result['schema'] = json_decode((string)$raw2, true)['data'] ?? null;
// Pool drive names — what does the API actually return for cache/pool drives?
$ch_pools = curl_init('http://localhost/graphql');
curl_setopt_array($ch_pools, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json', "x-api-key: {$key}"],
CURLOPT_POSTFIELDS => json_encode(['query' => '{ array { caches { name device type status fsType } } }']),
CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 8,
]);
$result['pool_drives'] = json_decode((string)curl_exec($ch_pools), true)['data'] ?? null;
curl_close($ch_pools);
// Round 2: introspect CpuUtilization and MemoryUtilization field names
$types2 = ['CpuUtilization','MemoryUtilization','TemperatureMetrics'];
$gql2 = '{ ' . implode(' ', array_map(fn($t) =>
"{$t}: __type(name: \"{$t}\") { kind fields { name type { name kind ofType { name kind } } } }",
$types2
)) . ' }';
$ch3 = curl_init('http://localhost/graphql');
curl_setopt_array($ch3, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json', "x-api-key: {$key}"],
CURLOPT_POSTFIELDS => json_encode(['query' => $gql2]),
CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 8,
]);
$result['schema2'] = json_decode((string)curl_exec($ch3), true)['data'] ?? null;
curl_close($ch3);
}
}
echo json_encode($result, JSON_PRETTY_PRINT);