r024: compact Docker inspect output
This commit is contained in:
+16
-7
@@ -197,7 +197,7 @@ function sanitize_log_output(string $text, int $max_chars = 50000): string {
|
||||
/**
|
||||
* Kompakte Container-Inspect-Ausgabe.
|
||||
*/
|
||||
function compact_container_inspect(string $raw): string {
|
||||
function compact_container_inspect(string $raw, string $detail = 'summary'): string {
|
||||
$data = json_decode($raw, true);
|
||||
if (json_last_error() !== JSON_ERROR_NONE || !is_array($data)) {
|
||||
return $raw;
|
||||
@@ -218,17 +218,26 @@ function compact_container_inspect(string $raw): string {
|
||||
'Image' => $data['Config']['Image'] ?? '',
|
||||
'NetworkMode' => $data['HostConfig']['NetworkMode'] ?? '',
|
||||
'Ports' => $data['NetworkSettings']['Ports'] ?? [],
|
||||
'Env' => $data['Config']['Env'] ?? [],
|
||||
'Mounts' => array_map(function ($m) {
|
||||
'RestartCount' => $data['RestartCount'] ?? 0,
|
||||
'Created' => $data['Created'] ?? '',
|
||||
];
|
||||
if ($detail === 'full') {
|
||||
$compact['Env'] = array_map(function ($entry) {
|
||||
if (!is_string($entry) || !str_contains($entry, '=')) return $entry;
|
||||
[$name, $value] = explode('=', $entry, 2);
|
||||
if (preg_match('/(KEY|TOKEN|SECRET|PASS|AUTH|COOKIE|ARL)/i', $name)) {
|
||||
return $name . '=<redacted>';
|
||||
}
|
||||
return $name . '=' . $value;
|
||||
}, $data['Config']['Env'] ?? []);
|
||||
$compact['Mounts'] = array_map(function ($m) {
|
||||
return [
|
||||
'Type' => $m['Type'] ?? '',
|
||||
'Source' => $m['Source'] ?? '',
|
||||
'Destination' => $m['Destination'] ?? '',
|
||||
];
|
||||
}, $data['Mounts'] ?? []),
|
||||
'RestartCount' => $data['RestartCount'] ?? 0,
|
||||
'Created' => $data['Created'] ?? '',
|
||||
];
|
||||
}, $data['Mounts'] ?? []);
|
||||
}
|
||||
return json_encode($compact, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
|
||||
|
||||
@@ -68,6 +68,24 @@ try {
|
||||
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 {
|
||||
|
||||
+5
-1
@@ -95,8 +95,12 @@ function call_tool(string $name, array $args): string {
|
||||
|
||||
case 'unraid_docker_inspect':
|
||||
$container = validate_name($args['container'] ?? null, 'container');
|
||||
$detail = $args['detail'] ?? 'summary';
|
||||
if (!in_array($detail, ['summary', 'full'], true)) {
|
||||
throw new InvalidArgumentException('detail must be summary or full');
|
||||
}
|
||||
$raw = docker_exec("inspect --type container -- $container");
|
||||
return compact_container_inspect($raw);
|
||||
return compact_container_inspect($raw, $detail);
|
||||
|
||||
case 'unraid_docker_logs':
|
||||
$container = validate_name($args['container'] ?? null, 'container');
|
||||
|
||||
+3
-1
@@ -27,13 +27,15 @@ function mua_tools(): array {
|
||||
],
|
||||
[
|
||||
'name' => 'unraid_docker_inspect',
|
||||
'description' => 'Inspect a single Docker container in detail (state, image, ports, env, mounts).',
|
||||
'description' => "Inspect one known Docker container directly. Default summary returns state, image, network mode and ports only; request detail='full' only when environment variables or mounts are required.",
|
||||
'inputSchema' => [
|
||||
'type' => 'object',
|
||||
'properties' => [
|
||||
'container' => ['type' => 'string', 'description' => 'Container name or ID'],
|
||||
'detail' => ['type' => 'string', 'enum' => ['summary', 'full'], 'description' => "Use 'summary' by default. 'full' additionally returns redacted environment and mounts."],
|
||||
],
|
||||
'required' => ['container'],
|
||||
'additionalProperties' => false,
|
||||
],
|
||||
],
|
||||
[
|
||||
|
||||
Reference in New Issue
Block a user