@@ -3,6 +3,9 @@ import { AbstractStartedContainer, ExecResult, GenericContainer, StartedTestCont
33const MONGODB_PORT = 27017 ;
44
55export class MongoDBContainer extends GenericContainer {
6+ private username : string | null = null ;
7+ private password : string | null = null ;
8+
69 constructor ( image = "mongo:4.0.1" ) {
710 super ( image ) ;
811 this . withExposedPorts ( MONGODB_PORT )
@@ -11,16 +14,41 @@ export class MongoDBContainer extends GenericContainer {
1114 . withStartupTimeout ( 120_000 ) ;
1215 }
1316
17+ public withUsername ( username : string ) : this {
18+ this . username = username ;
19+ return this ;
20+ }
21+
22+ public withPassword ( rootPassword : string ) : this {
23+ this . password = rootPassword ;
24+ return this ;
25+ }
26+
1427 public override async start ( ) : Promise < StartedMongoDBContainer > {
15- return new StartedMongoDBContainer ( await super . start ( ) ) ;
28+ 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+ ` ,
39+ ] ) ;
40+ this . withEnvironment ( { MONGO_INITDB_ROOT_USERNAME : this . username , MONGO_INITDB_ROOT_PASSWORD : this . password } ) ;
41+ }
42+
43+ return new StartedMongoDBContainer ( await super . start ( ) , this . username , this . password ) ;
1644 }
1745
1846 protected override async containerStarted ( startedTestContainer : StartedTestContainer ) : Promise < void > {
1947 await this . initReplicaSet ( startedTestContainer ) ;
2048 }
2149
2250 private async initReplicaSet ( startedTestContainer : StartedTestContainer ) {
23- await this . executeMongoEvalCommand ( startedTestContainer , " rs.initiate();" ) ;
51+ await this . executeMongoEvalCommand ( startedTestContainer , ` rs.initiate();` ) ;
2452 await this . executeMongoEvalCommand ( startedTestContainer , this . buildMongoWaitCommand ( ) ) ;
2553 }
2654
@@ -30,7 +58,15 @@ export class MongoDBContainer extends GenericContainer {
3058 }
3159
3260 private buildMongoEvalCommand ( command : string ) {
33- return [ this . getMongoCmdBasedOnImageTag ( ) , "--eval" , command ] ;
61+ const cmd = [ this . getMongoCmdBasedOnImageTag ( ) ] ;
62+
63+ if ( this . username && this . password ) {
64+ cmd . push ( "--username" , this . username , "--password" , this . password , "--authenticationDatabase" , "admin" ) ;
65+ }
66+
67+ cmd . push ( "--eval" , command ) ;
68+
69+ return cmd ;
3470 }
3571
3672 private getMongoCmdBasedOnImageTag ( ) {
@@ -58,11 +94,19 @@ export class MongoDBContainer extends GenericContainer {
5894}
5995
6096export class StartedMongoDBContainer extends AbstractStartedContainer {
61- constructor ( startedTestContainer : StartedTestContainer ) {
97+ constructor (
98+ startedTestContainer : StartedTestContainer ,
99+ private readonly username : string | null ,
100+ private readonly password : string | null
101+ ) {
62102 super ( startedTestContainer ) ;
63103 }
64104
65105 public getConnectionString ( ) : string {
106+ if ( this . username !== null && this . password !== null ) {
107+ return `mongodb://${ this . username } :${ this . password } @${ this . getHost ( ) } :${ this . getMappedPort ( MONGODB_PORT ) } ` ;
108+ }
109+
66110 return `mongodb://${ this . getHost ( ) } :${ this . getMappedPort ( MONGODB_PORT ) } ` ;
67111 }
68112}
0 commit comments