chore: prepare for PR
This commit is contained in:
parent
b40926e915
commit
1519666d4c
2 changed files with 92 additions and 7 deletions
|
|
@ -112,12 +112,52 @@ public function handle(StandaloneRedis|StandalonePostgresql|StandaloneMongodb|St
|
||||||
$dockercompose_base64 = base64_encode(Yaml::dump($docker_compose, 4, 2));
|
$dockercompose_base64 = base64_encode(Yaml::dump($docker_compose, 4, 2));
|
||||||
$nginxconf_base64 = base64_encode($nginxconf);
|
$nginxconf_base64 = base64_encode($nginxconf);
|
||||||
instant_remote_process(["docker rm -f $proxyContainerName"], $server, false);
|
instant_remote_process(["docker rm -f $proxyContainerName"], $server, false);
|
||||||
instant_remote_process([
|
|
||||||
"mkdir -p $configuration_dir",
|
try {
|
||||||
"echo '{$nginxconf_base64}' | base64 -d | tee $configuration_dir/nginx.conf > /dev/null",
|
instant_remote_process([
|
||||||
"echo '{$dockercompose_base64}' | base64 -d | tee $configuration_dir/docker-compose.yaml > /dev/null",
|
"mkdir -p $configuration_dir",
|
||||||
"docker compose --project-directory {$configuration_dir} pull",
|
"echo '{$nginxconf_base64}' | base64 -d | tee $configuration_dir/nginx.conf > /dev/null",
|
||||||
"docker compose --project-directory {$configuration_dir} up -d",
|
"echo '{$dockercompose_base64}' | base64 -d | tee $configuration_dir/docker-compose.yaml > /dev/null",
|
||||||
], $server);
|
"docker compose --project-directory {$configuration_dir} pull",
|
||||||
|
"docker compose --project-directory {$configuration_dir} up -d",
|
||||||
|
], $server);
|
||||||
|
} catch (\RuntimeException $e) {
|
||||||
|
if ($this->isNonTransientError($e->getMessage())) {
|
||||||
|
$database->update(['is_public' => false]);
|
||||||
|
|
||||||
|
$team = data_get($database, 'environment.project.team')
|
||||||
|
?? data_get($database, 'service.environment.project.team');
|
||||||
|
|
||||||
|
$team?->notify(
|
||||||
|
new \App\Notifications\Container\ContainerRestarted(
|
||||||
|
"TCP Proxy for {$database->name} database has been disabled due to error: {$e->getMessage()}",
|
||||||
|
$server,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
ray("Database proxy for {$database->name} disabled due to non-transient error: {$e->getMessage()}");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function isNonTransientError(string $message): bool
|
||||||
|
{
|
||||||
|
$nonTransientPatterns = [
|
||||||
|
'port is already allocated',
|
||||||
|
'address already in use',
|
||||||
|
'Bind for',
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($nonTransientPatterns as $pattern) {
|
||||||
|
if (str_contains($message, $pattern)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
45
tests/Feature/StartDatabaseProxyTest.php
Normal file
45
tests/Feature/StartDatabaseProxyTest.php
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Actions\Database\StartDatabaseProxy;
|
||||||
|
use App\Models\StandalonePostgresql;
|
||||||
|
use App\Models\Team;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
use Illuminate\Support\Facades\Notification;
|
||||||
|
|
||||||
|
uses(RefreshDatabase::class);
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
Notification::fake();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('database proxy is disabled on port already allocated error', function () {
|
||||||
|
$team = Team::factory()->create();
|
||||||
|
|
||||||
|
$database = StandalonePostgresql::factory()->create([
|
||||||
|
'team_id' => $team->id,
|
||||||
|
'is_public' => true,
|
||||||
|
'public_port' => 5432,
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect($database->is_public)->toBeTrue();
|
||||||
|
|
||||||
|
$action = new StartDatabaseProxy;
|
||||||
|
|
||||||
|
// Use reflection to test the private method directly
|
||||||
|
$method = new ReflectionMethod($action, 'isNonTransientError');
|
||||||
|
|
||||||
|
expect($method->invoke($action, 'Bind for 0.0.0.0:5432 failed: port is already allocated'))->toBeTrue();
|
||||||
|
expect($method->invoke($action, 'address already in use'))->toBeTrue();
|
||||||
|
expect($method->invoke($action, 'some other error'))->toBeFalse();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('isNonTransientError detects port conflict patterns', function () {
|
||||||
|
$action = new StartDatabaseProxy;
|
||||||
|
$method = new ReflectionMethod($action, 'isNonTransientError');
|
||||||
|
|
||||||
|
expect($method->invoke($action, 'Bind for 0.0.0.0:5432 failed: port is already allocated'))->toBeTrue()
|
||||||
|
->and($method->invoke($action, 'address already in use'))->toBeTrue()
|
||||||
|
->and($method->invoke($action, 'Bind for 0.0.0.0:3306 failed: port is already allocated'))->toBeTrue()
|
||||||
|
->and($method->invoke($action, 'network timeout'))->toBeFalse()
|
||||||
|
->and($method->invoke($action, 'connection refused'))->toBeFalse();
|
||||||
|
});
|
||||||
Loading…
Reference in a new issue