Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
15 changes: 9 additions & 6 deletions docs/preview/03-Features/04-Azure/04-Storage/02-cosmos.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ await using var collection = await TemporaryMongoDbCollection.CreateIfNotExistsA
cosmosDbAccountResourceId,
"<database-name>",
"<collection-name>",
logger);
logger,
cancellationToken);

// Interact with the collection during the lifetime of the fixture.
IMongoCollection<Shipment> client = collection.GetCollectionClient<Shipment>();
Expand All @@ -48,7 +49,7 @@ using Arcus.Testing;

await using TemporaryMongoDbCollection collection = ...

await collection.UpsertDocumentAsync(new Shipment { BoatName = "The Alice" });
await collection.UpsertDocumentAsync(new Shipment { BoatName = "The Alice" }, cancellationToken);
```

:::praise
Expand Down Expand Up @@ -124,7 +125,8 @@ await using var document = await TemporaryMongoDbDocument.UpsertDocumentAsync(
"<database-name>",
"<collection-name>",
shipment,
logger);
logger,
cancellationToken);

BsonValue documentId = document.Id;
```
Expand Down Expand Up @@ -162,7 +164,8 @@ await using var container = await TemporaryNoSqlContainer.CreateIfNotExistsAsync
"<database-name>",
"<container-name>",
"/partition-key-path",
logger);
logger,
cancellationToken);

// Interact with the container during the lifetime of the fixture.
Container client = container.Client;
Expand All @@ -177,7 +180,7 @@ using Arcus.Testing;

await using TemporaryNoSqlContainer container = ...

await container.UpsertItemAsync(new Shipment { Id = "123", BoatName = "The Alice" });
await container.UpsertItemAsync(new Shipment { Id = "123", BoatName = "The Alice" }, cancellationToken);
```

:::praise
Expand Down Expand Up @@ -242,7 +245,7 @@ Container containerClient = ...
var shipment = new Shipment { Id = "123", BoatName = "The Alice" };

await using var item = await TemporaryNoSqlItem.UpsertItemAsync(
containerClient, shipment, logger);
containerClient, shipment, logger, cancellationToken);

string itemId = item.Id;
PartitionKey partitionKey = item.PartitionKey;
Expand Down
29 changes: 21 additions & 8 deletions src/Arcus.Testing.Storage.Cosmos/MongoDbConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Azure;
using Azure.Core;
Expand All @@ -21,39 +22,51 @@ internal static class MongoDbConnection
/// <summary>
/// Authenticates a <see cref="MongoClient"/> with <see cref="DefaultAzureCredential"/>.
/// </summary>
internal static async Task<MongoClient> AuthenticateMongoClientAsync(ResourceIdentifier cosmosDbResourceId, string databaseName, string collectionName, ILogger logger)
internal static async Task<MongoClient> AuthenticateMongoClientAsync(
ResourceIdentifier cosmosDbResourceId,
string databaseName,
string collectionName,
ILogger logger,
CancellationToken cancellationToken)
{
AccessToken accessToken = await RequestAccessTokenAsync(logger).ConfigureAwait(false);
string responseBody = await RequestConnectionStringsAsync(cosmosDbResourceId, databaseName, collectionName, accessToken, logger).ConfigureAwait(false);
cancellationToken.ThrowIfCancellationRequested();

AccessToken accessToken = await RequestAccessTokenAsync(logger, cancellationToken).ConfigureAwait(false);
string responseBody = await RequestConnectionStringsAsync(cosmosDbResourceId, databaseName, collectionName, accessToken, logger, cancellationToken).ConfigureAwait(false);

string connectionString = ParseConnectionString(responseBody);
return new MongoClient(connectionString);
}

private static async Task<AccessToken> RequestAccessTokenAsync(ILogger logger)
private static async Task<AccessToken> RequestAccessTokenAsync(ILogger logger, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();

const string scope = "https://management.azure.com/.default";
var tokenProvider = new DefaultAzureCredential();

logger.LogRequestAccessToken(scope);
return await tokenProvider.GetTokenAsync(new TokenRequestContext(scopes: [scope])).ConfigureAwait(false);
return await tokenProvider.GetTokenAsync(new TokenRequestContext(scopes: [scope]), cancellationToken).ConfigureAwait(false);
}

private static async Task<string> RequestConnectionStringsAsync(
ResourceIdentifier cosmosDbResourceId,
string databaseName,
string collectionName,
AccessToken accessToken,
ILogger logger)
ILogger logger,
CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();

var listConnectionStringUrl = $"https://management.azure.com/{cosmosDbResourceId}/listConnectionStrings?api-version=2021-04-15";
logger.LogRequestConnectionString(listConnectionStringUrl);

using var request = new HttpRequestMessage(HttpMethod.Post, listConnectionStringUrl);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken.Token);

using HttpResponseMessage response = await HttpClient.SendAsync(request).ConfigureAwait(false);
string responseBody = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
using HttpResponseMessage response = await HttpClient.SendAsync(request, cancellationToken).ConfigureAwait(false);
string responseBody = await response.Content.ReadAsStringAsync(cancellationToken).ConfigureAwait(false);

if (!response.IsSuccessStatusCode)
{
Expand Down
Loading
Loading