I say.

A blog by Joakim Beijar, I solve interesting and mundane problems at HappySignals and hack at night on github.com/kaa.

Get API Connection parameters using the Azure REST API

16 Oct 2018

Sometimes the documentation provided by Microsoft for Azure leaves you wondering and wanting. Here’s how you can use the REST API of Azure to interrogate for details about connection parameters required to do ARM deployment of API connections.

Unless you’ve alread done it,

az login

then get the access token we’re going to use soon,

az account get-access-token --output json

you’ll get something like,

{
  "accessToken": "eyJ0eXAiOi...",
  "expiresOn": "2018-10-16 16:57:22.131352",
  "subscription": "deadbeef-dead...",
  "tenant": "deadbeef-dead....",
  "tokenType": "Bearer"
}

Make a note of the accessToken and the subscription values, and plug then into the following,

curl -H "Authorization: Bearer $TOKEN" https://management.azure.com/subscriptions/$SUBSCRIPTION/providers/Microsoft.Web/locations/$LOCATION/managedApis/$API?api-version=2016-06-01

Where you replace $TOKEN and $SUBSCRIPTION with the values retrieved above, $LOCATION with the azure region (eg. westeurope) and $API with the API you wish to interrogate (eg. zendesk)

Example request and response,

curl -H "Authorization: Bearer eyJ0eXAiOi..." https://management.azure.com/subscriptions/deadbeef-dead.../providers/Microsoft.Web/locations/westeurope/managedApis/zendesk?api-version=2016-06-01

and response,

{
  "properties": {
    "name": "zendesk",
    "connectionParameters": {
      "token:SubDomain": {
        "type": "string",
        "uiDefinition": {
          ...
        }
      },
      "token": {
        "type": "oauthSetting",
        "oAuthSettings": {
          ...
        },
        "uiDefinition": {
          ...
        }
      }
    },
    "metadata": {
      "source": "marketplace",
      "brandColor": "#03363d"
    },
    "runtimeUrls": [
      "https://logic-apis-westeurope.azure-apim.net/apim/zendesk"
    ],
    "generalInformation": {
      "iconUrl":   "https://connectoricons-prod.azureedge.net/zendesk/icon_1.0.1008.  1183.png",
      "displayName": "Zendesk",
      "description": ...,
      "releaseTag": "Preview",
      "tier": "Premium"
    },
    "capabilities": [
      "actions",
      "tabular"
    ]
  },
  ...
}

Batch updating Azure Storage blob properties in bash

24 Oct 2017

Today I realized that I’d left out setting the content type on a bunch of blobs that I uploaded over a number of days. My first thought was just to multi-select blobs in Azure Storage Explorer and be done with it, but alas it doesn’t allow batch updates. It looked more and more like I’d be forced to dvelve into Powershell to fix it - the horror!

Fortunately it turned out that the Azure CLI tool combined with the usual Unix toolbelt is flexible enough to get me out of this bind all by itself.

First set the connection string in an environment variable so you don’t have to keep wielding it around.

% az login
% export AZURE_STORAGE_CONNECTION_STRING=$(az storage account show-connection-string -g <resource-group> -n <storage-account> --output tsv)

Then the monster

% az storage blob list -c <container-name> --prefix <prefix> -o tsv \
 | awk '{print $3}' \
 | grep "\.jpg"\
 | xargs -n1 az storage blob update --content-type "image/jpeg" -c cdn -n

Begin by listing all blobs matching prefix in container container-name, selecting to output as tab separated values using az storage blob list -c <container-name> --prefix <prefix>. We pipe this to awk in order to select only the third (name) column and use grep to select only lines ending in .jpg. Finally we use xargs -n1 to pass each of the matching lines to az in order to set the content-type property to image/jpg for each of the blobs.

Azure Resource Manager Template tricks

26 Apr 2017

Azure Resource Manager Templates are a nice way to express your infrastructure as code when developing in the Azure cloud. The template language is a bit interesting to say the least though so you might need some tricks to bend it to your will.

Variable tricks

I’ll start with a few building blocks.

Using a string as a toggle

Sometimes you might need to turn a string into a toggle depending on if it has a value or not. The following construct turns an empty string into a 0 and any other value of string into a 1.

length(replace(take(string(length(variables('input'))),1),'0',''))

Let’s walk though it from the inside out.

  1. we start with the length of the string, length(variables('input'))
  2. convert it to string and take the first character, take(string(...),1), this will be 0 only if length is zero, otherwise 1...9
  3. we replace "0" with "", yielding a string of length either 0 or 1
  4. finally we convert this into an int either 0 or 1 depending on if the input was an empty string or not

Using a boolean as a toggle

We can use a similar trick to use a boolean as a toggle.

length(replace(take(string(variables('input')),1),'f',''))
  1. start by converting the boolean into a string, string(variables('input')) yielding either "true" or "false"
  2. take the first character and replace "f" with "", replace(take(...,1),'f',''), yielding a string of length 1 or 0
  3. the length of the string length(...) can directly be converted into a toggle

Boolean operations on toggles

We can combine the toggles using AND or XOR using the math functions,

mul(variables('a'),variables('b')) // AND
mod(add(variables('a'),variables('b'),2) //XOR

using some more string processing we can also achieve an OR operation

length(replace(take(string(add(variables('a'),variables('b))),1),'0',''))

Nested deployments tricks

Because nested deployments are processed twice from a templating perspective we can use that to conditionally deploy resources and also do some other tricks.

Toggling resource sets

Using the toggles and nested deployments we can enable and disable resources conditionally depending on the input.

{
  "$schema": "...",
  "contentVersion": "...",
  "parameters": {
    "yesNo": {
      "type": "bool",
      "defaultValue": true
    }
  },
  "variables": {
    "yesNoToggle": "length(replace(take(string(parameters('yesNo')),1),'f',''))",
    "yesNoResources": [
      [],
      [{ ... }]
    ]
  },
  "resources": [{
    "name": "...",
    "type": "Microsoft.Resources/deployments",
    "apiVersion": "2016-09-01",
    "properties": {
      "mode": "Incremental",
      "template": {
        "$schema": "...",
        "contentVersion": "...",
        "resources": "[variables('yesNoResources)[variables('yesNoResourceToggle')]]"
      }
    }
  }]
}

Using reference() in variables

Normally the reference() function cannot be used outside the resources part of the template since it’s evaluated at runtime after variables have be computed. Using nested deployments however we can pass the returned value of the function as parameters to the nested template.

{
  "$schema": "...",
  "contentVersion": "...",
  "resources": [{
    "name": "...",
    "type": "Microsoft.Resources/deployments",
    "apiVersion": "2016-09-01",
    "properties": {
      "mode": "Incremental",
      "template": {
        "$schema": "...",
        "contentVersion": "...",
        "parameters": {
          "innerValue": {
            "type": "string"
          }
        },
        "resources": [ 
          {
            "outputs": {
              "output": {
                "type": "string",
                "value": "[[parameters('innerValue')]"
              }
            }
          }
        ]
      },
      "parameters": {
        "innerValue": {
          "value": "[reference(...)]"
        }
      }
    }
  }]
}

Note that references to parameters defined in the inner template must be escaped as [[ because otherwise it would refer to a parameter in the outer template that is not defined.

Introducing Smack - really simple templating for JQuery

10 Jan 2014

I finally got around to posting my tiny roughly 700 byte minified templating engine to github.

It supports, automatic html encoding, attribute binding, iteration, conditionals and string interpolation, with a surprisingly powerful Knockout inspired syntax such as this.

<a data-bind="href: blogUrl">Home</a> 
<h1 data-bind="title"></h1>
<p>
  Published <abbr data-bind="friendlyDate,title:date"></abbr>
  <span data-bind="in {category}, "></span>
  <span data-bind="!'by <strong>{author}</strong>.'"></span>.
</p>
<ul>
  <li data-bind="#tags"><a data-bind=".,href:'?tag={.}'"></a></li>
</ul>
<p data-bind="?admin"><a href="#">Edit</a></p>
<div data-bind="!content"></div>
<h3 data-bind="'Comments ({comments.length})'"></h3>
<ul>
  <li data-bind="#comments">
    <strong data-bind="author"></strong>
    <p data-bind="text"></p>
    <p data-bind="?likes.length">Liked by <em data-bind="#likes,'{.} '"></em></p>
  </li>
</ul>

Using it is as simple as this

var template = $("#template").html()
var context = {
  admin: false,
  blogUrl: "http://example.com",
  author: "Bob Bobson",
  category: "javascript",
  title: "Hello world", 
  date: "2014-01-01",
  friendlyDate: "Yesterday",
  tags: ["tiny","template","jquery"], 
  content: "<p>This is a simple <strong>smack</strong> template.</p>",
  comments: [
    {author: "bob", text: "Great stuff!", likes: ["Cecil", "Mallory"]},
    {author: "alice", text: "Indeed!", likes: []}
  ]
}

// Apply template
var element = $(template)
  .smack(context)
  .appendTo(document.body);

Check it out at github.com/kaa/smack if you’re interested.

Fixing tlsdate drift in the CoreOS vagrant box

02 Jan 2014

The CoreOS vagrant image is a great way to get started quickly playing with docker. However, I find that when I suspend the host computer and bring it back up again with the VM running, the clock in the CoreOS VM has drifted. I figure this is because there are no guest additions in the VM which would otherwise synchronize the time automatically. Here is how to fix it with a systemd timer.

My first thought was to update /etc/tlsdate/tlsdated.conf and make it synchronize the clock more often. As configured tlsdated will synchronize time every 24h once it reaches a steady state. The problem is that in the CoreOS system the /etc directory is mapped readonly so it is not possible to change the configuration. My second thought was to just create a cron task to poll the time every 5 minutes using the tlsdate client, unfortunately CoreOS doesn’t seem to come with cron installed so that is a dead end.

Here is how I used systemd to schedule a periodic polling of the current date using the tlsdate client instead. I learned how from Jason’s blog post about creating timers.

First I created a service /media/state/units/tlsdatesync.service.

[Unit]
Description=Synchronize time with tlsdate

[Service]
Type=simple
ExecStart=/usr/bin/tlsdate

and a timer description, /media/state/units/tlsdatesync.timer

[Unit]
Description=Run tlsdate every five minutes

[Timer]
Unit=tlsdatesync.service
# Time to wait after booting before we run first time
OnBootSec=10min
# Time between running each consecutive time
OnUnitActiveSec=5min

[Install]
WantedBy=local.target

then I configured the service and timers, and enable the timer on startup,

% sudo systemctl restart local-enable.service
% sudo systemctl enable --runtime /media/state/units/tlsdatesync.timer

I checked the timers status with systemctl which confirmed the timer was running

% systemctl status tlsdatesync.timer
tlsdatesync.timer - Runs tlsdated every five minutes
   Loaded: loaded (/media/state/units/tlsdatesync.timer; enabled-runtime)
   Active: active (waiting) since Wed 2014-01-01 22:47:23 UTC; 10min ago

Jan 01 22:47:23 localhost systemd[1]: Starting Runs tlsdated every five minutes.
Jan 01 22:47:23 localhost systemd[1]: Started Runs tlsdated every five minutes.