Skip to content
Closed
Show file tree
Hide file tree
Changes from 66 commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
3c07308
Implement MongoDbContainer
silaev Oct 7, 2019
a2c5c69
change oraclejdk8 with openjdk11, delete obsolete ITTest
silaev Oct 7, 2019
8ddd6b4
Small fixes
silaev Oct 7, 2019
1795235
Fix docs
silaev Oct 8, 2019
ee5e4fa
Merge branch 'master' of https://github.com/testcontainers/testcontai…
silaev Oct 9, 2019
e06749d
fix mongodb.md
silaev Oct 9, 2019
1a2b1dc
Merge branch 'master' of https://github.com/testcontainers/testcontai…
silaev Oct 11, 2019
8f68d71
Code review remarks adjusted
silaev Oct 14, 2019
58ab3f2
Merge branch 'master' of https://github.com/testcontainers/testcontai…
silaev Oct 14, 2019
957cd51
Small fix mongodb.md
silaev Oct 14, 2019
991a5f8
Small fix mongodb.md
silaev Oct 14, 2019
4d9f360
Merge branch 'master' into master
rnorth Jan 29, 2020
72d2b30
Merge branch 'master' into master
rnorth Feb 7, 2020
c0fe7ba
Merge branch 'master' into master
rnorth Feb 8, 2020
509a454
Merge branch 'master' of https://github.com/testcontainers/testcontai…
silaev Feb 26, 2020
d1d0367
Merge branch 'master' of https://github.com/testcontainers/testcontai…
silaev Mar 6, 2020
184d4e2
Fix container exit code check
silaev Mar 6, 2020
fc45144
Merge branch 'master' of https://github.com/testcontainers/testcontai…
silaev Mar 13, 2020
cfe5177
Adjust tests and build.gradle to follow Testcontainers module test co…
silaev Mar 13, 2020
a74d766
Add Javadoc explaining the use of LOCALHOST
silaev Mar 13, 2020
7620cb8
Refactor to use a default replica set configuration
silaev Mar 16, 2020
4ca7c7b
Merge branch 'master' of https://github.com/testcontainers/testcontai…
silaev Apr 17, 2020
aad0e76
Remove extra tests
silaev Apr 17, 2020
b92d690
Remove extra unit tests
silaev Apr 18, 2020
9a746df
Merge branch 'master' of https://github.com/testcontainers/testcontai…
silaev Apr 18, 2020
5c3182e
Merge branch 'master' of https://github.com/testcontainers/testcontai…
silaev Apr 20, 2020
5f3145b
Remove MockMaker
silaev Apr 24, 2020
2ea01ce
Merge branch 'master' of https://github.com/testcontainers/testcontai…
silaev Apr 24, 2020
8b727f0
Move initReplicaSet to containerIsStarted, set timeout delay to 100ms…
silaev Apr 24, 2020
e714b26
Make initReplicaSet private
silaev Apr 24, 2020
5b5531d
Fix docs
silaev Apr 24, 2020
d892006
Fix docs
silaev Apr 24, 2020
7adc9f8
Fix docs
silaev Apr 24, 2020
c136592
Make mongoDbContainer final in test
silaev Apr 24, 2020
a773cc5
Fix docs
silaev Apr 24, 2020
fb325d4
Fix docs, change MongoDb with MongoDB, remove logReplicaSetStatus
silaev Apr 24, 2020
649dae2
Reuse secondary constructor
silaev Apr 24, 2020
cd23ddb
Adjust heading
silaev Apr 24, 2020
47c39e7
Remove configureMongoDBContainer
silaev Apr 24, 2020
8e57d07
Merge branch 'master' into master
rnorth May 8, 2020
78ad147
Update docs/modules/databases/mongodb.md
rnorth May 8, 2020
7cdbad4
Merge branch 'master' into master
rnorth May 8, 2020
6ba608e
Merge branch 'master' of https://github.com/testcontainers/testcontai…
silaev Jul 8, 2020
7a27fd1
Merge remote-tracking branch 'upstream/master'
silaev Jul 13, 2022
49682c2
Add Authentication to MongoDBContainer
silaev Jul 13, 2022
e97ed90
Adjust to code style
silaev Jul 13, 2022
0972312
Adjust to code style
silaev Jul 13, 2022
dac9070
Enable logs
silaev Jul 13, 2022
ae49077
Downgrade mongodb version for shouldTestAuthentication test
silaev Jul 13, 2022
79267b0
Show logs
silaev Jul 13, 2022
a498102
Rename vars for shouldTestAuthentication test
silaev Jul 14, 2022
42ef9e7
Clean up logs
silaev Jul 14, 2022
b61763c
Merge remote-tracking branch 'upstream/master'
silaev Jul 14, 2022
9ff0da8
Merge branch 'master' into add_auth_to_mongo_db_container
silaev Jul 14, 2022
e5fda5e
Merge remote-tracking branch 'upstream/master'
silaev Jul 30, 2022
69fb8cc
Merge branch 'master' into add_auth_to_mongo_db_container
silaev Jul 30, 2022
4e2ebc5
Fix keyFile permissions
silaev Jul 30, 2022
4441a2e
Fix CheckStyle
silaev Jul 30, 2022
97c0512
Change getDefaultConnectionString name with constructConnectionString…
silaev Aug 8, 2022
eb9eb2b
Merge remote-tracking branch 'upstream/master'
silaev Aug 16, 2022
779f5fc
Merge branch 'master' into add_auth_to_mongo_db_container
silaev Aug 16, 2022
bdd7e82
Merge upstream
silaev Aug 16, 2022
827a6a4
Prettify shouldTestAuthentication
silaev Aug 17, 2022
1c01a11
Merge remote-tracking branch 'upstream/main'
silaev Dec 14, 2022
6e54adb
Merge branch 'master' into add_auth_to_mongo_db_container
silaev Dec 14, 2022
47138ac
Resovle conflicts
silaev Dec 14, 2022
c76ddd1
Code review remarks adjusted
silaev Dec 15, 2022
72bd52b
Code review remarks adjusted
silaev Dec 15, 2022
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
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.testcontainers.containers;

import com.github.dockerjava.api.command.InspectContainerResponse;
import lombok.Builder;
import lombok.Getter;
import lombok.NonNull;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -27,7 +29,22 @@ public class MongoDBContainer extends GenericContainer<MongoDBContainer> {

private static final int AWAIT_INIT_REPLICA_SET_ATTEMPTS = 60;

private static final String MONGODB_DATABASE_NAME_DEFAULT = "test";
static final String DEFAULT_DATABASE_NAME = "test";

private static final String DEFAULT_USER = "test";

private static final String DEFAULT_PASSWORD = "test";

static final String DEFAULT_AUTHENTICATION_DATABASE_NAME = "admin";

private static final String AUTHENTICATION_KEY_FILE_NAME = "keyFile.key";

private static final String AUTHENTICATION_KEY_FILE_NAME_CONTAINER_PATH =
"/usr/local/bin/" + AUTHENTICATION_KEY_FILE_NAME;

private String username = DEFAULT_USER;

private String password = DEFAULT_PASSWORD;

/**
* @deprecated use {@link MongoDBContainer(DockerImageName)} instead
Expand All @@ -44,10 +61,40 @@ public MongoDBContainer(@NonNull final String dockerImageName) {
public MongoDBContainer(final DockerImageName dockerImageName) {
super(dockerImageName);
dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME);

withExposedPorts(MONGODB_INTERNAL_PORT);
withCommand("--replSet", "docker-rs");
waitingFor(Wait.forLogMessage("(?i).*waiting for connections.*", 1));
withClasspathResourceMapping(
AUTHENTICATION_KEY_FILE_NAME,
AUTHENTICATION_KEY_FILE_NAME_CONTAINER_PATH,
BindMode.READ_ONLY
);
waitingFor(Wait.forLogMessage("(?i).*waiting for connections.*", 2));
}

@Override
protected void configure() {
addEnv("MONGO_INITDB_ROOT_USERNAME", username);
addEnv("MONGO_INITDB_ROOT_PASSWORD", password);
withCreateContainerCmdModifier(it -> it.withEntrypoint("bash"));
setCommand(
"-c",
"chown mongodb " +
AUTHENTICATION_KEY_FILE_NAME_CONTAINER_PATH +
";chmod 400 " +
AUTHENTICATION_KEY_FILE_NAME_CONTAINER_PATH +
";/usr/local/bin/docker-entrypoint.sh --keyFile " +
AUTHENTICATION_KEY_FILE_NAME_CONTAINER_PATH +
" --replSet docker-rs"
);
}

public MongoDBContainer withUsername(final String username) {
this.username = username;
return self();
}

public MongoDBContainer withPassword(final String password) {
this.password = password;
return self();
}

/**
Expand All @@ -56,16 +103,16 @@ public MongoDBContainer(final DockerImageName dockerImageName) {
* @return a connection url pointing to a mongodb instance
*/
public String getConnectionString() {
return String.format("mongodb://%s:%d", getHost(), getMappedPort(MONGODB_INTERNAL_PORT));
return constructConnectionString(ConnectionString.builder().username(username).password(password).build());
}

/**
* Gets a replica set url for the default {@value #MONGODB_DATABASE_NAME_DEFAULT} database.
* Gets a replica set url for the default {@value #DEFAULT_DATABASE_NAME} database.
*
* @return a replica set url.
*/
public String getReplicaSetUrl() {
return getReplicaSetUrl(MONGODB_DATABASE_NAME_DEFAULT);
return getReplicaSetUrl(ConnectionString.builder().username(username).password(password).build());
}

/**
Expand All @@ -78,7 +125,22 @@ public String getReplicaSetUrl(final String databaseName) {
if (!isRunning()) {
throw new IllegalStateException("MongoDBContainer should be started first");
}
return getConnectionString() + "/" + databaseName;
return constructConnectionString(
ConnectionString.builder().databaseName(databaseName).username(username).password(password).build()
);
}

/**
* Gets a replica set url for a provided {@link org.testcontainers.containers.MongoDBContainer.ConnectionString}.
*
* @param connectionString an object describing a connection string.
* @return a replica set url.
*/
public String getReplicaSetUrl(final ConnectionString connectionString) {
if (!isRunning()) {
throw new IllegalStateException("MongoDBContainer should be started first");
}
return constructConnectionString(connectionString);
}

@Override
Expand All @@ -91,10 +153,20 @@ protected void containerIsStarted(InspectContainerResponse containerInfo, boolea
}

private String[] buildMongoEvalCommand(final String command) {
final String authOptions =
" -u " + username + " -p " + password + " --authenticationDatabase " + DEFAULT_AUTHENTICATION_DATABASE_NAME;
return new String[] {
"sh",
"-c",
"mongosh mongo --eval \"" + command + "\" || mongo --eval \"" + command + "\"",
"mongosh mongo" +
authOptions +
" --eval \"" +
command +
"\" || mongo " +
authOptions +
" --eval \"" +
command +
"\"",
};
}

Expand Down Expand Up @@ -149,6 +221,18 @@ private void initReplicaSet() {
checkMongoNodeExitCodeAfterWaiting(execResultWaitForMaster);
}

private String constructConnectionString(final ConnectionString connectionString) {
return String.format(
"mongodb://%s:%s@%s:%d/%s?authSource=%s",
connectionString.getUsername(),
connectionString.getPassword(),
getHost(),
getMappedPort(MONGODB_INTERNAL_PORT),
connectionString.getDatabaseName(),
DEFAULT_AUTHENTICATION_DATABASE_NAME
);
}

public static class ReplicaSetInitializationException extends RuntimeException {

ReplicaSetInitializationException(final String errorMessage) {
Expand All @@ -164,4 +248,16 @@ private boolean isReplicationSetAlreadyInitialized() {
);
return execCheckRsInit.getExitCode() == CONTAINER_EXIT_CODE_OK;
}

@Builder
@Getter
public static class ConnectionString {

@Builder.Default
private final String databaseName = DEFAULT_DATABASE_NAME;

private final String username;

private final String password;
}
Comment on lines +264 to +274
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mongo already provides a convinient way to create a client.

MongoClients.create(
                        MongoClientSettings.builder()
                            .credential(MongoCredential.createCredential(usernameRestrictedAccess, "admin", passwordRestrictedAccess.toCharArray()))
                            .applyConnectionString(new ConnectionString(String.format("mongodb://%s:%d", mongoDBContainer.getHost(), mongoDBContainer.getFirstMappedPort()) ))
                            .build()
                    )

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure that it's a good idea here because:

  • Exposing MongoClientSettings to the public API seems to be dangerous because a user might set a SRV DNS or other settings that MongoDBContainer does not support. I'd rather not allow a user to construct a URL on their side, it's safer to do delegate it to MongoDBContainer providing a URL string. Otherwise, we might receive some unexpected bug tickets here;

  • ConnectionString is for the public API purpose to expose only databaseName, username and password for now. As apposed to MongoClientSettings, it doesn't require setting auth db source, database etc. which simplifies the public API and takes control of it

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was not proposing to use Mongo API in MongoDBContainer. Just sharing how it can be done from the outside as in this suggestion

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather not allow a user to construct a URL on their side, it's safer to do delegate it to MongoDBContainer providing a URL string. Otherwise, we might receive some unexpected bug tickets here;

TBH, I do not expect users to do that but who knows.

I think our docs can be improved in order to make it clear

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We provide a URL string for a user via clear API that we take control of. I reckon it's not a good idea to constantly update docs mentioning "it does not support srv etc."? In my opionin, it's better not to provide a way to set srv.

I was not proposing to use Mongo API in MongoDBContainer. Just sharing how it can be done from the outside as in this suggestion

I see your point, but it's not a part of our public API. This way a user can construct everything, but having an issue with it is on their hands

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather not allow a user to construct a URL on their side, it's safer to do delegate it to MongoDBContainer providing a URL string. Otherwise, we might receive some unexpected bug tickets here;

TBH, I do not expect users to do that but who knows.

I think our docs can be improved in order to make it clear

I updated Java doc to make it clear

Copy link
Member

@kiview kiview Dec 16, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @silaev, but it is still unclear with me what is the issue with the approach suggested by @eddumelendez, since it is very close to how we do it for other modules.

So you think users will struggle doing it this way and construct invalid URLs? Especially since users would normally use getConnectionString(). Or maybe I am missing the point of the discussion?

I thought @eddumelendez's point was about not exposing MongoDBContainer.ConnectionString as a public API.

Copy link
Contributor Author

@silaev silaev Dec 16, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @kiview The idea of this builder is to provide 3 params for now (might be more in the future): username, pass and db name for MongoDBContainer to generate a URL as simple as this:

MongoClients.create(
    mongoDBContainer.getReplicaSetUrl(
        MongoDBContainer.ConnectionString
            .builder()
            .username(usernameRestrictedAccess)
            .password(passwordRestrictedAccess)
            .build()
    )
)

It’s similar to withUsername(...), withPassword(…) and withDatabaseName(...) etc. builder methods in the PostgreSQLContainer to generate a URL via getJdbcUrl(). As I understand, generating URL inside a container is close to how we do it for other modules. There is already public String getReplicaSetUrl(final String databaseName) {}, so I followed the same approach with a param here public String getReplicaSetUrl(final ConnectionString connectionString).

@eddumelendez proposed a solution when a URL is generated outside of MongoDBContainer via MongoClientSettings which we do not control. Is it close to how we do it for other modules ? This way a user has to construct a URL on their own and know some additional data:

MongoClients.create(
    MongoClientSettings.builder()
        .credential(MongoCredential.createCredential(usernameRestrictedAccess, "admin", passwordRestrictedAccess.toCharArray()))
        .applyConnectionString(new ConnectionString(String.format("mongodb://%s:%d", mongoDBContainer.getHost(), mongoDBContainer.getFirstMappedPort()) ))
        .build()
)

The second variant seems to me as quite complex and error prone, so I'm more comfortable with the first one. Correct me if I'm wrong, but the whole idea of Testcontainers is to simplify testing experience which, as I see it, the first variant follows

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @kiview , @eddumelendez
I haven’t heard back from you after my last comment. Did I have a change to convince you to go with the simple builder approach?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, thanks for ping us, I was thinking about it last week. There is a difference with the builders in database modules due to those are used by JdbcDatabaseContainer for the specific wait strategy and, well, JDBC API is in the JDK itself.

With latest changes in the MongoDbContainer, I would suggest the following:

  • Make authentication opt-in, withAuthenticationEnable(), instead of making it the default. Unless, a specific MongoDB version is forcing it, we can check on that version.
  • Provide withUsername and withPassword as initially provided in the PR
  • Do not provide a default key file. So, the user is aware of what's involved to run MongoDB with authentication enabled.
  • Make it work with sharding, if it is possible
  • Improve our javadocs and docs in general to show the correct usage of the module.

Testcontainers responsibility is to provide a ready to use service running in a container. There could be many configuration in the service itself which we do not master and we prefer a generic approach, meanwhile we are learning from uses cases, rather than do something at the beginning that can change later just because we are not aware of it.

I know the answer doesn't answer the last question but I think it is our best effort, meanwhile we also learn about MongoDB and how to use it. So, the builder can be revisited in the future. I'm also aware that this will involve more changes than initially expected but it is due to the evolution of the module itself.

}
16 changes: 16 additions & 0 deletions modules/mongodb/src/main/resources/keyFile.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
privateOldE8+8pPloNORolrRpGU6E6Ps8rh6GAcThtIfnh0Nfiy+fGvROwqlEtFmAY4Xb6
aDjb/cFoYSNIxh5DZaBD4hmllCkoAAl15WDKWEv+ELxj124KiyuzJUbu50iXYG+/
g6oWzElAdnckXCj+9CVhuw1dq9LgaIOd3n7NsrKK4rG7BgrdRl3HSpexBgd4WPva
jtIcvg+eKBvUysACGSpCubFQa1VoRiU7G0h5TYPXVBpmvN7cFHKANNKyggDPKlih
SfnMuXPGaecBm9UkmpHJoPUuzrE5wXStbho6SQzlbSBoxxgOCAHaAPtn7d3scP1i
lk8hoIyNjbq37D2b15VP9+JxBgkqywjcm3Z7D5m+NSI22xYD44kNBxvAIFUtE1RS
qgTFizA2ORb73TGfhhy2vuIJdsn97dZAMFOayiJvdzyIQJ9027d5eAVUE/U9UQjP
7BrHrJ+iV+PwggmIvwXDjFP7n0gs6tGmghfG/13y3lwpD+Xs84hcEbXitdns+8dE
lpnTkqUpGMexeuEuL4O5yfX46mVyT6+qvD+jb6y5oB1ydP/n3dmuWfoE3hv2rvVn
pFbPzuTF2mvIj0HTTmkNBCBh8Rq7McZ2vNW5nx3jdf8A+ICw6O9KlkemhHORIsIY
/HbsL1xjPs+gizMOddFwgfLovkQ9Oap7fAed+yl8JxqTWe5OMHZCDxyssZEOscnZ
xSWEXKWsWv2LLqtIdc++ZqrkvMWHNVqILcpe2upb7DbCVMjrsv5htXrYL7lgaItm
MpyP20q4ut7ja0YRwPITJyHNacJygAE/TViTL3K1JNXKHXCLWfIHGkVhYzc/9uv7
0nu5el6crurO57rQFC3T14huEQvouZl9SmHflkBFF7/kQeAJj10bmZWYae8mhdhb
zaJ2tUcsEgxEaZGrVK4f1NRAwBBY5t5AZMwLcYyIY1F1YZxw2BmrnPqr3GgSCcQ5
eMo3u9jKXXYJ6Eb3xwNpFXaGFPS1TmTK9y1CU8fXfDOsr7ln
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package org.testcontainers.containers;

import com.mongodb.BasicDBObject;
import com.mongodb.ConnectionString;
import com.mongodb.MongoCommandException;
import com.mongodb.ReadConcern;
import com.mongodb.ReadPreference;
import com.mongodb.TransactionOptions;
Expand All @@ -8,12 +11,17 @@
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.TransactionBody;
import org.bson.Document;
import org.junit.Test;
import org.testcontainers.utility.DockerImageName;

import java.util.Collections;
import java.util.Objects;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

public class MongoDBContainerTest {

Expand Down Expand Up @@ -98,7 +106,8 @@ public void shouldTestDatabaseName() {
try (final MongoDBContainer mongoDBContainer = new MongoDBContainer(DockerImageName.parse("mongo:4.0.10"))) {
mongoDBContainer.start();
final String databaseName = "my-db";
assertThat(mongoDBContainer.getReplicaSetUrl(databaseName)).endsWith(databaseName);
assertThat(databaseName)
.isEqualTo(new ConnectionString(mongoDBContainer.getReplicaSetUrl(databaseName)).getDatabase());
}
}

Expand All @@ -109,4 +118,73 @@ public void supportsMongoDB_6() {
executeTx(mongoDBContainer);
}
}

@Test
public void shouldTestAuthentication() {
final String usernameFullAccess = "my-name";
final String passwordFullAccess = "my-pass";
try (
final MongoDBContainer mongoDBContainer = new MongoDBContainer(DockerImageName.parse("mongo:4.4"))
.withUsername(usernameFullAccess)
.withPassword(passwordFullAccess)
) {
mongoDBContainer.start();
final ConnectionString connectionStringFullAccess = new ConnectionString(
mongoDBContainer.getReplicaSetUrl()
);
try (final MongoClient mongoSyncClientFullAccess = MongoClients.create(connectionStringFullAccess)) {
final MongoDatabase adminDatabase = mongoSyncClientFullAccess.getDatabase(
MongoDBContainer.DEFAULT_AUTHENTICATION_DATABASE_NAME
);
final MongoDatabase testDatabaseFullAccess = mongoSyncClientFullAccess.getDatabase(
MongoDBContainer.DEFAULT_DATABASE_NAME
);
final String collectionName = "my-collection";
final Document document1 = new Document("abc", 1);
testDatabaseFullAccess.getCollection(collectionName).insertOne(document1);
final String usernameRestrictedAccess = usernameFullAccess + "-restricted";
final String passwordRestrictedAccess = passwordFullAccess + "-restricted";
runCommand(
adminDatabase,
new BasicDBObject("createUser", usernameRestrictedAccess).append("pwd", passwordRestrictedAccess),
"read"
);
try (
final MongoClient mongoSyncRestrictedAccess = MongoClients.create(
mongoDBContainer.getReplicaSetUrl(
MongoDBContainer.ConnectionString
.builder()
.username(usernameRestrictedAccess)
.password(passwordRestrictedAccess)
.build()
Comment on lines +154 to +159
Copy link
Member

@eddumelendez eddumelendez Dec 14, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
mongoDBContainer.getReplicaSetUrl(
MongoDBContainer.ConnectionString
.builder()
.username(usernameRestrictedAccess)
.password(passwordRestrictedAccess)
.build()
MongoClientSettings.builder()
.credential(MongoCredential.createCredential(usernameRestrictedAccess, "admin", passwordRestrictedAccess.toCharArray()))
.applyConnectionString(new ConnectionString(String.format("mongodb://%s:%d", mongoDBContainer.getHost(), mongoDBContainer.getFirstMappedPort()) ))
.build()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pls, see the above mentioned discussion about MongoClientSettings

)
)
) {
final MongoCollection<Document> collection = mongoSyncRestrictedAccess
.getDatabase(MongoDBContainer.DEFAULT_DATABASE_NAME)
.getCollection(collectionName);
assertThat(collection.find().first()).isEqualTo(document1);
final Document document2 = new Document("abc", 2);
assertThatThrownBy(() -> collection.insertOne(document2)).isInstanceOf(MongoCommandException.class);
runCommand(adminDatabase, new BasicDBObject("updateUser", usernameRestrictedAccess), "readWrite");
collection.insertOne(document2);
assertThat(collection.countDocuments()).isEqualTo(2);
assertThat(connectionStringFullAccess.getUsername()).isEqualTo(usernameFullAccess);
assertThat(new String(Objects.requireNonNull(connectionStringFullAccess.getPassword())))
.isEqualTo(passwordFullAccess);
}
}
}
}

private void runCommand(MongoDatabase adminDatabase, BasicDBObject command, String role) {
adminDatabase.runCommand(
command.append(
"roles",
Collections.singletonList(
new BasicDBObject("role", role).append("db", MongoDBContainer.DEFAULT_DATABASE_NAME)
)
)
);
}
}