Azure / azure-functions-dotnet-worker

Azure Functions out-of-process .NET language worker
MIT License
432 stars 184 forks source link

ServiceBusTrigger ignores some configuration providers #2727

Open zvrba opened 2 months ago

zvrba commented 2 months ago

Description

On NET8 using the latest version (5.22.0) of Microsoft.Azure.Worker.Extensions.ServiceBus. My function signature looks like this

        public async Task Run(
            [ServiceBusTrigger("myqueue", Connection = "ServiceBus")]
            ServiceBusReceivedMessage message,
            ServiceBusMessageActions messageActions)

ServiceBus key is defined in Azure App Configuration service; the definition looks like this when inspecting configuration on the host object:

{Path = ServiceBus}
{Path = ServiceBus:FullyQualifiedNamespace, Value = <redacted>.servicebus.windows.net, Provider = AzureAppConfigurationProvider}

Running the function results in the following error in console output: "The listener for function 'Functions.DrainV1' was unable to start. Microsoft.Azure.WebJobs.Extensions.ServiceBus: Service Bus account connection string with name 'ServiceBus' does not exist in the settings. Make sure that it is a defined App Setting.".

On the other hand, when I use Connection = "ServiceBusX" with the following definition in the configuration

{Path = ServiceBusX}
{Path = ServiceBusX:FullyQualifiedNamespace, Value = <redacted>.servicebus.windows.net, Provider = EnvironmentVariablesConfigurationProvider}

the function starts up successfully.

Note that the only difference in the definitions of ServiceBus and ServiceBusX is the configuration provider.

Steps to reproduce

Set up a simple functions project with app configuration provider as follows (the settings are for local development) and single function with service bus trigger as given in the description.

    private static void Main(string[] args)
    {
        var opts = new Azure.Identity.DefaultAzureCredentialOptions
        {
            ExcludeManagedIdentityCredential = true,
            ExcludeWorkloadIdentityCredential = true,
        };
        var host = new HostBuilder()
            .ConfigureAppConfiguration(b =>
            {
                b.AddAzureAppConfiguration(o => o.Connect(
                    new Uri("https://<redacted>.azconfig.io"),
                    new Azure.Identity.DefaultAzureCredential(opts)));
            })
            .ConfigureFunctionsWebApplication()
            .ConfigureServices(services =>
            {
                services.AddApplicationInsightsTelemetryWorkerService();
                services.ConfigureFunctionsApplicationInsights();
                services.AddSingleton<IAuditRecordWriter, AuditRecordWriterV1>();
            })
            .Build();

Define ServiceBus connection in azure app configuration, and ServiceBusX connection in local.settings.json. Try using both in ServiceBusTrigger; when using ServiceBus the function fails to start up; when using ServiceBusX the function starts up successfully.

pctrung commented 2 months ago

I am experiencing the exact same issue as you, where the Connection attribute parameter of ServiceBusTrigger cannot be retrieved from Azure App Configuration, but it works fine when retrieved from local.settings.json. Additionally, there is also an issue with using %queueNameInConfiguration%to get the queue name from Azure App Configuration (but it also works fine with local.settings.json).

Moreover, I am facing a similar issue with TimerTrigger. I believe this issue occurs with attributes that use configuration values from a provider other than local, such as Azure App Configuration.

The steps to reproduce are the same as yours. Thank you, Azure team, for looking into this issue. I look forward to your response.

nicoletahermeneanu commented 3 weeks ago

I am facing the same issue as @pctrung with queue name and Connection attribute.

Is there any solution for it?

paulinventome commented 1 week ago

To add another voice, I am seeing the same issues across not Just ServiceBusTrigger but BlobTrigger and I imagine the rest of them.

They don't seem to be looking in App Configuration as a provider for anything at the moment.

Also going beyond that I've found that combining App Configuration and Managed Identity gets even less support because I don't think it's able to look at the whole __ syntax, even when we change that to a :

For example variablename_fullyQualifiedNamespace works in local settings but the same in App Configuration just doesn't resolve and I've tried every way I can think of.

almightydegu commented 13 hours ago

whats interesting with this is that it appears to not look at any of the configuration providers.

I tried to add the connection string to the environment variables:

var serviceBusConnection = builder.Configuration["ServiceBus:Namespace"];

Environment.SetEnvironmentVariable("ServiceBusConnection:fullyQualifiedNamespace", serviceBusConnection);

builder.Configuration.AddEnvironmentVariables();

So it looks like this:

{Path = ServiceBusConnection:fullyQualifiedNamespace, Value = <<REDACTED>>, Provider = EnvironmentVariablesConfigurationProvider}

But I still get "Make sure that it is a defined App Setting"

As a bonus, I tried manually setting it after loading the local.settings.json

builder.Configuration
    .SetBasePath(Environment.CurrentDirectory)
    .AddJsonFile("host.json", true)
    .AddJsonFile("local.settings.json", true);

builder.Configuration["ServiceBusConnection:fullyQualifiedNamespace"] = "<<REDACTED>>";

and that looks like this

{Path = ServiceBusConnection:fullyQualifiedNamespace, Value = <<REDACTED>>, Provider = JsonConfigurationProvider for 'local.settings.json' (Optional)}

But even with the provider being 'local.settings.json' still didn't work.