apt-get
, and on Windows, my current favorite is Chocolatey. Recently I needed to use more virtual machine (VM) in the cloud and I deceided that I should try using a Chocolatey script during the deployment. This way once the VM is created the softwares, I need is already installed! This post is all about my journey to get there, all scripts, issues and workarounds will be explained.The Goal
Creating a new VM on premises applying the OS update and installing all the tools you need (like Visual Stutio IDE) will takes hours... This solution should be done under 10 minutes (~7min in my case).
Once the VM is available, it should have Visual Studio 2017 Enterprise, VSCode, Git and Node.Js installed. In fact, I would like to use the same Chocolatey script I use regularly.
# Install Chocolatey
Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
# Install Software
choco install visualstudiocode -y
choco install git -y
choco install nodejs-lts -y
(Available on gist.github)The Tools
In this post I will use Azure CLI, because it will works on any environment. However, PowerShell can also be use only a few command will be different. The VM will be deploy with an Azure resource Manager (ARM) template. To create and edit the ARM template I like to use VSCode, you don't need it but it's so much easier with it! I use two extension.
The first one Azure Resource Manager Snippets will help by generating the schema for our needs. In a JSON file you just need to type
arm
en voila! You ahave a long list of ARM template!The second is Azure Resource Manager Tools. This extension provides language support for ARM and some validate. Very useful...
Creating the ARM Template
To Get started create a new JSon file. Then type
arm
and select the first option; to get an empty skeleton. Then add an extra line in resources
and type again arm
. This time scroll until you see arm-vm-windows
.A multi-cursor will allow you to edit the name of your VM everywhere in the file in one shot. Hit
Tab
to navigate automatically to the userName, and Tab
again to go to the password.Now we have a functional ARM template that we could deploy. However, let's add a few things first.
Searching the Image SKUs by Code
One of my favorite VM images for a DevBox is the one that includes Visual Studio pre-installed. One thing to know is those images are only deployable in an MSDN subscription. To specify wich image you want to use you need to pass a publisher, offer, and sku.
Here how to do it with Azure CLI commands
# List all the Publishers that contain VisualStudio (It's case sensitive)
az vm image list-publishers --location eastus --output table --query "[?contains(name,'VisualStudio')]"
# List all offers for the Publisher MicrosoftVisualStudio
az vm image list-offers --location eastus --publisher MicrosoftVisualStudio --output table
# List all availables SKUs for the Publisher MicrosoftVisualStudio with the Offer VisualStudio
az vm image list-skus --location eastus --publisher MicrosoftVisualStudio --offer VisualStudio --output table
Now that all the information is found, search in the ARM template and replace the current values by the one found. In my case, here are the new values.
"imageReference": {
"publisher": "MicrosoftVisualStudio",
"offer": "VisualStudio",
"sku": "VS-2017-Ent-Win10-N",
"version": "latest"
}
Adding our Custom Script
Great now we have a VM with Visual Studio but our applications are still not installed. That will be done by adding the Custom Script Extension for Windows to our template. documentation page, a sample schema is there ready to be use.
The last node of your template is currently another extension. For the purpose of this blog post let's remove it. You should have something like this.
We will copy/ paste the snippet from the documentation page a change a few little things. Change the
type
(thank to our VSCode Extension for that catch). Update the dependencies to reflet our demo. To use the extension your script needs to be available online. It could be in a blob storage (with some security) or just publicly available. In this case, the script is publicly available from my gist.github page. I created a variable in the variables section that contains the RAW URL of my script, and a reference to that varaibale is used in the
fileUris
. The extension will download the script and then execute a function locally. Change the
commandToExecute
to call our script with unrestricted execution policy.You have a timed window of ~30 minutes to execute your script. If it takes longer then that, your deployment will fail.
{
"apiVersion": "2015-06-15",
"type": "extensions",
"name": "config-app",
"location": "[resourceGroup().location]",
"dependsOn": [
"[concat('Microsoft.Compute/virtualMachines/', 'FrankDevBox')]"
],
"tags": {
"displayName": "config-app"
},
"properties": {
"publisher": "Microsoft.Compute",
"type": "CustomScriptExtension",
"typeHandlerVersion": "1.9",
"autoUpgradeMinorVersion": true,
"settings": {
"fileUris": [
"varaiables('scriptURL')]"
]
},
"protectedSettings": {
"commandToExecute": "[concat('powershell -ExecutionPolicy Unrestricted -File ', './SimpleDevBox.ps1')]"
}
}
}
`The ARM Template
It's finally time to deploy our VM.
# First, we need a Resource Group az group create --name frankDemo --location eastus # ALWAYS, always validate first... you will save a lot of time az group deployment validate --resource-group frankDemo --template-file /home/frank/Dev/DevBox/FrankDevBox.json #Finally deploy. This script should take between 5 to 10 minutes az group deployment create --name FrankDevBoxDemo --resource-group frankDemo --template-file /home/frank/Dev/DevBox/FrankDevBox.json --verbose
What's Next?!
We created one template; you could make it better.
Deploy from anywhere
By moving the
computerName
, adminUsername
, adminPassword
, and the script url in the parameters section, you could then put the template in a public place like GitHub. Then with use the one click deploy!Directly from the Github page or from anywhere you just need to build a URL from those two parts:
https://portal.azure.com/#create/Microsoft.Template/uri/
and the HTML Encoded URL to your template. If my template is available at
https://raw.githubusercontent.com/FBoucher/SimpleDevBox/master/azure-deploy.json
then the full url become:https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FFBoucher%2FSimpleDevBox%2Fmaster%2Fazure-deploy.json
Clicking that URL will bring you to the Azure Portal (portal.azure.com) in a customized form to deploy your template.
It cannot be easier! You can see mine on GitHub.
Auto shutdown
It's very easy to forget to turn off those VM. And whatever you are paying for them or your using the limited MSDN credit it's a really good practice to turn them down. Why not do that automatically!
That can be very simply done by adding a new resource in the template.
{ "name": "[concat('autoshutdown-', 'FrankDevBox')]", "type": "Microsoft.DevTestLab/schedules", "apiVersion": "2017-04-26-preview", "location": "[resourceGroup().location]", "properties": { "status": "Enabled", "taskType": "ComputeVmShutdownTask", "dailyRecurrence": { "time": "19:00" }, "timeZoneId": "UTC", "targetResourceId": "[resourceId('Microsoft.Compute/virtualMachines', 'FrankDevBox')]", "notificationSettings": { "status": "Enabled", "emailRecipient": "frank@frankysnotes.com", "notificationLocale": "en", "timeInMinutes": "30" } }, "dependsOn": [ "[concat('Microsoft.Compute/virtualMachines/', 'FrankDevBox')]" ] }
In Video Please!
If you prefer, I also have a video version of that post.
How to Create an Azure VM with Chocolatey
~Enjoy!
References:
- Chocolatey
- Azure Resource Manager Tools
- Azure Resource Manager Snippets
- Custom Script Extension for Windows
- All scripts from this post