How to set environment variables or inputs in timerTrigger Azure Functions? - node.js

I am trying to setup a timerTrigger azure function
My function.json:
{
"disabled": false,
"bindings": [
{
"type": "timerTrigger",
"direction": "in",
"name": "sampleCronTrigger",
"schedule": "*/5 * * * * *",
}
],
"entryPoint": "sampleCron",
"scriptFile": "index.js"
}
In this I need to set an environment variable, but I am not able to do so. I tried looking for some documentation but couldn't find anything which doesn't require some setup on the Azure console?
I can I define environment variables? Or If here is any way I can pass an input to the function, that works too.

App settings in a function app contain global configuration options that affect all functions for that function app. When you run locally, these settings are accessed as local environment variables.
Local settings file
The file local.settings.json stores app settings, connection strings, and settings for Azure Functions Core Tools. Settings in the local.settings.json file are only used by Functions tools when running locally. By default, these settings are not migrated automatically when the project is published to Azure. Use the --publish-local-settings switch when you publish to make sure these settings are added to the function app in Azure.
In Functions, app settings, such as service connection strings, are exposed as environment variables during execution. You can access these settings using process.env, as shown here in the GetEnvironmentVariable function:
module.exports = function (context, myTimer) {
var timeStamp = new Date().toISOString();
context.log('Node.js timer trigger function ran!', timeStamp);
context.log(GetEnvironmentVariable("AzureWebJobsStorage"));
context.log(GetEnvironmentVariable("WEBSITE_SITE_NAME"));
context.done();
};
function GetEnvironmentVariable(name)
{
return name + ": " + process.env[name];
}
There are several ways that you can add, update, and delete function app settings:
From Azure portal.
By using the Azure CLI.
When running locally, app settings are read from the local.settings.json project file.
References:
https://learn.microsoft.com/en-us/azure/azure-functions/functions-app-settings
https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-node#environment-variables
https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-node#environment-variables

Additionally for retrieving values from local.settings.json, another way is to create an IConfigurationRoot object using ExecutionContext executionContext.
ExecutionContext can be added to function definition:
[FunctionName("FunctionName")]
public static async Task Run(
[ServiceBusTrigger(...)]
SomeMessage msg,
ILogger log,
ExecutionContext executionContext)
{
}
After that, you can instantiate an IConfigurationRoot instance, which you instruct to optionally load local.appsettings.json.
var configurationRoot = new ConfigurationBuilder()
.SetBasePath(executionContext.FunctionAppDirectory)
.AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables()
.Build();
With the configurationRoot object, you can retrieve configuration values:
var value = configurationRoot["SomeKey"];
Example local.settings.json:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "...",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"SomeKey": "Value",
},
"Host": {
"LocalHttpPort": "7071"
}
}

Related

Timer based trigger - Testing locally

Trying to test CRON trigger function app locally but getting an error:
"The listener for function 'Functions.timer' was unable to start. Microsoft.Azure.WebJobs.Script: Could not create BlobServiceClient to obtain the BlobContainerClient using Connection: Storage."
local.settings.json
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "",
"FUNCTIONS_WORKER_RUNTIME": "node",
"ConnectionStrings:BlobStorageAccount": "UseDevelopmentStorage=true"
}
}
function.json
{
"bindings": [
{
"schedule": "*/1 * * * *",
"name": "reportScheduler",
"type": "timerTrigger",
"direction": "in"
}
],
"disabled": false
}
and index.js
const timer = async function(context, req) {
context.log("=======PROCESSED=======");
context.res = {
// status: 200, /* Defaults to 200 */
body: "HELLO WORLD",
};
};
module.exports = timer;
Really struggling with the documentation specifically around these error messages and translating those into the required changes in local.settings.json
other information:
npm i -g azure-functions-core-tools#3 --unsafe-perm true
func start
To run the azure functions (whatever the trigger type), need the azure functions core tools to be installed in your system.
That you can install using npm command or executable file installation available in this documentation.
Note: To install the azure function core tools using npm command is: npm i -g azure-functions-core-tools#3 --unsafe-perm true and you have to run this command in integrated terminal of Visual Studio Code.
For Windows, integrated terminal of VS Code is PowerShell, here you can find the integrated terminal:
To Create and run the Timer Triggered Function, please refer this documentation for step by step procedure.
I have created the timer trigger JavaScript Azure Function and started to run the function using command func start, running successfully:
I set the CRON expression to every minute for running the function so it is showing the function runs at every minute in the above output console.
local.settings.json code:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "node"
}
}
And
In your index.js:
const timer = async function(context, req
The req object refers to http request class so the req and res objects should be defined in function.json class like:
This documentation refers to Azure JavaScript Function Http Trigger.

Reading TopicName from config for Azure Function Service Bus Trigger not working

I have a service bus trigger function where I want to load the topic name from config
I have seen this post and I have tried the same approach Previous Question
public async Task MyFunctionAsync(
[ServiceBusTrigger("%TopicName%", "data-subscription", Connection = "event-bus-connection")]
string mySbMsg)
{
}
In my localsettings.json file I have
"bindings": [
{
"%TopicName%": "topic"
}
]
"bindings": [
{
"%TopicName%": "rockit-notification-topic"
}
]
This doesnt work
Microsoft.Azure.WebJobs.Host: Error indexing method 'MyFunction'. Microsoft.Azure.WebJobs.Host: '%TopicName%' does not resolve to a value.
Also, even if this did work, how do I add this to the settings of the function within the portal as this is an item in an array?
You shouldn't add the "bindings" section to you localsettings file.
localsettings.json should look something like that:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"event-bus-connection": "test",
"TopicName":"topic",
"SubsriptionName":"data-subscription"
}
}
On Azure Portal you can directly add it to App Service/Function Configuration like properies with name TopicName, SubsriptionName etc.

Unable to read Azure SignalR Connection String from Azure App Service Configuration Application Settings

I am working on an Azure SignalR application and everything is working fine on my local machine when I set the following section in my appsettings.json:
"Azure": {
"SignalR": {
"ConnectionString": "XXXXX"
}
}
And then initialize in my startup.cs as follows:
services.AddSignalR().AddAzureSignalR();
However when I create the same environment variable in my Azure App Service using App Service>Configration>ApplicationSettings:
My application is unable to start and I get the following application error:
System.ArgumentException: Connection string missing required properties endpoint and accesskey. (Parameter 'connectionString')
at Microsoft.Azure.SignalR.ConnectionStringParser.Parse(String connectionString)
at Microsoft.Azure.SignalR.ServiceEndpoint..ctor(String connectionString, EndpointType type, String name)
When I hardcore my connection string onto the AddAzureSignalR() connectionstring parameter and deploy everything works fine.
It would seem that azuresignalR is unable to pickup this environment variable, despite also being able to see it via the Kudo Appsettings page as Azure:SginalR:ConnectionString.
You need to initiate like this,
string azureSignalrConnectionString = configuration["Azure:SignalR:ConnectionString"];
services.AddSignalR().AddNewtonsoftJsonProtocol().AddAzureSignalR(options =>
{
options.ConnectionString = azureSignalrConnectionString;
});
So I asked this same question on the Azure SignalR github page and below was the answer I got:
EnvironmentVariablesConfigurationProvider automatically replaces __
with : . So when you configures connection string via environment
variables, you should use Azure__SignalR__ConnectionString as the key.
When you configures it via JSON file, you should use the origin key
Azure:SignalR:ConnectionString.
Once I changed it to the double underscores all worked
For net core 5, use:
string azureSignalrConnectionString = Configuration["Azure:SignalR:ConnectionString"];
services.AddSignalR()
.AddAzureSignalR(options =>
{
options.ConnectionString = azureSignalrConnectionString;
});
appsettings.json, like:
{
"Azure": {
"SignalR": {
"ConnectionString": "<your-connection-string>"
}
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}

Passing cloud table as an input binding

I am trying to create an azure function which takes azure table as storage, which then i read in the function. I am able to run the function when i specify the below signature
public static async System.Threading.Tasks.Task RunAsync([TimerTrigger("0 */1 * * * *")]TimerInfo myTimer, [Table("CovidUpdateTable")]CloudTable ServiceFormTable, [Blob("outcontainer/{DateTime}", FileAccess.Write)] Stream outputBlob, ILogger log)
Here, I have to specify the table name in table attribute even when i have specified it in the binding config as below
{
"type": "table",
"name": "ServiceFormTable",
"tableName": "CovidUpdateTable",
"take": 50,
"connection": "AzureWebJobsStorage",
"direction": "in"
}
in portal c# script I can directly bind to CloudTable but in Visual studio, It throws an error if i remove the table attribute and use just cloudtable. I am not sure what is the purpose of tablename in this config when I have to specify the name in table attribute.
When we create the function in Azure portal, it will create a c# script function(csx file) and generate function.json file for us. And the function will read the configs from the function.json file autosomally. So we can directly configure binging in the file and do not need to configure things in the code. But when we create the function in Visual Studio, it will create c# function (cs file) and will not generate function.json file for us. And the function will not read the configs from the function.json file autosomally. So we need to configure these settings with attribute. For more details, please refer to the document
Update
If you want to use the binding properties in local.settings.json, please refer to the following steps
local.settings.json
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"TableConnection": "<your azure table connection string>",
"Tablename": "<your table name>"
}
}
Configure code. You should use [Table("%Tablename%",Connection = "TableConnection")]CloudTable cloudTable, to bing Azure table
For example
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
[Table("%Tablename%",Connection = "TableConnection")]CloudTable cloudTable,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
log.LogInformation(cloudTable.Name);
var query = new TableQuery<DynamicTableEntity>();
foreach (var entity in
await cloudTable.ExecuteQuerySegmentedAsync(query, null))
{
log.LogInformation(
$"{entity.PartitionKey}\t{entity.RowKey}\t{entity.Timestamp}");
}
....
}
For more details, please refer to the document

Azure Functions settings not consistent betwen portal and local

Im working with Azure functions and have a problem.
I declared a local.settings.json file with my variables as follows:
{
"IsEncrypted": false,
"Values": {
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"TopicEndpoint": "my endpoint"
}
}
This allows my azure function to read the settings using:
var config = new ConfigurationBuilder()
.SetBasePath(context.FunctionAppDirectory)
.AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables()
.Build();
var myTopic = config["Values:TopicEndpoint"];
This allows me to publish and export my variables to the portal via:
func azure functionapp
publish myfunctionapp --publish-local-settings -i
However, upon publishing and verifying that the value is in the 'Application Settings' in the portal, the "Values:TopicEndpoint" doesn't exist.
In order to be able to access its value i have to put my variables directly under the json root:
{
"IsEncrypted": false,
"Values": {
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
}
"TopicEndpoint": "my endpoint"
}
That way I can safely use config['TopicEndpoint'] both in my local development environment, as well as on Azure. However, this defeats the purpose of the --publish-local-settings -i as it only exports the values found under the 'Values' key, so I have to create all my settings manually.
Do you know why this happens or if maybe Im missing something?
I guess you use it a bit in a different way it should be. The thing is that the values from the local.settings.json come as environment variables automatically, so you don't have to worry about working with the file at all. That's how we do it on our project and it works on all environments.
// see, just env variables
var configuration = new ConfigurationBuilder().AddEnvironmentVariables().Build();
// and then use
var value = configuration["TopicEndpoint"];
I found the issue.
The problem was that I was adding a separate secret.settings.json as suggested here
https://www.tomfaltesek.com/azure-functions-local-settings-json-and-source-control/
Therefore I was loading my configurations like this:
var config = new ConfigurationBuilder()
.SetBasePath(context.FunctionAppDirectory)
.AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
.AddJsonFile("secret.settings.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables()
.Build();
My local settings file looked like this:
{
"Values": {
"TopicEndpoint": "my endpoint"
}
}
And my secret settings like this:
{
"Values": {
"TopicKey": "my key"
}
}
This caused a conflict so I needed to remove the 'Values' key from the secret.settings.json so that it looked like this:
{
"TopicKey": "my key"
}
This way I am able to both use func azure functionapp publish myfunctionapp --publish-local-settings -i to deploy the values inside my local settings file and use both files as environment variables.

Resources