Skip to content

Commit a0b42c3

Browse files
committed
feat: add mongodb container and connection support
1 parent 69937e2 commit a0b42c3

16 files changed

+829
-0
lines changed

Aspire.sln

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aspire.MySqlConnector.Tests
158158
EndProject
159159
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestProject.IntegrationServiceA", "tests\testproject\TestProject.IntegrationServiceA\TestProject.IntegrationServiceA.csproj", "{DCF2D47A-921A-4900-B5B2-CF97B3531CE8}"
160160
EndProject
161+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aspire.MongoDB.Driver", "src\Components\Aspire.MongoDB.Driver\Aspire.MongoDB.Driver.csproj", "{20A5A907-A135-4735-B4BF-E13514F360E3}"
162+
EndProject
163+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aspire.MongoDB.Driver.Tests", "tests\Aspire.MongoDB.Driver.Tests\Aspire.MongoDB.Driver.Tests.csproj", "{E592E447-BA3C-44FA-86C1-EBEDC864A644}"
164+
EndProject
161165
Global
162166
GlobalSection(SolutionConfigurationPlatforms) = preSolution
163167
Debug|Any CPU = Debug|Any CPU
@@ -424,6 +428,14 @@ Global
424428
{DCF2D47A-921A-4900-B5B2-CF97B3531CE8}.Debug|Any CPU.Build.0 = Debug|Any CPU
425429
{DCF2D47A-921A-4900-B5B2-CF97B3531CE8}.Release|Any CPU.ActiveCfg = Release|Any CPU
426430
{DCF2D47A-921A-4900-B5B2-CF97B3531CE8}.Release|Any CPU.Build.0 = Release|Any CPU
431+
{20A5A907-A135-4735-B4BF-E13514F360E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
432+
{20A5A907-A135-4735-B4BF-E13514F360E3}.Debug|Any CPU.Build.0 = Debug|Any CPU
433+
{20A5A907-A135-4735-B4BF-E13514F360E3}.Release|Any CPU.ActiveCfg = Release|Any CPU
434+
{20A5A907-A135-4735-B4BF-E13514F360E3}.Release|Any CPU.Build.0 = Release|Any CPU
435+
{E592E447-BA3C-44FA-86C1-EBEDC864A644}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
436+
{E592E447-BA3C-44FA-86C1-EBEDC864A644}.Debug|Any CPU.Build.0 = Debug|Any CPU
437+
{E592E447-BA3C-44FA-86C1-EBEDC864A644}.Release|Any CPU.ActiveCfg = Release|Any CPU
438+
{E592E447-BA3C-44FA-86C1-EBEDC864A644}.Release|Any CPU.Build.0 = Release|Any CPU
427439
EndGlobalSection
428440
GlobalSection(SolutionProperties) = preSolution
429441
HideSolutionNode = FALSE
@@ -497,6 +509,8 @@ Global
497509
{165411FE-755E-4869-A756-F87F455860AC} = {4981B3A5-4AFD-4191-BF7D-8692D9783D60}
498510
{CA283D7F-EB95-4353-B196-C409965D2B42} = {27381127-6C45-4B4C-8F18-41FF48DFE4B2}
499511
{C8079F06-304F-49B1-A0C1-45AA3782A923} = {4981B3A5-4AFD-4191-BF7D-8692D9783D60}
512+
{20A5A907-A135-4735-B4BF-E13514F360E3} = {27381127-6C45-4B4C-8F18-41FF48DFE4B2}
513+
{E592E447-BA3C-44FA-86C1-EBEDC864A644} = {4981B3A5-4AFD-4191-BF7D-8692D9783D60}
500514
{DCF2D47A-921A-4900-B5B2-CF97B3531CE8} = {975F6F41-B455-451D-A312-098DE4A167B6}
501515
EndGlobalSection
502516
GlobalSection(ExtensibilityGlobals) = postSolution

Directory.Packages.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
<PackageVersion Include="JsonSchema.Net" Version="5.3.1" />
7272
<PackageVersion Include="Microsoft.FluentUI.AspNetCore.Components" Version="4.0.0" />
7373
<PackageVersion Include="Microsoft.FluentUI.AspNetCore.Components.Icons" Version="4.0.0" />
74+
<PackageVersion Include="MongoDB.Driver" Version="2.22.0" />
7475
<PackageVersion Include="MySqlConnector.DependencyInjection" Version="2.3.1" />
7576
<PackageVersion Include="Npgsql.DependencyInjection" Version="8.0.0-rc.2" />
7677
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.0-rc.2" />
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
namespace Aspire.Hosting.ApplicationModel;
5+
6+
/// <summary>
7+
/// Represents a MongoDb resource that requires a connection string.
8+
/// </summary>
9+
public interface IMongoDbResource : IResourceWithConnectionString
10+
{
11+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.Net.Sockets;
5+
using System.Text.Json;
6+
using Aspire.Hosting.ApplicationModel;
7+
8+
namespace Aspire.Hosting.MongoDb;
9+
10+
/// <summary>
11+
/// Provides extension methods for adding MongoDB resources to an <see cref="IDistributedApplicationBuilder"/>.
12+
/// </summary>
13+
public static class MongoDbBuilderExtensions
14+
{
15+
private const int DefaultContainerPort = 27017;
16+
private const string DefaultPassword = "password";
17+
private const string PasswordEnvVarName = "MONGO_INITDB_ROOT_PASSWORD";
18+
19+
/// <summary>
20+
/// Adds a MongoDB container to the application model. The default image is "mongo" and the tag is "latest".
21+
/// </summary>
22+
/// <returns></returns>
23+
/// <param name="builder">The <see cref="IDistributedApplicationBuilder"/>.</param>
24+
/// <param name="name">The name of the resource. This name will be used as the connection string name when referenced in a dependency.</param>
25+
/// <param name="port">The host port for MongoDB.</param>
26+
/// <param name="password">The password for the MongoDB root user. Defaults to a 'password' password.</param>
27+
/// <returns>A reference to the <see cref="IResourceBuilder{MongoDbContainerResource}"/>.</returns>
28+
public static IResourceBuilder<MongoDbContainerResource> AddMongoDbContainer(
29+
this IDistributedApplicationBuilder builder,
30+
string name,
31+
int port = DefaultContainerPort,
32+
string password = DefaultPassword)
33+
{
34+
var mongoDbContainer = new MongoDbContainerResource(name, password);
35+
36+
return builder
37+
.AddResource(mongoDbContainer)
38+
.WithAnnotation(new ManifestPublishingCallbackAnnotation(WriteMongoDbContainerToManifest))
39+
.WithAnnotation(new ServiceBindingAnnotation(ProtocolType.Tcp, port: port, containerPort: DefaultContainerPort)) // Internal port is always 27017.
40+
.WithAnnotation(new ContainerImageAnnotation { Image = "mongo", Tag = "latest" })
41+
.WithEnvironment(PasswordEnvVarName, () => mongoDbContainer.Password);
42+
}
43+
44+
/// <summary>
45+
/// Adds a MongoDB connection to the application model. Connection strings can also be read from the connection string section of the configuration using the name of the resource.
46+
/// </summary>
47+
/// <param name="builder">The <see cref="IDistributedApplicationBuilder"/>.</param>
48+
/// <param name="name">The name of the resource. This name will be used as the connection string name when referenced in a dependency.</param>
49+
/// <param name="connectionString">The MongoDB connection string (optional).</param>
50+
/// <returns>A reference to the <see cref="IResourceBuilder{MongoDbConnectionResource}"/>.</returns>
51+
public static IResourceBuilder<MongoDbConnectionResource> AddMongoDbConnection(this IDistributedApplicationBuilder builder, string name, string? connectionString = null)
52+
{
53+
var mongoDbConnection = new MongoDbConnectionResource(name, connectionString);
54+
55+
return builder
56+
.AddResource(mongoDbConnection)
57+
.WithAnnotation(new ManifestPublishingCallbackAnnotation((json) => WriteMongoDbConnectionToManifest(json, mongoDbConnection)));
58+
}
59+
60+
/// <summary>
61+
/// Adds a MongoDB database to the application model.
62+
/// </summary>
63+
/// <param name="builder">The MongoDB server resource builder.</param>
64+
/// <param name="name">The name of the resource. This name will be used as the connection string name when referenced in a dependency.</param>
65+
/// <returns>A reference to the <see cref="IResourceBuilder{MongoDbDatabaseResource}"/>.</returns>
66+
public static IResourceBuilder<MongoDbDatabaseResource> AddDatabase(this IResourceBuilder<MongoDbContainerResource> builder, string name)
67+
{
68+
var mongoDbDatabase = new MongoDbDatabaseResource(name, builder.Resource);
69+
70+
return builder.ApplicationBuilder
71+
.AddResource(mongoDbDatabase)
72+
.WithAnnotation(new ManifestPublishingCallbackAnnotation(
73+
(json) => WriteMongoDbDatabaseToManifest(json, mongoDbDatabase)));
74+
}
75+
76+
private static void WriteMongoDbContainerToManifest(Utf8JsonWriter jsonWriter)
77+
{
78+
jsonWriter.WriteString("type", "mongodb.server.v0");
79+
}
80+
81+
private static void WriteMongoDbConnectionToManifest(Utf8JsonWriter jsonWriter, MongoDbConnectionResource mongoDbConnection)
82+
{
83+
jsonWriter.WriteString("type", "mongodb.connection.v0");
84+
jsonWriter.WriteString("connectionString", mongoDbConnection.GetConnectionString());
85+
}
86+
87+
private static void WriteMongoDbDatabaseToManifest(Utf8JsonWriter json, MongoDbDatabaseResource mongoDbDatabase)
88+
{
89+
json.WriteString("type", "mongodb.database.v0");
90+
json.WriteString("parent", mongoDbDatabase.Parent.Name);
91+
}
92+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
namespace Aspire.Hosting.ApplicationModel;
5+
6+
/// <summary>
7+
/// A resource that represents a MongoDb connection.
8+
/// </summary>
9+
/// <param name="name">The name of the resource.</param>
10+
/// <param name="connectionString">The MongoDb connection string.</param>
11+
public class MongoDbConnectionResource(string name, string? connectionString) : Resource(name), IMySqlResource
12+
{
13+
private readonly string? _connectionString = connectionString;
14+
15+
/// <summary>
16+
/// Gets the connection string for the MongoDb server.
17+
/// </summary>
18+
/// <returns>The specified connection string.</returns>
19+
public string? GetConnectionString() => _connectionString;
20+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
namespace Aspire.Hosting.ApplicationModel;
5+
6+
/// <summary>
7+
/// A resource that represents a MongoDb container.
8+
/// </summary>
9+
/// <param name="name">The name of the resource.</param>
10+
/// <param name="password">The MongoDb root password.</param>
11+
public class MongoDbContainerResource(string name, string password) : ContainerResource(name), IMongoDbResource
12+
{
13+
public string Password { get; } = password;
14+
15+
/// <summary>
16+
/// Gets the connection string for the MongoDb server.
17+
/// </summary>
18+
/// <returns>A connection string for the MongoDb server in the form "mongodb://host:port".</returns>
19+
public string? GetConnectionString()
20+
{
21+
if (!this.TryGetAllocatedEndPoints(out var allocatedEndpoints))
22+
{
23+
throw new DistributedApplicationException("Expected allocated endpoints!");
24+
}
25+
26+
var allocatedEndpoint = allocatedEndpoints.Single();
27+
28+
return $"mongodb://root:{Password}@{allocatedEndpoint.Address}:{allocatedEndpoint.Port}";
29+
}
30+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
namespace Aspire.Hosting.ApplicationModel;
5+
6+
/// <summary>
7+
/// A resource that represents a MongoDb database. This is a child resource of a <see cref="MongoDbContainerResource"/>.
8+
/// </summary>
9+
/// <param name="name">The name of the resource.</param>
10+
/// <param name="mongoDbContainer">The MongoDb server resource associated with this database.</param>
11+
public class MongoDbDatabaseResource(string name, MongoDbContainerResource mongoDbContainer)
12+
: Resource(name), IMongoDbResource, IResourceWithParent<MongoDbContainerResource>
13+
{
14+
public MongoDbContainerResource Parent => mongoDbContainer;
15+
16+
/// <summary>
17+
/// Gets the connection string for the MongoDb database.
18+
/// </summary>
19+
/// <returns>A connection string for the MongoDb database.</returns>
20+
public string? GetConnectionString()
21+
{
22+
if (Parent.GetConnectionString() is { } connectionString)
23+
{
24+
return $"{connectionString}/{Name}";
25+
}
26+
27+
throw new DistributedApplicationException("Parent resource connection string was null.");
28+
}
29+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>$(NetCurrent)</TargetFramework>
5+
<IsPackable>true</IsPackable>
6+
<PackageTags>$(ComponentDatabasePackageTags) MongoDb</PackageTags>
7+
<Description>A generic MongoDb client that integrates with Aspire.</Description>
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<Compile Include="..\Common\HealthChecksExtensions.cs" Link="HealthChecksExtensions.cs" />
12+
</ItemGroup>
13+
14+
<ItemGroup>
15+
<PackageReference Include="MongoDB.Driver" />
16+
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" />
17+
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" />
18+
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" />
19+
</ItemGroup>
20+
21+
</Project>

0 commit comments

Comments
 (0)