Passing cloud table as an input binding - azure

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

Related

Azure Function - Trigger blob storage copy when last modified

First time working with azure functions. In my run.csx i have
public static void Run(Stream myBlob, string name, ILogger log)
{
log.LogInformation($"C# Blob trigger function Processed blob\n Name:{name} \n Size: {myBlob.Length} Bytes");
}
and in my functions.json i have
{
"bindings": [
{
"name": "myBlob",
"type": "blobTrigger",
"direction": "in",
"path": "insights-logs-auditlogs/{name}",
"connection": "stnhnmspsplunkmgmt_STORAGE"
},
{
"name": "Output",
"path": "test/{rand-guid}",
"connection": "sttestfuncapptest_STORAGE",
"direction": "out",
"type": "blob"
}
]
}
This works fine when i edit existing files in the containers, but i cant figure out how to do the copy when a change has happened. Anyone can point me in the right direction. Greatly appreciate it.
The Blob storage trigger starts a function when a new or updated blob is detected .
As this blob trigger for azure function writes a log when a blob is added or updated in the samples-workitems container.
Try to create a SAS URL for the blob with required permissions with minimum read and then use that for file copy in c# and publish in azure.
Please check this SO reference
[FunctionName("MyBlobTrigger")]
public async void Run([BlobTrigger("uploads/{name}", Connection = "UploadStorageAccount")]CloudBlockBlob myBlob, string name, ILogger log, CancellationToken cancellationToken)
{
// Get SAS for the blob
var sasToken = myBlob.GetSharedAccessSignature();
//SAS URI
var blobSasUrl = $"{myBlob.Uri.AbsoluteUri}{sasToken}";
ShareClient share = new ShareClient(storageConnection, fileShareName);
ShareDirectoryClient directory = share.GetRootDirectoryClient();
ShareFileClient fileShare = directory.GetFileClient(name);
ShareClient share = new ShareClient(storageConnection, fileShareName);
ShareDirectoryClient directory = share.GetRootDirectoryClient();
ShareFileClient fileShare = directory.GetFileClient(name);
try
{
fileShare.Create(myBlob.Properties.Length);
//Copy blob's contents to storage file using async file copy.
//await fileShare.StartCopyAsync(new Uri(blobSasUrl));
}
}
Other references:
c# - Azure Function Blob Trigger copy file to File Share - Stack Overflow
ADF: copy last modified blob - Microsoft Q&A / Microsoft Docs
LastModifiedDate with Azure Data Factory | Azure Blog and Updates | Microsoft Azure

How to set environment variables or inputs in timerTrigger Azure Functions?

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"
}
}

How do I configure 'ConsumerGroup` in local.settings.json while developing Azure Function Version 2

I have below code to catch all the messages arrives at IoT Hub
[FunctionName("device-message--funcapp-v2")]
public static void Run([IoTHubTrigger("testhub",
Connection = "IoTHubEventEndPoint",
ConsumerGroup = "ActualConsumerGroup")]EventData message,
ILogger log)
{
log.LogInformation($"C# IoT Hub trigger:
{Encoding.UTF8.GetString(message.Body.Array)}");
}
This works fine as expected, but now I do not want to hard code the ConsumerGroup. So I added below configuraiton entry in local.settings.json
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"EventHub": "",
"CosmosDb": "",
"ConfigurationConsumerGroup": "ActualConsumerGroup"
}
}
and changed code as below
[FunctionName("device-message--funcapp-v2")]
public static void Run([IoTHubTrigger("testhub",
Connection = "IoTHubEventEndPoint",
ConsumerGroup = "ConfigurationConsumerGroup")]EventData message,
ILogger log)
But it fails.
[1/18/2019 9:47:11 AM] Microsoft.Azure.EventHubs: The messaging entity 'iothub-ns-testhub-945897-3a6f492cc4:eventhub:lctesthub~8191|ConfigurationConsumerGroup' could not be found.
Use ConsumerGroup = "%ConfigurationConsumerGroup%" to read settings from local.settings.json. Check the doc. Note that the connection property of triggers and bindings is a special case and automatically resolves values as app settings, without percent signs.

How do you reference a blob from an Azure Timer Trigger Function?

I have an Azure Timer Trigger Function that should do some calculations and write the results to a json file in a pre-existing blob. How do I reference the pre-existing blob from within the Timer Triggered function?
I can't seem to find any documentation that provides a code sample. Can someone provide one?
First, you need to update your function.json configuration file, to bind the blob to the CloudBlockBlob instance you'll be using in your .csx code. You can edit it in Azure Portal via the "Integrate" option (the one with the lighting icon) under your function, in the Function Apps menu. On the top right of that page is a link that reads "Advanced Editor". Clicking that link will take you to your funciton's function.json file:
You'll see a JSON array named "bindings" that contains a JSON object that configures your timer. You'll want to add another JSON object to that array to bind your blob to a CloudBlockBlob instance that you'll be referencing in your function. Your function.json file will look something like this:
{
"bindings": [
{
"name": "myTimer",
"type": "timerTrigger",
"direction": "in",
"schedule": "0 */5 * * * *"
},
{
"type": "blob",
"name": "myBlob",
"path": "your-container-name/your_blob_filename.json",
"connection": "AzureWebJobsStorage",
"direction": "inout"
}
],
"disabled": false
}
Now you just need to update your function's Run method's signature. It looks like this by default:
public static void Run(TimerInfo myTimer, TraceWriter log)
Add your blob variable to the end of that signature (and also add the necessary includes):
#r "Microsoft.WindowsAzure.Storage"
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
public static void Run(TimerInfo myTimer, TraceWriter log, CloudBlockBlob myBlob)
And you're all set! "myBlob" is bound to the blob "your_blob_filename.json" in your "your-container-name" container.

Azure functions: how to bind query string parameters of http trigger function to SQL query of Cosmos DB

I am trying to run an http trigger Azure function with Cosmos DB input binding. I would like the url of the http trigger to include several parameters on the query string that become bound to the SQL query of the input Cosmos DB binding. I am trying the following bindings in function.json, but it does not work (the function does not even get triggered):
{
"direction": "in",
"type": "httpTrigger",
"authLevel": "anonymous",
"name": "req",
"methods": [ "get" ],
"route": "users/{age=age?}/{gender=gender?}"
},
{
"direction": "in",
"type": "documentDB",
"name": "users",
"databaseName": "Database",
"collectionName": "Users",
"sqlQuery": "SELECT * FROM x where x.age = {age} and x.gender = {gender}",
"connection": "COSMOSDB_CONNECTION_STRING"
},
According to this answer the route constraint users/{age=age?}/{gender=gender?} is valid for Web API, and according to the documentation you can use any Web API Route Constraint with your parameters. Ultimately I would to like make a GET request to the Azure function that looks like api/users?age=30&gender=male. How should this be done then?
I don't think you can configure a Cosmos DB binding to values defined in query parameters e.g. ?age=30. At least I haven't seen any examples like that in the functions documentation.
But you can bind them to the route parameters to achieve the same outcome, which you have pretty much done already.
Keeping that route of users/{age}/{gender}, your Cosmos SqlQuery will then pick up those route parameters when invoking a GET on http://yourfunctionhost/yourfunction/users/30/male
GET and POST parameter will be bound, so they can be used inside the sqlQuery without any additional configuration. Just give it a try, this has definitely changed in the past
You can bind the Query-Values to CosmosDB Input Binding:
Azure Cosmos DB input binding for Azure Functions 2.x and higher
[FunctionName("DocByIdFromQueryString")]
public static IActionResult Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)]
HttpRequest req,
[CosmosDB(
databaseName: "ToDoItems",
collectionName: "Items",
ConnectionStringSetting = "CosmosDBConnection",
Id = "{Query.id}",
PartitionKey = "{Query.partitionKey}")] ToDoItem toDoItem,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
if (toDoItem == null)
{
log.LogInformation($"ToDo item not found");
}
else
{
log.LogInformation($"Found ToDo item, Description={toDoItem.Description}");
}
return new OkResult();
}

Resources