mirror of
https://github.com/coollabsio/coolify.git
synced 2026-11-14 00:33:44 -04:00
Deployments failed with "Server is not functional" when the server was still flagged unreachable after a single failed scheduled check. Add Server::isFunctionalAfterRecheck(), which runs a live SSH and Docker connection check when the server is marked unreachable. It skips the check for disabled servers and servers with placeholder IPs, then re-evaluates isFunctional(). ApplicationDeploymentJob now uses it. ServerManagerJob no longer skips the SSH connection check for servers with a live Sentinel when the server is flagged unreachable or unusable. The Sentinel heartbeat does not restore these flags, so without the check they would never recover. Add feature tests for the recheck behavior and unit tests covering the Sentinel skip condition.
95 lines
3.0 KiB
PHP
95 lines
3.0 KiB
PHP
<?php
|
|
|
|
use App\Models\PrivateKey;
|
|
use App\Models\Server;
|
|
use App\Models\Team;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Facades\Process;
|
|
use Illuminate\Support\Facades\Storage;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
beforeEach(function () {
|
|
Storage::fake('ssh-keys');
|
|
Storage::fake('ssh-mux');
|
|
});
|
|
|
|
function createServerForFunctionalRecheckTest(array $settings): Server
|
|
{
|
|
$team = Team::factory()->create();
|
|
$privateKey = PrivateKey::factory()->create(['team_id' => $team->id]);
|
|
$server = Server::factory()->create([
|
|
'team_id' => $team->id,
|
|
'private_key_id' => $privateKey->id,
|
|
'ip' => '203.0.113.10',
|
|
]);
|
|
$server->settings->update($settings);
|
|
|
|
return $server->refresh();
|
|
}
|
|
|
|
it('marks a server functional again when the live SSH and Docker checks pass', function () {
|
|
$server = createServerForFunctionalRecheckTest(['is_reachable' => false, 'is_usable' => false]);
|
|
|
|
Process::fake([
|
|
'*' => Process::result(output: '{"Server":{"Version":"29.4.3"}}', exitCode: 0),
|
|
]);
|
|
|
|
expect($server->isFunctionalAfterRecheck())->toBeTrue()
|
|
->and((bool) $server->settings->fresh()->is_reachable)->toBeTrue()
|
|
->and((bool) $server->settings->fresh()->is_usable)->toBeTrue();
|
|
});
|
|
|
|
it('keeps a server not functional when the live SSH check fails', function () {
|
|
$server = createServerForFunctionalRecheckTest(['is_reachable' => false, 'is_usable' => false]);
|
|
|
|
Process::fake([
|
|
'*' => Process::result(errorOutput: 'Connection refused', exitCode: 255),
|
|
]);
|
|
|
|
expect($server->isFunctionalAfterRecheck())->toBeFalse()
|
|
->and((bool) $server->settings->fresh()->is_reachable)->toBeFalse();
|
|
});
|
|
|
|
it('does not connect to a reachable server that is marked unusable', function () {
|
|
$server = createServerForFunctionalRecheckTest(['is_reachable' => true, 'is_usable' => false]);
|
|
|
|
Process::fake();
|
|
|
|
expect($server->isFunctionalAfterRecheck())->toBeFalse();
|
|
|
|
Process::assertNothingRan();
|
|
});
|
|
|
|
it('keeps a server not functional when Docker does not respond', function () {
|
|
$server = createServerForFunctionalRecheckTest(['is_reachable' => false, 'is_usable' => false]);
|
|
|
|
Process::fake([
|
|
'*docker*' => Process::result(output: '', exitCode: 1),
|
|
'*' => Process::result(output: '', exitCode: 0),
|
|
]);
|
|
|
|
expect($server->isFunctionalAfterRecheck())->toBeFalse()
|
|
->and((bool) $server->settings->fresh()->is_usable)->toBeFalse();
|
|
});
|
|
|
|
it('does not connect to a server that is already functional', function () {
|
|
$server = createServerForFunctionalRecheckTest(['is_reachable' => true, 'is_usable' => true]);
|
|
|
|
Process::fake();
|
|
|
|
expect($server->isFunctionalAfterRecheck())->toBeTrue();
|
|
|
|
Process::assertNothingRan();
|
|
});
|
|
|
|
it('does not connect to a disabled server', function () {
|
|
$server = createServerForFunctionalRecheckTest(['is_reachable' => false, 'is_usable' => false, 'force_disabled' => true]);
|
|
|
|
Process::fake();
|
|
|
|
expect($server->isFunctionalAfterRecheck())->toBeFalse();
|
|
|
|
Process::assertNothingRan();
|
|
});
|