fix(engine-b): Proxmox agent exec repeated command fields; Traefik write throws on failure
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>feat/portal-design
parent
8825f9abfe
commit
03c4b6508f
|
|
@ -96,11 +96,16 @@ class HttpProxmoxClient implements ProxmoxClient
|
||||||
|
|
||||||
public function guestExec(string $node, int $vmid, string $command): array
|
public function guestExec(string $node, int $vmid, string $command): array
|
||||||
{
|
{
|
||||||
// The guest agent runs a program directly, not a shell — wrap compound
|
// Wrap compound commands (cd/&&/pipes/redirects/env) in an explicit shell
|
||||||
// commands (cd/&&/pipes/redirects/env) in an explicit shell. Proxmox is
|
// — the agent execs a program directly. Proxmox wants the argv as REPEATED
|
||||||
// form-encoded and takes `command` as an argv list.
|
// `command=` fields (not indexed command[0]=…), so build the body by hand.
|
||||||
$pid = $this->http()->asForm()
|
$body = collect(['/bin/sh', '-c', $command])
|
||||||
->post("/nodes/{$node}/qemu/{$vmid}/agent/exec", ['command' => ['/bin/sh', '-c', $command]])
|
->map(fn ($arg) => 'command='.rawurlencode($arg))
|
||||||
|
->implode('&');
|
||||||
|
|
||||||
|
$pid = $this->http()
|
||||||
|
->withBody($body, 'application/x-www-form-urlencoded')
|
||||||
|
->post("/nodes/{$node}/qemu/{$vmid}/agent/exec")
|
||||||
->throw()->json('data.pid');
|
->throw()->json('data.pid');
|
||||||
|
|
||||||
// Poll exec-status until the command has exited.
|
// Poll exec-status until the command has exited.
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
namespace App\Services\Traefik;
|
namespace App\Services\Traefik;
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Http;
|
use Illuminate\Support\Facades\Http;
|
||||||
|
use RuntimeException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes Traefik file-provider YAML into the configured dynamic directory (where
|
* Writes Traefik file-provider YAML into the configured dynamic directory (where
|
||||||
|
|
@ -19,7 +20,9 @@ class SshTraefikWriter implements TraefikWriter
|
||||||
$yaml = $this->render($subdomain, $fqdn, $targetHost);
|
$yaml = $this->render($subdomain, $fqdn, $targetHost);
|
||||||
|
|
||||||
$path = rtrim((string) config('provisioning.traefik.dynamic_path'), '/')."/{$subdomain}.yml";
|
$path = rtrim((string) config('provisioning.traefik.dynamic_path'), '/')."/{$subdomain}.yml";
|
||||||
file_put_contents($path, $yaml);
|
if (file_put_contents($path, $yaml) === false) {
|
||||||
|
throw new RuntimeException("Failed to write Traefik config: {$path}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function remove(string $subdomain): void
|
public function remove(string $subdomain): void
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue