-
Notifications
You must be signed in to change notification settings - Fork 609
AzureStorage auto create blob containers #9008
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
c04eaa3
2b8a4b7
a0a489d
875e113
7078ea2
7a68dc4
01918de
20e71f8
8ed57ef
83ac116
4112b73
05a0921
36edcda
ab1c8a5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# Instructions for GitHub and VisualStudio Copilot | ||
### https://github.blog/changelog/2025-01-21-custom-repository-instructions-are-now-available-for-copilot-on-github-com-public-preview/ | ||
|
||
|
||
## General | ||
|
||
* Make only high confidence suggestions when reviewing code changes. | ||
* Always use the latest version C#, currently C# 13 features. | ||
* Files must have CRLF line endings. | ||
|
||
## Formatting | ||
|
||
* Apply code-formatting style defined in `.editorconfig`. | ||
* Prefer file-scoped namespace declarations and single-line using directives. | ||
* Insert a newline before the opening curly brace of any code block (e.g., after `if`, `for`, `while`, `foreach`, `using`, `try`, etc.). | ||
* Ensure that the final return statement of a method is on its own line. | ||
* Use pattern matching and switch expressions wherever possible. | ||
* Use `nameof` instead of string literals when referring to member names. | ||
|
||
### Nullable Reference Types | ||
|
||
* Declare variables non-nullable, and check for `null` at entry points. | ||
* Always use `is null` or `is not null` instead of `== null` or `!= null`. | ||
* Trust the C# null annotations and don't add null checks when the type system says a value cannot be null. | ||
|
||
|
||
### Testing | ||
|
||
* We use xUnit SDK v3 with Microsoft.Testing.Platform (https://learn.microsoft.com/dotnet/core/testing/microsoft-testing-platform-intro) | ||
* Do not emit "Act", "Arrange" or "Assert" comments. | ||
* We do not use any mocking framework at the moment. Use NSubstitute, if necessary. Never use Moq. | ||
* Use "snake_case" for test method names but keep the original method under test intact. | ||
For example: when adding a test for methond "MethondToTest" instead of "MethondToTest_ShouldReturnSummarisedIssues" use "MethondToTest_should_return_summarised_issues". |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,19 @@ | ||
using Azure.Storage.Blobs; | ||
using Microsoft.Azure.Functions.Worker; | ||
using Microsoft.Extensions.Logging; | ||
|
||
namespace AzureFunctionsEndToEnd.Functions; | ||
|
||
public class MyAzureBlobTrigger(ILogger<MyAzureBlobTrigger> logger) | ||
public class MyAzureBlobTrigger(ILogger<MyAzureBlobTrigger> logger, BlobContainerClient containerClient) | ||
{ | ||
[Function(nameof(MyAzureBlobTrigger))] | ||
[BlobOutput("test-files/{name}.txt", Connection = "blob")] | ||
public string Run([BlobTrigger("blobs/{name}", Connection = "blob")] string triggerString) | ||
public async Task<string> RunAsync([BlobTrigger("blobs/{name}", Connection = "blob")] string triggerString, FunctionContext context) | ||
{ | ||
logger.LogInformation("C# blob trigger function invoked with {message}...", triggerString); | ||
var blobName = (string)context.BindingContext.BindingData["name"]!; | ||
await containerClient.UploadBlobAsync(blobName, new BinaryData(triggerString)); | ||
|
||
logger.LogInformation("C# blob trigger function invoked for 'blobs/{source}' with {message}...", blobName, triggerString); | ||
return triggerString.ToUpper(); | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System.Diagnostics.CodeAnalysis; | ||
using System.Runtime.CompilerServices; | ||
using Aspire.Hosting.ApplicationModel; | ||
using Aspire.Hosting.Azure; | ||
using Azure.Provisioning; | ||
|
||
namespace Aspire.Hosting; | ||
|
||
/// <summary> | ||
/// A resource that represents an Azure Blob Storage container. | ||
/// </summary> | ||
/// <param name="name">The name of the resource.</param> | ||
/// <param name="blobContainerName">The name of the blob container.</param> | ||
/// <param name="parent">The <see cref="AzureBlobStorageResource"/> that the resource is stored in.</param> | ||
public class AzureBlobStorageContainerResource(string name, string blobContainerName, AzureBlobStorageResource parent) : Resource(name), | ||
RussKie marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this implement IResourceWithAzureFunctionsConfig? cc @captainsafia There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My tests (per @captainsafia's guidance) didn't suggest any AF-specific implementations were necessary. As far as my limited knowledge goes, the functions require connections to the storage but not individual components within. |
||
IResourceWithConnectionString, | ||
IResourceWithParent<AzureBlobStorageResource> | ||
{ | ||
/// <summary> | ||
/// Gets the blob container name. | ||
/// </summary> | ||
public string BlobContainerName { get; } = ThrowIfNullOrEmpty(blobContainerName); | ||
|
||
/// <summary> | ||
/// Gets the connection string template for the manifest for the Azure Blob Storage container resource. | ||
/// </summary> | ||
public ReferenceExpression ConnectionStringExpression => Parent.GetConnectionString(BlobContainerName); | ||
|
||
/// <summary> | ||
/// Gets the parent <see cref="AzureBlobStorageResource"/> of this <see cref="AzureBlobStorageContainerResource"/>. | ||
/// </summary> | ||
public AzureBlobStorageResource Parent => parent ?? throw new ArgumentNullException(nameof(parent)); | ||
|
||
/// <summary> | ||
/// Converts the current instance to a provisioning entity. | ||
/// </summary> | ||
/// <returns>A <see cref="global::Azure.Provisioning.Storage.BlobContainer"/> instance.</returns> | ||
internal global::Azure.Provisioning.Storage.BlobContainer ToProvisioningEntity() | ||
RussKie marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
global::Azure.Provisioning.Storage.BlobContainer blobContainer = new(Infrastructure.NormalizeBicepIdentifier(Name)) | ||
{ | ||
Name = BlobContainerName | ||
}; | ||
|
||
return blobContainer; | ||
} | ||
|
||
private static string ThrowIfNullOrEmpty([NotNull] string? argument, [CallerArgumentExpression(nameof(argument))] string? paramName = null) | ||
{ | ||
ArgumentException.ThrowIfNullOrEmpty(argument, paramName); | ||
return argument; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Building new API and experimenting is horribly difficult because of these (and many more) "warnings as errors".
I'll revert this when I get to the finish line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Opps, I forgot to rollback this. I'll fix it in a follow up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you revert this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#9138