Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: add mongodb replset option with example #143

Merged
merged 3 commits into from
Jul 30, 2024

Conversation

sinyo-matu
Copy link
Contributor

@sinyo-matu sinyo-matu commented Jun 9, 2024

Thank you for the amazing work.
I really enjoy using testcontainers with Rust.

When working with MongoDB, it is very common to need to test transaction operations. Therefore, I added some options to facilitate this.

  • Added a new struct MongoReplSet, which represents a MongoDB server started with mongod --replSet. This enables Replica Set which is necessary for the transaction operations
  • Added with_name and with_tag for users' convenience to choose their preferred image and tag.
  • Added some relevant tests.
  • Breaking Change: Mongo.start() will no longer work. Instead, users need to explicitly call Mongo::default().

@sinyo-matu sinyo-matu changed the title Add mongodb replset option for mongo module feat!: Add mongodb replset option for mongo module Jun 9, 2024
@sinyo-matu sinyo-matu force-pushed the main branch 2 times, most recently from e61b2a6 to 01898b7 Compare June 9, 2024 17:46
Copy link
Contributor

@DDtKey DDtKey left a comment

Choose a reason for hiding this comment

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

Thank you for the contribution! 🙏 I really appreciate it!

I left couple of comments, please take a look and let me know what do you think.

Also, since we're touching the module, it would be great to add some basic documentation, for example like this one:

/// Module to work with [`RabbitMQ`] inside of tests.
///
/// Starts an instance of RabbitMQ with the [`management-plugin`] started by default,
/// so you are able to use the [`RabbitMQ Management HTTP API`] to manage the configuration if the started [`RabbitMQ`] instance at test runtime.
///
/// This module is based on the official [`RabbitMQ docker image`].
///
/// # Example
/// ```
/// use testcontainers_modules::{rabbitmq, testcontainers::runners::SyncRunner};
///
/// let rabbitmq_instance = rabbitmq::RabbitMq.start().unwrap();
///
/// let amqp_url = format!("amqp://{}:{}", rabbitmq_instance.get_host().unwrap(), rabbitmq_instance.get_host_port_ipv4(5672).unwrap());
///
/// // do something with the started rabbitmq instance..
/// ```
///
/// [`RabbitMQ`]: https://www.rabbitmq.com/
/// [`management-plugin`]: https://www.rabbitmq.com/management.html
/// [`RabbitMQ Management HTTP API`]: https://www.rabbitmq.com/management.html#http-api
/// [`RabbitMQ docker image`]: https://hub.docker.com/_/rabbitmq

src/mongo/standalong.rs Outdated Show resolved Hide resolved
src/mongo/mod.rs Outdated Show resolved Hide resolved
src/mongo/replset.rs Outdated Show resolved Hide resolved
@sinyo-matu
Copy link
Contributor Author

@DDtKey
Thanks for your kind comments!

I think the issue is how arguments are represented in current version of testcontainers. I'd like to refactor this part, so image will have override-able method args (just like env_vars and etc).
I'll prepare refactoring PR to testcontainers, but it might be released with some delay

I totally agree with you that we should expose only a single Mongo image for the user's convenience. As you mentioned, the representation of arguments makes it difficult to run different arguments driven by different options. Refactoring will be really helpful!

I think I may refactor my code after the release of testcontainers that includes the PR.

@sinyo-matu
Copy link
Contributor Author

And I would like to add examples for mongodb

DDtKey added a commit to testcontainers/testcontainers-rs that referenced this pull request Jun 10, 2024
- really common pattern is to use `Vec<String>`
- `args` isn't the best term, because in fact it's Docker's [CMD](https://docs.docker.com/reference/dockerfile/#cmd)
- it was not aligned with existing `ExecCommand`
- current interface is confusing and users struggle with it
- essentially it should be closer to the current representation of environment variables and other parameters
- new implementation allows to override args regardless of underlying type
- it's still will be possible to use custom strict arguments type for particular image which can be converted to list of strings if users want

Dependent PR to modules: testcontainers/testcontainers-rs-modules-community#143
DDtKey added a commit to testcontainers/testcontainers-rs that referenced this pull request Jun 10, 2024
…#649)

- really common pattern is to use `Vec<String>`
- `args` isn't the best term, because in fact it's Docker's
[CMD](https://docs.docker.com/reference/dockerfile/#cmd)
- it was not aligned with existing `ExecCommand`
- current interface is confusing and users struggle with it
- essentially it should be closer to the current representation of
environment variables and other parameters
- new implementation allows to override args regardless of underlying
type
- it's still will be possible to use custom strict arguments type for
particular image which can be converted to list of strings if users want

Dependent PR to modules:
testcontainers/testcontainers-rs-modules-community#143

Also, I'm preparing 2 follow-up PRs which will improve the user
experience.
@DDtKey
Copy link
Contributor

DDtKey commented Jun 25, 2024

Hi @sinyo-matu 👋

Sorry for delay, totally forgot to notify you that a new version of testcontainers has been released.

Now it's possible to encapsulate arguments as part of image itself!

@sinyo-matu sinyo-matu changed the title feat!: Add mongodb replset option for mongo module feat!: add mongodb replset option for mongo module Jul 13, 2024
@sinyo-matu sinyo-matu changed the title feat!: add mongodb replset option for mongo module feat!:add mongodb replset option, upgrade mongodb version and add mongodb example Jul 28, 2024
@sinyo-matu
Copy link
Contributor Author

Sorry for the delay!

  • Update my code. it is now following the new Image trait.
  • Upgrade mongodb to 3.0.1.
  • Add a simple example for mongo module

Copy link
Contributor

@DDtKey DDtKey left a comment

Choose a reason for hiding this comment

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

Thank you!
Just one question, but in general looks like LGTM

src/mongo/mod.rs Outdated Show resolved Hide resolved
src/mongo/mod.rs Outdated
Comment on lines 75 to 80
ExecCommand::new(vec![
"mongosh".to_string(),
"--eval".to_string(),
"'rs.status()'".to_string(),
])
.with_cmd_ready_condition(CmdWaitFor::message_on_stdout("ok: 1")),
Copy link
Contributor

Choose a reason for hiding this comment

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

I think rs.status doesn't wait for "ok", right?

In that case we probably need to wrap it into something like:

until mongosh --eval 'rs.status()'; do sleep 1; done

WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

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

However, I guess the command will return 0 exit status even for status!= ok 🤔

Copy link
Contributor Author

@sinyo-matu sinyo-matu Jul 29, 2024

Choose a reason for hiding this comment

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

Yes you're right. that is tricky🤔.

Another thought:
I confirmed below log outputs to stdout at the last parts of the replSet starting process.
So we can wait for it by with_container_ready_conditions

Rebuilding PrimaryOnlyService due to stepUp

And it is working for tests and my application usage.
There are still few starting processes after this log... so it is working for general situation IMO, but not a so solid solution.

Updated my code.

How about it?

@DDtKey DDtKey changed the title feat!:add mongodb replset option, upgrade mongodb version and add mongodb example feat!: add mongodb replset option, upgrade mongodb version and add mongodb example Jul 28, 2024
@DDtKey DDtKey changed the title feat!: add mongodb replset option, upgrade mongodb version and add mongodb example feat!: add mongodb replset option with example Jul 28, 2024
@sinyo-matu
Copy link
Contributor Author

@DDtKey
Thank you for the code review Artem

@DDtKey DDtKey merged commit 5dd3f98 into testcontainers:main Jul 30, 2024
4 of 6 checks passed
@github-actions github-actions bot mentioned this pull request Jul 30, 2024
DDtKey pushed a commit that referenced this pull request Jul 30, 2024
## 🤖 New release
* `testcontainers-modules`: 0.8.0 -> 0.9.0

<details><summary><i><b>Changelog</b></i></summary><p>

<blockquote>

## [0.9.0] - 2024-07-30

### Features

- Expose `watchdog` feature of testcontainers
([#168](#168))
- [**breaking**] Add mongodb replset option with example
([#143](#143))
- [**breaking**] Update testcontainers to 0.21.0
([#172](#172))

### Miscellaneous Tasks

- Update redis requirement from 0.25.0 to 0.26.0
([#171](#171))

<!-- generated by git-cliff -->
</blockquote>


</p></details>

---
This PR was generated with
[release-plz](https://github.com/MarcoIeni/release-plz/).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
DDtKey pushed a commit that referenced this pull request Sep 25, 2024
This PR makes sure that the way structs are constructed is consistent
and encourages the builder pattern.
It is based on this question:
#156 (comment)

For the changelog:

We now require you to use the builder pattern (instead of some structs
being [unit structs](https://doc.rust-lang.org/std/keyword.struct.html))
for all modules.
This ensures that if we add a field in the future that this will not
break your existing code.

This change is breaking for these modules:

| Module | before | after |
|--------|--------|--------|
| `cncf_distribution::CncfDistribution` | `CncfDistribution.start()` |
`CncfDistribution::default().start()` |
| `dynamodb_local::DynamoDb` | `DynamoDb.start()` |
`DynamoDb::default().start()` |
| `elasticmq::ElasticMq` | `ElasticMq.start()` |
`ElasticMq::default().start()` |
| ~`mongo::Mongo`~ (see #143) | ~`Mongo.start()`~ |
~`Mongo::default().start()`~ |
| `kwok::KwokCluster` | `KwokCluster.start()` |
`KwokCluster::default().start()` |
| `rabbitmq::RabbitMq` | `RabbitMq.start()` |
`RabbitMq::default().start()` |
| `redis::stack::RedisStack` | `RedisStack.start()` |
`RedisStack::default().start()` |
| `redis::standalone::Redis` | `Redis.start()` |
`Redis::default().start()` |
| `victoria_metrics::VictoriaMetrics` | `VictoriaMetrics.start()` |
`VictoriaMetrics::default().start()` |
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants