Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
d11b66a
Initial addition of CosmosDB support, based on SqlServer
Pilchie Oct 3, 2023
3374fb6
Remove Healthchecks support from CosmosDB EF Component
Pilchie Oct 11, 2023
1e60bf5
DO NOT MERGE: Update sample to use CosmosDB instead of PostgreSQL
Pilchie Oct 1, 2023
4eaae64
Cleanup connection string handling in Cosmos EF
Pilchie Oct 17, 2023
6421e60
Cleanup connection string handling in Cosmos component
Pilchie Oct 17, 2023
07d8284
Update CosmosDB package to get OTel support
Pilchie Oct 17, 2023
8dae4bd
Use the parent name for the connection
Pilchie Oct 17, 2023
f706813
Revert last change
Pilchie Oct 17, 2023
3f8b528
Fix text build break
Pilchie Oct 17, 2023
0ac6633
Remove cruft around configuration schema
Pilchie Oct 17, 2023
ed5c74b
Udpate manifest strings
Pilchie Oct 18, 2023
8b72bf0
Add CosmosDB components to Progress and Telemetry
Pilchie Oct 18, 2023
a98aaee
Rename CosmosDB components to Aspire.Azure.Data.Cosmos[.EntityFramewo…
Pilchie Oct 18, 2023
3f0bb37
Rename Cosmos DB directories
Pilchie Oct 18, 2023
4bd8129
Rename some namespaces and related
Pilchie Oct 18, 2023
9d7442a
Rename options -> settings
Pilchie Oct 19, 2023
aff38a2
Rename Cosmos Components to follow naming guidelines
Pilchie Oct 20, 2023
9cf1d52
Merge remote-tracking branch 'upstream/main' into azure-cosmosdb
Pilchie Oct 24, 2023
a4a9b29
Fix mis-merges
Pilchie Oct 25, 2023
9b412bd
Update to CosmosDB preview package and pin to get OpenTelemetry support
Pilchie Oct 25, 2023
4709022
Merge remote-tracking branch 'upstream/main' into azure-cosmosdb
Pilchie Oct 26, 2023
dcab2df
Update comments and add Keyed DI to Aspire.Microsoft.Azure.Cosmos
Pilchie Oct 27, 2023
2067377
Update exception message
Pilchie Oct 27, 2023
ce8f094
Add log categories to Cosmos Component schemas
Pilchie Oct 27, 2023
46db475
Add basic support for CosmosClientOptions (no IConfiguration binding …
Pilchie Oct 27, 2023
49908bd
Remove healthchecks support from CosmosDB Component
Pilchie Oct 30, 2023
e5c96ac
Add README for Aspire.Microsoft.Azure.Cosmos
Pilchie Oct 30, 2023
8d04a70
Add README for Aspire.Microsoft.EntityFrameworkCore.Cosmos, and renam…
Pilchie Oct 30, 2023
0af6420
Update config schema to be nested for Aspire.Microsoft.EntityFramewor…
Pilchie Oct 30, 2023
c9f434c
Rename AzureDataCosmosSettings -> AzureCosmosDBSettings
Pilchie Oct 30, 2023
c880d96
Remove metrics support from Aspire.Microsoft.Azure.Cosmos
Pilchie Oct 30, 2023
e495d03
Remove WithAzureCosmosDB extension from hosting
Pilchie Oct 30, 2023
f2feb2b
Remove setting for DatabaseName from Aspire.Microsoft.EntityFramework…
Pilchie Oct 30, 2023
053e84b
Rename AzureEntityFrameworkCoreCosmosDBSettings -> EntityFrameworkCor…
Pilchie Oct 30, 2023
2765016
Update Aspire_Components_Progress.md
Pilchie Oct 30, 2023
6770b32
Prepare to make Aspire install by default on upgrades for web workloa…
danegsta Oct 26, 2023
77d4b68
Text alignment with ellipsis (#536)
tlmii Oct 26, 2023
e8a6bda
Metrics page alignment (#537)
tlmii Oct 26, 2023
447e1d3
Provide an explicit target to generate the Aspire manifest (#534)
baronfel Oct 27, 2023
64c0994
Fix one place where service discovery isn't AOT compatible (#540)
davidfowl Oct 27, 2023
735035e
Updated otel versions to latest (#542)
davidfowl Oct 27, 2023
362baf5
Add log level select (#541)
JamesNK Oct 27, 2023
254e82e
Display Container ID (#544)
tlmii Oct 27, 2023
b0db3db
Enable ConfigurationBinder source gen on components by default (#535)
eerhardt Oct 27, 2023
952f5fd
Service Discovery: make host name propagation opt-in (#548)
ReubenBond Oct 27, 2023
3f03c80
Fix Aspire.Npgsql.csproj to be packable (#549)
eerhardt Oct 27, 2023
0f413bd
Update dependencies from https://github.com/dotnet/arcade build 20231…
dotnet-maestro[bot] Oct 27, 2023
c491f20
Fix metrics applications list (#552)
tlmii Oct 27, 2023
bc01c19
Add unit test coverage for redis, postgres, containers (#551)
BrennanConroy Oct 27, 2023
bf0e4fa
Add new DistributedApplicationOptions object, refactor DCP location c…
danegsta Oct 27, 2023
e580324
Use correct metadata name (#555)
danegsta Oct 27, 2023
484f53b
Add RabbitMQ Component (#556)
eerhardt Oct 28, 2023
8573329
Support running multiple instances of DAB in the same process (#560)
davidfowl Oct 28, 2023
f1a8a79
Display new error logs count to projects page (#545)
JamesNK Oct 28, 2023
2c9699e
Update Azure dependencies to latest versions (#563)
eerhardt Oct 29, 2023
7474fd1
Fixes creation of user secrets when user secrets does not yet exist (…
bjorkstromm Oct 29, 2023
3584144
Various log filter fixes (#571)
JamesNK Oct 30, 2023
5ab2c0b
Update metrics page to use SelectViewModel (#573)
JamesNK Oct 30, 2023
1cb8dcd
Change Dashboard to use Fluent UI vNext (#575)
vnbaaij Oct 30, 2023
49af7e4
[main] Update dependencies from microsoft/usvc-apiserver (#577)
dotnet-maestro[bot] Oct 30, 2023
5653395
Simplify view model caching (#557)
smitpatel Oct 30, 2023
bce48ec
Details Views (#561)
tlmii Oct 30, 2023
828f5dd
Account for case sensitive paths on nix systems (#584)
danegsta Oct 31, 2023
54326ee
Adds Azure hosting support for App Configuration (#574)
bjorkstromm Oct 31, 2023
20138fa
Switch to using Path.GetRandomFileName() from uuid (#587)
danegsta Oct 31, 2023
6cbcac5
Fix trace order (#588)
JamesNK Oct 31, 2023
6ed5925
Add TokenCredential support to Aspire.Microsoft.EntityFrameworkCore.C…
Pilchie Oct 31, 2023
92ecb4c
Add TokenCredential support to Aspire.Microsoft.Azure.Cosmos
Pilchie Oct 31, 2023
61d05e9
Merge remote-tracking branch 'upstream/main' into azure-cosmosdb
Pilchie Oct 31, 2023
85a66a8
Add empty RatingsService
Pilchie Oct 31, 2023
4f01310
Add a RatingsService and use it from the frontend
Pilchie Nov 1, 2023
8d76cc1
Revert changes to catalogdb
Pilchie Nov 1, 2023
0130296
Update expected service lifetime to singleton
Pilchie Nov 1, 2023
f22856d
Revert "Add a RatingsService and use it from the frontend"
Pilchie Nov 1, 2023
c86dec1
Revert "Add empty RatingsService"
Pilchie Nov 1, 2023
97aa291
Apply suggestions from code review
Pilchie Nov 1, 2023
b372614
Merge remote-tracking branch 'upstream/main' into azure-cosmosdb
Pilchie Nov 1, 2023
7898ce9
Fix project type guid
Pilchie Nov 1, 2023
932723c
Remove TODO
Pilchie Nov 1, 2023
6214639
Fix typo in exception message
Pilchie Nov 1, 2023
24c71a4
Add PackageTags, Descriptions, and Icons
Pilchie Nov 1, 2023
138579d
Add AccountEndpoint to ConfigurationScheama.json
Pilchie Nov 1, 2023
3f53c4f
Remove healthcheck from comment
Pilchie Nov 1, 2023
0a40231
A couple more code review fixes
Pilchie Nov 1, 2023
3209cc5
WIP
Pilchie Nov 1, 2023
2f89327
Merge remote-tracking branch 'upstream/main' into azure-cosmosdb
Pilchie Nov 1, 2023
ea41461
Fix DB context builder config
Pilchie Nov 2, 2023
2a17893
Add xml doc comments for CosmosDB hosting methods and types
Pilchie Nov 2, 2023
0058fa1
Move Cosmos DB hosting to Aspire.Hosting.Azure
Pilchie Nov 2, 2023
2a3d1cc
Update manifest type names
Pilchie Nov 2, 2023
f58be30
Merge branch 'main' into azure-cosmosdb
mitchdenny Nov 2, 2023
9595b88
Respond to PR feedback
eerhardt Nov 2, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions Aspire.sln
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aspire.Hosting.Azure.Provis
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "eShopLite", "eShopLite", "{A68BA1A5-1604-433D-9778-DC0199831C2A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aspire.Microsoft.Azure.Cosmos", "src\Components\Aspire.Microsoft.Azure.Cosmos\Aspire.Microsoft.Azure.Cosmos.csproj", "{23298562-C1D4-41CD-83FE-426C94FEE35F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aspire.Microsoft.EntityFrameworkCore.Cosmos", "src\Components\Aspire.Microsoft.EntityFrameworkCore.Cosmos\Aspire.Microsoft.EntityFrameworkCore.Cosmos.csproj", "{00C9BA50-2AFB-4D9C-A2D6-8154BCCD0A63}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aspire.Microsoft.Azure.Cosmos.Tests", "tests\Aspire.Microsoft.Azure.Cosmos.Tests\Aspire.Microsoft.Azure.Cosmos.Tests.csproj", "{A5836BC1-6A45-4BB6-9D22-A7F750890AB8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aspire.Microsoft.EntityFrameworkCore.Cosmos.Tests", "tests\Aspire.Microsoft.EntityFrameworkCore.Cosmos.Tests\Aspire.Microsoft.EntityFrameworkCore.Cosmos.Tests.csproj", "{FDA02617-9C49-4DA8-A43A-A34DBA9B8596}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CatalogDb", "samples\eShopLite\CatalogDb\CatalogDb.csproj", "{A84C4EE3-2601-4804-BCDC-E9948E164A22}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{991DB378-6CB5-4441-BFC3-657400690FC3}"
Expand Down Expand Up @@ -370,6 +378,22 @@ Global
{D4BD974F-6505-43FC-A94E-2019F0DB5D5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D4BD974F-6505-43FC-A94E-2019F0DB5D5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D4BD974F-6505-43FC-A94E-2019F0DB5D5D}.Release|Any CPU.Build.0 = Release|Any CPU
{23298562-C1D4-41CD-83FE-426C94FEE35F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{23298562-C1D4-41CD-83FE-426C94FEE35F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{23298562-C1D4-41CD-83FE-426C94FEE35F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{23298562-C1D4-41CD-83FE-426C94FEE35F}.Release|Any CPU.Build.0 = Release|Any CPU
{00C9BA50-2AFB-4D9C-A2D6-8154BCCD0A63}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{00C9BA50-2AFB-4D9C-A2D6-8154BCCD0A63}.Debug|Any CPU.Build.0 = Debug|Any CPU
{00C9BA50-2AFB-4D9C-A2D6-8154BCCD0A63}.Release|Any CPU.ActiveCfg = Release|Any CPU
{00C9BA50-2AFB-4D9C-A2D6-8154BCCD0A63}.Release|Any CPU.Build.0 = Release|Any CPU
{A5836BC1-6A45-4BB6-9D22-A7F750890AB8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A5836BC1-6A45-4BB6-9D22-A7F750890AB8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A5836BC1-6A45-4BB6-9D22-A7F750890AB8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A5836BC1-6A45-4BB6-9D22-A7F750890AB8}.Release|Any CPU.Build.0 = Release|Any CPU
{FDA02617-9C49-4DA8-A43A-A34DBA9B8596}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FDA02617-9C49-4DA8-A43A-A34DBA9B8596}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FDA02617-9C49-4DA8-A43A-A34DBA9B8596}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FDA02617-9C49-4DA8-A43A-A34DBA9B8596}.Release|Any CPU.Build.0 = Release|Any CPU
{A84C4EE3-2601-4804-BCDC-E9948E164A22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A84C4EE3-2601-4804-BCDC-E9948E164A22}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A84C4EE3-2601-4804-BCDC-E9948E164A22}.Release|Any CPU.ActiveCfg = Release|Any CPU
Expand Down Expand Up @@ -446,6 +470,10 @@ Global
{E2EC79D0-80F7-4471-9613-D7C8C3D52F95} = {B80354C7-BE58-43F6-8928-9F3A74AB7F47}
{D4BD974F-6505-43FC-A94E-2019F0DB5D5D} = {B80354C7-BE58-43F6-8928-9F3A74AB7F47}
{A68BA1A5-1604-433D-9778-DC0199831C2A} = {D173887B-AF42-4576-B9C1-96B9E9B3D9C0}
{23298562-C1D4-41CD-83FE-426C94FEE35F} = {27381127-6C45-4B4C-8F18-41FF48DFE4B2}
{00C9BA50-2AFB-4D9C-A2D6-8154BCCD0A63} = {27381127-6C45-4B4C-8F18-41FF48DFE4B2}
{A5836BC1-6A45-4BB6-9D22-A7F750890AB8} = {4981B3A5-4AFD-4191-BF7D-8692D9783D60}
{FDA02617-9C49-4DA8-A43A-A34DBA9B8596} = {4981B3A5-4AFD-4191-BF7D-8692D9783D60}
{A84C4EE3-2601-4804-BCDC-E9948E164A22} = {A68BA1A5-1604-433D-9778-DC0199831C2A}
{4D8A92AB-4E77-4965-AD8E-8E206DCE66A4} = {27381127-6C45-4B4C-8F18-41FF48DFE4B2}
{165411FE-755E-4869-A756-F87F455860AC} = {4981B3A5-4AFD-4191-BF7D-8692D9783D60}
Expand Down
4 changes: 3 additions & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<PackageVersion Include="Azure.Security.KeyVault.Secrets" Version="4.5.0" />
<PackageVersion Include="Azure.Storage.Blobs" Version="12.18.0" />
<PackageVersion Include="Azure.Storage.Queues" Version="12.16.0" />
<PackageVersion Include="Microsoft.Azure.Cosmos" Version="3.36.0-preview" />

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.

Looks like 3.36.0 is out now.

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.

CosmosDB does versioning wrong right now :(. 3.36.0-preview is actually 3.36.0 + preview stuff. In this case it's the difference between distributed tracing being on or off by default, so I'm happy to change if you want.

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.

That is some messed up versioning for sure. Definitely not how the rest of the ecosystem does it.

<PackageVersion Include="Microsoft.Extensions.Azure" Version="1.7.1" />
<!-- Azure Management SDK for .NET dependencies -->
<PackageVersion Include="Azure.ResourceManager.KeyVault" Version="1.2.0-beta.2" />
Expand Down Expand Up @@ -45,6 +46,7 @@
<!-- sql client dependencies -->
<PackageVersion Include="Microsoft.Data.SqlClient" Version="5.1.1" />
<!-- efcore dependencies -->
<PackageVersion Include="Microsoft.EntityFrameworkCore.Cosmos" Version="$(EfCoreVersion)" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="$(EfCoreVersion)" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="$(EfCoreVersion)" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="$(EfCoreVersion)" />
Expand Down Expand Up @@ -101,4 +103,4 @@
<PackageVersion Include="Microsoft.Signed.Wix" Version="1.0.0-v3.14.0.5722" />
<PackageVersion Include="Microsoft.DotNet.Build.Tasks.Installers" Version="8.0.0-beta.23371.1" />
</ItemGroup>
</Project>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// 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;
using Aspire.Hosting.Azure.Data.Cosmos;
using System.Text.Json;

namespace Aspire.Hosting;

/// <summary>
/// Provides extension methods for adding Azure Cosmos DB resources to an <see cref="IDistributedApplicationBuilder"/>.
/// </summary>
public static class AzureCosmosDBCloudApplicationBuilderExtensions
{
/// <summary>
/// Adds an Azure Cosmos DB connection to the application model.
/// </summary>
/// <param name="builder">The <see cref="IDistributedApplicationBuilder"/>.</param>
/// <param name="name">The name of the resource. This name will be used as the connection string name when referenced in a dependency.</param>
/// <param name="connectionString">The connection string.</param>
/// <returns>A reference to the <see cref="IResourceBuilder{AzureCosmosDatabaseResource}"/>.</returns>
public static IResourceBuilder<AzureCosmosDBConnectionResource> AddAzureCosmosDB(
this IDistributedApplicationBuilder builder,
string name,
string? connectionString = null)
{
var connection = new AzureCosmosDBConnectionResource(name, connectionString);
return builder.AddResource(connection)
.WithAnnotation(new ManifestPublishingCallbackAnnotation(jsonWriter => WriteCosmosDBConnectionToManifest(jsonWriter, connection)));
}

private static void WriteCosmosDBConnectionToManifest(Utf8JsonWriter jsonWriter, AzureCosmosDBConnectionResource cosmosDbConnection)
{
jsonWriter.WriteString("type", "azure.cosmosdb.connection.v0");
jsonWriter.WriteString("connectionString", cosmosDbConnection.GetConnectionString());
}

private static void WriteCosmosDBDatabaseToManifest(Utf8JsonWriter jsonWriter, AzureCosmosDatabaseResource cosmosDatabase)
{
jsonWriter.WriteString("type", "azure.cosmosdb.database.v0");
jsonWriter.WriteString("parent", cosmosDatabase.Parent.Name);
jsonWriter.WriteString("databaseName", cosmosDatabase.Name);
}

/// <summary>
/// Adds an Azure Cosmos DB database to a <see cref="IResourceBuilder{AzureCosmosDatabaseResource}"/>.
/// </summary>
/// <param name="builder">The <see cref="IDistributedApplicationBuilder"/>.</param>
/// <param name="name">The name of the resource. This name will be used as the connection string name when referenced in a dependency.</param>
/// <returns>A reference to the <see cref="IResourceBuilder{AzureCosmosDatabaseResource}"/>.</returns>
public static IResourceBuilder<AzureCosmosDatabaseResource> AddDatabase(this IResourceBuilder<AzureCosmosDBConnectionResource> builder, string name)
{
var cosmosDatabase = new AzureCosmosDatabaseResource(name, builder.Resource);
return builder
.ApplicationBuilder
.AddResource(cosmosDatabase)
.WithAnnotation(new ManifestPublishingCallbackAnnotation(
(json) => WriteCosmosDBDatabaseToManifest(json, cosmosDatabase)));
}
}
21 changes: 21 additions & 0 deletions src/Aspire.Hosting.Azure/AzureCosmosDBConnectionResource.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// 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.Azure.Data.Cosmos;

/// <summary>
/// Represents a connection to an Azure Cosmos DB account.
/// </summary>
/// <param name="name">The resource name.</param>
/// <param name="connectionString">The connection string to use to connect.</param>
public class AzureCosmosDBConnectionResource(string name, string? connectionString)
: Resource(name), IResourceWithConnectionString
{
/// <summary>
/// Gets the connection string to use for this database.
/// </summary>
/// <returns>The connection string to use for this database.</returns>
public string? GetConnectionString() => connectionString;
}
29 changes: 29 additions & 0 deletions src/Aspire.Hosting.Azure/AzureCosmosDatabaseResource.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// 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.Azure.Data.Cosmos;

/// <summary>
/// Represents an Azure Cosmos DB database.
/// </summary>
/// <param name="name">The database name.</param>
/// <param name="parent">The parent <see cref="AzureCosmosDBConnectionResource"/>.</param>
public class AzureCosmosDatabaseResource(string name, AzureCosmosDBConnectionResource parent)
: Resource(name), IResourceWithParent<AzureCosmosDBConnectionResource>, IResourceWithConnectionString
{
/// <summary>
/// Gets the parent <see cref="AzureCosmosDBConnectionResource"/>.
/// </summary>
public AzureCosmosDBConnectionResource Parent { get; } = parent;

/// <summary>
/// Gets the connection string to use for this database.
/// </summary>
/// <returns>The connection string to use for this database.</returns>
public string? GetConnectionString()
{
return Parent.GetConnectionString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>$(NetCurrent)</TargetFramework>
<IsPackable>true</IsPackable>
<EnableConfigurationBindingGenerator>false</EnableConfigurationBindingGenerator>
<IsAotCompatible>false</IsAotCompatible>
Comment thread
Pilchie marked this conversation as resolved.
<PackageTags>$(ComponentAzurePackageTags) cosmos cosmosdb data database db</PackageTags>
<Description>A client for Azure Cosmos DB that integrates with Aspire, including logging and telemetry.</Description>
<PackageIconFullPath>$(SharedDir)AzureCosmosDB_256x.png</PackageIconFullPath>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Azure.Identity" />
<PackageReference Include="Microsoft.Azure.Cosmos" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" />
<PackageReference Include="OpenTelemetry.Extensions.Hosting" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Aspire.Microsoft.Azure.Cosmos;
using Azure.Identity;
using Microsoft.Azure.Cosmos;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace Microsoft.Extensions.Hosting;

/// <summary>
/// Azure CosmosDB extension
/// </summary>
public static class AspireAzureCosmosDBExtensions
{
private const string DefaultConfigSectionName = "Aspire:Microsoft:Azure:Cosmos";

/// <summary>
/// Registers <see cref="CosmosClient" /> as a singleton in the services provided by the <paramref name="builder"/>.
/// Configures logging and telemetry for the <see cref="CosmosClient" />.
/// </summary>
/// <param name="builder">The <see cref="IHostApplicationBuilder" /> to read config from and add services to.</param>
/// <param name="connectionName">The connection name to use to find a connection string.</param>
/// <param name="configureSettings">An optional method that can be used for customizing the <see cref="AzureCosmosDBSettings"/>. It's invoked after the settings are read from the configuration.</param>
/// <param name="configureClientOptions">An optional method that can be used for customizing the <see cref="CosmosClientOptions"/>.</param>
/// <remarks>Reads the configuration from "Aspire:Microsoft:Azure:Cosmos" section.</remarks>
/// <exception cref="InvalidOperationException">If required ConnectionString is not provided in configuration section</exception>
public static void AddAzureCosmosDB(
this IHostApplicationBuilder builder,
string connectionName,
Action<AzureCosmosDBSettings>? configureSettings = null,
Action<CosmosClientOptions>? configureClientOptions = null)
{
AddAzureCosmosDB(builder, DefaultConfigSectionName, configureSettings, configureClientOptions, connectionName, serviceKey: null);
}

/// <summary>
/// Registers <see cref="CosmosClient" /> as a singleton for given <paramref name="name" /> in the services provided by the <paramref name="builder"/>.
/// Configures logging and telemetry for the <see cref="CosmosClient" />.
/// </summary>
/// <param name="builder">The <see cref="IHostApplicationBuilder" /> to read config from and add services to.</param>
/// <param name="name">The name of the component, which is used as the <see cref="ServiceDescriptor.ServiceKey"/> of the service and also to retrieve the connection string from the ConnectionStrings configuration section.</param>
/// <param name="configureSettings">An optional method that can be used for customizing the <see cref="AzureCosmosDBSettings"/>. It's invoked after the settings are read from the configuration.</param>
/// <param name="configureClientOptions">An optional method that can be used for customizing the <see cref="CosmosClientOptions"/>.</param>
/// <remarks>Reads the configuration from "Aspire:Microsoft:Azure:Cosmos:{name}" section.</remarks>
/// <exception cref="InvalidOperationException">If required ConnectionString is not provided in configuration section</exception>
public static void AddKeyedAzureCosmosDB(
this IHostApplicationBuilder builder,
string name,
Action<AzureCosmosDBSettings>? configureSettings = null,
Action<CosmosClientOptions>? configureClientOptions = null)
{
AddAzureCosmosDB(builder, $"{DefaultConfigSectionName}:{name}", configureSettings, configureClientOptions, connectionName: name, serviceKey: name);
}

private static void AddAzureCosmosDB(
this IHostApplicationBuilder builder,
string configurationSectionName,
Action<AzureCosmosDBSettings>? configureSettings,
Action<CosmosClientOptions>? configureClientOptions,
string connectionName,
string? serviceKey)
{
ArgumentNullException.ThrowIfNull(builder);

var settings = new AzureCosmosDBSettings();
builder.Configuration.GetSection(configurationSectionName).Bind(settings);

if (builder.Configuration.GetConnectionString(connectionName) is string connectionString)
{
if (Uri.TryCreate(connectionString, UriKind.Absolute, out var uri))
{
settings.AccountEndpoint = uri;
}
else
{
settings.ConnectionString = connectionString;
}
}

configureSettings?.Invoke(settings);

var clientOptions = new CosmosClientOptions();
// Needs to be enabled for either logging or tracing to work.
clientOptions.CosmosClientTelemetryOptions.DisableDistributedTracing = false;
if (settings.Tracing)
{
builder.Services.AddOpenTelemetry().WithTracing(tracerProviderBuilder =>
{
tracerProviderBuilder.AddSource("Azure.Cosmos.Operation");
});
}

configureClientOptions?.Invoke(clientOptions);

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.

The clientOptions should be bound to the config, so users can configure them using normal configuration.

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.

That's on my todolist, but it's not easy, since I don't think many parts of the clientOptions type are actually serializable. Thoughts there, or it doesn't matter because those parts just won't be settable in config?

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.

What I've been doing is walking through the type and looking for simple properties. You can see all of them in the other Azure components schema, or in the RabbitMQ schema I just did a few days ago:

https://github.com/dotnet/aspire/blob/dd917e5daa91f855e101d87bc7e164a5c4f03e4e/src/Components/Aspire.RabbitMQ.Client/ConfigurationSchema.json#L12-L43

And then add a test for it like so:

https://github.com/dotnet/aspire/blob/dd917e5daa91f855e101d87bc7e164a5c4f03e4e/tests/Aspire.RabbitMQ.Client.Tests/AspireRabbitMQExtensionsTests.cs#L112-L158

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.

Can we consider merging this and I'll expand on that in a separate PR?


if (serviceKey is null)
{
builder.Services.AddSingleton(_ => ConfigureDb());
}
else
{
builder.Services.AddKeyedSingleton(serviceKey, (sp, key) => ConfigureDb());
}

CosmosClient ConfigureDb()
{
if (!string.IsNullOrEmpty(settings.ConnectionString))
{
return new CosmosClient(settings.ConnectionString, clientOptions);
}
else if (settings.AccountEndpoint is not null)
{
var credential = settings.Credential ?? new DefaultAzureCredential();
return new CosmosClient(settings.AccountEndpoint.OriginalString, credential, clientOptions);
}
else
{
throw new InvalidOperationException(
$"A CosmosClient could not be configured. Ensure valid connection information was provided in 'ConnectionStrings:{connectionName}' or either " +
$"{nameof(settings.ConnectionString)} or {nameof(settings.AccountEndpoint)} must be provided " +
$"in the '{configurationSectionName}' configuration section.");
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Azure.Core;

namespace Aspire.Microsoft.Azure.Cosmos;

/// <summary>
/// The settings relevant to accessing Azure Cosmos DB.
/// </summary>
public sealed class AzureCosmosDBSettings
{
/// <summary>
/// Gets or sets the connection string of the Azure Cosmos database to connect to.
/// </summary>
public string? ConnectionString { get; set; }

/// <summary>
/// <para>Gets or sets a boolean value that indicates whether the OpenTelemetry tracing is enabled or not.</para>
/// <para>Enabled by default.</para>
/// </summary>
public bool Tracing { get; set; } = true;

/// <summary>
/// A <see cref="Uri"/> referencing the Azure Cosmos DB Endpoint.
/// This is likely to be similar to "https://{account_name}.queue.core.windows.net".
/// </summary>
/// <remarks>
/// Must not contain shared access signature.
/// Used along with <see cref="Credential"/> to establish the connection.
/// </remarks>
public Uri? AccountEndpoint { get; set; }

/// <summary>
/// Gets or sets the credential used to authenticate to the Azure Cosmos DB endpoint.
/// </summary>
public TokenCredential? Credential { get; set; }
}

Loading