Skip to content

Enable replicaSet support for MongoDb#5712

Closed
twsouthwick wants to merge 7 commits intomicrosoft:mainfrom
twsouthwick:mongodb-replica
Closed

Enable replicaSet support for MongoDb#5712
twsouthwick wants to merge 7 commits intomicrosoft:mainfrom
twsouthwick:mongodb-replica

Conversation

@twsouthwick
Copy link
Copy Markdown
Member

@twsouthwick twsouthwick commented Sep 14, 2024

Description

This change adds support for replica sets in MongoDb. In order to support this a couple changes are required:

  • Connection strings have query parameters as options that define the replica set. To support this, the expression builder is now called manually to build it up, as well as changing the database connection string to no long reference the server connection string directly (as the server connection string may have the replicaSet option)
  • The target port and the exposed port must be the same for replica sets to work. This adds a check that updates the MongoDb server to not be proxied and have the same port. Ideally, if no port is set, we should use a random one but I couldn't figure out how to do that in an idiomatic way.

Fixes #5238

Checklist

  • Is this feature complete?
    • Yes. Ready to ship.
    • No. Follow-up changes expected.
  • Are you including unit tests for the changes and scenario tests if relevant?
    • Yes
    • No
  • Did you add public API?
    • Yes
      • If yes, did you have an API Review for it?
        • Yes
        • No
      • Did you add <remarks /> and <code /> elements on your triple slash comments?
        • Yes
        • No
    • No
  • Does the change make any security assumptions or guarantees?
    • Yes
      • If yes, have you done a threat model and had a security review?
        • Yes
        • No
    • No
  • Does the change require an update in our Aspire docs?
    • Yes
      • Link to aspire-docs issue:
    • No
Microsoft Reviewers: Open in CodeFlow

@ghost ghost added the area-app-model Issues pertaining to the APIs in Aspire.Hosting, e.g. DistributedApplication label Sep 14, 2024
@dotnet-policy-service dotnet-policy-service Bot added the community-contribution Indicates that the PR has been added by a community member label Sep 14, 2024
@twsouthwick twsouthwick marked this pull request as draft September 14, 2024 03:56
@davidfowl davidfowl added mongodb Issues related to mongodb integrations area-integrations Issues pertaining to Aspire Integrations packages and removed area-app-model Issues pertaining to the APIs in Aspire.Hosting, e.g. DistributedApplication labels Sep 14, 2024
{
if (builder.Resource.TryGetLastAnnotation<MongoDbReplicaSetAnnotation>(out _))
{
throw new InvalidOperationException("A replica set has already been added to the MongoDB server resource.");
Copy link
Copy Markdown
Contributor

@davidfowl davidfowl Sep 16, 2024

Choose a reason for hiding this comment

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

Why throw instead of noop? Because of the name?

Copy link
Copy Markdown
Member Author

@twsouthwick twsouthwick Sep 16, 2024

Choose a reason for hiding this comment

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

yeah. I can check if there's already one with the same name and return in those cases if you want

Comment thread src/Aspire.Hosting.MongoDB/MongoDBBuilderExtensions.cs Outdated
Comment thread src/Aspire.Hosting.MongoDB/MongoDBBuilderExtensions.cs Outdated
var dir = Path.Combine(Path.GetTempPath(), "aspire.mongo", Path.GetRandomFileName());
Directory.CreateDirectory(dir);

var rsInitContents = $$"""rs.initiate({ _id:'{{replicaSet}}', members:[{_id:0,host:'localhost:{{port}}'}]})""";
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

@davidfowl I'd prefer to be able to just docker exec into the container after it started, but couldn't figure out how to do that so I'm running a container and configuring things to ensure it completes before anything else needs to use the db. If there is a better way to do this with aspire things, let me know

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We're adding support for this in Aspire 9 very soon. Might be better to wait until that support is available in the app model.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

cool - is there a tracking issue for that?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

@davidfowl any progress on being able to exec into the container?

Comment thread src/Aspire.Hosting.MongoDB/MongoDBServerResource.cs
Comment thread src/Aspire.Hosting/ResourceBuilderExtensions.cs
// See the conversation about setting up replica sets in Docker here: https://github.com/docker-library/mongo/issues/246
static string GetReplicaSetInitDockerfileDir(string replicaSet, string host, int port)
{
var dir = Directory.CreateTempSubdirectory("aspire.mongo").FullName;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

A couple notes here:

  1. Who cleans up this directory?
  2. On Unix, this is going to create a directory that only the current user can access. If the container is running on non-root, the container won't be able to access this folder.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

is there a pattern that already exists to handle creating/cleaning up directories? Maybe another reason as @davidfowl mentioned above to maybe wait to exec into a container

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

So after some thought, I think a pattern we can use here is:

  • Put the docker file in the nuget package
  • Mark it as content so it gets copied to the output (we'lll want to name it so it doesn't conflict)
  • Use build arguments to parameterize the docker file and pass that state in

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

With #7136, we have now introduced a new "IAspireStore" API:

https://github.com/dotnet/aspire/blob/acdf5012407c2ab0259f4b6f075acb6c668949f3/src/Aspire.Hosting/ApplicationModel/IAspireStore.cs#L17-L22

This file could be written there and my above concerns would be resolved.

Comment thread src/Aspire.Hosting.MongoDB/MongoDBDatabaseResource.cs Outdated
@twsouthwick
Copy link
Copy Markdown
Member Author

/azp run

@azure-pipelines
Copy link
Copy Markdown

Commenter does not have sufficient privileges for PR 5712 in repo dotnet/aspire

@twsouthwick twsouthwick marked this pull request as ready for review September 18, 2024 19:42
.WithHttpEndpoint(targetPort: 8081, name: "http")
.ExcludeFromManifest();
.ExcludeFromManifest()
.WaitFor(builder);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm not sure about using WaitFor invisibly like this. I can see the benefit but if one of the mongo db instances files to start then you won't be able to inspect any of the other databases.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I added that because once you have a replica set, the existing connection string may cause express to fail if it tries to connect before the replica set is initialized (a race condition) and it doesn't recover from it.

@creyke
Copy link
Copy Markdown

creyke commented Oct 28, 2024

+1 for this. Missing replica sets doesn't just block transactions, it also blocks change streams.

These are two very commonly utilised features.

This looks close to done, but is not active... is this likely to get merged @twsouthwick?

Thanks in advance.

@twsouthwick
Copy link
Copy Markdown
Member Author

@creyke I'd like to get this in, but in order to set up the replica set, we must run some commands in the container. sounds like docker exec support will be available soon, so this is waiting on that. Once that is available, I'll update it so this can be merged.

@feritzcan2
Copy link
Copy Markdown

@creyke I'd like to get this in, but in order to set up the replica set, we must run some commands in the container. sounds like docker exec support will be available soon, so this is waiting on that. Once that is available, I'll update it so this can be merged.

Still no luck? Thats highly blocker for integration testing /(

@alexjamesbrown
Copy link
Copy Markdown

@twsouthwick was there anything left to do on this? Currently using the workaround on this issue
#6811 - but definitely feels like this support should be in Aspire core.

private static void ConfigureMongoExpressContainer(EnvironmentCallbackContext context, MongoDBServerResource resource)
{
// Mongo Exporess assumes Mongo is being accessed over a default Aspire container network and hardcodes the resource address
var sb = new StringBuilder($"mongodb://{resource.Name}:{resource.PrimaryEndpoint.TargetPort}/?directConnection=true");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

ReferenceExpressionBuilder

@danmoseley
Copy link
Copy Markdown
Member

@twsouthwick is this still in progress?

@danmoseley danmoseley added the needs-author-action An issue or pull request that requires more info or actions from the author. label Feb 2, 2025
@davidfowl
Copy link
Copy Markdown
Contributor

@twsouthwick @eerhardt and I have an offline thread about this one.

@davidfowl davidfowl removed the needs-author-action An issue or pull request that requires more info or actions from the author. label Feb 17, 2025
@alexjamesbrown
Copy link
Copy Markdown

Just commenting again as not to close this issue

@davidfowl / @eerhardt was there any update on this at all?

/// .WaitFor(messaging);
/// </code>
/// </example>
public static IResourceBuilder<T> WaitFor<T>(this IResourceBuilder<T> builder, IResourceBuilder<IResource> dependency, bool includeHealthChecks) where T : IResource
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I wonder if bool includeHealthChecks should instead be a WaitType. We currently have WaitUntilHealthy and WaitForCompletion. But could add WaitUntilStarted.

@twsouthwick
Copy link
Copy Markdown
Member Author

I took a stab at updating it, but have found that since I did the first attempt that, password auth has been added. That adds a complication for enabling replica sets as that then requires a certificate to be used as well.

The place I'm getting stuck on is that I can generate a cert, but getting it into the container is weird.

  • If I do it as one of the mongo init scripts, I can generate it, but then I can't set the permissions correctly
  • I've seen people attempt to do it by doing it in the entrypoint (i.e. [some commands to create cert and set permissions]; call_original_entrypoint.sh $@) but it appears the Aspire doesn't allow setting an entrypoint to an arbitrary command like that.

@danmoseley
Copy link
Copy Markdown
Member

next action here seems to be a question for @eerhardt and I know he's pretty engaged right now.

@eerhardt
Copy link
Copy Markdown
Member

eerhardt commented May 1, 2025

@twsouthwick @davidfowl and I met offline and had some ideas how to move this forward. We think if we had something like #6481, we could make this simpler.

@danmoseley
Copy link
Copy Markdown
Member

OK I'm going to close this as it sounds like we're blocked on that. Feel free to reopen, or create a new PR, when ready to continue @twsouthwick

@danmoseley danmoseley closed this May 8, 2025
@github-actions github-actions Bot locked and limited conversation to collaborators Jun 8, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-integrations Issues pertaining to Aspire Integrations packages community-contribution Indicates that the PR has been added by a community member mongodb Issues related to mongodb integrations

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MongoDB Transactions requires replicas

8 participants