This follows on from a previous question. I'm trying to build an Azure function to run as a Linux container image in an isolated process using .NET 6 and v4 of the functions runtime.
I have followed the Microsoft guide to get a working, running sample function with HTTP trigger. I have then begun the process of adding my code to the app and immediately become blocked. This is the Main
method of my Program
:
public static void Main()
{
var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults()
.ConfigureAppConfiguration((context, builder) =>
{
builder.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
builder.AddEnvironmentVariables();
})
.ConfigureServices((context, collection) => ConfigureServices(collection, context.Configuration))
.Build();
host.Run();
}
What I've discovered is that the function works fine until I add the line builder.AddEnvironmentVariables();
. With this change only, the function suddenly craps out on startup with the exception:
System.InvalidOperationException at Microsoft.Azure.WebJobs.Script.Workers.Rpc.RpcFunctionInvocationDispatcherLoadBalancer.GetLanguageWorkerChannel
There's a message hidden in there saying "Did not find any initialized language workers" which I understand is Azure Function language for "something bad happened during startup but I'm not going to tell you what or why".
In my particular use case I'm depending on the function being able to use environment variables as a config source because my pipeline will be passing these to the ARM template as site config. So my question is, how is this possible in isolated mode?
Well it turns out that environment variables are added automatically by the call to
ConfigureFunctionsWorkerDefaults
. You can see this here in WorkerHostBuilderExtensions. I have no idea why attempting to add environment variables as a config source in the traditional dotnet core way causes the whole thing to blow up, but at least I'm unblocked. Hope this helps someone else.It's woth also pointing out that this will affect the order in which you use the
ConfigureAppConfiguration
andConfigureFunctionsWorkerDefaults
extensions. Since the latter adds console input and environment variables as config sources, if you also use an appsettings.json on disk it's likely you'll want environment variables to override its config soConfigureFunctionsWorkerDefaults
would need to be called afterConfigureAppConfiguration
. Therefore myProgram
looks like this: