-
-
Notifications
You must be signed in to change notification settings - Fork 288
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
[Enhancement]: Add one node replica set support #1154
Comments
I have tried to add this functionality on this branch https://github.com/testcontainers/testcontainers-dotnet/tree/57bf8adf56e3ae701b8b488113a1e8db01d41a4a Please view https://github.com/testcontainers/testcontainers-dotnet/blob/57bf8adf56e3ae701b8b488113a1e8db01d41a4a/tests/Testcontainers.MongoDb.Tests/MongoDbReplicaSetContainerTest.cs as it's the closest I got. The biggest challenge I am finding is due to the random port. Not really a problem with testcontainers but with a lack of knowledge about mongodb and docker networking. The mentioned test works well, and it demonstrates how a replica set can be created and initiated and available through a connection string such as But it works because I am disabling the random port, which is not Ok. If I specify a random port I could get the port number being used but, when initiating the replica set, I would get an error
I have manually tried to start the container without executing the
and this works well for the port 27017, but if I am using a random port and I try to initiate it with that other port (e.g: 51523)
Useful links: |
Hi @diegosasw, just cross-posting my question here |
I've had a look at your Go PR. I'm wondering whether you know why this is not working for me. |
I've been trying to do this as well, the closest I've gotten is this: public static IContainer CreateMongoDBWithReplicaSet(Action<ContainerBuilder>? config = null)
{
var builder = new ContainerBuilder()
.WithImage("mongo:7.0")
.WithCommand("--replSet rs0 --bind_ip_all")
.WithPortBinding(MongoDbBuilder.MongoDbPort, true)
.WithEnvironment("MONGO_INITDB_ROOT_USERNAME", MongoDbBuilder.DefaultUsername)
.WithEnvironment("MONGO_INITDB_ROOT_PASSWORD", MongoDbBuilder.DefaultPassword)
.WithWaitStrategy(Wait.ForUnixContainer().UntilPortIsAvailable(MongoDbBuilder.MongoDbPort))
.WithStartupCallback(async (container, cancellationToken) =>
{
await container.ExecAsync(["bash", "-c", $"echo 'disableTelemetry()' | mongosh -u $MONGO_INITDB_ROOT_USERNAME -p $MONGO_INITDB_ROOT_PASSWORD"], isSuccess: result =>
{
result.Stderr.Should().BeNullOrEmpty();
if (!string.IsNullOrEmpty(result.Stdout))
{
Console.WriteLine("stdout:" + result.Stdout);
}
return true;
}, cancellationToken: cancellationToken);
await container.ExecAsync(["bash", "-c", $"echo 'try {{ rs.status() }} catch (err) {{ rs.initiate({{_id: \"rs0\", members: [{{ _id: 0, host: \"localhost:{MongoDbBuilder.MongoDbPort}\" }}]}}) }};' | mongosh -u $MONGO_INITDB_ROOT_USERNAME -p $MONGO_INITDB_ROOT_PASSWORD"], e =>
{
return false;
}, cancellationToken: cancellationToken);
return;
await container.ExecAsync(["bash", "-c", $"echo 'disableTelemetry(); rs.initiate({{_id: \"rs0\", members: [{{ _id: 0, host: \"localhost:{MongoDbBuilder.MongoDbPort}\" }}]}});' | mongosh -u $MONGO_INITDB_ROOT_USERNAME -p $MONGO_INITDB_ROOT_PASSWORD"], e =>
{
return false;
}, cancellationToken: cancellationToken);
});
config?.Invoke(builder);
return builder.Build();
}
static async Task<bool> ExecAsync(this IContainer container, List<string> commands, Func<ExecResult, bool>? isSuccess = null, bool throwOnFailure = true, int attempts = 10, int delayInMS = 100, CancellationToken cancellationToken = default)
{
var attemptCount = 0;
while (attemptCount < attempts)
{
try
{
var result = await container.ExecAsync(commands, cancellationToken);
if (result.ExitCode == 0)
{
return isSuccess is not null && !isSuccess(result)
? throw new Exception($"Command failed. Stdout: {result.Stdout}, Stderr: {result.Stderr}")
: true;
}
result.ExitCode.Should().Be(0,
because: $"MongoDB replica set initialization failed. Attempt {attemptCount + 1} of 10. Stdout: {result.Stdout}, Stderr: {result.Stderr}");
}
catch
{
await Task.Delay(delayInMS, cancellationToken);
attemptCount++;
}
}
return throwOnFailure
? throw new Exception("Failed to execute command.")
: false;
} It's failing as it requires a key, which I've been trying to use mount paths to generate and executing commands but so far failing. |
Hey all, I've been looking for the same functionality myself and have implemented it locally before I saw this issue. I've just created a PR that provides a working configuration for a single node replica set - I've tested it locally on our integration tests, and it's been working perfectly so far Let me know what you think |
Problem
There is no one-node replica set support for testcontainers-dotnet but the java version seems to have something. However, by looking at the java code I have some doubts whether that's properly initializing the replica set.
Solution
Add a
WithReplicaSet(string replicaSetName = "rs0")
or similar builder method.Add another method to initialize the replica set.
Add another method to obtain the ReplicaSet connection string which should be something similar to
mongodb://{hostname}:{mapped_port}/?replicaSet=rs0
Benefit
It would allow testing mongoDb replica set and things such as change streams, only available on replica sets. Also, it would get closer to the Java version in functionality.
Alternatives
Currently, mongoDb containers with one node replica set are possible to be created with
Ductus.FluentDocker
.Also with testcontainers, but the random port is a challenge.
Would you like to help contributing this enhancement?
Yes
The text was updated successfully, but these errors were encountered: