fix(database): check MongoDB health with ping

The MongoDB health check passed only on the writable primary
(db.hello().isWritablePrimary or isMaster().ismaster). A replica set
that was never initiated, which is common for Prisma setups, and any
non-primary member were reported unhealthy after a restart.

The check now runs db.adminCommand({ ping: 1 }) with mongosh or the
legacy mongo shell. Ping needs no authentication, passes on every
running member, and still fails when mongod is not reachable.
This commit is contained in:
Andras Bacsai
2026-10-01 07:16:27 +02:00
parent 13a57cc059
commit 658ac6bca5
2 changed files with 9 additions and 8 deletions
+2 -1
View File
@@ -330,6 +330,7 @@ class StartMongodb
/**
* The shell is chosen when the check runs: images before MongoDB 5 (and some custom images) have only the legacy mongo shell.
* The check uses ping, which needs no authentication and passes on members that are not the writable primary (e.g. an uninitiated replica set).
*/
private function generate_health_check_command(): array
{
@@ -354,7 +355,7 @@ class StartMongodb
$command = [
...$command,
'--eval',
$legacy ? 'quit(db.isMaster().ismaster === true ? 0 : 1)' : 'quit(db.hello().isWritablePrimary === true ? 0 : 1)',
'quit(db.adminCommand({ ping: 1 }).ok === 1 ? 0 : 1)',
];
return implode(' ', array_map('escapeshellarg', $command));
+7 -7
View File
@@ -35,7 +35,7 @@ function runMongodbHealthCheck(array $healthCheck, array $availableShells): stri
return trim((string) $output);
}
it('uses mongosh when the image has it and the legacy mongo shell otherwise', function (array $availableShells, bool $enableSsl, ?string $sslMode, array $expectedCall) {
it('checks liveness with ping using mongosh when the image has it and the legacy mongo shell otherwise', function (array $availableShells, bool $enableSsl, ?string $sslMode, array $expectedCall) {
$healthCheck = generatedMongodbHealthCheckCommand([
'uuid' => 'mongodb-test-resource',
'image' => 'registry.example.com/mongo:any',
@@ -54,32 +54,32 @@ it('uses mongosh when the image has it and the legacy mongo shell otherwise', fu
})->with([
'mongosh without TLS' => [['mongosh', 'mongo'], false, null, [
'mongosh', '--quiet', '--host', 'mongodb-test-resource', '--eval',
'quit(db.hello().isWritablePrimary === true ? 0 : 1)',
'quit(db.adminCommand({ ping: 1 }).ok === 1 ? 0 : 1)',
]],
'mongosh with TLS require' => [['mongosh'], true, 'require', [
'mongosh', '--quiet', '--host', 'mongodb-test-resource',
'--tls', '--tlsCAFile', '/etc/mongo/certs/ca.pem', '--eval',
'quit(db.hello().isWritablePrimary === true ? 0 : 1)',
'quit(db.adminCommand({ ping: 1 }).ok === 1 ? 0 : 1)',
]],
'mongosh with TLS verify-full' => [['mongosh'], true, 'verify-full', [
'mongosh', '--quiet', '--host', 'mongodb-test-resource',
'--tls', '--tlsCAFile', '/etc/mongo/certs/ca.pem',
'--tlsCertificateKeyFile', '/etc/mongo/certs/server.pem', '--eval',
'quit(db.hello().isWritablePrimary === true ? 0 : 1)',
'quit(db.adminCommand({ ping: 1 }).ok === 1 ? 0 : 1)',
]],
'legacy mongo without TLS' => [['mongo'], false, null, [
'mongo', '--quiet', '--host', 'mongodb-test-resource', '--eval',
'quit(db.isMaster().ismaster === true ? 0 : 1)',
'quit(db.adminCommand({ ping: 1 }).ok === 1 ? 0 : 1)',
]],
'legacy mongo with TLS require' => [['mongo'], true, 'require', [
'mongo', '--quiet', '--host', 'mongodb-test-resource',
'--ssl', '--sslCAFile', '/etc/mongo/certs/ca.pem', '--eval',
'quit(db.isMaster().ismaster === true ? 0 : 1)',
'quit(db.adminCommand({ ping: 1 }).ok === 1 ? 0 : 1)',
]],
'legacy mongo with TLS verify-full' => [['mongo'], true, 'verify-full', [
'mongo', '--quiet', '--host', 'mongodb-test-resource',
'--ssl', '--sslCAFile', '/etc/mongo/certs/ca.pem',
'--sslPEMKeyFile', '/etc/mongo/certs/server.pem', '--eval',
'quit(db.isMaster().ismaster === true ? 0 : 1)',
'quit(db.adminCommand({ ping: 1 }).ok === 1 ? 0 : 1)',
]],
]);