Category Archives: Azure Resource Manager

Changing the App Service Plan of an Azure App Service

To allow a number of App Services to scale independently I needed to pull one of them out of an App Service Plan where it had lived with 3 others to sit in it’s own plan – experience had shown me that it’s scaling characteristics are really quite different from the other App Services.

You can do this straightforwardly and pretty much instantly either in the Portal (there’s a Change App Service Plan option in Settings) or with PowerShell (with the Set-AzureRmAppServicePlan cmdlet).

Super simple – but I did encounter one gotcha. This doesn’t move any deployment slots you might have created and so you end up in a situation with the main App Service sat in one App Service Plan and it’s deployment slots in another which probably isn’t what you want and, in any case, Azure won’t let you swap slots in different service plans.

The solution is simple: you can also move them between App Service Plans in the same way.

 

Azure Resource Manager and Powershell 1.0

Microsoft recently updated Azure Powershell to 1.0 in the process introducing a large number of breaking changes to the CmdLet’s. Essentially they’ve removed Switch-AzureMode and instead of that the Azure Resource Manager cmdlets have all had an Rm introduced to them so for example:

New-AzureResourceGroupDeployment

becomes

New-AzureRmResourceGroupDeployment

For the most part the errors on upgrading a Powershell script are obvious and a rename will get you going however somewhat confusingly there are now pairs of cmdlet’s that do the same thing but only effect the different cmdlet sets.

An example of one that caught me out is Select-AzureSubscription. I’ve got numerous Azure subscriptions and scripts that deploy into different subscriptions depending on what I’m doing. Previously I used Select-AzureSubscription along with Switch-AzureMode and this worked. The problem is that Select-AzureSubscription still works – but it has no effect on the cmdlets that use the Rm prefix.

This led, confusingly, to a resource group being created in a different subscription to the one I intended and resources with the same name as in my intended resource group (resources which already existed) being created, or attempted to be created, in this new resource group. They failed as they already existed with the same names elsewhere.

The fix was to use Select-AzureRmSubscription.

 

Add-AzureAccount and Build Servers

If you followed my previous post you might be wandering how this works on a build server as the Add-AzureAccount cmdlet that you use to gain access to Azure pops up an interactive dialog box. Not helpful in the build of an automated build pipeline.

The best way to handle this scenario with Azure Resource Manager is with a service principal account. Rather than repeat excellent work I suggest heading over to David Ebbo’s blog, he has an excellent post on using service principal accounts to do this.

How To: Publish an AngularJS Website with Azure Resource Manager Templates

I’ve recently been working on the deployment of some fairly complex micro-service projects using the new Azure Resource Manager and in the Microsoft space everything went fine, it’s all pretty self-explanatory, there’s some useful tooling in Visual Studio and some great quick-start templates.

Then I hit my UI layer. This is an AngularJS app which I prefer to work on outside of Visual Studio – I like to use the best tools for the job and while I definitely find Visual Studio is just that for C# and other Microsoft native technologies I find it often lags behind in the web space, though it’s got and continues to get a lot better.

Basically I have a folder in my project folder space (not in the .sln file) containing my AngularJS app and a bunch of typical web tools to run the build and packages: npm, bower and grunt. For various reasons although the project source is in GitHub I couldn’t (without a fair bit of hassle) deploy directly from their using the source code deployment model.

And so how do you publish a folder of files to an Azure website using Azure Resource Manager?

Below I’ll present one way using the Yeoman generated Angular template as a sample which, using grunt, builds to a folder called dist. As a prerequisite for this you’ll need Azure Powershell -I’m using 0.8 at the time of writing (1.0 contains some changes to the Azure Resource Manager cmdlets but as I write this it’s in preview, the changes are nothing earth shattering).

You can find source code for the below in GitHub.

Firstly you need to create an Azure Resource Manager template – the one we’re using is here. I’ve not going to cover every bit of this as Microsoft have plenty of documentation and samples however it’s worth looking at this bit towards the end:

"resources": [
  {
    "name": "MSDeploy",
    "type": "extensions",
    "location": "[parameters('location')]",
    "apiVersion": "2014-06-01",
    "dependsOn": [
      "[concat('Microsoft.Web/sites/', parameters('siteName'))]"
    ],
    "tags": {
      "displayName": "ContentDeploy"
    },
    "properties": {
      "packageUri": "[concat(parameters('packageUrl'), parameters('sasToken'))]",
      "dbType": "None",
      "connectionString": "",
      "setParameters": {
          "IIS Web Application Name": "[parameters('siteName')]"
      }
    }
  }
]

This invokes the deployment of a Web Deployment package at URL specified by packageUrl. I’m using an Azure Storage Account for this and so to access the package do so we need a Shared Access Signature which we’ll see how to generate later.

As I want to automate everything I’ve also got a template for creating a storage account into which the package can be uploaded and you can see this template here.

I’m going to glue these two templates together with a Powershell script using the Azure Powershell cmdlets. To get started with this launch Azure Powershell and before running any scripts add your Azure subscription:

Add-AzureAccount

You’ll be prompted to log into your account.

The Powershell script I’m using to glue all this is called deploy.ps1 and you can find it here. I’m going to break this down section by section. Firstly we just deploy a bunch of fairly (if you know Azure) self explanatory settings – the hosting plan, resource group, website and storage account to create / use and the location of those resources:

# Deployment settings
$hostingPlanName = "ArmAngularSampleHostingPlan"
$resourceGroupName = "ArmAngularSample"
$storageAccountName = "armangularsamplesa"
$location = "West Europe"
$siteName = "ArmAngularSampleWebsite"

Then we optionally select an Azure subscription (if you only have one subscription you won’t need to do this) and switch Powershell into Azure Resource Manager mode.

# Configure Azure and the Powershell shell
# Select-AzureSubscription -SubscriptionId {{your-subscription-id}}
Switch-AzureMode AzureResourceManager

Now we create the resource group within which our templates are going to run:

# Create Azure Resoure Group
New-AzureResourceGroup -Name $resourceGroupName -Location $location -Force

Next we deploy our storage resources using Azure Resource Manager and then we get hold of the access key – we’ll need that in a minute. In such a small deployment this split of storage and service might seem a little naive but in more complex scenarios it’s fairly common to do a bunch of work on storage before deploying updated services (and vice versa):

# Deploy storage
New-AzureResourceGroupDeployment -ResourceGroupName $resourceGroupName `
                                 -Name AzmSampleStorageDeployment `
                                 -TemplateFile "storagedeploy.json" `
                                 -appStorageAccountName $storageAccountName 				 
$storageAccountKey = (Get-AzureStorageAccountKey -ResourceGroupName $resourceGroupName -Name $storageAccountName).Key1

Having done that we get grunt to build a distribution version of our Angular site and then we invoke MSBuild to create a deployment package from the folder. To do this MSBuild needs a project file and nearly every example you see will use a .csproj file – which is fine if you’re using Visual Studio but what if we’re not? Well you can also use a .publishproj file which you can find here. This file is absolute boilerplate – it will work for any folder and so you can copy and use mine for your own projects. We need to move this into the dist folder that grunt has created (you can use it elsewhere but as dist is cleaned each time this is easiest).

# Build deployment package
grunt build
cp .\website.publishproj .\dist\website.publishproj
C:\"Program Files (x86)"\MSBuild\14.0\bin\msbuild.exe .\dist\website.publishproj /T:Package /P:PackageLocation="." /P:_PackageTempDir="packagetmp"
$websitePackage = ".\dist\website.zip"

The setting of /P:PackageLocation=”.” causes the package to be dropped in the dist folder and the /P:_PackageTempDir=”packagetmp” causes MSBuild to use a packagetmp subfolder of dist to be used for temporary files – this can be useful as it’s easy to run into the “classic” Windows file length issues otherwise (it will use a temp location in AppData by default).

Having generated a package (called website.zip and located in the dist folder) we need to upload it to somewhere Azure can access. I’m using the storage account we created earlier. So that the Azure Resoure Manager incarnation of Web Deploy can access the package we generate a Shared Access Signature with read privileges:

# Upload packages
$storageCtx = New-AzureStorageContext -StorageAccountName $storageAccountName -StorageAccountKey $storageAccountKey
if (-Not (Get-AzureStorageContainer -Context $storageCtx | Where-Object { $_.Name -eq "packages" }) ) {
    New-AzureStorageContainer -Name "packages" -Context $storageCtx -Permission Off
}
Set-AzureStorageBlobContent -File $websitePackage -Container "packages" -Blob website.zip -Context $storageCtx -Force
$uploadedPackage = "https://$storageAccountName.blob.core.windows.net/packages/website.zip"
$sasToken = New-AzureStorageContainerSASToken -Container "packages" -Context $storageCtx -Permission r
$sasToken = ConvertTo-SecureString $sasToken -AsPlainText -Force

And finally we deploy our services via the Azure Resource Manager template we saw earlier:

New-AzureResourceGroupDeployment -ResourceGroupName $resourceGroupName `
                                 -Name AnalyticsLiveServiceDeployment `
                                 -TemplateFile "azuredeploy.json" `
                                 -hostingPlanName $hostingPlanName `
                                 -location $location `
                                 -siteName $siteName `
                                 -packageUrl $uploadedPackage `
                                 -sasToken $sasToken

And that’s it. If you run .\deploy.ps1 (you’ll need to set your own unique storage account and website name) then as long as you have an Azure subscription this will deploy and you’ll be able to see the Yeoman template running in Azure.

Hopefully that’s helpful and will save you some of the pain that always seems to come with the territory of deployment – particularly where MSBuild is involved!