Using Managed RunCommand in an ARM Template

Joseph Calev

Perhaps one of the largest differences between “Action RunCommand” (internally called RunCommand V1) and “Managed RunCommand” (internally called RunCommand V2) is that Managed RunCommands are ARM resources themselves. That means you can use them in ARM templates.

Recently, I needed to issue a RunCommand in an ARM template, so I looked around for examples how to do this. Yes, even though we wrote RunCommand, we’re just as lazy as anyone else. However, I didn’t find anything, so I thought I’d share how this works so others may be lazy where I failed.

The following is an example resource for a VM.

{
  "type": "Microsoft.Compute/virtualMachines/runCommands",
  "name": "[concat(parameters('linuxVmName'),'/linuxVmRunCommand')]",
  "apiVersion": "2019-12-01",
  "location": "[parameters('region')]",
  "properties": {
    "source": {
      "scriptUri": "[parameters('linuxScriptUri')]"
    },
    "parameters": [
      {
        "name": "[parameters('firstParameterName')]",
        "value": "[parameters('firstParameterValue')]"
      },
      {
        "name": "[parameters('secondParameterName')]",
        "value": "[parameters('secondParameterValue')]"
      }
    ],
    "outputBlobUri": "[parameters('linuxVMOutputBlobUri')]",
    "errorBlobUri": "[parameters('linuxVMErrorBlobUri')]",
    "timeoutInSeconds": 20
  }
}

This is fairly straightforward. In this case, we’re downloading the script using a Sas uri, providing blobs to capture the output and error logs (also as Sas uris), requiring the script to finish in 20 seconds. I found the VMSS syntax to be slightly more confusing.

{
  "type": "Microsoft.Compute/virtualMachineScaleSets/virtualMachines/runCommands",
  "name": "[concat(parameters('windowsVmssName'), '/0/windowsVmRunCommand')]",
  "apiVersion": "2019-12-01",
  "location": "[parameters('region')]",
  "properties": {
    "source": {
      "scriptUri": "[parameters('windowsScriptUri')]"
    },
    "parameters": [
      {
        "name": "[parameters('firstParameterName')]",
        "value": "[parameters('firstParameterValue')]"
      },
      {
        "name": "[parameters('secondParameterName')]",
        "value": "[parameters('secondParameterValue')]"
      }
    ],
    "outputBlobUri": "[parameters('windowsVMSSOutputBlobUri')]",
    "errorBlobUri": "[parameters('windowsVMSSErrorBlobUri')]",
    "timeoutInSeconds": 20
  }
}

While everything else is the same, the name is a bit more confusing due to rather maddening rules governing path segment counts in ARM templates. The thing to keep in mind here is we only support RunCommands on specific instances of a VMSS. We don’t currently support running a command across an entire VMSS, though it isn’t difficult to automate this.

After some trial and error, the name of the RunCommand needs to have three segments, which should be the VMSS name + the instance + the name of your runCommand.

My hope is this helps you avoid the same trial and error.

Important note: On some Linux distros, adding a managed RunCommand may fail if the distro uses a very old version of the Guest Agent that does not support managed RunCommand. Changes were necessary to the agent to support the ability for multiple commands.

0 comments

Leave a comment

Feedback usabilla icon