11import { AbstractStartedContainer , ExecResult , GenericContainer , StartedTestContainer , Wait } from "testcontainers" ;
22
3+ import crypto from "crypto" ;
4+ import { promises as fs } from "fs" ;
5+ import os from "os" ;
6+ import path from "path" ;
7+
38const MONGODB_PORT = 27017 ;
49
510export class MongoDBContainer extends GenericContainer {
@@ -26,32 +31,36 @@ export class MongoDBContainer extends GenericContainer {
2631
2732 public override async start ( ) : Promise < StartedMongoDBContainer > {
2833 if ( this . username && this . password ) {
29- const containerKeyfilePath = "/tmp/mongo-keyfile" ;
30- this . withCommand ( [
31- "/bin/sh" ,
32- "-c" ,
33- `
34- openssl rand -base64 756 > ${ containerKeyfilePath } &&
35- chmod 600 ${ containerKeyfilePath } &&
36- chown mongodb:mongodb ${ containerKeyfilePath } &&
37- exec mongod --replSet rs0 --keyFile ${ containerKeyfilePath } --bind_ip_all
38- ` ,
34+ const keyfileContainerPath = "/tmp/mongodb-keyfile" ;
35+
36+ const keyfileContent = crypto . randomBytes ( 32 ) . toString ( "base64" ) ;
37+
38+ const tempDir = await fs . mkdtemp ( path . join ( os . tmpdir ( ) , "mongo-keyfile-" ) ) ;
39+ const keyfileHostPath = path . join ( tempDir , "mongodb-keyfile" ) ;
40+ await fs . writeFile ( keyfileHostPath , keyfileContent , { mode : 0o600 } ) ;
41+
42+ this . withCopyFilesToContainer ( [
43+ {
44+ source : keyfileHostPath ,
45+ target : keyfileContainerPath ,
46+ mode : 0o600 ,
47+ } ,
3948 ] ) ;
49+
50+ this . withCommand ( [ "--replSet" , "rs0" , "--keyFile" , keyfileContainerPath , "--bind_ip_all" ] ) ;
51+
4052 this . withEnvironment ( { MONGO_INITDB_ROOT_USERNAME : this . username , MONGO_INITDB_ROOT_PASSWORD : this . password } ) ;
4153 }
4254
4355 return new StartedMongoDBContainer ( await super . start ( ) , this . username , this . password ) ;
4456 }
4557
4658 protected override async containerStarted ( startedTestContainer : StartedTestContainer ) : Promise < void > {
47- // if (this.username && this.password) {
48- // await this.waitForRootUser(startedTestContainer);
49- // }
5059 await this . initReplicaSet ( startedTestContainer ) ;
5160 }
5261
5362 private async initReplicaSet ( startedTestContainer : StartedTestContainer ) {
54- await this . executeMongoEvalCommand ( startedTestContainer , ` rs.initiate();` ) ;
63+ await this . executeMongoEvalCommand ( startedTestContainer , " rs.initiate();" ) ;
5564 await this . executeMongoEvalCommand ( startedTestContainer , this . buildMongoWaitCommand ( ) ) ;
5665 }
5766
@@ -64,7 +73,7 @@ export class MongoDBContainer extends GenericContainer {
6473 const cmd = [ this . getMongoCmdBasedOnImageTag ( ) ] ;
6574
6675 if ( this . username && this . password ) {
67- cmd . push ( "--username" , this . username , "--password" , this . password , "--authenticationDatabase" , "admin" ) ;
76+ cmd . push ( "--username" , this . username , "--password" , this . password ) ;
6877 }
6978
7079 cmd . push ( "--eval" , command ) ;
@@ -83,24 +92,6 @@ export class MongoDBContainer extends GenericContainer {
8392 }
8493 }
8594
86- // private async waitForRootUser(startedTestContainer: StartedTestContainer) {
87- // const checkCommand = this.buildMongoEvalCommand("db.runCommand({ connectionStatus: 1 })");
88-
89- // for (let i = 0; i < 30; i++) {
90- // const result = await startedTestContainer.exec(checkCommand);
91- // if (
92- // result.exitCode === 0 &&
93- // result.output.includes(`${this.username}`) &&
94- // !result.output.includes(`UserNotFound`)
95- // ) {
96- // return;
97- // }
98- // await new Promise((res) => setTimeout(res, 1000));
99- // }
100-
101- // throw new Error("Root user not ready after 30s");
102- // }
103-
10495 private buildMongoWaitCommand ( ) {
10596 return `
10697 var attempt = 0;
0 commit comments