AzureStorage auto create blob containers
Resolves #5167
Description
Checklist
- Is this feature complete?
- [x] Yes. Ready to ship.
- [ ] No. Follow-up changes expected.
- Are you including unit tests for the changes and scenario tests if relevant?
- [x] Yes
- [ ] No
- Did you add public API?
- [x] Yes
- If yes, did you have an API Review for it?
- [ ] Yes
- [x] No
- Did you add
<remarks />and<code />elements on your triple slash comments?- [ ] Yes
- [ ] No
- If yes, did you have an API Review for it?
- [ ] No
- [x] Yes
- Does the change make any security assumptions or guarantees?
- [ ] Yes
- If yes, have you done a threat model and had a security review?
- [ ] Yes
- [ ] No
- If yes, have you done a threat model and had a security review?
- [x] No
- [ ] Yes
- Does the change require an update in our Aspire docs?
- [x] Yes
- Link to aspire-docs issue (consider using one of the following templates):
- [ ] No
- [x] Yes
Are you doing the client integration side of this as well?
For the most part this changeset copies the patterns implemented for AzureServiceBus.
I tested it locally in the emulator and deploying to Azure (configuring the Azure subscription details in secrets.json)
Emulator
Azure
var builder = DistributedApplication.CreateBuilder(args);
var storage = builder.AddAzureStorage("storage");
var blobs = storage.AddBlobs("blobs");
var blobContainer = blobs.AddBlobContainer("mycontainer");
var queues = storage.AddQueues("queues");
builder.AddProject<Projects.AzureStorageEndToEnd_ApiService>("api")
.WithExternalHttpEndpoints()
.WithReference(blobs).WaitFor(blobs)
.WithReference(blobContainer).WaitFor(blobContainer)
.WithReference(queues).WaitFor(queues);
Are you doing the client integration side of this as well?
Yes, though I may do it as a follow up.
The latest iteration adds the ability to register BlobContainerClient with AddAzureBlobContainerClient(), and then get the client directly:
builder.AddAzureBlobContainerClient("foocontainer");
var app = builder.Build();
app.MapGet("/", async (BlobContainerClient bcc) =>
{
}
@davidfowl @eerhardt @captainsafia @mitchdenny: I believe the client integration is complete, reviews are appreciated. There are also few open questions for which I'd appreciate your input.
I tested various scenarios, e.g.:
// Host
var storage = builder.AddAzureStorage("storage");
var blobs = storage.AddBlobs("blobs");
blobs.AddBlobContainer("mycontainer1", blobContainerName: "test-container-1");
blobs.AddBlobContainer("mycontainer2", blobContainerName: "test-container-2");
var storage2 = builder.AddAzureStorage("storage2");
var blobs2 = storage2.AddBlobs("blobs2");
var blobContainer2 = blobs2.AddBlobContainer("foocontainer", blobContainerName: "foo-container");
builder.AddProject<Projects.AzureStorageEndToEnd_ApiService>("api")
.WithExternalHttpEndpoints()
.WithReference(blobs).WaitFor(blobs)
.WithReference(blobContainer2).WaitFor(blobContainer2)
.WithReference(queues).WaitFor(queues);
// Client
builder.AddAzureBlobClient("blobs");
builder.AddAzureBlobContainerClient("foocontainer");
app.MapGet("/test", async (BlobServiceClient bsc, BlobContainerClient fooContainerClinet) => { }
builder.AddAzureBlobClient("blobs");
builder.AddKeyedAzureBlobContainerClient("foocontainer");
app.MapGet("/test", async (BlobServiceClient bsc, [FromKeyedServices("foocontainer")] BlobContainerClient fooContainerClinet) => { }
builder.AddAzureBlobClient("blobs")
.AddKeyedAzureBlobContainerClient(blobContainerName: "test-container-1")
.AddKeyedAzureBlobContainerClient(blobContainerName: "test-container-2");
app.MapGet("/", async (BlobServiceClient bsc,
[FromKeyedServices("test-container-1")] BlobContainerClient keyedContainerClient1,
[FromKeyedServices("test-container-2")] BlobContainerClient keyedContainerClient2) => { }
AF are TBD, as well as various tests.
@eerhardt @sebastienros I added tests but I'm really unsure if or what more tests are needed.
Implementation-wise, I think, this is ready.
@eerhardt please let me know if there are any tweaks you want to make it and I'll action those as a follow up.
https://github.com/dotnet/aspire/blob/c029d9caa81ca6bbae49f47925c12a5a04d78ebf/.github/copilot-instructions.md?plain=1#L31
@RussKie why not use Moq?
why not use Moq?
Because it's no longer OSS-friendly.