Azure Web App Powershell Resource Manager Mode - Connection String Slot Setting - powershell

I'm adding Connection Strings to my Azure Web App using the AzureResourceManager mode in Powershell.
Using the Azure Resource Explorer I've found the correct Powershell to add a connection string to my web app
$PropertiesObject = #{
#Property = value;
MembershipConnection = #{
Value = "Server=tcp:members.database.windows.net,1433;Database=Membership;User ID=User#members;Password=passwordgoeshere;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;";
Type = "2";
}
}
New-AzureResource -PropertyObject $PropertiesObject -ResourceGroupName $resGroup -ResourceType Microsoft.Web/sites/config -ResourceName "$siteName/connectionstrings" -OutputObjectFormat New -ApiVersion "2015-08-01" -Force
However, I can't find a way of marking the Connection String as a Slot Setting, so that it doesn't move when switching between my Staging and Production deployment slots.
In the Portal, it's a simple checkbox alongside the connection string.
Thanks very much for any help!

You might already know that you can do this in the Azure Service Management Mode like this:
> Switch-AzureMode -Name AzureServiceManagement
> Set-AzureWebsite -Name myapp -SlotStickyConnectionStringNames #("my_db")
I appreciate, though, that your question is about using the Azure Resource Manager.

Related

Azure App Service ApiApp

I am trying to create an API App in Azure App Service with PowerShell.
The cmdlet I am calling always create a Web App by default. If it is possible, I would like to know how I can specify the type/kind to be Api App instead of Web App?
New-AzureRmWebApp -Name $name -Location $location -AppServicePlan $plan -ResourceGroupName $resourceGroup
From my reading there is not much different between both except the icon, is it worth it to set the type to "Api App" if it's what my app is all about?
I am using version 5.4.0 of AzureRM PowerShell module.
> Get-Module "AzureRM"
ModuleType Version Name
---------- ------- ----
Script 5.4.0 AzureRM
Just call New-AzureRmResource instead and pass in -Kind 'api':
# CREATE "just-an-api" API App
$ResourceLocation = "West US"
$ResourceName = "just-an-api"
$ResourceGroupName = "demo"
$PropertiesObject = #{
# serverFarmId points to the App Service Plan resource id
serverFarmId = "/subscriptions/SUBSCRIPTION-GUID/resourceGroups/demo/providers/Microsoft.Web/serverfarms/plan1"
}
New-AzureRmResource -Location $ResourceLocation `
-PropertyObject $PropertiesObject `
-ResourceGroupName $ResourceGroupName `
-ResourceType Microsoft.Web/sites `
-ResourceName "just-an-api/$ResourceName" `
-Kind 'api' `
-ApiVersion 2016-08-01 -Force
..which produces an API App, a Microsoft.Web/sites resource type of the api kind:
Hold on.. How did you come up with this stuff?
Visit https://resources.azure.com and navigate to an existing API App, build the PowerShell syntax by combining the PowerShell tab with the desired values from the JSON resource definition.
There is not a parameter in New-AzureRmWebApp supported to explicitly indicate whether API App or Web App. The resource provider is still Microsoft.Web. And there is no parameter which indicates the type in ARM template.
These two types technically still work in the same way. The difference would be the purpose, icon, OS running choice and debugging capability (refer here What is the difference between an API App and a Web App?).
You may want to classify between the two types by tagging it, which would help manage in case your resource groups have many web resources.
You can create API App via Azure Portal, or Visual Studio.
Also, look at Azure API Management for more flexibility of API wrapping instead of Azure App Service.

How to add an application from the Azure AD Gallery Programmatically

How do I add an application from the AAD Gallery programmatically and configure it? I checked AAD Powershell commands but I could not find out how to use it to provision a pre-integrated applications from the Azure AD gallery. There is the New-AzureRmADApplication -DisplayName "NewApplication" -HomePage "http://www.microsoft.com" -IdentifierUris "http://NewApplication" for example but not an Add-AzureRmADApplication or similar. The application I need is already available under the "Developer Services" category in the AAD Applications Gallery and all I need is to add it and configure its Single-sign on and Provisioning attributes. Is that even possible or do I have to create a new app? Even if I created a new application how do I configure it past the just adding the HomePage and IdentifierUris parameters which is all I can do using the New-AzureRmADApplication cmndlt?
Any help would be appreciated. Thank you
There is currently no way to configure the applications from the AAD Application Gallery programmatically. You can refer to the following post:
https://social.msdn.microsoft.com/Forums/en-US/42f262e2-150e-48bd-a741-cbabf42fcf77/how-to-add-and-configure-aad-application-from-the-gallery-programatically?forum=WindowsAzureAD
In case anyone come's across this question again, this is now possible, with the AzVm modules, instead of AzRm.
First you get the "Gallery Application Version"
$galleryApp = Get-AzGalleryApplicationVersion -GalleryName $GalleryName `
-GalleryApplicationName $AppName `
-ResourceGroupName $ResourceGroupName
Then create a new app instance for your current PowerShell Session
$appInstance = New-GalleryApplication -PackageReferenceId $galleryApp.Id
You'll also need to set the order parameter after you create the instance. There's no parameter to set it when it's defined.
$appInstance.Order = $int32Value
Finally, add the application to your Virtual Machine
Add-AzVmGalleryApplication -VM $VirtualMachineObjet `
-GalleryApplication $appInstance
-ResourceGroupName $ResourceGroupName
Once the application(s) are added, you need to push the update with "Update-AzVm", otherwise they won't actually deploy.
Here's the full example:
$galleryApp = Get-AzGalleryApplicationVersion -GalleryName $GalleryName `
-GalleryApplicationName $AppName `
-ResourceGroupName $ResourceGroupName
$appInstance = New-GalleryApplication -PackageReferenceId $galleryApp.Id
$appInstance.Order = $int32Value
Add-AzVmGalleryApplication -VM $VirtualMachineObjet `
-GalleryApplication $appInstance `
-ResourceGroupName $ResourceGroupName `
-Order $int32Value
Update-AzVm -ResourceGroupName $ResourceGroupName -VM $VirtualMachineObject

How do I reconfigure the Azure diagnostics extension when recreating an Azure VM

I need to make changes to a Azure Resource Manager Virtual Machine that are not allowed on an existing machine, such as changing the availability group. So I have to delete and recreate the machine, attaching the existing disks, network adapters, etc. to the new VM. I have a PowerShell script to do this, but I'm running into a problem with Virtual Machine extensions.
Here's my code:
$NewVMConfig = New-AzureRmVMConfig -VMName $VM.Name -VMSize $VM.HardwareProfile.VmSize
$NewVMConfig = Set-AzureRmVMOSDisk -VM $NewVMConfig -Name $VM.StorageProfile.OSDisk.Name -VhdUri $VM.StorageProfile.OSDisk.VHD.Uri -CreateOption attach -Windows
foreach ($disk in $vm.StorageProfile.DataDisks) {
$NewVMConfig = Add-AzureRmVMDataDisk -VM $NewVMConfig -Name $disk.Name -VhdUri $disk.Vhd.Uri -Caching $disk.Caching -DiskSizeInGB $disk.DiskSizeGB -CreateOption attach -Lun $disk.Lun
}
$NewVMConfig.AvailabilitySetReference = $VM.AvailabilitySetReference
$NewVMConfig.DiagnosticsProfile = $VM.DiagnosticsProfile
$NewVMConfig.Extensions = $VM.Extensions
$NewVMConfig.NetworkProfile = $VM.NetworkProfile
$location = $VM.Location
$resourceGroupName = $VM.ResourceGroupName
# Delete machine.
Remove-AzureRmVM -ResourceGroupName $VM.ResourceGroupName -Name $VM.Name
# Recreate machine
New-AzureRmVM -ResourceGroupName $resourceGroupName -Location $location -VM $NewVMConfig
Notice the line:
$NewVMConfig.Extensions = $VM.Extensions
The script runs without any error, but the new VM doesn't have the same extensions as the original. The diagnostics extension is gone and it now has the BGInfo extension which wasn't on the original machine.
I can use the Remove-AzureRmVMExtension command to remove the BGInfo extension, but I have been unsuccessful at recreating the diagnostics extensions. I've tried both Set-AzureRmVMExtension and Set-AzureRmVMDiagnosticsExtension to no avail.
Those VM extension commands do not support ARM yet. Hence, I suggest you to use ARM template instead. There is a quick-start template specifically for Windows VM with diagnostics extension on GitHub. You can download it and modify it to meet your needs, like specifying a VHD for your VM. And, use New-AzureRmResourceGroupDeployment to deploy your vm.
For your case, combining the above template with 201-specialized-vm-in-existing-vnet template would meet your needs.
Note: the 201-vm-diagnostics-extension-windows template deploys a Windows VM with diagnostics extension, while the 201-specialized-vm-in-existing-vnet template deploys a VM with existing VNet and VHD
For more information about this, see Create a Windows Virtual machine with monitoring and diagnostics using Azure Resource Manager Template.
For more information about authoring ARM template, see Authoring Azure Resource Manager templates.
For more information about deploying ARM template, see Deploy a Resource Group with Azure Resource Manager template.
Jack Zeng's answer with the virtual machine template showed me what was missing in my attempts to reconfigure the Azure diagnostics extension.
The key is that when you get a VM and look at the Extensions property (or the ExtensionsText property) it doesn't include the protected settings of the extension. (That's one way in which they are protected.) Thus you don't have all the information you need to recreate the extension. You have to rebuild the protected settings, which would vary from extension to extension, so you need to know what the specific extension requires. The virtual machine template to which Jack provide a link shows what information is needed for the protected settings of the Azure diagnostics extension, namely the storage account name, key, and endpoint.
Running the following code after recreating the virtual machine successfully reconfigured the diagnostics. In this code $VM is the original virtual machine object we got from calling Get-AzureRmVM before recreating the machine.
$diagnosticsExtension = $VM.Extensions | Where { $_.Name -eq 'Microsoft.Insights.VMDiagnosticsSettings' }
# The $VM.Extensions.Settings property does not correctly return the values of the different settings.
# Instead, use the $VM.ExtensionsText property to get the old settings.
$oldSettings = $VM.ExtensionsText | ConvertFrom-Json | Where { $_.Name -eq 'Microsoft.Insights.VMDiagnosticsSettings' } | foreach {$_.'properties.settings'}
# Need settings in a hash table.
$settings = #{
xmlCfg = $oldSettings.xmlCfg;
StorageAccount = $oldSettings.StorageAccount
}
$storageAccounts = Get-AzureRmStorageAccount
$storageAccount = $storageAccounts | Where { $_.StorageAccountName -eq $settings.StorageAccount }
$storageAccountKeys = $storageAccount | Get-AzureRmStorageAccountKey
$protectedSettings = #{
storageAccountName = $settings.StorageAccount;
storageAccountKey = $storageAccountKeys.Key1;
storageAccountEndPoint = "https://core.windows.net/"
}
Write-Host "Reconfiguring Azure diagnostics extension on $Name..."
$result = Set-AzureRmVMExtension -ResourceGroupName $newVM.ResourceGroupName -VMName $newVM.Name -Name $diagnosticsExtension.name -Publisher $diagnosticsExtension.Publisher -ExtensionType $diagnosticsExtension.VirtualMachineExtensionType -TypeHandlerVersion $diagnosticsExtension.TypeHandlerVersion -Settings $settings -ProtectedSettings $protectedSettings -Location $diagnosticsExtension.Location
Note that I am running version 1.2.1 of the Azure PowerShell extensions. In this release, Set-AzureRmVMDiagnosticsExtension appears to be broken, so I did not use it.

Add virtual folder to Azure Web App

I want to automate my deployment to Azure Web App.
I am using Octopus Deploy to deploy my app to a Azure Web App into a sub-folder based on my git-branch.
This works.
The problem is, that I need to add that folder to the list of virtual directories in the Application Settings of the Web App and I also have to mark it as an application.
How can I do this?
I can use anything that is possible with PowerShell.
P.S. I found this old thread: https://social.msdn.microsoft.com/Forums/azure/en-US/990f41fd-f8b6-43a0-b942-cef0308120b2/add-virtual-application-and-directory-to-an-azure-website-using-powershell?forum=windowsazurewebsitespreview, but this no longer seems to be working.
I'd recommend looking into the Azure Resource Manager - https://resources.azure.com - if you drill down to an existing Web App you can view REST & PowerShell commands for managing resources. In the Web App JSON, you'll find a section for Virtual Applications:
"virtualApplications": [
{
"virtualPath": "/",
"physicalPath": "site\\wwwroot",
"preloadEnabled": true,
"virtualDirectories": null
}
],
Since you are using Azure PowerShell, after Get-AzureSubscription, you should be able to do something like:
# PowerShell equivalent script
Switch-AzureMode -Name AzureResourceManager
# GET web
Get-AzureResource -ResourceGroupName yourResourceGroup -ResourceType Microsoft.Web/sites/config -ResourceName yourWebApp/web -OutputObjectFormat New -ApiVersion 2015-08-01
# SET web
$PropertiesObject = #{
#Property = value;
}
Set-AzureResource -PropertyObject $PropertiesObject -ResourceGroupName yourResourceGroup -ResourceType Microsoft.Web/sites/config -ResourceName yourWebApp/web -OutputObjectFormat New -ApiVersion 2015-08-01 -Force

How to force Azure Storage Account as classic

We recently built a infrastructure and application deployment framework using the Azure Resource Manager and templates. In order to deploy a Cloud Service, it is required to first setup an Azure Storage Account. As of recently, this was accomplished by running:
Switch-AzureMode AzureResourceManager
New-AzureStorageAccount -ResourceGroupName $resourceGroupName -StorageAccountName $storageAccountName -Location $locationName -Type Standard_LRS
This would create a storage account that the New-AzureDeployment cmdlet could use for the deployment. As far as I can remember, the storage account created would be one that the now labeled as "classic" in the UI. However, with recent changes, the storage account that is now created using the script above is non-classic (V2). This V2 storage account is not recognized by the New-AzureDeployment, and it throws this in the Powershell script:
New-AzureDeployment : ResourceNotFound: The storage account 'teststorage' was not found.
If I manually create the classic storage account in the UI, I can use it for my deployment, and it works just fine.
So is it possible to do one of the following:
Force the storage account to be created as classic via Powershell?
Instruct the New-AzureDeployment cmdlet to use the V2 storage account via Powershell?
Switch back to asm mode (the v1 api) and create the storage account from there:
switch-azuremode -Name AzureServiceManagement
Because someone else may find this helpful with the later versions of Azure resource manager (my version was 1.0.4)....
In the latest versions of AzureRM for PSVersion 5.0.10514.6, this can be done through a powershell cmdlet.
Assuming you have:
a) Authenticated to Azure RM: Login-AzureRMAccount
b) Already have created the resource group: New-AzureRmResourceGroup -Name $resourceGroupName -Location "South Central US"
You can then do something like this to get a classic storage account:
New-AzureRmResource -ResourceName "" -ResourceGroupName $resourceGroupName -ResourceType "Microsoft.ClassicStorage/StorageAccounts" -Location "South Central US" -Properties #{ AccountType = "Standard_LRS" } -ApiVersion "2015-06-01"
You can actually use ARM (Azure Resource Manager) to create a "Classic" (i.e. old portal) storage account. To do this, add the below json into your "Resources", adjusting the params as you require. The advantage this has over #Trondh answer is that this will be provisioned as part of your resource group. When you switch back to the ASM your classic storage account will just be added to a random resource group that you cannot move.
{
"name": "[concat(parameters('BuildStorageName'), 'classic')]",
"type": "Microsoft.ClassicStorage/storageAccounts",
"location": "[parameters('BuildStorageLocation')]",
"apiVersion": "2015-06-01",
"dependsOn": [ ],
"properties": {
"accountType": "[parameters('BuildStorageType')]"
}
}
Jason's answer is definitively the best solution..
$resourceGroupName= "myrsgroupp"
$classicStorageName = "myclassicstoragename"
$location = "North Europe"
New-AzureRmResource -ResourceGroupName $resourceGroupName -ResourceName $classicStorageName -ResourceType "Microsoft.ClassicStorage/StorageAccounts" -Location $location -Properties #{AccountType="Standard_LRS"} -ApiVersion "2015-06-01" -Force