@@ -41,10 +41,16 @@ public class MongoDBContainer extends GenericContainer<MongoDBContainer> {
4141
4242 private static final String STARTER_SCRIPT = "/testcontainers_start.sh" ;
4343
44+ private static final String SCRIPT_DESTINATION_DEFAULT = "/docker-entrypoint-initdb.d/init.js" ;
45+
46+ private static final String SCRIPT_DESTINATION_MANUAL = "/tmp/init.js" ;
47+
4448 private boolean shardingEnabled ;
4549
4650 private boolean rsEnabled ;
4751
52+ private String initScriptPath ;
53+
4854 public MongoDBContainer (@ NonNull String dockerImageName ) {
4955 this (DockerImageName .parse (dockerImageName ));
5056 }
@@ -68,6 +74,26 @@ protected void containerIsStarted(InspectContainerResponse containerInfo, boolea
6874 if (this .rsEnabled ) {
6975 initReplicaSet (reused );
7076 }
77+
78+ boolean isClusterMode = this .shardingEnabled || this .rsEnabled ;
79+
80+ if (isClusterMode && this .initScriptPath != null ) {
81+ executeInitScriptInContainer ();
82+ }
83+ }
84+
85+ @ Override
86+ protected void configure () {
87+ super .configure ();
88+ boolean isClusterMode = this .shardingEnabled || this .rsEnabled ;
89+ if (this .initScriptPath != null ) {
90+ String destination = isClusterMode ? SCRIPT_DESTINATION_MANUAL : SCRIPT_DESTINATION_DEFAULT ;
91+ withCopyFileToContainer (MountableFile .forClasspathResource (this .initScriptPath ), destination );
92+ }
93+
94+ if (this .initScriptPath != null && !isClusterMode ) {
95+ this .waitStrategy = Wait .forLogMessage ("(?i).*waiting for connections.*" , 2 );
96+ }
7197 }
7298
7399 private String [] buildMongoEvalCommand (String command ) {
@@ -208,19 +234,42 @@ public String getReplicaSetUrl(String databaseName) {
208234 /**
209235 * Executes a MongoDB initialization script from the classpath during startup.
210236 * <p>
211- * The script will be copied to {@code /docker-entrypoint-initdb.d/init.js}.
212- * This method also adjusts the {@link org.testcontainers.containers.wait.strategy.WaitStrategy}
213- * to expect the "waiting for connections" log message twice, as the execution of an init script
214- * causes MongoDB to restart.
237+ * In standalone mode, the script will be copied to {@code /docker-entrypoint-initdb.d/init.js},
238+ * and the {@link org.testcontainers.containers.wait.strategy.WaitStrategy} is adjusted
239+ * to expect the "waiting for connections" log message twice.
240+ * <p>
241+ * In Replica Set or Sharding mode, the script is copied to a temporary location and executed
242+ * manually after the cluster is initialized.
215243 *
216244 * @param scriptPath the path to the init script file on the classpath
217245 * @return this container instance
218246 */
219247 public MongoDBContainer withInitScript (String scriptPath ) {
220- withCopyFileToContainer (MountableFile .forClasspathResource (scriptPath ), "/docker-entrypoint-initdb.d/init.js" );
221-
222- this .waitStrategy = Wait .forLogMessage ("(?i).*waiting for connections.*" , 2 );
223-
248+ this .initScriptPath = scriptPath ;
224249 return this ;
225250 }
251+
252+ @ SneakyThrows
253+ private void executeInitScriptInContainer () {
254+ String cmd =
255+ "mongosh " +
256+ MONGODB_DATABASE_NAME_DEFAULT +
257+ " " +
258+ SCRIPT_DESTINATION_MANUAL +
259+ " || mongo " +
260+ MONGODB_DATABASE_NAME_DEFAULT +
261+ " " +
262+ SCRIPT_DESTINATION_MANUAL ;
263+
264+ ExecResult result = execInContainer ("sh" , "-c" , cmd );
265+ if (result .getExitCode () != CONTAINER_EXIT_CODE_OK ) {
266+ throw new IllegalStateException (
267+ String .format (
268+ "Failed to execute init script.\n Stdout: %s\n Stderr: %s" ,
269+ result .getStdout (),
270+ result .getStderr ()
271+ )
272+ );
273+ }
274+ }
226275}
0 commit comments