From f0936d9272a2ceb920aefa6e59f5c20234abd9c8 Mon Sep 17 00:00:00 2001 From: Alireza Baloochi Date: Mon, 10 Feb 2025 11:19:14 +0330 Subject: [PATCH] Add DbGate support for MongoDB (#453) * Add DbGate support for MongoDB * Add new package for shared types * Add tests for mongodb exts * Add mongodb readme * Add readme for dbgate package * Add test coverage for using diffent database types with dbgate in same apphost * Update Readme * Update CODEOWNERS * Add shields to README --- CODEOWNERS | 10 +- CommunityToolkit.Aspire.sln | 52 +++++- Directory.Packages.props | 1 + README.md | 12 ++ ...olkit.Aspire.Hosting.DbGate.AppHost.csproj | 22 +++ .../Program.cs | 21 +++ .../Properties/launchSettings.json | 29 +++ .../appsettings.json | 9 + ....Hosting.MongoDB.Extensions.AppHost.csproj | 20 ++ .../Program.cs | 11 ++ .../Properties/launchSettings.json | 29 +++ .../appsettings.json | 9 + .../Program.cs | 2 +- ...munityToolkit.Aspire.Hosting.DbGate.csproj | 16 ++ .../DbGateBuilderExtensions.cs | 3 + .../DbGateContainerImageTags.cs | 0 .../DbGateContainerResource.cs | 0 .../PublicAPI.Shipped.txt | 1 + .../PublicAPI.Unshipped.txt | 8 + .../README.md | 1 + ...t.Aspire.Hosting.MongoDB.Extensions.csproj | 21 +++ .../MongoDBBuilderExtensions.cs | 94 ++++++++++ .../PublicAPI.Shipped.txt | 1 + .../PublicAPI.Unshipped.txt | 2 + .../README.md | 32 ++++ ...spire.Hosting.PostgreSQL.Extensions.csproj | 7 +- .../PublicAPI.Unshipped.txt | 8 - .../AddDbGateTests.cs | 173 ++++++++++++++++++ .../AppHostTests.cs | 20 ++ ...Toolkit.Aspire.Hosting.DbGate.Tests.csproj | 6 +- .../AppHostTests.cs | 20 ++ ...re.Hosting.MongoDB.Extensions.Tests.csproj | 7 + .../ResourceCreationTests.cs | 173 ++++++++++++++++++ 33 files changed, 794 insertions(+), 26 deletions(-) create mode 100644 examples/dbgate/CommunityToolkit.Aspire.Hosting.DbGate.AppHost/CommunityToolkit.Aspire.Hosting.DbGate.AppHost.csproj create mode 100644 examples/dbgate/CommunityToolkit.Aspire.Hosting.DbGate.AppHost/Program.cs create mode 100644 examples/dbgate/CommunityToolkit.Aspire.Hosting.DbGate.AppHost/Properties/launchSettings.json create mode 100644 examples/dbgate/CommunityToolkit.Aspire.Hosting.DbGate.AppHost/appsettings.json create mode 100644 examples/mongodb-ext/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.AppHost/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.AppHost.csproj create mode 100644 examples/mongodb-ext/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.AppHost/Program.cs create mode 100644 examples/mongodb-ext/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.AppHost/Properties/launchSettings.json create mode 100644 examples/mongodb-ext/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.AppHost/appsettings.json create mode 100644 src/CommunityToolkit.Aspire.Hosting.DbGate/CommunityToolkit.Aspire.Hosting.DbGate.csproj rename src/{Shared/dbgate => CommunityToolkit.Aspire.Hosting.DbGate}/DbGateBuilderExtensions.cs (96%) rename src/{Shared/dbgate => CommunityToolkit.Aspire.Hosting.DbGate}/DbGateContainerImageTags.cs (100%) rename src/{Shared/dbgate => CommunityToolkit.Aspire.Hosting.DbGate}/DbGateContainerResource.cs (100%) create mode 100644 src/CommunityToolkit.Aspire.Hosting.DbGate/PublicAPI.Shipped.txt create mode 100644 src/CommunityToolkit.Aspire.Hosting.DbGate/PublicAPI.Unshipped.txt create mode 100644 src/CommunityToolkit.Aspire.Hosting.DbGate/README.md create mode 100644 src/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.csproj create mode 100644 src/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions/MongoDBBuilderExtensions.cs create mode 100644 src/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions/PublicAPI.Shipped.txt create mode 100644 src/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions/PublicAPI.Unshipped.txt create mode 100644 src/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions/README.md create mode 100644 tests/CommunityToolkit.Aspire.Hosting.DbGate.Tests/AppHostTests.cs create mode 100644 tests/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.Tests/AppHostTests.cs create mode 100644 tests/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.Tests/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.Tests.csproj create mode 100644 tests/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.Tests/ResourceCreationTests.cs diff --git a/CODEOWNERS b/CODEOWNERS index 4c1260f6..584706b3 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -83,5 +83,13 @@ /src/CommunityToolkit.Aspire.Hosting.PostgreSQL.Extensions/ @Alirexaa /tests/CommunityToolkit.Aspire.Hosting.PostgreSQL.Extensions.Tests/ @Alirexaa /examples/postgres-ext/ @Alirexaa + +# CommunityToolkit.Aspire.Hosting.DbGate +/src/CommunityToolkit.Aspire.Hosting.DbGate/ @Alirexaa /tests/CommunityToolkit.Aspire.Hosting.DbGate.Tests/ @Alirexaa -/src/Shared/dbgate/ @Alirexaa +/examples/dbgate/ @Alirexaa + +# CommunityToolkit.Aspire.Hosting.MongoDB.Extensions +/src/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions/ @Alirexaa +/tests/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.Tests/ @Alirexaa +/examples/mongodb-ext/ @Alirexaa \ No newline at end of file diff --git a/CommunityToolkit.Aspire.sln b/CommunityToolkit.Aspire.sln index 6b2c05c3..d5289aba 100644 --- a/CommunityToolkit.Aspire.sln +++ b/CommunityToolkit.Aspire.sln @@ -280,6 +280,7 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommunityToolkit.Aspire.Hosting.RavenDB.ServiceDefaults", "examples\ravendb\CommunityToolkit.Aspire.Hosting.RavenDB.ServiceDefaults\CommunityToolkit.Aspire.Hosting.RavenDB.ServiceDefaults.csproj", "{3D076CFF-6482-4126-9F29-C7617E7D2F5B}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommunityToolkit.Aspire.Hosting.RavenDB.ApiService", "examples\ravendb\CommunityToolkit.Aspire.Hosting.RavenDB.ApiService\CommunityToolkit.Aspire.Hosting.RavenDB.ApiService.csproj", "{D214CBF5-D5E4-4641-868D-66B0C5337DD5}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommunityToolkit.Aspire.Hosting.DbGate.Tests", "tests\CommunityToolkit.Aspire.Hosting.DbGate.Tests\CommunityToolkit.Aspire.Hosting.DbGate.Tests.csproj", "{BDAF7D27-C600-4419-9782-CF15BA5272E9}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "postgres-ext", "postgres-ext", "{204BB8D8-04E3-4FE5-BB08-E793BF532F2F}" @@ -302,6 +303,20 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommunityToolkit.Aspire.GoF EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommunityToolkit.Aspire.Hosting.GoFeatureFlag.Tests", "tests\CommunityToolkit.Aspire.Hosting.GoFeatureFlag.Tests\CommunityToolkit.Aspire.Hosting.GoFeatureFlag.Tests.csproj", "{96458513-CAA8-498B-B4EE-3BF994140741}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommunityToolkit.Aspire.Hosting.MongoDB.Extensions", "src\CommunityToolkit.Aspire.Hosting.MongoDB.Extensions\CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.csproj", "{511D321E-277E-465A-AD62-B9971A6DD17E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommunityToolkit.Aspire.Hosting.DbGate", "src\CommunityToolkit.Aspire.Hosting.DbGate\CommunityToolkit.Aspire.Hosting.DbGate.csproj", "{72054ADC-94AC-48D4-9718-72B70E830CD2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.Tests", "tests\CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.Tests\CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.Tests.csproj", "{57EF72E3-24DA-41B3-A3A1-B69E26421F68}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "mongodb-ext", "mongodb-ext", "{8406E585-3329-48C5-B268-8C2140B720B6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.AppHost", "examples\mongodb-ext\CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.AppHost\CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.AppHost.csproj", "{A461FE7E-2458-428C-B794-6CC388031F16}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dbgate", "dbgate", "{50FBAF3E-E0BB-44FF-884F-660357C1CC54}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommunityToolkit.Aspire.Hosting.DbGate.AppHost", "examples\dbgate\CommunityToolkit.Aspire.Hosting.DbGate.AppHost\CommunityToolkit.Aspire.Hosting.DbGate.AppHost.csproj", "{AFEAF08C-4959-4CF2-8806-4E75F8F73B2E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -800,6 +815,26 @@ Global {96458513-CAA8-498B-B4EE-3BF994140741}.Debug|Any CPU.Build.0 = Debug|Any CPU {96458513-CAA8-498B-B4EE-3BF994140741}.Release|Any CPU.ActiveCfg = Release|Any CPU {96458513-CAA8-498B-B4EE-3BF994140741}.Release|Any CPU.Build.0 = Release|Any CPU + {511D321E-277E-465A-AD62-B9971A6DD17E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {511D321E-277E-465A-AD62-B9971A6DD17E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {511D321E-277E-465A-AD62-B9971A6DD17E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {511D321E-277E-465A-AD62-B9971A6DD17E}.Release|Any CPU.Build.0 = Release|Any CPU + {72054ADC-94AC-48D4-9718-72B70E830CD2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {72054ADC-94AC-48D4-9718-72B70E830CD2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {72054ADC-94AC-48D4-9718-72B70E830CD2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {72054ADC-94AC-48D4-9718-72B70E830CD2}.Release|Any CPU.Build.0 = Release|Any CPU + {57EF72E3-24DA-41B3-A3A1-B69E26421F68}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {57EF72E3-24DA-41B3-A3A1-B69E26421F68}.Debug|Any CPU.Build.0 = Debug|Any CPU + {57EF72E3-24DA-41B3-A3A1-B69E26421F68}.Release|Any CPU.ActiveCfg = Release|Any CPU + {57EF72E3-24DA-41B3-A3A1-B69E26421F68}.Release|Any CPU.Build.0 = Release|Any CPU + {A461FE7E-2458-428C-B794-6CC388031F16}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A461FE7E-2458-428C-B794-6CC388031F16}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A461FE7E-2458-428C-B794-6CC388031F16}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A461FE7E-2458-428C-B794-6CC388031F16}.Release|Any CPU.Build.0 = Release|Any CPU + {AFEAF08C-4959-4CF2-8806-4E75F8F73B2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AFEAF08C-4959-4CF2-8806-4E75F8F73B2E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AFEAF08C-4959-4CF2-8806-4E75F8F73B2E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AFEAF08C-4959-4CF2-8806-4E75F8F73B2E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -944,16 +979,6 @@ Global {BDAF7D27-C600-4419-9782-CF15BA5272E9} = {899F0713-7FC6-4750-BAFC-AC650B35B453} {204BB8D8-04E3-4FE5-BB08-E793BF532F2F} = {8519CC01-1370-47C8-AD94-B0F326B1563F} {356853EE-2C47-429C-B6CF-F3F76B6FFD91} = {899F0713-7FC6-4750-BAFC-AC650B35B453} - {BEA41234-DFF9-49AE-AD6C-42A9D54202E7} = {414151D4-7009-4E78-A5C6-D99EBD1E67D1} - {6782F1C1-5146-549F-82A8-60C82F1C7F16} = {8519CC01-1370-47C8-AD94-B0F326B1563F} - {97E455C1-C914-4C51-87A9-2C213CE2ED5B} = {6782F1C1-5146-549F-82A8-60C82F1C7F16} - {5DF8F833-F6F8-4C9C-ABEC-80EC0C734A88} = {414151D4-7009-4E78-A5C6-D99EBD1E67D1} - {E48F6DDD-D62D-4723-810D-0F178C35E8B8} = {6782F1C1-5146-549F-82A8-60C82F1C7F16} - {DD7042A1-8E44-40A8-B338-DC2F7B755702} = {6782F1C1-5146-549F-82A8-60C82F1C7F16} - {E54E9DCA-1420-4306-83B6-D45D6EC49DBF} = {414151D4-7009-4E78-A5C6-D99EBD1E67D1} - {0E6EBCFB-DEF5-496C-95AF-00884826CFC8} = {899F0713-7FC6-4750-BAFC-AC650B35B453} - {861FE61C-90EE-49B0-BCC8-8417C293CC21} = {899F0713-7FC6-4750-BAFC-AC650B35B453} - {52846E18-99D1-4040-AF5F-17FC69198BCE} = {899F0713-7FC6-4750-BAFC-AC650B35B453} {F926FB8A-77C6-4D39-AE44-9A7C11A3202D} = {414151D4-7009-4E78-A5C6-D99EBD1E67D1} {002E2F54-BB99-41F2-98D5-D6CC3B6A2845} = {8519CC01-1370-47C8-AD94-B0F326B1563F} {FE9F4F1A-1115-4F18-96D8-C8A4AD50CDA5} = {002E2F54-BB99-41F2-98D5-D6CC3B6A2845} @@ -962,6 +987,13 @@ Global {C40D5274-DACF-4962-A58A-F08BDA80D0E2} = {414151D4-7009-4E78-A5C6-D99EBD1E67D1} {F4891827-BE07-4547-AF89-2734FB8DE6D5} = {899F0713-7FC6-4750-BAFC-AC650B35B453} {96458513-CAA8-498B-B4EE-3BF994140741} = {899F0713-7FC6-4750-BAFC-AC650B35B453} + {511D321E-277E-465A-AD62-B9971A6DD17E} = {414151D4-7009-4E78-A5C6-D99EBD1E67D1} + {72054ADC-94AC-48D4-9718-72B70E830CD2} = {414151D4-7009-4E78-A5C6-D99EBD1E67D1} + {57EF72E3-24DA-41B3-A3A1-B69E26421F68} = {899F0713-7FC6-4750-BAFC-AC650B35B453} + {8406E585-3329-48C5-B268-8C2140B720B6} = {8519CC01-1370-47C8-AD94-B0F326B1563F} + {A461FE7E-2458-428C-B794-6CC388031F16} = {8406E585-3329-48C5-B268-8C2140B720B6} + {50FBAF3E-E0BB-44FF-884F-660357C1CC54} = {8519CC01-1370-47C8-AD94-B0F326B1563F} + {AFEAF08C-4959-4CF2-8806-4E75F8F73B2E} = {50FBAF3E-E0BB-44FF-884F-660357C1CC54} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {08B1D4B8-D2C5-4A64-BB8B-E1A2B29525F0} diff --git a/Directory.Packages.props b/Directory.Packages.props index fab4ba51..8619e75b 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -12,6 +12,7 @@ + diff --git a/README.md b/README.md index 1ab168f8..aa448bdc 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,8 @@ This repository contains the source code for the .NET Aspire Community Toolkit, | - **Learn More**: [`RavenDB.Client`][ravendb-integration-docs]
- Stable 📦: [![CommunityToolkit.Aspire.RavenDB.Client][ravendb-client-shields]][ravendb-client-nuget]
- Preview 📦: [![CommunityToolkit.Aspire.RavenDB.Client][ravendb-client-shields-preview]][ravendb-client-nuget-preview] | An Aspire client integration for the [RavenDB.Client](https://www.nuget.org/packages/RavenDB.client) package. | | - **Learn More**: [`Hosting.GoFeatureFlag`][go-feature-flag-integration-docs]
- Stable 📦: [![CommunityToolkit.Aspire.Hosting.GoFeatureFlag][go-feature-flag-shields]][go-feature-flag-nuget]
- Preview 📦: [![CommunityToolkit.Aspire.Hosting.GoFeatureFlag][go-feature-flag-shields-preview]][go-feature-flag-nuget-preview] | An Aspire hosting integration leveraging the [GoFeatureFlag](https://gofeatureflag.org/) container. | | - **Learn More**: [`GoFeatureFlag`][go-feature-flag-integration-docs]
- Stable 📦: [![CommunityToolkit.Aspire.GoFeatureFlag][go-feature-flag-client-shields]][go-feature-flag-client-nuget]
- Preview 📦: [![CommunityToolkit.Aspire.GoFeatureFlag][go-feature-flag-client-shields-preview]][go-feature-flag-client-nuget-preview] | An Aspire client integration for the [GoFeatureFlag](https://github.com/open-feature/dotnet-sdk-contrib/tree/main/src/OpenFeature.Contrib.Providers.GOFeatureFlag) package. | +| - **Learn More**: [`Hosting.MongoDB.Extensions`][mongodb-ext-integration-docs]
- Stable 📦: [![CommunityToolkit.Aspire.MongoDB.Extensions][mongodb-ext-shields]][mongodb-ext-nuget]
- Preview 📦: [![CommunityToolkit.Aspire.Hosting.MongoDB.Extensions][mongodb-ext-shields-preview]][mongodb-ext-nuget-preview] | An integration that contains some additional extensions for hosting MongoDB container. | +| - **Learn More**: [`Hosting.PostgreSQL.Extensions`][postgres-ext-integration-docs]
- Stable 📦: [![CommunityToolkit.Aspire.PostgreSQL.Extensions][postgres-ext-shields]][postgres-ext-nuget]
- Preview 📦: [![CommunityToolkit.Aspire.Hosting.PostgreSQL.Extensions][postgres-ext-shields-preview]][postgres-ext-nuget-preview] | An integration that contains some additional extensions for hosting MongoDB container. | ## 🙌 Getting Started @@ -204,3 +206,13 @@ This project is supported by the [.NET Foundation](https://dotnetfoundation.org) [go-feature-flag-client-nuget]: https://nuget.org/packages/CommunityToolkit.Aspire.GoFeatureFlag/ [go-feature-flag-client-shields-preview]: https://img.shields.io/nuget/vpre/CommunityToolkit.Aspire.GoFeatureFlag?label=nuget%20(preview) [go-feature-flag-client-nuget-preview]: https://nuget.org/packages/CommunityToolkit.Aspire.GoFeatureFlag/absoluteLatest +[mongodb-ext-integration-docs]: https://learn.microsoft.com/dotnet/aspire/community-toolkit/hosting-mongodb-extensions +[mongodb-ext-shields]: https://img.shields.io/nuget/v/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions +[mongodb-ext-nuget]: https://nuget.org/packages/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions/ +[mongodb-ext-shields-preview]: https://img.shields.io/nuget/vpre/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions?label=nuget%20(preview) +[mongodb-ext-nuget-preview]: https://nuget.org/packages/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions/absoluteLatest +[postgres-ext-integration-docs]: https://learn.microsoft.com/dotnet/aspire/community-toolkit/hosting-postgres-extensions +[postgres-ext-shields]: https://img.shields.io/nuget/v/CommunityToolkit.Aspire.Hosting.PostgreSQL.Extensions +[postgres-ext-nuget]: https://nuget.org/packages/CommunityToolkit.Aspire.Hosting.PostgreSQL.Extensions/ +[postgres-ext-shields-preview]: https://img.shields.io/nuget/vpre/CommunityToolkit.Aspire.Hosting.PostgreSQL.Extensions?label=nuget%20(preview) +[postgres-ext-nuget-preview]: https://nuget.org/packages/CommunityToolkit.Aspire.Hosting.PostgreSQL.Extensions/absoluteLatest diff --git a/examples/dbgate/CommunityToolkit.Aspire.Hosting.DbGate.AppHost/CommunityToolkit.Aspire.Hosting.DbGate.AppHost.csproj b/examples/dbgate/CommunityToolkit.Aspire.Hosting.DbGate.AppHost/CommunityToolkit.Aspire.Hosting.DbGate.AppHost.csproj new file mode 100644 index 00000000..84e37e61 --- /dev/null +++ b/examples/dbgate/CommunityToolkit.Aspire.Hosting.DbGate.AppHost/CommunityToolkit.Aspire.Hosting.DbGate.AppHost.csproj @@ -0,0 +1,22 @@ + + + + + Exe + enable + enable + true + + + + + + + + + + + + + + diff --git a/examples/dbgate/CommunityToolkit.Aspire.Hosting.DbGate.AppHost/Program.cs b/examples/dbgate/CommunityToolkit.Aspire.Hosting.DbGate.AppHost/Program.cs new file mode 100644 index 00000000..c6e37237 --- /dev/null +++ b/examples/dbgate/CommunityToolkit.Aspire.Hosting.DbGate.AppHost/Program.cs @@ -0,0 +1,21 @@ +var builder = DistributedApplication.CreateBuilder(args); + +var postgres1 = builder.AddPostgres("postgres1") + .WithDbGate(c => c.WithHostPort(8068)); +postgres1.AddDatabase("db1"); +postgres1.AddDatabase("db2"); + +var postgres2 = builder.AddPostgres("postgres2") + .WithDbGate(); +postgres2.AddDatabase("db3"); +postgres2.AddDatabase("db4"); + +var mongodb1 = builder.AddMongoDB("mongodb1").WithDbGate(); +mongodb1.AddDatabase("db5"); +mongodb1.AddDatabase("db6"); + +var mongodb2 = builder.AddMongoDB("mongodb2").WithDbGate(); +mongodb2.AddDatabase("db7"); +mongodb2.AddDatabase("db8"); + +builder.Build().Run(); \ No newline at end of file diff --git a/examples/dbgate/CommunityToolkit.Aspire.Hosting.DbGate.AppHost/Properties/launchSettings.json b/examples/dbgate/CommunityToolkit.Aspire.Hosting.DbGate.AppHost/Properties/launchSettings.json new file mode 100644 index 00000000..00e91269 --- /dev/null +++ b/examples/dbgate/CommunityToolkit.Aspire.Hosting.DbGate.AppHost/Properties/launchSettings.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "https://localhost:17202;http://localhost:15211", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "DOTNET_ENVIRONMENT": "Development", + "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21182", + "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:22097" + } + }, + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "http://localhost:15211", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "DOTNET_ENVIRONMENT": "Development", + "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:19298", + "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:20141" + } + } + } +} diff --git a/examples/dbgate/CommunityToolkit.Aspire.Hosting.DbGate.AppHost/appsettings.json b/examples/dbgate/CommunityToolkit.Aspire.Hosting.DbGate.AppHost/appsettings.json new file mode 100644 index 00000000..31c092aa --- /dev/null +++ b/examples/dbgate/CommunityToolkit.Aspire.Hosting.DbGate.AppHost/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning", + "Aspire.Hosting.Dcp": "Warning" + } + } +} diff --git a/examples/mongodb-ext/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.AppHost/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.AppHost.csproj b/examples/mongodb-ext/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.AppHost/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.AppHost.csproj new file mode 100644 index 00000000..a1ea1e7c --- /dev/null +++ b/examples/mongodb-ext/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.AppHost/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.AppHost.csproj @@ -0,0 +1,20 @@ + + + + + Exe + enable + enable + true + + + + + + + + + + + + diff --git a/examples/mongodb-ext/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.AppHost/Program.cs b/examples/mongodb-ext/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.AppHost/Program.cs new file mode 100644 index 00000000..b8abdf46 --- /dev/null +++ b/examples/mongodb-ext/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.AppHost/Program.cs @@ -0,0 +1,11 @@ +var builder = DistributedApplication.CreateBuilder(args); + +var mongodb1 = builder.AddMongoDB("mongodb1").WithDbGate(c => c.WithHostPort(8090)); +mongodb1.AddDatabase("db1"); +mongodb1.AddDatabase("db2"); + +var mongodb2 = builder.AddMongoDB("mongodb2").WithDbGate(); +mongodb2.AddDatabase("db3"); +mongodb2.AddDatabase("db4"); + +builder.Build().Run(); diff --git a/examples/mongodb-ext/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.AppHost/Properties/launchSettings.json b/examples/mongodb-ext/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.AppHost/Properties/launchSettings.json new file mode 100644 index 00000000..cad6fa6a --- /dev/null +++ b/examples/mongodb-ext/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.AppHost/Properties/launchSettings.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "https://localhost:17058;http://localhost:15268", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "DOTNET_ENVIRONMENT": "Development", + "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21178", + "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:22264" + } + }, + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "http://localhost:15268", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "DOTNET_ENVIRONMENT": "Development", + "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:19258", + "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:20169" + } + } + } +} diff --git a/examples/mongodb-ext/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.AppHost/appsettings.json b/examples/mongodb-ext/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.AppHost/appsettings.json new file mode 100644 index 00000000..31c092aa --- /dev/null +++ b/examples/mongodb-ext/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.AppHost/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning", + "Aspire.Hosting.Dcp": "Warning" + } + } +} diff --git a/examples/postgres-ext/CommunityToolkit.Aspire.Hosting.PostgreSQL.Extensions.AppHost/Program.cs b/examples/postgres-ext/CommunityToolkit.Aspire.Hosting.PostgreSQL.Extensions.AppHost/Program.cs index b0d368c9..ffe82f81 100644 --- a/examples/postgres-ext/CommunityToolkit.Aspire.Hosting.PostgreSQL.Extensions.AppHost/Program.cs +++ b/examples/postgres-ext/CommunityToolkit.Aspire.Hosting.PostgreSQL.Extensions.AppHost/Program.cs @@ -1,7 +1,7 @@ var builder = DistributedApplication.CreateBuilder(args); var postgres1 = builder.AddPostgres("postgres1") - .WithDbGate(c=> c.WithHostPort(8068)); + .WithDbGate(c => c.WithHostPort(8068)); postgres1.AddDatabase("db1"); postgres1.AddDatabase("db2"); diff --git a/src/CommunityToolkit.Aspire.Hosting.DbGate/CommunityToolkit.Aspire.Hosting.DbGate.csproj b/src/CommunityToolkit.Aspire.Hosting.DbGate/CommunityToolkit.Aspire.Hosting.DbGate.csproj new file mode 100644 index 00000000..43aa0633 --- /dev/null +++ b/src/CommunityToolkit.Aspire.Hosting.DbGate/CommunityToolkit.Aspire.Hosting.DbGate.csproj @@ -0,0 +1,16 @@ + + + + hosting dbgate + A .NET Aspire integration for dbgate hosting. + + + + + + + + + + + diff --git a/src/Shared/dbgate/DbGateBuilderExtensions.cs b/src/CommunityToolkit.Aspire.Hosting.DbGate/DbGateBuilderExtensions.cs similarity index 96% rename from src/Shared/dbgate/DbGateBuilderExtensions.cs rename to src/CommunityToolkit.Aspire.Hosting.DbGate/DbGateBuilderExtensions.cs index 122ceb8b..978aeb26 100644 --- a/src/Shared/dbgate/DbGateBuilderExtensions.cs +++ b/src/CommunityToolkit.Aspire.Hosting.DbGate/DbGateBuilderExtensions.cs @@ -62,6 +62,9 @@ public static IResourceBuilder WithDataBindMount(this I /// The resource builder. /// The name of the resource. This name will be used as the connection string name when referenced in a dependency. /// The host port to bind the underlying container to. + /// + /// Multiple calls will return the same resource builder instance. + /// /// A reference to the . public static IResourceBuilder AddDbGate(this IDistributedApplicationBuilder builder, [ResourceName] string name, int? port = null) { diff --git a/src/Shared/dbgate/DbGateContainerImageTags.cs b/src/CommunityToolkit.Aspire.Hosting.DbGate/DbGateContainerImageTags.cs similarity index 100% rename from src/Shared/dbgate/DbGateContainerImageTags.cs rename to src/CommunityToolkit.Aspire.Hosting.DbGate/DbGateContainerImageTags.cs diff --git a/src/Shared/dbgate/DbGateContainerResource.cs b/src/CommunityToolkit.Aspire.Hosting.DbGate/DbGateContainerResource.cs similarity index 100% rename from src/Shared/dbgate/DbGateContainerResource.cs rename to src/CommunityToolkit.Aspire.Hosting.DbGate/DbGateContainerResource.cs diff --git a/src/CommunityToolkit.Aspire.Hosting.DbGate/PublicAPI.Shipped.txt b/src/CommunityToolkit.Aspire.Hosting.DbGate/PublicAPI.Shipped.txt new file mode 100644 index 00000000..7dc5c581 --- /dev/null +++ b/src/CommunityToolkit.Aspire.Hosting.DbGate/PublicAPI.Shipped.txt @@ -0,0 +1 @@ +#nullable enable diff --git a/src/CommunityToolkit.Aspire.Hosting.DbGate/PublicAPI.Unshipped.txt b/src/CommunityToolkit.Aspire.Hosting.DbGate/PublicAPI.Unshipped.txt new file mode 100644 index 00000000..da1165fe --- /dev/null +++ b/src/CommunityToolkit.Aspire.Hosting.DbGate/PublicAPI.Unshipped.txt @@ -0,0 +1,8 @@ +Aspire.Hosting.ApplicationModel.DbGateContainerResource +Aspire.Hosting.ApplicationModel.DbGateContainerResource.DbGateContainerResource(string! name) -> void +Aspire.Hosting.ApplicationModel.DbGateContainerResource.PrimaryEndpoint.get -> Aspire.Hosting.ApplicationModel.EndpointReference! +Aspire.Hosting.DbGateBuilderExtensions +static Aspire.Hosting.DbGateBuilderExtensions.AddDbGate(this Aspire.Hosting.IDistributedApplicationBuilder! builder, string! name, int? port = null) -> Aspire.Hosting.ApplicationModel.IResourceBuilder! +static Aspire.Hosting.DbGateBuilderExtensions.WithDataBindMount(this Aspire.Hosting.ApplicationModel.IResourceBuilder! builder, string! source, bool isReadOnly = false) -> Aspire.Hosting.ApplicationModel.IResourceBuilder! +static Aspire.Hosting.DbGateBuilderExtensions.WithDataVolume(this Aspire.Hosting.ApplicationModel.IResourceBuilder! builder, string? name = null, bool isReadOnly = false) -> Aspire.Hosting.ApplicationModel.IResourceBuilder! +static Aspire.Hosting.DbGateBuilderExtensions.WithHostPort(this Aspire.Hosting.ApplicationModel.IResourceBuilder! builder, int? port) -> Aspire.Hosting.ApplicationModel.IResourceBuilder! \ No newline at end of file diff --git a/src/CommunityToolkit.Aspire.Hosting.DbGate/README.md b/src/CommunityToolkit.Aspire.Hosting.DbGate/README.md new file mode 100644 index 00000000..7b5d65ce --- /dev/null +++ b/src/CommunityToolkit.Aspire.Hosting.DbGate/README.md @@ -0,0 +1 @@ +This package is designed to be used internally by the community toolkit and is not intended to be used directly in the application code. diff --git a/src/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.csproj b/src/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.csproj new file mode 100644 index 00000000..6eeefb08 --- /dev/null +++ b/src/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.csproj @@ -0,0 +1,21 @@ + + + + hosting mongodb dbgate + A .NET Aspire integration for extending mongodb hosting. + + + + + + + + + + + + + + + + diff --git a/src/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions/MongoDBBuilderExtensions.cs b/src/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions/MongoDBBuilderExtensions.cs new file mode 100644 index 00000000..43088201 --- /dev/null +++ b/src/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions/MongoDBBuilderExtensions.cs @@ -0,0 +1,94 @@ +using Aspire.Hosting.ApplicationModel; +using System.Text; + +namespace Aspire.Hosting; + +/// +/// Provides extension methods for adding MongoDB resources to an . +/// +public static class MongoDBBuilderExtensions +{ + /// + /// Adds an administration and development platform for MongoDB to the application model using DbGate. + /// + /// + /// This version of the package defaults to the tag of the container image. + /// + /// The MongoDB server resource builder. + /// Configuration callback for DbGate container resource. + /// The name of the container (Optional). + /// + /// Use in application host with a MongoDB resource + /// + /// var builder = DistributedApplication.CreateBuilder(args); + /// + /// var mongodb = builder.AddMongoDB("mongodb") + /// .WithDbGate(); + /// var db = mongodb.AddDatabase("db"); + /// + /// var api = builder.AddProject<Projects.Api>("api") + /// .WithReference(db); + /// + /// builder.Build().Run(); + /// + /// + /// A reference to the . + public static IResourceBuilder WithDbGate(this IResourceBuilder builder, Action>? configureContainer = null, string? containerName = null) + { + ArgumentNullException.ThrowIfNull(builder); + + containerName ??= $"{builder.Resource.Name}-dbgate"; + + var dbGateBuilder = DbGateBuilderExtensions.AddDbGate(builder.ApplicationBuilder, containerName); + + dbGateBuilder + .WithEnvironment(context => ConfigureDbGateContainer(context, builder.ApplicationBuilder)) + .WaitFor(builder); + + configureContainer?.Invoke(dbGateBuilder); + + return builder; + } + + private static void ConfigureDbGateContainer(EnvironmentCallbackContext context, IDistributedApplicationBuilder applicationBuilder) + { + var mongoDBInstances = applicationBuilder.Resources.OfType(); + + var counter = 1; + + // Multiple WithDbGate calls will be ignored + if (context.EnvironmentVariables.ContainsKey($"LABEL_mongodb{counter}")) + { + return; + } + + foreach (var mongoDBServer in mongoDBInstances) + { + // DbGate assumes MongoDB is being accessed over a default Aspire container network and hardcodes the resource address + // This will need to be refactored once updated service discovery APIs are available + context.EnvironmentVariables.Add($"LABEL_mongodb{counter}", mongoDBServer.Name); + context.EnvironmentVariables.Add($"URL_mongodb{counter}", mongoDBServer.ConnectionStringExpression); + context.EnvironmentVariables.Add($"ENGINE_mongodb{counter}", "mongo@dbgate-plugin-mongo"); + + counter++; + } + + var instancesCount = mongoDBInstances.Count(); + if (instancesCount > 0) + { + var strBuilder = new StringBuilder(); + strBuilder.AppendJoin(',', Enumerable.Range(1, instancesCount).Select(i => $"mongodb{i}")); + var connections = strBuilder.ToString(); + + string CONNECTIONS = context.EnvironmentVariables.GetValueOrDefault("CONNECTIONS")?.ToString() ?? string.Empty; + if (string.IsNullOrEmpty(CONNECTIONS)) + { + context.EnvironmentVariables["CONNECTIONS"] = connections; + } + else + { + context.EnvironmentVariables["CONNECTIONS"] += $",{connections}"; + } + } + } +} \ No newline at end of file diff --git a/src/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions/PublicAPI.Shipped.txt b/src/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions/PublicAPI.Shipped.txt new file mode 100644 index 00000000..7dc5c581 --- /dev/null +++ b/src/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions/PublicAPI.Shipped.txt @@ -0,0 +1 @@ +#nullable enable diff --git a/src/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions/PublicAPI.Unshipped.txt b/src/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions/PublicAPI.Unshipped.txt new file mode 100644 index 00000000..740a292b --- /dev/null +++ b/src/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions/PublicAPI.Unshipped.txt @@ -0,0 +1,2 @@ +Aspire.Hosting.MongoDBBuilderExtensions +static Aspire.Hosting.MongoDBBuilderExtensions.WithDbGate(this Aspire.Hosting.ApplicationModel.IResourceBuilder! builder, System.Action!>? configureContainer = null, string? containerName = null) -> Aspire.Hosting.ApplicationModel.IResourceBuilder! \ No newline at end of file diff --git a/src/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions/README.md b/src/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions/README.md new file mode 100644 index 00000000..4f05d2be --- /dev/null +++ b/src/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions/README.md @@ -0,0 +1,32 @@ +# CommunityToolkit.Aspire.Hosting.MongoDB.Extensions library + +This integration contains extensions for the [MongoDB hosting package](https://nuget.org/packages/Aspire.Hosting.MongoDB) for .NET Aspire. + +The integration provides support for running [DbGate](https://github.com/dbgate/dbgate) to interact with the MongoDB database. + +## Getting Started + +### Install the package + +In your AppHost project, install the package using the following command: + +```dotnetcli +dotnet add package CommunityToolkit.Aspire.Hosting.MongoDB.Extensions +``` + +### Example usage + +Then, in the _Program.cs_ file of `AppHost`, define an MongoDB resource, then call `AddMongoDB`: + +```csharp +var mongodb = builder.AddMongoDB("mongodb") + .WithDbGate(); +``` + +## Additional Information + +https://learn.microsoft.com/dotnet/aspire/community-toolkit/hosting-mongodb-extensions + +## Feedback & contributing + +https://github.com/CommunityToolkit/Aspire \ No newline at end of file diff --git a/src/CommunityToolkit.Aspire.Hosting.PostgreSQL.Extensions/CommunityToolkit.Aspire.Hosting.PostgreSQL.Extensions.csproj b/src/CommunityToolkit.Aspire.Hosting.PostgreSQL.Extensions/CommunityToolkit.Aspire.Hosting.PostgreSQL.Extensions.csproj index f0db8c3c..6b738bac 100644 --- a/src/CommunityToolkit.Aspire.Hosting.PostgreSQL.Extensions/CommunityToolkit.Aspire.Hosting.PostgreSQL.Extensions.csproj +++ b/src/CommunityToolkit.Aspire.Hosting.PostgreSQL.Extensions/CommunityToolkit.Aspire.Hosting.PostgreSQL.Extensions.csproj @@ -12,9 +12,10 @@ - - - + + + + diff --git a/src/CommunityToolkit.Aspire.Hosting.PostgreSQL.Extensions/PublicAPI.Unshipped.txt b/src/CommunityToolkit.Aspire.Hosting.PostgreSQL.Extensions/PublicAPI.Unshipped.txt index 749bc5dd..0fa5e608 100644 --- a/src/CommunityToolkit.Aspire.Hosting.PostgreSQL.Extensions/PublicAPI.Unshipped.txt +++ b/src/CommunityToolkit.Aspire.Hosting.PostgreSQL.Extensions/PublicAPI.Unshipped.txt @@ -1,10 +1,2 @@ -Aspire.Hosting.ApplicationModel.DbGateContainerResource -Aspire.Hosting.ApplicationModel.DbGateContainerResource.DbGateContainerResource(string! name) -> void -Aspire.Hosting.ApplicationModel.DbGateContainerResource.PrimaryEndpoint.get -> Aspire.Hosting.ApplicationModel.EndpointReference! -Aspire.Hosting.DbGateBuilderExtensions Aspire.Hosting.PostgresBuilderExtensions -static Aspire.Hosting.DbGateBuilderExtensions.AddDbGate(this Aspire.Hosting.IDistributedApplicationBuilder! builder, string! name, int? port = null) -> Aspire.Hosting.ApplicationModel.IResourceBuilder! -static Aspire.Hosting.DbGateBuilderExtensions.WithDataBindMount(this Aspire.Hosting.ApplicationModel.IResourceBuilder! builder, string! source, bool isReadOnly = false) -> Aspire.Hosting.ApplicationModel.IResourceBuilder! -static Aspire.Hosting.DbGateBuilderExtensions.WithDataVolume(this Aspire.Hosting.ApplicationModel.IResourceBuilder! builder, string? name = null, bool isReadOnly = false) -> Aspire.Hosting.ApplicationModel.IResourceBuilder! -static Aspire.Hosting.DbGateBuilderExtensions.WithHostPort(this Aspire.Hosting.ApplicationModel.IResourceBuilder! builder, int? port) -> Aspire.Hosting.ApplicationModel.IResourceBuilder! static Aspire.Hosting.PostgresBuilderExtensions.WithDbGate(this Aspire.Hosting.ApplicationModel.IResourceBuilder! builder, System.Action!>? configureContainer = null, string? containerName = null) -> Aspire.Hosting.ApplicationModel.IResourceBuilder! \ No newline at end of file diff --git a/tests/CommunityToolkit.Aspire.Hosting.DbGate.Tests/AddDbGateTests.cs b/tests/CommunityToolkit.Aspire.Hosting.DbGate.Tests/AddDbGateTests.cs index ded8bbad..57e85db2 100644 --- a/tests/CommunityToolkit.Aspire.Hosting.DbGate.Tests/AddDbGateTests.cs +++ b/tests/CommunityToolkit.Aspire.Hosting.DbGate.Tests/AddDbGateTests.cs @@ -169,4 +169,177 @@ public void VerifyWithData(bool useVolume) Assert.False(mountAnnotation.IsReadOnly); } } + + [Fact] + public async Task WithDbGateShouldAddAnnotationsForMultipleDatabaseTypes() + { + var builder = DistributedApplication.CreateBuilder(); + + var mongodbResourceBuilder1 = builder.AddMongoDB("mongodb1") + .WithEndpoint("tcp", e => e.AllocatedEndpoint = new AllocatedEndpoint(e, "localhost", 27017)) + .WithDbGate(); + + var mongodbResource1 = mongodbResourceBuilder1.Resource; + + var mongodbResourceBuilder2 = builder.AddMongoDB("mongodb2") + .WithEndpoint("tcp", e => e.AllocatedEndpoint = new AllocatedEndpoint(e, "localhost", 27018)) + .WithDbGate(); + + var mongodbResource2 = mongodbResourceBuilder2.Resource; + + var postgresResourceBuilder1 = builder.AddPostgres("postgres1") + .WithDbGate(); + + var postgresResource1 = postgresResourceBuilder1.Resource; + + var postgresResourceBuilder2 = builder.AddPostgres("postgres2") + .WithDbGate(); + + var postgresResource2 = postgresResourceBuilder2.Resource; + + using var app = builder.Build(); + + var appModel = app.Services.GetRequiredService(); + + var dbGateResource = appModel.Resources.OfType().SingleOrDefault(); + + Assert.NotNull(dbGateResource); + + Assert.Equal("mongodb1-dbgate", dbGateResource.Name); + + var envs = await dbGateResource.GetEnvironmentVariableValuesAsync(); + + Assert.NotEmpty(envs); + Assert.Collection(envs, + item => + { + Assert.Equal("LABEL_mongodb1", item.Key); + Assert.Equal(mongodbResource1.Name, item.Value); + }, + async item => + { + Assert.Equal("URL_mongodb1", item.Key); + Assert.Equal(await mongodbResource1.ConnectionStringExpression.GetValueAsync(default), item.Value); + }, + item => + { + Assert.Equal("ENGINE_mongodb1", item.Key); + Assert.Equal("mongo@dbgate-plugin-mongo", item.Value); + }, + item => + { + Assert.Equal("LABEL_mongodb2", item.Key); + Assert.Equal(mongodbResource2.Name, item.Value); + }, + async item => + { + Assert.Equal("URL_mongodb2", item.Key); + Assert.Equal(await mongodbResource2.ConnectionStringExpression.GetValueAsync(default), item.Value); + }, + item => + { + Assert.Equal("ENGINE_mongodb2", item.Key); + Assert.Equal("mongo@dbgate-plugin-mongo", item.Value); + }, + item => + { + Assert.Equal("CONNECTIONS", item.Key); + Assert.Equal("mongodb1,mongodb2,postgres1,postgres2", item.Value); + }, + item => + { + Assert.Equal("LABEL_postgres1", item.Key); + Assert.Equal(postgresResource1.Name, item.Value); + }, + item => + { + Assert.Equal("SERVER_postgres1", item.Key); + Assert.Equal(postgresResource1.Name, item.Value); + }, + item => + { + Assert.Equal("USER_postgres1", item.Key); + Assert.Equal("postgres", item.Value); + }, + item => + { + Assert.Equal("PASSWORD_postgres1", item.Key); + Assert.Equal(postgresResource1.PasswordParameter.Value, item.Value); + }, + item => + { + Assert.Equal("PORT_postgres1", item.Key); + Assert.Equal(postgresResource1.PrimaryEndpoint.TargetPort.ToString(), item.Value); + }, + item => + { + Assert.Equal("ENGINE_postgres1", item.Key); + Assert.Equal("postgres@dbgate-plugin-postgres", item.Value); + }, + item => + { + Assert.Equal("LABEL_postgres2", item.Key); + Assert.Equal(postgresResource2.Name, item.Value); + }, + item => + { + Assert.Equal("SERVER_postgres2", item.Key); + Assert.Equal(postgresResource2.Name, item.Value); + }, + item => + { + Assert.Equal("USER_postgres2", item.Key); + Assert.Equal("postgres", item.Value); + }, + item => + { + Assert.Equal("PASSWORD_postgres2", item.Key); + Assert.Equal(postgresResource2.PasswordParameter.Value, item.Value); + }, + item => + { + Assert.Equal("PORT_postgres2", item.Key); + Assert.Equal(postgresResource2.PrimaryEndpoint.TargetPort.ToString(), item.Value); + }, + item => + { + Assert.Equal("ENGINE_postgres2", item.Key); + Assert.Equal("postgres@dbgate-plugin-postgres", item.Value); + }); + } + + [Fact] + public void WithDbGateShouldShouldAddOneDbGateResourceForMultipleDatabaseTypes() + { + var builder = DistributedApplication.CreateBuilder(); + + var mongodbResourceBuilder1 = builder.AddMongoDB("mongodb1") + .WithDbGate(); + + var mongodbResource1 = mongodbResourceBuilder1.Resource; + + var mongodbResourceBuilder2 = builder.AddMongoDB("mongodb2") + .WithDbGate(); + + var mongodbResource2 = mongodbResourceBuilder2.Resource; + + var postgresResourceBuilder1 = builder.AddPostgres("postgres1") + .WithDbGate(); + + var postgresResource1 = postgresResourceBuilder1.Resource; + + var postgresResourceBuilder2 = builder.AddPostgres("postgres2") + .WithDbGate(); + + var postgresResource2 = postgresResourceBuilder2.Resource; + + using var app = builder.Build(); + + var appModel = app.Services.GetRequiredService(); + + var dbGateResource = appModel.Resources.OfType().SingleOrDefault(); + + var containerResource = Assert.Single(appModel.Resources.OfType()); + Assert.Equal("mongodb1-dbgate", containerResource.Name); + } } diff --git a/tests/CommunityToolkit.Aspire.Hosting.DbGate.Tests/AppHostTests.cs b/tests/CommunityToolkit.Aspire.Hosting.DbGate.Tests/AppHostTests.cs new file mode 100644 index 00000000..25c4250e --- /dev/null +++ b/tests/CommunityToolkit.Aspire.Hosting.DbGate.Tests/AppHostTests.cs @@ -0,0 +1,20 @@ +using CommunityToolkit.Aspire.Testing; +using Aspire.Components.Common.Tests; + +namespace CommunityToolkit.Aspire.Hosting.DbGate.Tests; + +[RequiresDocker] +public class AppHostTests(AspireIntegrationTestFixture fixture) : IClassFixture> +{ + [Fact] + public async Task ResourceStartsAndRespondsOk() + { + var resourceName = "postgres1-dbgate"; + await fixture.ResourceNotificationService.WaitForResourceHealthyAsync(resourceName).WaitAsync(TimeSpan.FromMinutes(5)); + var httpClient = fixture.CreateHttpClient(resourceName); + + var response = await httpClient.GetAsync("/"); + + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + } +} \ No newline at end of file diff --git a/tests/CommunityToolkit.Aspire.Hosting.DbGate.Tests/CommunityToolkit.Aspire.Hosting.DbGate.Tests.csproj b/tests/CommunityToolkit.Aspire.Hosting.DbGate.Tests/CommunityToolkit.Aspire.Hosting.DbGate.Tests.csproj index 1d03f7f9..5f9c01c7 100644 --- a/tests/CommunityToolkit.Aspire.Hosting.DbGate.Tests/CommunityToolkit.Aspire.Hosting.DbGate.Tests.csproj +++ b/tests/CommunityToolkit.Aspire.Hosting.DbGate.Tests/CommunityToolkit.Aspire.Hosting.DbGate.Tests.csproj @@ -1,11 +1,11 @@  + + - - - + diff --git a/tests/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.Tests/AppHostTests.cs b/tests/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.Tests/AppHostTests.cs new file mode 100644 index 00000000..ecb50be9 --- /dev/null +++ b/tests/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.Tests/AppHostTests.cs @@ -0,0 +1,20 @@ +using CommunityToolkit.Aspire.Testing; +using Aspire.Components.Common.Tests; + +namespace CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.Tests; + +[RequiresDocker] +public class AppHostTests(AspireIntegrationTestFixture fixture) : IClassFixture> +{ + [Fact] + public async Task ResourceStartsAndRespondsOk() + { + var resourceName = "mongodb1-dbgate"; + await fixture.ResourceNotificationService.WaitForResourceHealthyAsync(resourceName).WaitAsync(TimeSpan.FromMinutes(5)); + var httpClient = fixture.CreateHttpClient(resourceName); + + var response = await httpClient.GetAsync("/"); + + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + } +} \ No newline at end of file diff --git a/tests/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.Tests/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.Tests.csproj b/tests/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.Tests/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.Tests.csproj new file mode 100644 index 00000000..8f041930 --- /dev/null +++ b/tests/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.Tests/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.Tests.csproj @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tests/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.Tests/ResourceCreationTests.cs b/tests/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.Tests/ResourceCreationTests.cs new file mode 100644 index 00000000..bef81aba --- /dev/null +++ b/tests/CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.Tests/ResourceCreationTests.cs @@ -0,0 +1,173 @@ +using Aspire.Hosting; + +namespace CommunityToolkit.Aspire.Hosting.MongoDB.Extensions.Tests; + +public class ResourceCreationTests +{ + [Fact] + public async Task WithDbGateAddsAnnotations() + { + var builder = DistributedApplication.CreateBuilder(); + + var mongodbResourceBuilder = builder.AddMongoDB("mongodb") + .WithEndpoint("tcp", e => e.AllocatedEndpoint = new AllocatedEndpoint(e, "localhost", 27017)) + .WithDbGate(); + + var mongodbResource = mongodbResourceBuilder.Resource; + + using var app = builder.Build(); + + var appModel = app.Services.GetRequiredService(); + + var dbGateResource = appModel.Resources.OfType().SingleOrDefault(); + + Assert.NotNull(dbGateResource); + + Assert.Equal("mongodb-dbgate", dbGateResource.Name); + + var envs = await dbGateResource.GetEnvironmentVariableValuesAsync(); + + Assert.NotEmpty(envs); + Assert.Collection(envs, + item => + { + Assert.Equal("LABEL_mongodb1", item.Key); + Assert.Equal(mongodbResource.Name, item.Value); + }, + async item => + { + Assert.Equal("URL_mongodb1", item.Key); + Assert.Equal(await mongodbResource.ConnectionStringExpression.GetValueAsync(default), item.Value); + }, + item => + { + Assert.Equal("ENGINE_mongodb1", item.Key); + Assert.Equal("mongo@dbgate-plugin-mongo", item.Value); + }, + item => + { + Assert.Equal("CONNECTIONS", item.Key); + Assert.Equal("mongodb1", item.Value); + }); + } + + [Fact] + public void MultipleWithDbGateCallsAddsOneDbGateResource() + { + var builder = DistributedApplication.CreateBuilder(); + builder.AddMongoDB("mongodb1").WithDbGate(); + builder.AddMongoDB("mongodb2").WithDbGate(); + + using var app = builder.Build(); + + var appModel = app.Services.GetRequiredService(); + + var dbGateResource = appModel.Resources.OfType().SingleOrDefault(); + Assert.NotNull(dbGateResource); + + Assert.Equal("mongodb1-dbgate", dbGateResource.Name); + } + + [Fact] + public void WithDbGateShouldChangeDbGateHostPort() + { + var builder = DistributedApplication.CreateBuilder(); + var mongodbResourceBuilder = builder.AddMongoDB("mongodb") + .WithDbGate(c => c.WithHostPort(8068)); + + using var app = builder.Build(); + + var appModel = app.Services.GetRequiredService(); + + var dbGateResource = appModel.Resources.OfType().SingleOrDefault(); + Assert.NotNull(dbGateResource); + + var primaryEndpoint = dbGateResource.Annotations.OfType().Single(); + Assert.Equal(8068, primaryEndpoint.Port); + } + + [Fact] + public void WithDbGateShouldChangeDbGateContainerImageTag() + { + var builder = DistributedApplication.CreateBuilder(); + var mongodbResourceBuilder = builder.AddMongoDB("mongodb") + .WithDbGate(c => c.WithImageTag("manualTag")); + using var app = builder.Build(); + + var appModel = app.Services.GetRequiredService(); + + var dbGateResource = appModel.Resources.OfType().SingleOrDefault(); + Assert.NotNull(dbGateResource); + + var containerImageAnnotation = dbGateResource.Annotations.OfType().Single(); + Assert.Equal("manualTag", containerImageAnnotation.Tag); + } + + [Fact] + public async Task WithDbGateAddsAnnotationsForMultipleMongoDBResource() + { + var builder = DistributedApplication.CreateBuilder(); + + var mongodbResourceBuilder1 = builder.AddMongoDB("mongodb1") + .WithEndpoint("tcp", e => e.AllocatedEndpoint = new AllocatedEndpoint(e, "localhost", 27017)) + .WithDbGate(); + + var mongodbResource1 = mongodbResourceBuilder1.Resource; + + var mongodbResourceBuilder2 = builder.AddMongoDB("mongodb2") + .WithEndpoint("tcp", e => e.AllocatedEndpoint = new AllocatedEndpoint(e, "localhost", 27018)) + .WithDbGate(); + + var mongodbResource2 = mongodbResourceBuilder2.Resource; + + using var app = builder.Build(); + + var appModel = app.Services.GetRequiredService(); + + var dbGateResource = appModel.Resources.OfType().SingleOrDefault(); + + Assert.NotNull(dbGateResource); + + Assert.Equal("mongodb1-dbgate", dbGateResource.Name); + + var envs = await dbGateResource.GetEnvironmentVariableValuesAsync(); + + Assert.NotEmpty(envs); + Assert.Collection(envs, + item => + { + Assert.Equal("LABEL_mongodb1", item.Key); + Assert.Equal(mongodbResource1.Name, item.Value); + }, + async item => + { + Assert.Equal("URL_mongodb1", item.Key); + Assert.Equal(await mongodbResource1.ConnectionStringExpression.GetValueAsync(default), item.Value); + }, + item => + { + Assert.Equal("ENGINE_mongodb1", item.Key); + Assert.Equal("mongo@dbgate-plugin-mongo", item.Value); + }, + item => + { + Assert.Equal("LABEL_mongodb2", item.Key); + Assert.Equal(mongodbResource2.Name, item.Value); + }, + async item => + { + Assert.Equal("URL_mongodb2", item.Key); + Assert.Equal(await mongodbResource2.ConnectionStringExpression.GetValueAsync(default), item.Value); + }, + item => + { + Assert.Equal("ENGINE_mongodb2", item.Key); + Assert.Equal("mongo@dbgate-plugin-mongo", item.Value); + }, + item => + { + Assert.Equal("CONNECTIONS", item.Key); + Assert.Equal("mongodb1,mongodb2", item.Value); + }); + } +}