Open BigBd1 opened 4 years ago
@BigBd1, with a quick look, I don't see an easy way to retrieve the QueueTrigger information from App Configuration. User code can retrieve configuration from App Configuration only at runtime but QueueTrigger attribute requires the information at build time.
This will be something we will have to take a deeper look and probably discuss with the Azure Functions team.
cc: @lisaguthrie @yegu-ms
I'm trying to read the queue name from App Configuration as well, but without luck. And yes, it seems the problem is that settings are read at runtime only.
For ServiceBus connection strings, it is solved by having a standard name for the setting, i.e. AzureWebJobsServiceBus
, which is known by Azure Functions and loaded outside your solution. It isn't a custom string loaded manually and provided to an extension function, as described here.
What is the current status? Is this something you expect to support?
QueueTrigger attribute requires the information at build time.
It does require a string at build time, but by using a %Namespace:Key%
identifier it will be loaded at runtime. I have a suspicion that it might be possible to somehow hook into the configuration system to provide this value 🤔
After all, the key is typically provided in a local.settings.json
@JosXa, the value is available at runtime, but Azure Functions need the value earlier than that. In the current design of Azure Functions, it's too late when the configuration is loaded from App Configuration at runtime.
@BigBd1 Maybe we can generalize the issue title to Use App Configuration setting for Azure Function Triggers
, as every dynamically configurable trigger is affected?
Is there any resolution for this issue? I am looking any way to read the topicname,subscriptionname, ServiceBusConnectionString in ServiceBusTrigger from azure app configuration. Please let me know.
@cvanama I stumble uppon this issue a few weeks ago as I wanted to use App Configuration for SignalR and CosmosDB parameters. This is actually simpler than it looks and you should be able to update the following code with a service bus.
First the Function itself:
public class CosmosSignalFunction
{
[FunctionName("function")]
public async Task Run(
[CosmosDBTrigger(
databaseName: "%CosmosDB:DatabaseName%",
collectionName: "%CosmosDB:CircleRepository:Name%",
ConnectionStringSetting = "CosmosDB:ConnectionString",
CreateLeaseCollectionIfNotExists = true,
LeaseCollectionName = "leases")]IReadOnlyList<Document> input,
[SignalR(
HubName = "WishlistHub",
ConnectionStringSetting = "SignalR:ConnectionString")] IAsyncCollector<SignalRMessage> signalRMessages,
ILogger log)
{
foreach (var entry in input)
{
// Do stuff
}
}
}
As you can see, nothing much here, I'm just using bindings expression for my parameters. Cf: https://docs.microsoft.com/en-us/azure/azure-functions/functions-bindings-expressions-patterns
The magic happens in the Startup class of the function (I assume that you use Azure Function ~2 or higer), this is where you inject all your services and dependencies.
public class Startup : IWebJobsStartup
{
public IConfiguration Configuration { get; set; }
public void Configure(IWebJobsBuilder builder)
{
var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.CreateDefaultAzureFunctionConfiguration();
Configuration = configurationBuilder.Build();
builder.Services.Replace(ServiceDescriptor.Singleton(typeof(IConfiguration), Configuration));
ConfigureService(builder.Services);
}
public IServiceCollection ConfigureService(IServiceCollection services)
{
// Options
services.Configure<DefaultDocumentDbOptions>(
Configuration.GetSection(DefaultDocumentDbOptions.SectionName));
return services;
}
}
The important line is that one:
builder.Services.Replace(ServiceDescriptor.Singleton(typeof(IConfiguration), Configuration));
This will replace the configuration injected through the App Settings by the Azure Function SDK by the configuration built with App Configuration. So when using the parameters bindings expressions you must refer to the App Configuration section of your parameter.
Btw, the configurationBuilder.CreateDefaultAzureFunctionConfiguration()
is a custom extension method that manage the App Configuration with AddAzureAppConfiguration
, there is nothing special there.
@JulesP96 Thanks lot for your reply, i will try this approach and will get back to you if found any issues.
@JulesP96 this worked perfectly thank you.
One thing that tripped me up - notice that Connection string is not being replaced here and isn't surrounded by %
it is literally the name of the setting that holds the connection string.
Also, while this works I do get the following warning
The Functions scale controller may not scale the following functions correctly because some configuration values were modified in an external startup class.
For my purposes this is not an issue because we are actually limiting the instances to specifically not scale (so downstream services aren't overwhelmed) but it would be great for azure app configuration to be supported first-class by azure functions.
@JulesP96 thanks for sharing. Just add a note for others who may come across this thread.
IConfiguration
. You can add Azure App Configuration as an extra configuration source to your Function App. See details in the quick start.The Function App sample in this repo is updated to include this https://github.com/Azure/AppConfiguration/blob/main/examples/DotNetCore/AzureFunction/FunctionApp/ReadQueuedMessage.cs
Is there also a solution for this problem in case a out of process function is used. Unfortunately the solution mentioned by @JulesP96 does not seem to work in that scenario. I added it to the program.cs but if I set a breakpoint it hits only after the function is started.
.ConfigureServices((context, services) => { var configuration = context.Configuration; services.Replace(ServiceDescriptor.Singleton(typeof(IConfiguration), configuration));
Is there also a solution for this problem in case a out of process function is used. Unfortunately the solution mentioned by @JulesP96 does not seem to work in that scenario. I added it to the program.cs but if I set a breakpoint it hits only after the function is started.
.ConfigureServices((context, services) => { var configuration = context.Configuration; services.Replace(ServiceDescriptor.Singleton(typeof(IConfiguration), configuration));
I have the same problem, did you find any solution?
No unfortunately not. I am using the functions configuration for now. The out of process functions are not mature at all, there are many things that do not work yet or only work with a work around if you do something more than the basic stuff.
The support for expression resolution for the out-of-process Azure Functions is tracked at https://github.com/Azure/azure-functions-dotnet-worker/issues/1253.
Is there any update on this? Now NET7 only supports azure functions isolated and having to replicate configurations in each function instead of using app configuration is pretty bad. Considering we COULD do it in Azure Function In-Process
While we are waiting for the Azure Functions team to address https://github.com/Azure/azure-functions-dotnet-worker/issues/1253. An alternative solution is to leverage the App Configuration reference feature in App Service/Azure Functions:
Assume you have a Storage queue triggered Function app and you reference the queue name from the variable queuename
in your Function. You can
Storage:QueueName
with no label in App Configuration for the actual queue name.queuename
in Azure Functions and set its value to something like this:
@Microsoft.AppConfiguration(Endpoint=https://<your-store-name>.azconfig.io; Key=Storage:QueueName)
What's used in step 2 is an App Configuration reference. See here for more information. This way, you can manage your Function trigger information in App Configuration and step 2 is a one-time change.
Hello,
In an Azure Function V2, is it possible to bind the connection string or the queue name of the QueueTrigger attribute to an Azure App Configuration Setting ?
Thanks for your help !