From Proof-of-Concept to Controlled Deployment of Azure Resources using Pulumi

Facebook
Twitter
LinkedIn

Previously, we looked into deploying Azure resources using infrastructure-as-code using Pulumi. In this post, I will walk through creating the C# (or TypeScript etc) code from manual prototyping and proof-of-concept deployments in Azure to making them using Pulumi.

First, I create a new resource group manually in my Azure tenant. I named it Template. Here, I create a single web application.

I then export the resource group as a template and convert it to some base Pulumi code. It does not perform all options perfectly but, together with the Pulumi documentation, it gives me a quick way of identifying how to structure the commands.

First, I open the terminal and log on to Azure. I will then select the correct subscription, then list all my resource groups, and export the ARM template for that resource group to a file.

				
					# Log on to Azure
az login
# Use the web browser to log in then return to terminal
# List all accounts
az account list
# This will return all your subscriptions. Copy the 'id' value of the subscription to use, then, for example
az account set --subscription 301cb97f-0000-0000-9a3e-9010373f5602
# Now we list all resource groups
az group list
# I will now export all items from 'Template' to an ARM template file
az group export -g Template > .\export.json
				
			

The JSON file now contains the ARM template as:

				
					{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "serverfarms_plan_pulumitemplate_name": {
      "type": "String"
    },
    "sites_app_pulumitemplate_001_name": {
      "type": "String"
    }
  },
  "resources": [
    {
      "apiVersion": "2018-02-01",
      "kind": "app",
      "location": "UK South",
      "name": "[parameters('serverfarms_plan_pulumitemplate_name')]",
      "properties": {
        "hyperV": false,
        "isSpot": false,
        "isXenon": false,
        "maximumElasticWorkerCount": 1,
        "perSiteScaling": false,
        "reserved": false,
        "targetWorkerCount": 0,
        "targetWorkerSizeId": 0
      },
      "sku": {
        "capacity": 0,
        "family": "F",
        "name": "F1",
        "size": "F1",
        "tier": "Free"
      },
      "type": "Microsoft.Web/serverfarms"
    },
    {
      "apiVersion": "2018-11-01",
      "dependsOn": [
        "[resourceId('Microsoft.Web/serverfarms', parameters('serverfarms_plan_pulumitemplate_name'))]"
      ],
      "kind": "app",
      "location": "UK South",
      "name": "[parameters('sites_app_pulumitemplate_001_name')]",
      "properties": {
        "clientAffinityEnabled": true,
        "clientCertEnabled": false,
        "containerSize": 0,
        "dailyMemoryTimeQuota": 0,
        "enabled": true,
        "hostNameSslStates": [
          {
            "hostType": "Standard",
            "name": "[concat(parameters('sites_app_pulumitemplate_001_name'), '.azurewebsites.net')]",
            "sslState": "Disabled"
          },
          {
            "hostType": "Repository",
            "name": "[concat(parameters('sites_app_pulumitemplate_001_name'), '.scm.azurewebsites.net')]",
            "sslState": "Disabled"
          }
        ],
        "hostNamesDisabled": false,
        "httpsOnly": false,
        "hyperV": false,
        "isXenon": false,
        "redundancyMode": "None",
        "reserved": false,
        "scmSiteAlsoStopped": false,
        "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', parameters('serverfarms_plan_pulumitemplate_name'))]",
        "siteConfig": {}
      },
      "type": "Microsoft.Web/sites"
    },
    {
      "apiVersion": "2018-11-01",
      "dependsOn": [
        "[resourceId('Microsoft.Web/sites', parameters('sites_app_pulumitemplate_001_name'))]"
      ],
      "location": "UK South",
      "name": "[concat(parameters('sites_app_pulumitemplate_001_name'), '/web')]",
      "properties": {
        "alwaysOn": false,
        "autoHealEnabled": false,
        "azureStorageAccounts": {},
        "defaultDocuments": [
          "Default.htm",
          "Default.html",
          "Default.asp",
          "index.htm",
          "index.html",
          "iisstart.htm",
          "default.aspx",
          "index.php",
          "hostingstart.html"
        ],
        "detailedErrorLoggingEnabled": false,
        "experiments": {
          "rampUpRules": []
        },
        "ftpsState": "AllAllowed",
        "http20Enabled": false,
        "httpLoggingEnabled": false,
        "ipSecurityRestrictions": [
          {
            "action": "Allow",
            "description": "Allow all access",
            "ipAddress": "Any",
            "name": "Allow all",
            "priority": 1
          }
        ],
        "loadBalancing": "LeastRequests",
        "localMySqlEnabled": false,
        "logsDirectorySizeLimit": 35,
        "managedPipelineMode": "Integrated",
        "minTlsVersion": "1.2",
        "netFrameworkVersion": "v5.0",
        "numberOfWorkers": 1,
        "publishingUsername": "$app-pulumitemplate-001",
        "remoteDebuggingEnabled": false,
        "requestTracingEnabled": false,
        "reservedInstanceCount": 0,
        "scmIpSecurityRestrictions": [
          {
            "action": "Allow",
            "description": "Allow all access",
            "ipAddress": "Any",
            "name": "Allow all",
            "priority": 1
          }
        ],
        "scmIpSecurityRestrictionsUseMain": false,
        "scmType": "None",
        "use32BitWorkerProcess": true,
        "virtualApplications": [
          {
            "physicalPath": "site\\wwwroot",
            "preloadEnabled": false,
            "virtualPath": "/"
          }
        ],
        "webSocketsEnabled": false
      },
      "type": "Microsoft.Web/sites/config"
    },
    {
      "apiVersion": "2018-11-01",
      "dependsOn": [
        "[resourceId('Microsoft.Web/sites', parameters('sites_app_pulumitemplate_001_name'))]"
      ],
      "location": "UK South",
      "name": "[concat(parameters('sites_app_pulumitemplate_001_name'), '/', parameters('sites_app_pulumitemplate_001_name'), '.azurewebsites.net')]",
      "properties": {
        "hostNameType": "Verified",
        "siteName": "app-pulumitemplate-001"
      },
      "type": "Microsoft.Web/sites/hostNameBindings"
    }
  ],
  "variables": {}
}
				
			

Converting ARM template to Pulumi syntax

Copy the contents of export.json and open the ARM to Pulumi tool. I paste in my ARM template on the left, then choose C# on the right (or whatever syntax you need).

The code is generated for me. It is not perfect and will require refactoring. I suggest doing this once you have a base Pulumi project created, as described in the previous post, and use this technique to find specific configurations or new resource syntax.

We can now merge the code into our main Pulumi project and run pulumi up to deploy to our controlled resource group. After that, I compare the Template and controlled resource group assets and keep making changes to my script until I am happy with the result.

Leave a Reply

Your email address will not be published. Required fields are marked *