Archive for March, 2021

Showing costs in Azure Managed App createUIDefinition.json

Some Azure Managed Application publishers have ARM templates which cause their ARM template to vary in cost. To help reduce sticker shock, those publishers want some way to show how choices in the deployment will influence the cost to run the application. Getting this value is not trivial. Depending on many factors, the costs will be different for different users. Azure prices change based on a variety of conditions:

  • Commitment to use Azure expressed in a contract with Microsoft will provide different discounts based on the dollar value of that commitment.
  • Customer may purchase Azure through a Cloud Service Provider who discounts Azure usage.
  • Customer may be paying full, advertised price.
  • And so on…

At the time of this writing, no mechanism exists to find the customer prices for resources. That said, you can give a customer an idea of how much one resource type will cost: you can show them the costs for VMs. It is pretty common for an ARM template to create a variable number of virtual machines based on application parameters. In these kinds of templates, the virtual machine count can dominate the costs for running that managed application. Many partners want a mechanism which enables them to show how much those VMs will cost. While you cannot query the value directly, you can display the information to the user via a control in your createUIDefinition.json: use a SizeSelector. How would this work in practice?

Let’s assume something quite basic: a user picks an integer value from a range. In this case, the ARM template will scale the VM count linearly with the integer: one VM for every 2 units. If we have the following Slider declared:

{
    "name": "unitCount",
    "type": "Microsoft.Common.Slider",
    "min": 2,
    "max": 100,
    "label": "Units",
    "subLabel": "",
    "defaultValue": 5,
    "showStepMarkers": false,
    "toolTip": "Pick the number of units",
    "constraints": {
        "required": false
    },
    "visible": true
}

Then we can let the user know how many VMs will be created and display that as a TextBlock where the text value is:

"text": "[concat(string(steps('ApplicationCharacteristics').unitCount.value), ' was selected. ', string(div(steps('ApplicationCharacteristics').unitCount.value, 2)), ' VMs will be created.' )]"

Finally, we can add the SizeSelector to show the cost of each VM which is allowed. Many of the ARM templates with this kind of setup will constrain the selection of VM to 1-4 different sizes. We will do that by limiting the information displayed to the user by using the allowedSizes constraint.

{
    "name": "sizes",
    "type": "Microsoft.Compute.SizeSelector",
    "label": "Size",
    "toolTip": "",
    "recommendedSizes": [
        "Standard_D32_v4",
        "Standard_D48_v4",
        "Standard_D64_v4"
    ],
    "constraints": {
        "allowedSizes": [
            "Standard_D4_v4",
            "Standard_D16_v4",
            "Standard_D32_v4",
            "Standard_D48_v4",
            "Standard_D64_v4"
        ]
    },
    "osPlatform": "Windows",
    
    "count": "[div(steps('ApplicationCharacteristics').unitCount.value, 2)]",
    "visible": true
}

We can now show the user how much each VM will cost. The user still needs to do some math to convert the cost per VM to an overall cost. The SizeSelector will display the user’s costs, and now the user can get an idea for what the VM cost component of the managed application will be.

Please note: when running in the Create UI Definition Sandbox, the Size Selector may return Cost/month of Unavailable in some cases.

To try this on your own, try using the Sandbox and paste in the following createUiDefinition.json:

{
    "$schema": "https://schema.management.azure.com/schemas/0.1.2-preview/CreateUIDefinition.MultiVm.json#",
    "handler": "Microsoft.Azure.CreateUIDef",
    "version": "0.1.2-preview",
    "parameters": {
      "config": {
        "basics": {
          "description": "Sample UI Definition which uses a SizeSelector to estimate price",
          "resourceGroup": {
            "allowExisting": true
          }
        }
      },
      "basics": [],
      "steps": [
        {
          "name": "ApplicationCharacteristics",
          "label": "Pick some characteristics of your application",
          "subLabel": {
            "preValidation": "Select your options",
            "postValidation": "Done"
          },
          "bladeTitle": "Application options",
          "elements": [
            {
              "name": "Infoenvironment",
              "type": "Microsoft.Common.InfoBox",
              "visible": true,
              "options": {
                "icon": "Info",
                "text": "For every 2 units, we add one VM to the deployment."
              }
            },
            {
                "name": "unitCount",
                "type": "Microsoft.Common.Slider",
                "min": 2,
                "max": 100,
                "label": "Units",
                "subLabel": "",
                "defaultValue": 5,
                "showStepMarkers": false,
                "toolTip": "Pick the number of units",
                "constraints": {
                    "required": false
                },
                "visible": true
            },
            {
                "name": "unitDisplay",
                "type": "Microsoft.Common.TextBlock",
                "visible": true,
                "options": {
                  
                  "text": "[concat(string(steps('ApplicationCharacteristics').unitCount.value), ' was selected. ', string(div(steps('ApplicationCharacteristics').unitCount.value, 2)), ' VMs will be created.' )]"
                }
            },
            {
                "name": "sizeReview",
                "type": "Microsoft.Common.TextBlock",
                "visible": true,
                "options": {
                  "text": "Use the size selector to see how much the VMs will cost."
                }
            },
            {
                "name": "sizes",
                "type": "Microsoft.Compute.SizeSelector",
                "label": "Size",
                "toolTip": "",
                "recommendedSizes": [
                    "Standard_D32_v4",
                    "Standard_D48_v4",
                    "Standard_D64_v4"
                ],
                "constraints": {
                    "allowedSizes": [
                        "Standard_D4_v4",
                        "Standard_D16_v4",
                        "Standard_D32_v4",
                        "Standard_D48_v4",
                        "Standard_D64_v4"
                    ]
                },
                "osPlatform": "Windows",
                
                "count": "[div(steps('ApplicationCharacteristics').unitCount.value, 2)]",
                "visible": true
            }
          ]
        }
      ],
      "outputs": {
            "unitCount" : "[steps('ApplicationCharacteristics').unitCount.value]"
      }
    }
  }

Leave a comment