Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
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
Next Next commit
Add AddBlobContainer on AzureStorageResource
  • Loading branch information
sebastienros committed Jul 1, 2025
commit 4b11a688be39d23be7617da8cfa3f8bdcd7cfaba
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,20 @@
container.WithDataBindMount();
});

var blobs = storage.AddBlobs("blobs");
blobs.AddBlobContainer("mycontainer1", blobContainerName: "test-container-1");
blobs.AddBlobContainer("mycontainer2", blobContainerName: "test-container-2");
storage.AddBlobContainer("mycontainer1", blobContainerName: "test-container-1");
storage.AddBlobContainer("mycontainer2", blobContainerName: "test-container-2");

var queues = storage.AddQueues("queues");

var storage2 = builder.AddAzureStorage("storage2").RunAsEmulator(container =>
{
container.WithDataBindMount();
});
var blobs2 = storage2.AddBlobs("blobs2");
var blobContainer2 = blobs2.AddBlobContainer("foocontainer", blobContainerName: "foo-container");

var blobContainer2 = storage2.AddBlobContainer("foocontainer", blobContainerName: "foo-container");

builder.AddProject<Projects.AzureStorageEndToEnd_ApiService>("api")
.WithExternalHttpEndpoints()
.WithReference(blobs).WaitFor(blobs)
.WithReference(blobContainer2).WaitFor(blobContainer2)
.WithReference(queues).WaitFor(queues);

Expand Down
41 changes: 41 additions & 0 deletions src/Aspire.Hosting.Azure.Storage/AzureStorageExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -313,13 +313,54 @@ public static IResourceBuilder<AzureBlobStorageResource> AddBlobs(this IResource
});
}

/// <summary>
/// Creates a builder for the <see cref="AzureBlobStorageContainerResource"/> which can be referenced to get the Azure Storage blob container endpoint for the storage account.
/// </summary>
/// <param name="builder">The <see cref="IResourceBuilder{T}"/> for <see cref="AzureStorageResource"/>/</param>
/// <param name="name">The name of the resource.</param>
/// <param name="blobContainerName">The name of the blob container.</param>
/// <returns>An <see cref="IResourceBuilder{T}"/> for the <see cref="AzureBlobStorageContainerResource"/>.</returns>
public static IResourceBuilder<AzureBlobStorageContainerResource> AddBlobContainer(this IResourceBuilder<AzureStorageResource> builder, [ResourceName] string name, string? blobContainerName = null)
{
ArgumentNullException.ThrowIfNull(builder);
ArgumentException.ThrowIfNullOrEmpty(name);

blobContainerName ??= name;

// Create the blob storage resource implicitly
var blobsName = $"{builder.Resource.Name}-blobs";
var blobsResource = new AzureBlobStorageResource(blobsName, builder.Resource);

AzureBlobStorageContainerResource resource = new(name, blobContainerName, blobsResource);
builder.Resource.BlobContainers.Add(resource);

string? connectionString = null;

var healthCheckKey = $"{resource.Name}_check";

BlobServiceClient? blobServiceClient = null;
builder.ApplicationBuilder.Services.AddHealthChecks().AddAzureBlobStorage(
sp => blobServiceClient ??= CreateBlobServiceClient(connectionString ?? throw new InvalidOperationException("Connection string is not initialized.")),
optionsFactory: sp => new HealthChecks.Azure.Storage.Blobs.AzureBlobStorageHealthCheckOptions { ContainerName = blobContainerName },
name: healthCheckKey);

return builder.ApplicationBuilder
.AddResource(resource)
.WithHealthCheck(healthCheckKey)
.OnConnectionStringAvailable(async (containerResource, @event, ct) =>
{
connectionString = await resource.Parent.ConnectionStringExpression.GetValueAsync(ct).ConfigureAwait(false);
});
}

/// <summary>
/// Creates a builder for the <see cref="AzureBlobStorageContainerResource"/> which can be referenced to get the Azure Storage blob container endpoint for the storage account.
/// </summary>
/// <param name="builder">The <see cref="IResourceBuilder{T}"/> for <see cref="AzureBlobStorageResource"/>/</param>
/// <param name="name">The name of the resource.</param>
/// <param name="blobContainerName">The name of the blob container.</param>
/// <returns>An <see cref="IResourceBuilder{T}"/> for the <see cref="AzureBlobStorageContainerResource"/>.</returns>
[Obsolete("Use AddBlobContainer on IResourceBuilder<AzureStorageResource> instead.")]
public static IResourceBuilder<AzureBlobStorageContainerResource> AddBlobContainer(this IResourceBuilder<AzureBlobStorageResource> builder, [ResourceName] string name, string? blobContainerName = null)
{
ArgumentNullException.ThrowIfNull(builder);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,7 @@ public async Task VerifyWaitForOnAzureStorageEmulatorForBlobContainersBlocksDepe
.RunAsEmulator()
.WithHealthCheck("blocking_check");

var blobs = storage.AddBlobs("blobs");
var blobContainer = blobs.AddBlobContainer("testblobcontainer");
var blobContainer = storage.AddBlobContainer("testblobcontainer");

var dependentResource = builder.AddContainer("nginx", "mcr.microsoft.com/cbl-mariner/base/nginx", "1.22")
.WaitFor(blobContainer);
Expand Down Expand Up @@ -114,8 +113,9 @@ public async Task VerifyAzureStorageEmulatorResource()
var blobContainerName = "my-container";

using var builder = TestDistributedApplicationBuilder.Create().WithTestAndResourceLogging(testOutputHelper);
var blobs = builder.AddAzureStorage("storage").RunAsEmulator().AddBlobs(blobsResourceName);
var container = blobs.AddBlobContainer(blobContainerName);
var storage = builder.AddAzureStorage("storage").RunAsEmulator();
var blobs = storage.AddBlobs(blobsResourceName);
var container = storage.AddBlobContainer(blobContainerName);

using var app = builder.Build();
await app.StartAsync();
Expand Down Expand Up @@ -150,7 +150,7 @@ public async Task VerifyAzureStorageEmulator_blobcontainer_auto_created()
using var builder = TestDistributedApplicationBuilder.Create().WithTestAndResourceLogging(testOutputHelper);
var storage = builder.AddAzureStorage("storage").RunAsEmulator();
var blobs = storage.AddBlobs("BlobConnection");
var blobContainer = blobs.AddBlobContainer("testblobcontainer");
var blobContainer = storage.AddBlobContainer("testblobcontainer");

using var app = builder.Build();
await app.StartAsync();
Expand Down
10 changes: 4 additions & 6 deletions tests/Aspire.Hosting.Azure.Tests/AzureStorageExtensionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ public async Task AddBlobContainer_ConnectionString_resolved_expected_RunAsEmula
Assert.True(storage.Resource.IsContainer());

var blobs = storage.AddBlobs("blob");
var blobContainer = blobs.AddBlobContainer(name: "myContainer", blobContainerName);
var blobContainer = storage.AddBlobContainer(name: "myContainer", blobContainerName);

string? blobConnectionString = await ((IResourceWithConnectionString)blobs.Resource).ConnectionStringExpression.GetValueAsync(default);
string? blobContainerConnectionString = await ((IResourceWithConnectionString)blobContainer.Resource).ConnectionStringExpression.GetValueAsync(default);
Expand All @@ -255,7 +255,7 @@ public async Task AddBlobContainer_ConnectionString_resolved_expected()
storage.Resource.Outputs["blobEndpoint"] = "https://myblob";

var blobs = storage.AddBlobs("blob");
var blobContainer = blobs.AddBlobContainer(name: "myContainer", blobContainerName);
var blobContainer = storage.AddBlobContainer(name: "myContainer", blobContainerName);

string? blobsConnectionString = await ((IResourceWithConnectionString)blobs.Resource).ConnectionStringExpression.GetValueAsync(default);
string expected = $"Endpoint={blobsConnectionString};ContainerName={blobContainerName}";
Expand All @@ -269,8 +269,7 @@ public void AddBlobContainer_ConnectionString_unresolved_expected()
using var builder = TestDistributedApplicationBuilder.Create();

var storage = builder.AddAzureStorage("storage");
var blobs = storage.AddBlobs("blob");
var blobContainer = blobs.AddBlobContainer(name: "myContainer");
var blobContainer = storage.AddBlobContainer(name: "myContainer");

Assert.Equal("Endpoint={storage.outputs.blobEndpoint};ContainerName=myContainer", blobContainer.Resource.ConnectionStringExpression.ValueExpression);
}
Expand All @@ -281,8 +280,7 @@ public async Task ResourceNamesBicepValid()
using var builder = TestDistributedApplicationBuilder.Create();
var storage = builder.AddAzureStorage("storage");

var blobs = storage.AddBlobs("myblobs");
var blob = blobs.AddBlobContainer(name: "myContainer", blobContainerName: "my-blob-container");
var blob = storage.AddBlobContainer(name: "myContainer", blobContainerName: "my-blob-container");
var queues = storage.AddQueues("myqueues");
var tables = storage.AddTables("mytables");

Expand Down