Azure Functions table binding not being created when developing locally - azure

I'm attempting to use an output table binding with an Azure Function V2 (node).
I have added the table binding to function.json, as described in the documentation.
{
"tableName": "Person",
"connection": "MyStorageConnectionAppSetting",
"name": "tableBinding",
"type": "table",
"direction": "out"
}
And then I am attempting to insert some content in to that table, again using the example as described in the documentation.
for (var i = 1; i < 10; i++) {
context.bindings.tableBinding.push({
PartitionKey: "Test",
RowKey: i.toString(),
Name: "Name " + i
});
}
To confirm - I have also added a setting called MyStorageConnectionAppSetting in to local.settings.json, with a valid Storage Account connection string as it's value.
Sadly though, this is failing and I'm seeing the following error -
System.Private.CoreLib: Exception while executing function: Functions.config. System.Private.CoreLib: Result: Failure
Exception: TypeError: Cannot read property 'push' of undefined
It seems that the binding object has not be created as expected, but I have no idea why.
The package Microsoft.Azure.WebJobs.Extensions.Storage is included in extensions.csproj, and the Function App starts just fine when I call func start.
Although I believe that no connection to the Storage Account is taking place, I did try to run my function both when the Table existed, and when it didn't.

Make sure the parameter has been initialized before usage. The output binding is undefined unless it's initialized or assigned value.
context.bindings.tableBinding = [];

Related

App Insights Connection String reference, give ERROR BCP178, with for loop

I have a bicep that creates apps in for loop.
var App = {
(...)
}
module app 'app:latest' = [for i in range(0, length(App.appServices)): {
name: 'app${i}'
params: {
(...)
}
}]
I want to connect it with app insights.
I found I could use reference to resolve APPLICATIONINSIGHTS_CONNECTION_STRING:
siteConfig: {
linuxFxVersion: 'NODE|14-lts'
appSettings: [
{
name: 'APPLICATIONINSIGHTS_CONNECTION_STRING'
value: reference(resourceId(resourceGroup().name,'Microsoft.insights/components/', 'app1'), '2020-02-02').ConnectionString
}
And unfortunately this throw error:
Error BCP178: This expression is being used in the for-expression, which requires a value that can be calculated at the start of the deployment. You are referencing a variable which cannot be calculated at the start ("App" -> "applicationinsights_connection_string" -> "reference").
INFO: Command ran in 17.855 seconds (init: 0.252, invoke: 17.602)
How do I make it work? How do I force bicep to resolve it first?
Is there another way to link apps created with for loop with application insights?
P.S
code above works fine without for loop for a single app.
Error BCP178: This expression is being used in the for-expression, which requires a value that can be calculated at the start of the deployment.
This error means that referencing value must be given before the loop begins. So, build an array of connection strings outside of the loop and then reference that array within the loop.
create an array of connection strings by using a for loop outside of the module declaration. We then reference this array inside the loop that creates the app modules and assign the appropriate connection string to the params. appInsightsConnectionString property.
var appInsightsConnections = [ for i in range(0, length(app1.appServices)): ```
reference(resourceId(resourceGroup().name,'Microsoft.insights/components/', 'app1'), '2020-02-02').ConnectionString]
Add this in your bicep code:
params: {
(...)
appInsightsConnectionString: appInsightsConnections[i]
}
I made the above changes and ran a sample template taken from MSDoc and was able to deploy it successfully.
Refer this template to connect an app service with application insights.

Azure Bicep - Subresource reference with resourceId()

I am deploying an App Gateway on Azure using a Bicep template (relevant pieces shown below).
var applicationGatewayId = resourceId('Microsoft.Network/applicationGateways', applicationGatewayName)
resource applicationGateway 'Microsoft.Network/applicationGateways#2021-08-01' = {
properties: {
urlPathMaps: [
{
properties: {
defaultBackendAddressPool: {
id: '${applicationGatewayId}/backendAddressPools/backendpool-test'
}
}
]
}
}
My question is about the id of the backendAddressPool in the example. I get a warning when compiling: Warning use-resource-id-functions: If property "id" represents a resource ID, it must use a symbolic resource reference, be a parameter or start with one of these functions: extensionResourceId, guid, if, reference, resourceId, subscription, subscriptionResourceId, tenantResourceId. [https://aka.ms/bicep/linter/use-resource-id-functions].
I tried using ${applicationGateway.id}/backendAddressPools/backendpool-test, but that results in a cyclic reference error. For other resource types I used resourceId(), but for this example I wouldn't know how to.
I tried, e.g., resourceId('Microsoft.Network/ApplicationGatewayBackendAddressPool', '${prefix}-backendpool-infocat'), but that seems to result in a different resource type altogether (doesn't compile into the same id, at least).
This question is applicable to other subresources too, such as:
applicationGateway.urlPathMaps.defaultBackendAddressPool
applicationGateway.urlPathMaps.pathRules.backendAddressPool
applicationGateway.urlPathMaps.pathRules.backendHttpSettings
...
So how does one refer to these subresources properly, when there's no readily defined resourceType to be used in resourceId()? Can the warnings be avoided?
Thanks in advance!
Try this:
id:resourceId('Microsoft.Network/applicationGateways/backendAddressPools', applicationGatewayName, applicationGatewayBackendAddressPoolName)

change tabulator's placeholder at runtime

I bumped into the problem of how to change tabulator's placeholder at runtime. As it is suggested to ask questions on StackOverflow, here it is. There is an issue (closed - https://github.com/olifolkerd/tabulator/issues/1415) having a suggested solution that I tried. Unfortunately, it throws an error during creation:
tabulator.min.js:4 Uncaught TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.
at s.redraw (tabulator.min.js:4)
at e.h.redraw (tabulator.min.js:6)
at ResizeObserver.<anonymous> (tabulator.min.js:12)
tabulator version is 4.9.3. jsfiddle: https://jsfiddle.net/ivos/6pq75brv/3/
the setup is simple:
var data = [{id:1}, {id:2}, {id:3}];
var placeholder = $("<span>Waiting for data</span>");
var conf = {
// placeholder: "Waiting for data",
placeholder: placeholder,
columns: [
{ title: "Id", field: "id", headerFilter: "input" },
],
dataFiltered: (filters, rows) =>{
placeholder.text(filters.length > 0 ? 'No Results': 'Waiting for data');
},
};
var t = new Tabulator('#tbl', conf);
setTimeout(function(){ t.setData(data)}, 5000); // timeout is just to show the initial placeholder
If I apply a filter (i.e. 5) I got
Uncaught TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.
at s.redraw (tabulator.min.js:4)
at e.h.redraw (tabulator.min.js:6)
at ResizeObserver.<anonymous> (tabulator.min.js:12)
Because Tabulator uses a virtual DOM you cannot manipulate elements from outside of it.
There is no built in way to change the place holder option once the table has been set.
That being said i can certainly point you to a very hacky way of achieving this, that i would recommend against because it manipulates internal variables and that may result in it not working in future, but it should achieve what you are hoping for.
So assuming you are creating your table on a variable called table, the following should work:
table.options.placeholder = "new placeholder message";

Reading nested attribute in data source (of a Cloud Run service that might not exist) in Terraform

I'm using Terraform v0.14.4 with GCP. I have a Cloud Run service that won't be managed with Terraform (it might exist or not), and I want to read its url.
If the service exists this works ok:
data "google_cloud_run_service" "myservice" {
name = "myservice"
location = "us-central1"
}
output "myservice" {
value = data.google_cloud_run_service.myservice.status[0].url
}
But if it doesn't exist, I can't get it to work!. What I've tried:
data.google_cloud_run_service.myservice.*.status[*].url
status is null
length(data.google_cloud_run_service.myservice) > 0 ? data.google_cloud_run_service.myservice.*.status[0].url : ""
Tried with join("", data.google_cloud_run_service.myservice.*.status)
I get this error: data.google_cloud_run_service.myservice is object with 9 attributes
coalescelist(data.google_cloud_run_service.myservice.*.status, <...>)
It just returns [null], and using compact over the result gets me a Invalid value for "list" parameter: element 0: string required.
Any ideas?
It seems like you are working against the design of this data source a little here, but based on the error messages you've shown it seems like the behavior is that status is null when the requested object doesn't exist and is a list when it does, and so you'll need to write an expression that can deal with both situations.
Here's my attempt, based only on the documentation of the resource along with some assumptions I'm making based on the error message you included:
output "myservice" {
value = (
data.google_cloud_run_service.myservice.status != null ?
data.google_cloud_run_service.myservice.status[0].url :
null
)
}
There is another potentially-shorter way to write that, relying on the try function's ability to catch dynamic errors and return a fallback value, although this does go against the recommendations in the documentation in that it forces an unfamiliar future reader to do a bit more guesswork to understand in which situations the expression might succeed and which it might return the fallback:
output "myservice" {
value = try(data.google_cloud_run_service.myservice.status[0].url, null)
}

How do I add framework assemblies in Azure Function

I need to add System.Web.Script.Serialization and System.Web.Extensions to my function app so that I can deserialize json string using the following code :
JavaScriptSerializer serializer = new JavaScriptSerializer();
dynamic item = serializer.Deserialize<object>("{ \"test\":\"some data\" }");
string test= item["test"];
This does not work :
#r "System.Web.Script.Serialization"
#r "System.Web.Extensions"
How do I add resolve this issue?
I can't get that work, so I ended up using Newtonsoft Json serializer/deserializer. What you need to do is, follow this instruction to upload project.json file to your function app with this content -
{
"frameworks": {
"net46":{
"dependencies": {
"Newtonsoft.Json": "9.0.1"
}
}
}
}
This basically creates dependency. Then add this name space to your code : "using Newtonsoft.Json.Linq". Voila, you can convert your json string to object like this :
dynamic item = JObject.Parse("{number:1000}");
log.Info($"My number is: {item.number}");
The initial reference likely failed because you were trying to add an assembly reference to System.Web.Script.Serialization, which is a namespace. Adding a reference to System.Web.Extensions should work, but using Json.NET is recommended anyway.

Resources