Azure Bicep deployment – non-descript error

Azure deployment can be hard.

To deploy and maintain azure resources, we are using bicep templates (a main template, invoking child modules to create individual resources). In addition we have environment-parameter-files, to encapsulate the differences between each environment.

Today, I had to add some Function App Alerts via the bicep-template. Basically the only part in this task, was to create a new module, that could create the Alerts for an array of Function Apps.

Feeling confident, I made the change, pushed it to the Azure Devops repository and invoked the Devops pipeline.

Sadly it failed with this very non-descriptive failure

ERROR: InvalidTemplate - Deployment template validation failed: 'The
template resource 'xxKeyVault' at line '1' and column '9939' is
not valid: The template function 'reference' is not expected at this
location. Please see https://aka.ms/arm-functions for usage details..
Please see https://aka.ms/arm-functions for usage details.'.

I had no idea about the reason – since i had changed nothing wrt. keyvaults and added no references.

az bicep lint showed no issues.

The ARM-template file that Devops was trying to deploy, was not available (we use MS agents)

Trying local deployment:

az deployment group what-if --name Test --resource-group rg-test-dev
--template-file modules\main.bicep --parameters params\dev.json
--subscription "Test - DEV" --mode Incremental

showed the same error – but gave no indications to the cause.

Doing a bicep build (az bicep build --file modules\main.bicep) produced a template-file, but it was clearly not identical to the one that Devops pipeline did

After hours of debugging, the error turned out to be simple:
module functionAppAlerts 'functionAppAlerts.bicep' = {
name: 'functionAppAlerts'
params: {
actionGroupId: actionGroups.outputs.actionGroupsId
timerTriggeredFunctionApps: functionAppNames_timerTriggered
location: location
tags: tags
}
}

I had not given the module a name.

Currently, I have no idea, how this oversight could lead to the error above.

Broadlink RM Pro – Setup

Bought a Broadlink RM Pro (with Wifi, IR and RF)

To setup without an app:
– Press reset (until it quick-blinks)
– Press reset (until it slow-blinks)
– Now it is in AP mode – showing an SSID called BroadlinkProv (or, on some devices, it is called BroadLink_WiFi_Device)
– Connect to this SSID (no encryption)
– No TCP ports are being listened on
– Broadlink devices uses QUIC protocol over UDP port 80
– It has been reverse engineered here: ipsumdomus.com
– in an test with nmap (sudo nmap -sU -p80-85 –system-dns) ports 82-85 (but NOT 81) also seemed open
– if I scanned more UDP ports, the AP would disappear (probably because it reboots because of no connectivity to cloud)
– python library can can setup (I have not made it work yet, though) and control Broadlink devices: github

Parsing a Database connectionstring to individual values

From time to time, you may have to access (in some code) the individual values of a database connectionstring – and what to do if you only have the connectionstring available?

In my case, it happened in Azure, where we normally use the connectionstring for Function Apps, but when I needed to deploy a Logic App, I suddenly needed the individual values (for the Logic App’s associated ‘API Connection’)

Here it tells us that this C# class can do the parsing, but it only mentions “Initial Catalog” and “Data Source” – and what do we do, if our connectionstring uses “Server” and “Database”

It turns out (also in above description) that the class can also handle the synonyms – so if your connectionstring uses “Database”, you can get that value via “InitialCatalog”.

Short example code showing the synonyms – it can be tested here

public static void Main()
{
var cs = “Server=tcp:yada1.database.windows.net,1433;Database=yada2-dev;Persist Security Info=False;User ID=yada3-dev;Password=yada4;...................”;

System.Data.SqlClient.SqlConnectionStringBuilder sb = new System.Data.SqlClient.SqlConnectionStringBuilder(cs);
Console.WriteLine($”Server: {sb[“Server”]}”);
Console.WriteLine($”DataSource: {sb.DataSource}”);
Console.WriteLine($”Database: {sb[“Database”]}”);
Console.WriteLine($”Database: {sb.InitialCatalog}”);
Console.WriteLine($”User: {sb.UserID}”);
Console.WriteLine($”Password: {sb.Password}”);
}

Azure Bicep Deployment – Maintenance Windows for sql-databases

Automating things using bicep for Azure deployment can be hard.

While it is trivially easy to find out how to configure maintenance windows for an SQL database using the Azure Portal directly, it is equally hard to find out how to set it using bicep deployment

No direct search gives any relevant links (apart from saying the the maintenanceConfigurationId in the bicep-file must a “string”)

Continue reading “Azure Bicep Deployment – Maintenance Windows for sql-databases”

Battery replacement on Ventus GPS Route Logger G730

Disassembling Ventus GPS Route Logger G730 for battery replacement

  • Remove the purple cover that covers the round bottom at the top
    • It can carefully be angled out from the backend, and when it is free, the top part kan be lifted
  • Inside the new opening, there are a metal clip on each side. Push both toward the middle at the same time
    • Top cover now slides off
  • By lifting slightly on the back and pushing on the USB Connector, the whole circuit board can now be pushed out

The battery inside is labeled:

– 502248
+ 450mAh 3.7V

It seems to be glued in place

Returning Json response from Azure Function v3+

It can be a pain to return json-responses from a Function App, when you also want the proper Content-Type HTTP header to be returned, which it of course should.

If you do it the straight-forward way (works the same with OkObjectResult) –

return new BadRequestObjectResult(jsonResponse);

if response contains a json string, it will be returned ok, but the Content-Type will be “text/plain”

BadRequestObjectResult resp = new BadRequestObjectResult(jsonResponse);
resp.ContentTypes.Add(MediaTypeHeaderValue.Parse("application/json"));
resp.Value = jsonResponse;
return resp;

if response contains a json string, the special characters (like “) will be escaped, and it will no longer return valid json, but the Content-Type is ok (application/json)

If the content-type is not set in above example, the special characters are not escaped

Continue reading “Returning Json response from Azure Function v3+”

Boomi – Java keystore

If you need to interact directly with the Java keystore (cacerts) that Boomi uses, then the default password for this is “changeit”

It does not seem to be documented anywhere – but it is included in a few of the example keytool commands that can be found in Boomi Community – for instance the one below.

https://community.boomi.com/s/article/Connecting-to-an-IFS-Applications-server-using-a-self-signed-certificate

 

How to compare two revisions of a Boomi component

Everything that you develop in Boomi (processes, maps, connectors, profiles, etc.) is a component and a component in Boomi is always represented (behind the pretty GUI) as a XML document.

This means, that if you have made any change in a Boomi component, and wants to verify which change that you made, you can determine this by comparing two revisions of the ComponentXML for the changed component. This will be a text-comparison and not a GUI-one, but with a little practice, it is easy enough to interpret.

Continue reading “How to compare two revisions of a Boomi component”

Excel – open as “ReadOnly” / Viewing by default

If you open Excel files from Sharepoint, they by default open in Edit mode.

This sadly means, that whenever people interact with the sheet – for instance by filtering, this filtering will be saved. Extreeeemely annoying.

This may very well not be what you want. Fortunately, you can still set you Excel file to open by default in “Viewing” mode.
Continue reading “Excel – open as “ReadOnly” / Viewing by default”