My demo is this session was titled “Write once, deploy anywhere“. The purpose of this demo was to show using a single ARM template (JSON file) and a single PowerShell script to deploy a VM regardless of deploying to Azure or Azure Stack. The demo was a success so yes this is really possible. In this post I will break down the JSON file, the PowerShell script, how it works and the download link for the files.

Getting the JSON file and the PowerShell script just right was a challenge as there are still some slight differences between the settings of Azure and Azure Stack. Note that this is the case with Azure Stack TP1 and I fully expect that this will change when it GA’s. In any case it is good to look at this stuff now to start to learn the ins and outs. In the end it was the combined Power of the ARM template and PowerShell to overcome any challenges. Let’s start off by taking a look at the differences in ARM between Azure and Azure Stack in the following table:

Property

Azure

Azure Stack

Location

Azure region (example: CentralUS)

local

blobStorageEndpoint

blob.core.windows.net

blob.azurestack.local

vmSize

Standard_D1

Standard_A1

vmName apiVersion

2015-06-15

2015-06-15

StorageAccountName apiVersion

2015-06-15

2015-06-15

nicName apiVersion

2015-06-15

2015-05-01-preview

vrtualNetworkName apiVersion

2015-06-15

2015-05-01-preview

networkSecurityGroupName apiVersion

2015-06-15

2015-05-01-preview

dnsNameForPublicIP apiVersion

2015-06-15

2015-05-01-preview

torageAccountName apiVersion

2015-06-15

2015-05-01-preview

NOTE: For the apiVersion on the resources Azure Stack requires 2015-05-01-preview. Resources in Azure ARM templates default to apiVersion 2015-06-15. So if we left the resources in the ARM template at apiVersion 2015-06-15 the deployment would fail on Azure Stack. However we are in luck as Azure will accept apiVersion 2015-05-01-preview. So I set vmName and StorageAccountName to apiVersion 2015-06-15 and the rest of the resources apiVersion to 2015-05-01-preview.

vmName and StorageAccountName use the same apiVersion for both Azure and Azure Stack. So Azure Stack accepts 2015-06-15 for both. Even those these are not different across Azure and Azure Stack I still wanted to list it anyway in the table.

If you have multiple subscriptions you will need to input the subscription ID. In my case my Azure has multiple subscriptions but my Azure Stack does not in this lab. In my script for Azure you need the subscription ID. In Azure Stack you do not. You may need to modify this behavior in the script if your scenario is different.

For the deployment it consists of two files. These files are:

AzureandAzureStack.json

CreateVMAzureorAzureStack.ps1

Here is what we have if we crack open the JSON file.

A few things to note about the PowerShell script is that

We prompt to identify if it is an Azure or Azure Stack deployment. We then run the appropriate block of code.

In each of the deployment types (Azure or Azure Stack) we have some things hard coded in (for example blobStorageEndpoint and vmSize) and somethings pulled in dynamically by prompting for them during the script execution (for example subscriptionId and adminPassword).

We are pulling in the parameter and variable values when using New-AzureRmResourceGroup and New-AzureRmResourceGroupDeployment.

NOTE:I am not a PowerShell expert. I am sure there are better more efficient ways to accomplish what I am doing here in the PowerShell script. Nothing was available to accomplish the write once, deploy anywhere goal so I put something together. Feel free to enhance the script and release back to the community.

Here is an example of the location parameter and variable in the JSON file.

The parameter:

The variable:

Referenced in the vmName resource:

Here is an example of how we are leveraging this in the PowerShell script.

For Azure:

For Azure Stack:

Note that you can deploy VM’s to Azure or Azure Stack in many ways (Visual Studio, the portal etc..). I decided to leverage PowerShell to do the deployment’s as it gives me a great amount of flexibility. For the official article on using PowerShell to deploy VM’s to Azure Stack visit:

Now let’s look at deploying a VM to both Azure and Azure Stack using a single PowerShell script and a single ARM template.

— AZURE —

Run the script and you are prompted for some of the VM info.

Then you are prompted to log into your Azure account.

You need to input your subscription ID.

Specify the region you want to deploy to.

You will be prompted to enter the admin password you want to use for the VM.

After entering the admin password the deployment starts. When it is finished you will see a success message and the Azure portal will be launched in your default browser.

— AZURE STACK–

Run the script and you are prompted for some of the VM info.

Then you are prompted to log into your Azure account.

Note here that the script adds the Azure Stack environment and authenticates it with PowerShell. This is a step we did not have to do when deploying to Azure.

You will be prompted to enter the admin password you want to use for the VM.

After entering the admin password the deployment starts. When it is finished you will see a success message and the Azure Stack portal will be launched in your default browser. Note that on Azure Stack you could look at Hyper-V manager or fail-over cluster manager and see the new VM spinning up as shown in the following screenshot.

In this blog post I gave an example of deploying a VM. With the use of ARM templates you can deploy many other things beyond VM’s. The possibilities that ARM brings to the table along with the whole idea of Hybrid Cloud are exciting. That wraps up this blog post. You can download the JSON file and PowerShell script here: