I'm trying to create a super basic Azure Function, but am having trouble with environment variables. Following various tutorials online,
var config = new ConfigurationBuilder()
.SetBasePath(context.FunctionAppDirectory)
.AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables()
.Build();
log.Info(config["AzureWebJobsStorage"]);
My local.settings.json looks like this:
{
"IsEncrypted": false,
"Values": {
"FUNCTIONS_WORKER_RUNTIME": "<language worker>",
"AzureWebJobsStorage": "abc123",
"AzureWebJobsDashboard": "abc123",
"MyBindingConnection": "abc123"
},
"Host": {
"LocalHttpPort": 7071,
"CORS": "*"
}
}
When I run this locally, that
log.Info(config["AzureWebJobsStorage"]);
line returns nothing... but when I deploy to Azure I see "abc123" in the console.
If, however, I alter that line to
log.Info(config["Values:AzureWebJobsStorage"]);
Then when I run locally, I see "abc123" but when I deploy to Azure I see nothing.
Is there something I'm missing to be able to reach the environment variables the same way locally vs deployed?
EDIT: To clarify, these settings are configured in the app settings for the function:
Assuming you are using targeting the ~2 runtime for your Azure Functions you can access your configuration values through:
log.Info(Environment.GetEnvironmentVariable("AzureWebJobsStorage", EnvironmentVariableTarget.Process));
Those environmental variables work when you are testing your function locally. However, when you deploy to the Azure Function Portal, you need to setup your variables using their built-in system to handle Environmental Variables.
Copy and past your key-values into the sections that I highlighted in the image below.
<
Related
I have a Function App which is successfully running locally and successfully running as "Azure Function App Container",
but when I'm trying to deploy it as simply "Azure Function App", right after publishing it can't read the fields that I put in the appsettings.json file (I put there s3 key access and secret key among other things), the error that is shown is that "No RegionEndpoint or ServiceURL configured", which should be taken from the appsettings.json file.
This is what happens in my startup class:
public override void Configure(IFunctionsHostBuilder builder)
{
var config = new ConfigurationBuilder()
.SetBasePath(Environment.CurrentDirectory)
.AddJsonFile("appsettings.json", false)
.AddUserSecrets(Assembly.GetExecutingAssembly(), false)
.AddEnvironmentVariables()
.Build();
builder.Services.AddLogging();
builder.Services.AddSingleton<IConfiguration>(config);
builder.Services.AddSingleton(svc =>
{
var client = new AzureLogAnalyticsClient(
config[LogAnalyticsWorkspaceID],
config[LogAnalyticsKey]);
client.TimeStampField = config["LogAnalyticsTimestampField"];
return client;
});
}
An Azure Function App deployment will not read appsettings.json by default. Instead, put those configuration values in the Azure Function's application settings.
This can be done by logging into the Azure portal, going to your Azure Function, then:
Click "Configuration" on the Azure Function blade.
Choose Application Settings in the header.
Enter your settings in the table below.
I have created an Azure Function v2. In most articles I people suggest following:
var config = new ConfigurationBuilder()
.SetBasePath(context.FunctionAppDirectory)
.AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables()
.Build();
Does a function hosted on azure also have a local.settings.json file? Will this code snippet get the app settings defined in Azure? Or do you need to change local.settings.json before publish? I thought local.settings.json was a local developer thing?
Is there any recommended practices using above snippet vs
Environment.GetEnvironmentVariable("xx")?
The first way you posted works just fine, both locally and in the cloud.
Note: In Azure, there is no local.settings.json (or should never be). This is only being used when debugging locally. There it is being picked up by the Functions runtime the same way it picks up AppSettings when running in Azure - and the settings are injected into your app as env variables. I have been using this for most of the time.
However, I recently started to switch to the second way, using Environment variables (Environment.GetEnvironmentVariable("xx")). Why? Simply because it is shorter and requires not extra usings etc. Apart from that there is no difference that I am aware of in using either of those ways.
I'm currently setting up a multiple publisher/single subscriber architecture, using Azure Storage Queues to buffer events and Azure Functions as the subscriber.
Publisher -> Queue -> Function
Creating the function is no problem, the part I am trying to work out is how to set up a development and a production deployment of the same function. I have created the function in Visual Studio, and the connection is a constant string literal:
public static class FooAdded
{
[FunctionName("FooAdded")]
public static void Run([QueueTrigger("tracker-readings", Connection = "https://foo.queue.core.windows.net/?sv=...")]string myQueueItem, TraceWriter log)
{
log.Info($"C# Queue trigger function processed: {myQueueItem}");
}
}
How can I provide a different value for the connection, depending on whether I deploy to the development environment or the live environment?
To set up local debug environment
You can use local.settings.json file to define the local settings. The prerequisite for using Azure storage locally is that you need to have Azure Storage Emulator running on your machine. In the local.settings.json file define the Azure Storage Account connection string as UseDevelopmentStorage=true. The file should look something like this:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"AzureWebJobsDashboard": "UseDevelopmentStorage=true"
}
}
By default, if no value is provided for the Connection property of the QueueTrigger attribute, it will use the AzureWebJobsStorage setting:
public static class FooAdded
{
[FunctionName("FooAdded")]
public static void Run([QueueTrigger("tracker-readings")]string myQueueItem, TraceWriter log)
{
log.Info($"C# Queue trigger function processed: {myQueueItem}");
}
}
Alternatively, if you want to explicitly specify a connection string, then you can set the Connection to the name of the connection string (not the connection string itself), and add an entry for it in the Values section of the configuration file:
QueueTrigger("tracker-readings", Connection = "CustomConnection")
In the local.settings.json file:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"AzureWebJobsDashboard": "UseDevelopmentStorage=true",
"CustomConnection": "Some custom connection string"
}
}
For more details refer to the official documentation:
Develop and run Azure functions locally
App settings reference
To set up an Azure environment:
The values in local.settings.json do not get published to Azure, and so a value for each setting needs to be defined in the Azure environment that you are deploying to. Note that the values for AzureWebJobsStorage and AzureWebJobsDashboard are set automatically based off the storage account you choose when creating the function.
The easiest way to define settings is through the Azure portal. Go to Application Settings in the Function App and define the actual value of the storage account connection string. You do not need to make any code changes to the azure function, it will automatically pick up the connection string from application settings.
Alternatively, you can use Azure Resource Manager templates, to deploy and update the environment settings programmatically.
Each function app you create in Azure has its own environment, so after providing values for the relevant settings, you can deploy your function to multiple environments in Azure (Dev/Test/Prod etc.) as well as debug your code locally without changing connection strings everytime.
Have the connection string in an environment variable(or an app setting in app services). You can then have the app setting set to to different values in different environments.
I am trying to work out is how to set up a development and a production deployment of the same function.
I am not clear why you want to create a function both as production and development.
Actually, Azure billing is based on your app service plan, so you create one more azure function may not cost more. You could create two function to distinguish them more clearly.
If you still want to use a single function, as Travis said, you could set two connection string in app settings for different environment.
This is a well known scenario and fully supported. All you need to do manage you deployment with the ARM Template and a Parameter File.
Deploy resources with Resource Manager templates and Azure PowerShell
The connection string, along with any other Sub/Resource Group dependent settings are just parameters.
You can set Connection to a config value (something like Connection=AppSettingsKey.DatabaseConnectionString) and then have different settings for different platforms (dev, staging, prod).
Depending on your tooling for build and deployment, you can inject config values for connection strings during one of these steps.
Another option would be to use a Keyvault secret that stores the connection string.
I have the following function, which I define locally and am able to debug it normally.
[FunctionName("QueueTrigger")]
public static void DUMMYFUNCTION(
[QueueTrigger("myqueue", Connection = "AzureWebJobsStorage")]string myQueueItem, TraceWriter log)
{
log.Info($"C# function processed: {myQueueItem}");
}
Locally, "AzureWebJobsStorage" is defined in the local.settings.json file to use the storage account which has "myqueue". In the function settings on Azure "AzureWebJobsStorage" is also set to the correct connection string (same as the one set locally). That means, I do not have the same problem as in Azure Function does not execute in Azure (No Error)
Now, I use Visual Studio Team Service to host my source code in a git repository. I've configured the deployment to use the source code and deploy the functions contained in it.
I don't think the issue is related to VSTS because the deployment is performed successfully and the function is displayed in my functions list:
After the deployment, the file function.json is generated and has the content below:
{
"generatedBy": "Microsoft.NET.Sdk.Functions.Generator-1.0.8",
"configurationSource": "attributes",
"bindings": [
{
"type": "queueTrigger",
"connection": "AzureWebJobsStorage",
"queueName": "myqueue",
"name": "myQueueItem"
}],
"disabled": false,
"scriptFile": "../bin/myAssembly.dll",
"entryPoint": "myAssembly.MyClass.DUMMYFUNCTION"
}
The problem is that, when I add an item to the queue while debugging it locally, the function is executed, but when the function is running on azure it does not.
What do I need to change in the code to have it work on azure as well? I thought it would work out-of-the-box.
Is your function running at all? If you go in the KUDU, do you see any log that your function actually ran?
If your function is not running at all, Azure functions 2 (using the .NET Standard 2 framework) is still in preview (beta). So when you deploy your function through, make sure to go in the Application Settings of your function app and set the FUNCTIONS_EXTENSION_VERSION value to beta
I have a .NET Core 2.0 Web API that is failing to read the environment specific app.settings file. As far as I can tell I have followed all the relevant steps.
This is my Startup.cs constructor:
public Startup(IHostingEnvironment env)
{
var config = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables();
}
I then have an appsettings.json file structure of:
appsettings.json
-appsettings.debug.json
-appsettings.release.json
-appsettings.production.json
And on the server where my API is deployed to I have a system environment variable key/value pair of
Variable = ASPNETCORE_ENVIRONMENT Value = Release
But when I make calls into the API the appsettings.production.json values are used, which (from what I understand) is the default when an environment variable of ASPNETCORE_ENVIRONMENT is not found.
Thoughts on what my setup might be missing to cause this default behavior?
You haven't specified, but I'm assuming your running in IIS. If that's the case, you need to edit the advanced properties of your App Pool and set the "Load User Profile" option to true. Otherwise, it won't actually read from your environment variables.