Transitioned from obsolete gateway object classes (`edge_gateway_shell_action_jobs_o`, `edge_gateway_shell_events_o`, `edge_gateway_shell_sessions_o`, `edge_gateway_update_jobs_o`) to the new agent implementation (`edge-gateway-agent/agent.php`).
177 lines
6.6 KiB
PHP
177 lines
6.6 KiB
PHP
<?php
|
|
|
|
app_require('classes/edge_gateway_agent_artifact_locator.php');
|
|
app_require('classes/edge_gateway_install_service.php');
|
|
app_require('classes/edge_gateway_manager.php');
|
|
|
|
use classes\edge_gateway_agent_artifact_locator;
|
|
use classes\edge_gateway_install_service;
|
|
use classes\edge_gateway_manager;
|
|
|
|
class EdgeGatewayInstallServiceHarness extends edge_gateway_install_service
|
|
{
|
|
public function __construct()
|
|
{
|
|
}
|
|
}
|
|
|
|
class EdgeGatewayManagerArtifactHarness extends edge_gateway_manager
|
|
{
|
|
public function __construct()
|
|
{
|
|
}
|
|
}
|
|
|
|
function with_edge_gateway_artifact_env(array $values, callable $callback): void
|
|
{
|
|
$keys = ['EDGE_AGENT_ARTIFACT_DIR'];
|
|
$originals = [];
|
|
foreach ($keys as $key) {
|
|
$originals[$key] = getenv($key);
|
|
}
|
|
|
|
try {
|
|
foreach ($keys as $key) {
|
|
if (array_key_exists($key, $values) && $values[$key] !== null) {
|
|
putenv($key . '=' . $values[$key]);
|
|
continue;
|
|
}
|
|
putenv($key);
|
|
}
|
|
|
|
$callback();
|
|
} finally {
|
|
foreach ($originals as $key => $value) {
|
|
if ($value === false) {
|
|
putenv($key);
|
|
continue;
|
|
}
|
|
putenv($key . '=' . $value);
|
|
}
|
|
}
|
|
}
|
|
|
|
function remove_edge_gateway_temp_path(string $path): void
|
|
{
|
|
if (is_file($path)) {
|
|
unlink($path);
|
|
return;
|
|
}
|
|
|
|
if (is_dir($path)) {
|
|
rmdir($path);
|
|
}
|
|
}
|
|
|
|
it('resolves edge-agent artifacts from a supported runtime layout', function (): void {
|
|
$path = edge_gateway_agent_artifact_locator::resolve('agent.php', app_path());
|
|
|
|
expect(str_replace('\\', '/', $path))->toEndWith('/resources/edge-gateway-agent/agent.php');
|
|
expect(is_file($path))->toBeTrue();
|
|
});
|
|
|
|
it('prioritizes router resources before mounted and baked-in artifact directories', function (): void {
|
|
with_edge_gateway_artifact_env(['EDGE_AGENT_ARTIFACT_DIR' => null], function (): void {
|
|
$candidatePaths = array_map(
|
|
static fn(string $path): string => str_replace('\\', '/', $path),
|
|
edge_gateway_agent_artifact_locator::candidatePaths(
|
|
'agent.php',
|
|
'/var/www/html',
|
|
'/services/edge-agent/php-agent',
|
|
'/opt/truckwash-edge-agent-artifacts'
|
|
)
|
|
);
|
|
|
|
expect(array_slice($candidatePaths, 0, 3))->toBe([
|
|
'/var/www/html/resources/edge-gateway-agent/agent.php',
|
|
'/services/edge-agent/php-agent/agent.php',
|
|
'/opt/truckwash-edge-agent-artifacts/agent.php',
|
|
]);
|
|
expect($candidatePaths)->toContain('/var/edge-agent/php-agent/agent.php');
|
|
expect($candidatePaths)->toContain('/var/www/edge-agent/php-agent/agent.php');
|
|
});
|
|
});
|
|
|
|
it('reads install artifacts through the shared locator', function (): void {
|
|
$service = new EdgeGatewayInstallServiceHarness();
|
|
$contents = $service->readArtifact('truckwash-edge-agent.service');
|
|
|
|
expect($contents)->toContain('ExecStart=/usr/bin/php /opt/truckwash-edge-agent/agent.php');
|
|
});
|
|
|
|
it('builds update payloads with checksums from resolved artifact paths', function (): void {
|
|
$manager = new EdgeGatewayManagerArtifactHarness();
|
|
$payload = $manager->buildUpdateOperationRequest('2.0.0', 'stable');
|
|
|
|
expect($payload['artifactSha256'])->toBe(hash_file('sha256', app_path('resources/edge-gateway-agent/agent.php')));
|
|
expect($payload['serviceUnitSha256'])->toBe(hash_file('sha256', app_path('resources/edge-gateway-agent/truckwash-edge-agent.service')));
|
|
});
|
|
|
|
it('falls back to baked-in artifacts when the mount path is absent', function (): void {
|
|
$tempRoot = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'edge-gateway-baked-' . bin2hex(random_bytes(6));
|
|
$appPath = $tempRoot . DIRECTORY_SEPARATOR . 'services' . DIRECTORY_SEPARATOR . 'nginx' . DIRECTORY_SEPARATOR . 'app';
|
|
$missingMountPath = $tempRoot . DIRECTORY_SEPARATOR . 'services' . DIRECTORY_SEPARATOR . 'edge-agent' . DIRECTORY_SEPARATOR . 'php-agent';
|
|
$bakedPath = $tempRoot . DIRECTORY_SEPARATOR . 'baked-artifacts';
|
|
$bakedAgentPath = $bakedPath . DIRECTORY_SEPARATOR . 'agent.php';
|
|
|
|
@mkdir($appPath, 0777, true);
|
|
@mkdir($bakedPath, 0777, true);
|
|
file_put_contents($bakedAgentPath, "<?php\n// baked artifact\n");
|
|
|
|
try {
|
|
$resolvedPath = edge_gateway_agent_artifact_locator::resolve(
|
|
'agent.php',
|
|
$appPath,
|
|
$missingMountPath,
|
|
$bakedPath
|
|
);
|
|
|
|
expect(str_replace('\\', '/', $resolvedPath))->toBe(str_replace('\\', '/', $bakedAgentPath));
|
|
} finally {
|
|
remove_edge_gateway_temp_path($bakedAgentPath);
|
|
foreach ([
|
|
$bakedPath,
|
|
$appPath,
|
|
dirname($appPath),
|
|
dirname(dirname($appPath)),
|
|
dirname($missingMountPath),
|
|
dirname(dirname($missingMountPath)),
|
|
$tempRoot,
|
|
] as $directory) {
|
|
remove_edge_gateway_temp_path($directory);
|
|
}
|
|
}
|
|
});
|
|
|
|
it('explains the legacy dist mount mismatch when php artifacts are unavailable', function (): void {
|
|
$tempRoot = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'edge-gateway-artifacts-' . bin2hex(random_bytes(6));
|
|
$appPath = $tempRoot . DIRECTORY_SEPARATOR . 'services' . DIRECTORY_SEPARATOR . 'nginx' . DIRECTORY_SEPARATOR . 'app';
|
|
$legacyDistPath = $tempRoot . DIRECTORY_SEPARATOR . 'services' . DIRECTORY_SEPARATOR . 'edge-agent' . DIRECTORY_SEPARATOR . 'dist';
|
|
|
|
@mkdir($appPath, 0777, true);
|
|
@mkdir($legacyDistPath, 0777, true);
|
|
file_put_contents($legacyDistPath . DIRECTORY_SEPARATOR . 'agent.mjs', '// legacy node artifact');
|
|
|
|
try {
|
|
edge_gateway_agent_artifact_locator::resolve('agent.php', $appPath);
|
|
test()->fail('Expected artifact resolution to fail when php-agent artifacts are missing.');
|
|
} catch (Exception $exception) {
|
|
expect($exception->getMessage())->toContain('Missing edge agent artifact: agent.php.');
|
|
expect($exception->getMessage())->toContain('Deploy the router-owned artifacts under');
|
|
expect($exception->getMessage())->toContain('Legacy Node dist artifact found at');
|
|
expect($exception->getMessage())->toContain('Remove /services/edge-agent/dist and deploy the router resources instead of depending on the legacy mount.');
|
|
} finally {
|
|
remove_edge_gateway_temp_path($legacyDistPath . DIRECTORY_SEPARATOR . 'agent.mjs');
|
|
foreach ([
|
|
$legacyDistPath,
|
|
dirname($legacyDistPath),
|
|
$appPath,
|
|
dirname($appPath),
|
|
dirname(dirname($appPath)),
|
|
$tempRoot,
|
|
] as $directory) {
|
|
remove_edge_gateway_temp_path($directory);
|
|
}
|
|
}
|
|
});
|