From 3a80354c305e1c0cb31b4e9138a1affb32eeae4c Mon Sep 17 00:00:00 2001 From: Tim Heuer Date: Wed, 7 Feb 2024 18:29:07 -0800 Subject: [PATCH] Adds Mongo Express (#2091) * Adds Mongo Express to MongoDB builder extensions * Move tests due to test refactor * Simplify ctor PR feedback Co-authored-by: David Fowler --------- Co-authored-by: David Fowler --- .../Mongo.ApiService/Mongo.ApiService.http | 5 ++- playground/mongo/Mongo.AppHost/Program.cs | 3 +- .../MongoDB/MongoDBBuilderExtensions.cs | 40 +++++++++++++++++++ .../MongoDB/MongoExpressContainerResource.cs | 9 +++++ .../MongoDB/AddMongoDBTests.cs | 20 ++++++++++ 5 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 src/Aspire.Hosting/MongoDB/MongoExpressContainerResource.cs diff --git a/playground/mongo/Mongo.ApiService/Mongo.ApiService.http b/playground/mongo/Mongo.ApiService/Mongo.ApiService.http index f0fd72181d..e9c1f22113 100644 --- a/playground/mongo/Mongo.ApiService/Mongo.ApiService.http +++ b/playground/mongo/Mongo.ApiService/Mongo.ApiService.http @@ -1,6 +1,7 @@ -@CosmosEndToEnd.ApiService_HostAddress = http://localhost:5301 +@ApiService_HostAddress = http://localhost:5301 -GET {{CosmosEndToEnd.ApiService_HostAddress}}/weatherforecast/ +GET {{ApiService_HostAddress}}/ Accept: application/json ### + diff --git a/playground/mongo/Mongo.AppHost/Program.cs b/playground/mongo/Mongo.AppHost/Program.cs index fad385ca1f..a6b2cb0a6f 100644 --- a/playground/mongo/Mongo.AppHost/Program.cs +++ b/playground/mongo/Mongo.AppHost/Program.cs @@ -3,7 +3,8 @@ var builder = DistributedApplication.CreateBuilder(args); -var db = builder.AddMongoDB("mongo"); +var db = builder.AddMongoDBContainer("mongo") + .WithMongoExpress(); builder.AddProject("api") .WithReference(db); diff --git a/src/Aspire.Hosting/MongoDB/MongoDBBuilderExtensions.cs b/src/Aspire.Hosting/MongoDB/MongoDBBuilderExtensions.cs index 26fe42acd2..fcb54baeee 100644 --- a/src/Aspire.Hosting/MongoDB/MongoDBBuilderExtensions.cs +++ b/src/Aspire.Hosting/MongoDB/MongoDBBuilderExtensions.cs @@ -3,6 +3,7 @@ using System.Net.Sockets; using Aspire.Hosting.ApplicationModel; +using Aspire.Hosting.MongoDB; using Aspire.Hosting.Publishing; namespace Aspire.Hosting; @@ -69,6 +70,45 @@ public static IResourceBuilder AddDatabase(this IResour .WithManifestPublishingCallback(context => context.WriteMongoDBDatabaseToManifest(mongoDBDatabase)); } + /// + /// Adds a MongoExpress administration and development platform for MongoDB to the application model. + /// + /// The MongoDB server resource builder. + /// The host port for the application ui. + /// The name of the container (Optional). + /// A reference to the . + public static IResourceBuilder WithMongoExpress(this IResourceBuilder builder, int? hostPort = null, string? containerName = null) where T : IMongoDBParentResource + { + containerName ??= $"{builder.Resource.Name}-mongoexpress"; + + var mongoExpressContainer = new MongoExpressContainerResource(containerName); + builder.ApplicationBuilder.AddResource(mongoExpressContainer) + .WithAnnotation(new ContainerImageAnnotation { Image = "mongo-express", Tag = "latest" }) + .WithEnvironment(context => ConfigureMongoExpressContainer(context, builder.Resource)) + .WithHttpEndpoint(containerPort: 8081, hostPort: hostPort, name: containerName) + .ExcludeFromManifest(); + + return builder; + } + + private static void ConfigureMongoExpressContainer(EnvironmentCallbackContext context, IResource resource) + { + var hostPort = GetResourcePort(resource); + + context.EnvironmentVariables.Add("ME_CONFIG_MONGODB_URL", $"mongodb://host.docker.internal:{hostPort}/?directConnection=true"); + + static int GetResourcePort(IResource resource) + { + if (!resource.TryGetAllocatedEndPoints(out var allocatedEndpoints)) + { + throw new DistributedApplicationException( + $"MongoDB resource \"{resource.Name}\" does not have endpoint annotation."); + } + + return allocatedEndpoints.Single().Port; + } + } + private static void WriteMongoDBContainerToManifest(this ManifestPublishingContext context, MongoDBContainerResource resource) { context.WriteContainer(resource); diff --git a/src/Aspire.Hosting/MongoDB/MongoExpressContainerResource.cs b/src/Aspire.Hosting/MongoDB/MongoExpressContainerResource.cs new file mode 100644 index 0000000000..77081ec93c --- /dev/null +++ b/src/Aspire.Hosting/MongoDB/MongoExpressContainerResource.cs @@ -0,0 +1,9 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Aspire.Hosting.ApplicationModel; + +namespace Aspire.Hosting.MongoDB; +internal sealed class MongoExpressContainerResource(string name) : ContainerResource(name) +{ +} diff --git a/tests/Aspire.Hosting.Tests/MongoDB/AddMongoDBTests.cs b/tests/Aspire.Hosting.Tests/MongoDB/AddMongoDBTests.cs index 90106d8cd7..51a447d264 100644 --- a/tests/Aspire.Hosting.Tests/MongoDB/AddMongoDBTests.cs +++ b/tests/Aspire.Hosting.Tests/MongoDB/AddMongoDBTests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Net.Sockets; +using Aspire.Hosting.MongoDB; using Microsoft.Extensions.DependencyInjection; using Xunit; @@ -96,4 +97,23 @@ public void MongoDBCreatesConnectionString() Assert.Equal("mongodb://localhost:27017/mydatabase", connectionString); } + + [Fact] + public void WithMongoExpressAddsContainer() + { + var builder = DistributedApplication.CreateBuilder(); + builder.AddMongoDB("mongo").WithMongoExpress(); + + Assert.Single(builder.Resources.OfType()); + } + + [Fact] + public void WithMongoExpressOnMultipleResources() + { + var builder = DistributedApplication.CreateBuilder(); + builder.AddMongoDB("mongo").WithMongoExpress(); + builder.AddMongoDB("mongo2").WithMongoExpress(); + + Assert.Equal(2, builder.Resources.OfType().Count()); + } }