aemorales1
aemorales1

Reputation: 322

Start MongoDb Test Container with credentials

I am able to start the mongo image, insert and read data just fine using the snippet below. Similar to the redis example on testcontainers.org.

private static final int MONGO_PORT = 27017;

@ClassRule
public static MongoDBContainer mongo = new MongoDBContainer("mongo:3.2.4")
        .withExposedPorts(MONGO_PORT);

By default mongo doesn't have credentials but I'm looking for a way to set the credentials so that my app's MongoClient can get user/password from system properties and connect properly. I've tried adding the root user/password with the below but that didn't set the credentials properly.

@ClassRule
public static MongoDBContainer mongo = new MongoDBContainer("mongo:3.2.4")
        .withExposedPorts(MONGO_PORT)
        .withEnv("MONGO_INITDB_ROOT_USERNAME", "admin")
        .withEnv("MONGO_INITDB_ROOT_PASSWORD", "admin");

My question is: How can I start the test container with a username and password to allow my app to connect to it during my integration test using wiremock.

Upvotes: 1

Views: 10267

Answers (2)

Oleksii Zghurskyi
Oleksii Zghurskyi

Reputation: 4365

In short, you can find working example of test with MongoDB container here.

To provide, more details: you can configure authentication to MongoDB test container by using GenericContainer and setting environment with following properties MONGO_INITDB_ROOT_USERNAME, MONGO_INITDB_ROOT_PASSWORD:

@ClassRule
public static final GenericContainer<?> MONGODB = new GenericContainer<>(DockerImageName.parse(MONGO_IMAGE))
        .withEnv("MONGO_INITDB_ROOT_USERNAME", USERNAME)
        .withEnv("MONGO_INITDB_ROOT_PASSWORD", PASSWORD)
        .withEnv("MONGO_INITDB_DATABASE", TEST_DATABASE)
        .withExposedPorts(MONGO_PORT);

Then you should use MongoClient with corresponding MongoCredential. For example, below is the test, that writes and reads document to/from MongoDB container.

@Test
public void shouldWriteAndReadMongoDocument() {
    ServerAddress serverAddress = new ServerAddress(MONGODB.getHost(), MONGODB.getMappedPort(MONGO_PORT));
    MongoCredential credential = MongoCredential.createCredential(USERNAME, AUTH_SOURCE_DB, PASSWORD.toCharArray());
    MongoClientOptions options = MongoClientOptions.builder().build();

    MongoClient mongoClient = new MongoClient(serverAddress, credential, options);
    MongoDatabase database = mongoClient.getDatabase(TEST_DATABASE);
    MongoCollection<Document> collection = database.getCollection(TEST_COLLECTION);

    Document expected = new Document("name", "foo").append("foo", 1).append("bar", "string");
    collection.insertOne(expected);

    Document actual = collection.find(new Document("name", "foo")).first();
    assertThat(actual).isEqualTo(expected);
}

Notes:

  • To find more details on environment variables, you check documentation here (specifically, Environment Variables section)

  • To find more details on authenticated connection to MongoDB, you check documentation here

Upvotes: 0

Rob Evans
Rob Evans

Reputation: 2874

Checking the docs you can have a GenericContainer rather than specifically a MongoDbContainer (not certain this makes much difference given it looks largely like I've got the same as what you've already tried)...

I've then run:

private static final int MONGO_PORT = 27017;

    /**
     * https://hub.docker.com/_/mongo shows:
     *
     * $ docker run -d --network some-network --name some-mongo \
     *     -e MONGO_INITDB_ROOT_USERNAME=mongoadmin \
     *     -e MONGO_INITDB_ROOT_PASSWORD=secret \
     *     mongo
     */
    public static GenericContainer mongo = new GenericContainer(DockerImageName.parse("mongo:4.4.1"));

    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("MONGO_INITDB_ROOT_USERNAME=mongoadministrator");
        list.add("MONGO_INITDB_ROOT_PASSWORD=secret");
        list.add("MONGO_INITDB_DATABASE=db");
        mongo.setEnv(list);
        mongo.withExposedPorts(MONGO_PORT);
        mongo.start();
    }

the logs from the container show: docker logs [container_id]:

...
Successfully added user: {
    "user" : "mongoadministrator",  <<<<<
    "roles" : [
        {
            "role" : "root",
            "db" : "admin"
        }
    ]
}
...

I can login successfully inside the container with my new administrative user:

> docker exec -it 3ae15f01074c bash
Error: No such container: 3ae15f01074c

> docker ps -a
CONTAINER ID        IMAGE                       COMMAND                  CREATED             STATUS              PORTS                      NAMES
755e214f23d6        mongo:4.4.1                 "docker-entrypoint.s…"   2 seconds ago       Up 2 seconds        0.0.0.0:32803->27017/tcp   elegant_keldysh
cdb4f55930f4        testcontainers/ryuk:0.3.0   "/app"                   3 seconds ago       Up 3 seconds        0.0.0.0:32802->8080/tcp    testcontainers-ryuk-ef84751e-bfd4-41eb-b381-1c1206186eda

> docker exec -it 755e214f23d6 bash
root@755e214f23d6:/# mongo admin -u mongoadministrator
MongoDB shell version v4.4.1
Enter password:                      <<<<<<<<<<<<<<<< BAD PASSWORD ENTERED HERE
connecting to: mongodb://127.0.0.1:27017/admin?compressors=disabled&gssapiServiceName=mongodb
Error: Authentication failed. :
connect@src/mongo/shell/mongo.js:374:17
@(connect):2:6
exception: connect failed
exiting with code 1

root@755e214f23d6:/# mongo admin -u mongoadministrator
MongoDB shell version v4.4.1
Enter password:                   <<<<<<<< GOOD PASSWORD secret ENTERED HERE
connecting to: mongodb://127.0.0.1:27017/admin?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("63279398-d9c6-491d-9bd9-6b619dc4a99d") }
MongoDB server version: 4.4.1
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
    https://docs.mongodb.com/
Questions? Try the MongoDB Developer Community Forums
    https://community.mongodb.com
---
The server generated these startup warnings when booting: 
        2020-10-24T22:06:24.914+00:00: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine. See http://dochub.mongodb.org/core/prodnotes-filesystem
---
---
        Enable MongoDBs free cloud-based monitoring service, which will then receive and display
        metrics about your deployment (disk utilization, CPU, operation statistics, etc).

        The monitoring data will be available on a MongoDB website with a unique URL accessible to you
        and anyone you share the URL with. MongoDB may use this information to make product
        improvements and to suggest MongoDB products and deployment options to you.

        To enable free monitoring, run the following command: db.enableFreeMonitoring()
        To permanently disable this reminder, run the following command: db.disableFreeMonitoring()
---
> 

Upvotes: 3

Related Questions