Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 47 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/mongodb-runner/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
"@mongodb-js/saslprep": "^1.6.0",
"@peculiar/x509": "^2.1.0",
"debug": "^4.4.0",
"mongodb": "^7.5.0",
"mongodb": "~7.5.0",
"mongodb-connection-string-url": "^7.0.2",
"reflect-metadata": "^0.2.2",
"yargs": "^18.2.0"
Expand Down
160 changes: 106 additions & 54 deletions packages/mongodb-runner/src/mongocluster.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -365,69 +365,121 @@ describe('MongoCluster', function () {
if (process.platform !== 'linux') return this.skip(); // No docker
});

it('can spawn a 8.0.x replset using docker', async function () {
cluster = await MongoCluster.start({
version: '8.0.x',
topology: 'replset',
tmpDir,
docker: 'mongo:8.0',
downloadOptions: {
distro: 'ubuntu2404',
},
});
expect(cluster.connectionString).to.be.a('string');
expect(cluster.serverVersion).to.match(/^8\./);
const hello = await cluster.withClient(async (client) => {
return await client.db('admin').command({ hello: 1 });
});
expect(+hello.passives.length + +hello.hosts.length).to.equal(3);
});

it('can spawn a 8.0.x sharded env using docker', async function () {
cluster = await MongoCluster.start({
version: '8.0.x',
topology: 'sharded',
tmpDir,
docker: 'mongo:8.0',
shards: 1,
secondaries: 0,
downloadOptions: {
distro: 'ubuntu2404',
},
});
expect(cluster.connectionString).to.be.a('string');
expect(cluster.serverVersion).to.match(/^8\./);
const hello = await cluster.withClient(async (client) => {
return await client.db('admin').command({ hello: 1 });
});
expect(hello.msg).to.equal('isdbgrid');
});

it('can spawn a 8.0.x standalone mongod with TLS enabled and get build info', async function () {
cluster = await MongoCluster.start({
version: '8.0.x',
topology: 'standalone',
tmpDir,
args: [
// These exercise the docker code path across server generations. 4.2 is
// included because it is the easiest way to ensure that MongoServer can
// handle the pre-4.4 log format (in the devtools-shared CI, we only test
// ubuntu-latest otherwise). It also requires the legacy TLS arguments.
const dockerVersions = [
{
version: '4.2.x',
docker: 'mongo:4.2',
replsetDistro: 'ubuntu1804',
otherDistro: 'ubuntu1604',
tlsArgs: [
'--sslMode',
'requireSSL',
'--sslPEMKeyFile',
`/projectroot/test/fixtures/${SERVER_KEY}`,
'--sslCAFile',
`/projectroot/test/fixtures/${CA_CERT}`,
],
docker: [
`--volume=${path.resolve(__dirname, '..')}:/projectroot:ro`,
'mongo:8.0',
},
{
version: '8.0.x',
docker: 'mongo:8.0',
replsetDistro: 'ubuntu2404',
otherDistro: 'ubuntu2404',
tlsArgs: [
'--tlsMode',
'requireTLS',
'--tlsCertificateKeyFile',
`/projectroot/test/fixtures/${SERVER_KEY}`,
'--tlsCAFile',
`/projectroot/test/fixtures/${CA_CERT}`,
],
},
{
version: '9.0.x',
docker: 'mongo:9.0',
replsetDistro: 'ubuntu2404',
otherDistro: 'ubuntu2404',
tlsArgs: [
'--tlsMode',
'requireTLS',
'--tlsCertificateKeyFile',
`/projectroot/test/fixtures/${SERVER_KEY}`,
'--tlsCAFile',
`/projectroot/test/fixtures/${CA_CERT}`,
],
downloadOptions: {
distro: 'ubuntu2404',
},
},
];

for (const {
version,
docker,
replsetDistro,
otherDistro,
tlsArgs,
} of dockerVersions) {
const serverVersion = new RegExp(`^${version.split('.')[0]}\\.`);

it(`can spawn a ${version} replset using docker`, async function () {
cluster = await MongoCluster.start({
version,
topology: 'replset',
tmpDir,
docker,
downloadOptions: {
distro: replsetDistro,
},
});
expect(cluster.connectionString).to.be.a('string');
expect(cluster.serverVersion).to.match(serverVersion);
const hello = await cluster.withClient(async (client) => {
return await client.db('admin').command({ hello: 1 });
});
expect(+hello.passives.length + +hello.hosts.length).to.equal(3);
});
expect(cluster.connectionString).to.be.a('string');
expect(cluster.serverVersion).to.match(/^8\./);
expect(cluster.serverVariant).to.equal('community');
});

it(`can spawn a ${version} sharded env using docker`, async function () {
cluster = await MongoCluster.start({
version,
topology: 'sharded',
tmpDir,
docker,
shards: 1,
secondaries: 0,
downloadOptions: {
distro: otherDistro,
},
});
expect(cluster.connectionString).to.be.a('string');
expect(cluster.serverVersion).to.match(serverVersion);
const hello = await cluster.withClient(async (client) => {
return await client.db('admin').command({ hello: 1 });
});
expect(hello.msg).to.equal('isdbgrid');
});

it(`can spawn a ${version} standalone mongod with TLS enabled and get build info`, async function () {
cluster = await MongoCluster.start({
version,
topology: 'standalone',
tmpDir,
args: tlsArgs,
docker: [
`--volume=${path.resolve(__dirname, '..')}:/projectroot:ro`,
docker,
],
downloadOptions: {
distro: otherDistro,
},
});
expect(cluster.connectionString).to.be.a('string');
expect(cluster.serverVersion).to.match(serverVersion);
expect(cluster.serverVariant).to.equal('community');
});
}
});

it('can spawn a 6.x enterprise standalone mongod', async function () {
Expand Down
30 changes: 29 additions & 1 deletion packages/mongodb-runner/src/mongologreader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,21 @@ export function isFailureToSetupListener(entry: LogEntry): boolean {
* @returns The port in question, or an -1 if the log line did not match.
*/
function getPortFromLogEntry(logEntry: LogEntry): number {
let match;
// Log message id 23016 has the format
// { t: <timestamp>, s: 'I', c: 'NETWORK', id: 23016, ctx: 'listener', msg: '...', attr: { port: 27020 } }
if (logEntry.id === 23016) {
return logEntry.attr.port;
}
// Or, 4.2-style: <timestamp> I NETWORK [listener] waiting for connections on port 27020
if (
logEntry.id === undefined &&
(match = /^waiting for connections on port (?<port>\d+)( ssl)?$/i.exec(
logEntry.message,
))
) {
return +(match.groups?.port ?? '0');
}
if (isFailureToSetupListener(logEntry)) {
throw new Error(
`Failed to setup listener (${logEntry.message} ${JSON.stringify(
Expand Down Expand Up @@ -140,11 +150,29 @@ export type BuildInfo = { version: string | null; modules: string[] | null };
* @returns Partial build info.
*/
function getBuildInfoFromLogEntry(logEntry: LogEntry): Partial<BuildInfo> {
let match;
// Log message id 23403 has the format
// { t: <timestamp>, s: 'I', c: 'CONTROL', id: 23403, ctx: 'initandlisten', msg: '...', attr: { buildInfo: { ... } } }
// { t: <timestamp>, s: 'I', c: 'CONTROL', id: 23403, ctx: 'initandlisten', msg: '...', attr: { buildInfO: { ... } } }
if (logEntry.id === 23403) {
return logEntry.attr.buildInfo;
}
// Or, 4.2-style, split across multiple lines
if (
logEntry.id === undefined &&
(match = /^(?:db|mongos) version v(?<version>.+)$/i.exec(logEntry.message))
) {
return { version: match.groups?.version };
}
if (
logEntry.id === undefined &&
(match = /^modules: (?<moduleList>.+)$/i.exec(logEntry.message))
) {
return {
modules: match.groups?.moduleList
?.split(' ')
?.filter((module) => module !== 'none'),
};
}
return {};
}

Expand Down
Loading