Add dockerized fake-agent for integration testing and live edge-broker smoke tests. Introduce agent CLI status command and report helpers. Add browser shell session handling for disconnected agents. Extend tests and improve token validation flow.
This commit is contained in:
@@ -166,13 +166,14 @@ class edge_gateway_manager
|
||||
public function recordHeartbeat(int $gatewayId, string $plainToken, array $payload): array
|
||||
{
|
||||
$gateway = $this->authenticateGateway($gatewayId, $plainToken);
|
||||
$existingMetadata = (array)($gateway->metadata_json->value() ?? []);
|
||||
$gateway->status->set((string)($payload['status'] ?? self::STATUS_ONLINE));
|
||||
$gateway->hostname->set($payload['hostname'] ?? $gateway->hostname->value());
|
||||
$gateway->installed_version->set($payload['installed_version'] ?? $gateway->installed_version->value());
|
||||
$gateway->target_version->set($payload['target_version'] ?? $gateway->target_version->value());
|
||||
$gateway->last_heartbeat_at->set($this->now());
|
||||
$gateway->last_seen_ip->set($this->remoteIp());
|
||||
$gateway->metadata_json->set((array)($payload['metadata'] ?? $gateway->metadata_json->value() ?? []));
|
||||
$gateway->metadata_json->set(array_merge($existingMetadata, (array)($payload['metadata'] ?? [])));
|
||||
|
||||
if (isset($payload['inventory']) && is_array($payload['inventory'])) {
|
||||
$this->syncDeviceInventory($gatewayId, $payload['inventory']);
|
||||
@@ -612,6 +613,11 @@ class edge_gateway_manager
|
||||
return 'curl -fsSL ' . escapeshellarg($this->buildInstallScriptUrl($plainToken)) . ' | sudo bash';
|
||||
}
|
||||
|
||||
public function buildInstallTokenVerifyUrl(string $plainToken): string
|
||||
{
|
||||
return rtrim($this->getApiBaseUrl(), '/') . '/edge-agent/install-token/verify?token=' . urlencode($plainToken);
|
||||
}
|
||||
|
||||
public function buildInstallScriptUrl(string $plainToken): string
|
||||
{
|
||||
return rtrim($this->getApiBaseUrl(), '/') . '/edge-agent/install.sh?token=' . urlencode($plainToken);
|
||||
@@ -631,6 +637,7 @@ class edge_gateway_manager
|
||||
$script = <<<'BASH'
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
curl -fsSL "__VERIFY_URL__" >/dev/null
|
||||
INSTALL_DIR=/opt/truckwash-edge-agent
|
||||
mkdir -p "$INSTALL_DIR"
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
@@ -665,12 +672,32 @@ echo 'TruckWash edge agent installed.'
|
||||
BASH;
|
||||
|
||||
return strtr($script, [
|
||||
'__VERIFY_URL__' => $this->buildInstallTokenVerifyUrl($plainToken),
|
||||
'__PACKAGE_URL__' => rtrim($this->getApiBaseUrl(), '/') . '/edge-agent/artifacts/package.json',
|
||||
'__AGENT_URL__' => rtrim($this->getApiBaseUrl(), '/') . '/edge-agent/artifacts/agent.mjs',
|
||||
'__CONFIG_JSON__' => (string)$configJson,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function verifyInstallToken(string $plainToken): array
|
||||
{
|
||||
$claimToken = $this->requireClaimToken($plainToken);
|
||||
if ($claimToken->used_at->value() !== null) {
|
||||
throw new Exception('Install token has already been used');
|
||||
}
|
||||
|
||||
return [
|
||||
'valid' => true,
|
||||
'claim_token_id' => (int)$claimToken->id,
|
||||
'department_id' => (int)$claimToken->department_id->value(),
|
||||
'label' => $claimToken->label->value(),
|
||||
'expires_at' => (string)$claimToken->expires_at->value(),
|
||||
];
|
||||
}
|
||||
|
||||
public function buildBrowserShellWsUrl(string $sessionToken): ?string
|
||||
{
|
||||
$brokerUrl = $this->getBrokerPublicUrl();
|
||||
@@ -700,15 +727,7 @@ BASH;
|
||||
return $this->normalizeBrokerPublicUrl($configured);
|
||||
}
|
||||
|
||||
$apiBaseUrl = $this->getApiBaseUrl();
|
||||
$parsed = parse_url($apiBaseUrl);
|
||||
if (!is_array($parsed) || !isset($parsed['host'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$scheme = ($parsed['scheme'] ?? 'https') === 'https' ? 'https' : 'http';
|
||||
$port = getenv('EDGE_BROKER_PUBLIC_PORT') ?: '4300';
|
||||
return $this->normalizeBrokerPublicUrl($scheme . '://' . $parsed['host'] . ':' . $port);
|
||||
return $this->buildNormalizedBrokerOrigin($this->getApiBaseUrl());
|
||||
}
|
||||
|
||||
public function getApiBaseUrl(): string
|
||||
@@ -785,9 +804,15 @@ BASH;
|
||||
|
||||
private function normalizeBrokerPublicUrl(string $url): string
|
||||
{
|
||||
$parsed = parse_url($url);
|
||||
$normalized = $this->buildNormalizedBrokerOrigin($url);
|
||||
return $normalized ?? trim($url);
|
||||
}
|
||||
|
||||
private function buildNormalizedBrokerOrigin(string $url): ?string
|
||||
{
|
||||
$parsed = parse_url(trim($url));
|
||||
if (!is_array($parsed) || !isset($parsed['host'])) {
|
||||
return trim($url);
|
||||
return null;
|
||||
}
|
||||
|
||||
$host = (string)$parsed['host'];
|
||||
@@ -800,15 +825,6 @@ BASH;
|
||||
if (isset($parsed['port'])) {
|
||||
$normalized .= ':' . $parsed['port'];
|
||||
}
|
||||
if (isset($parsed['path'])) {
|
||||
$normalized .= $parsed['path'];
|
||||
}
|
||||
if (isset($parsed['query'])) {
|
||||
$normalized .= '?' . $parsed['query'];
|
||||
}
|
||||
if (isset($parsed['fragment'])) {
|
||||
$normalized .= '#' . $parsed['fragment'];
|
||||
}
|
||||
|
||||
return $normalized;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user