Using http header value in azure function binding - azure

I am trying to read the api_key from the headers and pass it as binding expression, as show below:
{
"type": "table",
"direction": "in",
"name": "subscriptions",
"tableName": "subscriptions",
"partitionKey": "{api_key}",
"take": "50",
"connection": "learnbindingslab1_STORAGE"
}
what would the correct expression to get the api_key from the request headers?

It seems you can use any value under context.bindingData, and you can access nested data with dot notation - so in this case given:
context.bindingData =
{
"headers": {
"some-header": "value"
}
}
You can use it as a binding expression in Id/PartitionKey/sqlQuery with {headers.some-header}.
{
"Id": "{headers.some-id}",
"PartitionKey": "{headers.some-key}",
"sqlQuery": "SELECT * FROM O WHERE O.key = {headers.some-value}"
}

Related

Handling optional parameters in Azure function table bindings

I'm trying to use a filter on an Azure function to look up a row in a table based on an optional route parameter. If the parameter isn't provided, or doesn't match a row, a default row should be returned. This works if I provide a matching value, or a wrong value, I get a row as I expect. If I provide no value at all, I get the following error:
Exception while executing function: Functions.link. Microsoft.Azure.WebJobs.Extensions.Storage: Object reference not set to an instance of an object.
The three key bits (AFAIU) are:
httpTrigger route: "link/{ref?}"
Table filter: "Email eq '{ref}' or Default eq true"
Endpoint URL: https://[subdomain].azurewebsites.net/api/link/(ref)
Is there some way to construct the filter or route so that I get the second clause of the filter when the optional parameter is not provided? Or is there a better way to do this?
My full function.json looks like this:
{
"bindings": [
{
"authLevel": "anonymous",
"type": "httpTrigger",
"route": "link/{ref?}",
"direction": "in",
"name": "req",
"methods": [
"get"
]
},
{
"name": "emailRule",
"type": "table",
"take": "1",
"filter": "Email eq '{ref}' or Default eq true",
"tableName": "RedirectRules",
"connection": "TestStorageConnectionAppSetting",
"direction": "in"
},
{
"type": "http",
"direction": "out",
"name": "res"
}
]
}
Try to use this route "route": "link/{ref=''}", this way you dont have null value but always empty string

How to insert data to bigquery table with custom fields with NodeJS?

I'm using npm BigQuery module for inserting data into bigquery. I have a custom field say params which is of type RECORD and accept any int,float or string value as a key value pair. How can I insert to such fields?
Looked into this, but could not find anything useful
[https://cloud.google.com/nodejs/docs/reference/bigquery/1.3.x/Table#insert]
If I understand correctly, you are asking for a map with ANY TYPE value, which is not support in BigQuery.
You may have a map with value type info with a record like below schema.
Your insert code needs to pick correct type_value to set.
{
"name": "map_field",
"type": "RECORD",
"mode": "REPEATED",
"fields": [
{
"name": "key",
"type": "STRING",
},
{
"name": "int_value",
"type": "INTEGER"
},
{
"name": "string_value",
"type": "STRING"
},
{
"name": "float_value",
"type": "FLOAT"
}
]
}

Nested iteration over JSON using groovy closure in REST-assured

I have the following JSON response for my REST endpoint:
{
"response": {
"status": 200,
"startRow": 0,
"endRow": 1,
"totalRows": 1,
"next": "",
"data": {
"id": "workflow-1",
"name": "SampleWorkflow",
"tasks": [
{
"id": "task-0",
"name": "AWX",
"triggered_by": ["task-5"]
},
{
"id": "task-1",
"name": "BrainStorming",
"triggered_by": ["task-2", "task-5"]
},
{
"id": "task-2",
"name": "OnHold",
"triggered_by": ["task-0", "task-4", "task-7", "task-8", "task9"]
},
{
"id": "task-3",
"name": "InvestigateSuggestions",
"triggered_by": ["task-6"]
},
{
"id": "task-4",
"name": "Mistral",
"triggered_by": ["task-3"]
},
{
"id": "task-5",
"name": "Ansible",
"triggered_by": ["task-3"]
},
{
"id": "task-6",
"name": "Integration",
"triggered_by": []
},
{
"id": "task-7",
"name": "Tower",
"triggered_by": ["task-5"]
},
{
"id": "task-8",
"name": "Camunda",
"triggered_by": ["task-3"]
},
{
"id": "task-9",
"name": "HungOnMistral",
"triggered_by": ["task-0", "task-7"]
},
{
"id": "task-10",
"name": "MistralIsChosen",
"triggered_by": ["task-1"]
}
]
}
}
}
I am using rest-assured with a groovy gpath expression for an extraction as follows:
given()
.when()
.get("http://localhost:8080/workflow-1")
.then()
.extract()
.path("response.data.tasks.findAll{ it.triggered_by.contains('task-3') }.name")
which correctly gives me [Mistral, Ansible, Camunda]
What I am trying to achieve is to find the task names that are triggered by the InvestigateSuggestions task. But I don't know for sure that the taskId I have to pass in to contains() is task-3; I only know its name i.e. InvestigateSuggestions. So I attempt to do:
given()
.when()
.get("http://localhost:8080/workflow-1")
.then()
.extract()
.path("response.data.tasks.findAll{
it.triggered_by.contains(response.data.tasks.find{
it.name.equals('InvestigateSuggestions')}.id) }.name")
which does not work and complains that the parameter "response" was used but not defined.
How do I iterate over the outer collection from inside the findAll closure to find the correct id to pass into contains() ??
You can make use of a dirty secret, the restAssuredJsonRootObject. This is undocumented (and subject to change although it has never change as far as I can remember in the 7 year+ lifespan of REST Assured).
This would allow you to write:
given()
.when()
.get("http://localhost:8080/workflow-1")
.then()
.extract()
.path("response.data.tasks.findAll{
it.triggered_by.contains(restAssuredJsonRootObject.response.data.tasks.find{
it.name.equals('InvestigateSuggestions')}.id) }.name")
If you don't want to use this "hack" then you need to do something similar to what Michael Easter proposed in his answer.
When it comes to generating matchers based on the response body the story is better. See docs here.
I'm not sure if this is idiomatic but one approach is to find the id first and then substitute into another query:
#Test
void testCase1() {
def json = given()
.when()
.get("http://localhost:5151/egg_minimal/stacko.json")
// e.g. id = 'task-3' for name 'InvestigateSuggestions'
def id = json
.then()
.extract()
.path("response.data.tasks.find { it.name == 'InvestigateSuggestions' }.id")
// e.g. tasks have name 'task-3'
def tasks = json
.then()
.extract()
.path("response.data.tasks.findAll{ it.triggered_by.contains('${id}') }.name")
assertEquals(['Mistral', 'Ansible', 'Camunda'], tasks)
}

Azure Function binding: get both EventData and strongly typed message

I have the following function definition.
Message type:
type MailboxItem = {
CustomerID: int
AssetID: int
}
Code:
let Run(item: MailboxItem, userNames: string, log: TraceWriter) =
log.Verbose("F# function executing for " + item.AssetID.ToString())
And function.json:
{
"bindings": [
{
"type": "eventHubTrigger",
"name": "item",
"direction": "in",
"path": "eventhubpath",
"connection": <connection>,
"consumerGroup": "$Default"
},
{
"type": "blob",
"name": "userNames",
"path": "blobpath/{CustomerID}-{AssetID}",
"connection": <connection>,
"direction": "in"
}
],
"disabled": false
}
As you can see, I'm using properties of the incoming message to bind an input blob from Blob Storage.
Now, I need to extend my function to access some metadata of the incoming message via EventData class (e.g. sequence number). Is it possible to add EventData parameter but also keep the binding to properties of the message body?
No not currently, unfortunately, though this is a common ask and something we're tracking in our repo here and will hopefully get to soon. Until we do, it is an either/or - you can bind to EventData or your custom POCO.

Error indexing method FunctionName does not resolve to a value

Does anyone know why I'm getting this error?
Here is my SendGrid output binding:
{
"bindings": [
{
"name": "docId",
"type": "queueTrigger",
"direction": "in",
"queueName": "movedocument",
"connection": "cpoffice365_STORAGE"
},
{
"type": "sendGrid",
"name": "message",
"apiKey": "<MYSENDGRIDKEY>",
"from": "<MYFROMEMAIL>",
"direction": "out"
}
],
"disabled": false
}
My code compiles, but then it throws this error in the log:
Microsoft.Azure.WebJobs.Host: Error indexing method 'Functions.<MYFUNCTIONAME>'. Microsoft.Azure.WebJobs.Host: '<MYSENDGRIDKEY>' does not resolve to a value.
Statto,
Please make sure you define an app setting (Function app settings > App Settings) with the name matching what you've used for your binding configuration, where the value is your Sendgrid key.
The binding configuration expects that to be an app setting name, not the actual key.
Thanks!

Resources