I found this answer for the question :
It's possible to create App Service Plans using Azure Powershell?
Does anyone know how to create a CONSUMPTION app-service-plan with Azure?
When I look at the properties (using https://resources.azure.com/ ) of one I made (by the Gui), I see the following properties;
},
"sku": {
"name": "Y1",
"tier": "Dynamic",
"size": "Y1",
"family": "Y",
"capacity": 0
}
{
"id": "/subscriptions/xxxxxxxxxxxxxxxxxxxxxxxx/resourceGroups/MyResourceGroup/providers/Microsoft.Web/serverfarms/MyHandMadeConsumptionAppServicePlan",
"name": "MyHandMadeConsumptionAppServicePlan",
"type": "Microsoft.Web/serverfarms",
"kind": "functionapp",
"location": "East US",
But if I try (the important part being "-Tier Dynamic")
$plan = New-AzureRmAppServicePlan -Name 'MyPowershellCreatedAppServicePlan' -ResourceGroupName 'MyResourceGroup' -Location 'PickALocation' -Tier Dynamic
I get the exception:
Exception - + Cannot validate argument on parameter 'Tier'. The
argument "Dynamic" does not belong to the set
"Free,Shared,Basic,Standard,Premium,PremiumV2" specified by the
ValidateSet attribute. Supply an argument that is in the set and then
try the command again.
Geeze Louise.
This has been racking me for 3 days. I finally found some help (urls I mention).
It looks like this cannot be accomplished (currently) with New-AzureRmAppServicePlan.
But you can fall back onto the more generic New-AzureRmResource.
The code I finally got to work:
function SafeCreateAppServicePlan(
[Parameter(Mandatory = $true)]
[System.String]$location,
[Parameter(Mandatory = $true)]
[System.String]$resourceGroupName,
[Parameter(Mandatory = $true)]
[String]$appServicePlanName
)
{
Write-Host "SafeCreateAppServicePlan.Parameter:location: $location"
Write-Host "SafeCreateAppServicePlan.Parameter:resourceGroupName: $resourceGroupName"
Write-Host "SafeCreateAppServicePlan.Parameter:appServicePlanName: $appServicePlanName"
$SkuName = "Y1"
$SkuTier = "Dynamic"
$WebAppApiVersion = "2015-08-01"
$fullObject = @{
location = $location
sku = @{
name = $SkuName
tier = $SkuTier
}
}
Write-Host "Ensuring the $appServicePlanName app service plan exists"
$plan = Get-AzureRmAppServicePlan -Name $appServicePlanName -ResourceGroupName $resourceGroupName -ErrorAction SilentlyContinue
if(-not $plan) {
Write-Host "Creating $appServicePlanName app service plan"
New-AzureRmResource -ResourceGroupName $resourceGroupName -ResourceType Microsoft.Web/serverfarms -Name $appServicePlanName -IsFullObject -PropertyObject $fullObject -ApiVersion $WebAppApiVersion -Force
}
else {
Write-Host "$appServicePlanName app service plan already exists"
}
}
The help I got:
https://github.com/davidebbo/AzureWebsitesSamples/blob/master/PowerShell/HelperFunctions.ps1
(search the url above for "SkuName" to find the magic lines.
Please note, this is only part of the overall equation to deploy the INFRASTRUCTURE for azure functions (if you are not using arm templates). When I say the infrastructure, the code below does not deploy the azure-functions themselves, but the below will setup the infrastructure needed to do this.
This guy does a good job of explaining:
https://clouddeveloper.space/2017/10/26/deploy-azure-function-using-powershell/
"clouddeveloper" basically says that for consumption plan azure functions, you need to have a storage account. This lines up with the "info" button you get when you manually add a Function-App via the azure portal.
"A storage account that supports Blob, Queue, and Table Storage is
required. When using a Consumption plan function definitions are
stored in File Storage."
So my full code, that will create an App-Service-Plan, create a Storage Account, create an App-Service (that is azure functions/function app friendly) and match up the storage-account to the app-service is:
function SafeCreateAppServicePlan(
[Parameter(Mandatory = $true)]
[System.String]$location,
[Parameter(Mandatory = $true)]
[System.String]$resourceGroupName,
[Parameter(Mandatory = $true)]
[String]$appServicePlanName
)
{
Write-Host "SafeCreateAppServicePlan.Parameter:location: $location"
Write-Host "SafeCreateAppServicePlan.Parameter:resourceGroupName: $resourceGroupName"
Write-Host "SafeCreateAppServicePlan.Parameter:appServicePlanName: $appServicePlanName"
$SkuName = "Y1"
$SkuTier = "Dynamic"
$WebAppApiVersion = "2015-08-01"
$fullObject = @{
location = $location
sku = @{
name = $SkuName
tier = $SkuTier
}
}
Write-Host "Ensuring the $appServicePlanName app service plan exists"
$plan = Get-AzureRmAppServicePlan -Name $appServicePlanName -ResourceGroupName $resourceGroupName -ErrorAction SilentlyContinue
if(-not $plan) {
Write-Host "Creating $appServicePlanName app service plan"
New-AzureRmResource -ResourceGroupName $resourceGroupName -ResourceType Microsoft.Web/serverfarms -Name $appServicePlanName -IsFullObject -PropertyObject $fullObject -ApiVersion $WebAppApiVersion -Force
}
else {
Write-Host "$appServicePlanName app service plan already exists"
}
}
function SafeCreateAzureFunctionAppService(
[Parameter(Mandatory = $true)]
[System.String]$location,
[Parameter(Mandatory = $true)]
[System.String]$resourceGroupName,
[Parameter(Mandatory = $true)]
[String]$appServicePlanName,
[Parameter(Mandatory = $true)]
[String]$functionAppName
)
{
Write-Host "SafeCreateAzureFunctionAppService.Parameter:location: $location"
Write-Host "SafeCreateAzureFunctionAppService.Parameter:resourceGroupName: $resourceGroupName"
Write-Host "SafeCreateAzureFunctionAppService.Parameter:appServicePlanName: $appServicePlanName"
Write-Host "SafeCreateAzureFunctionAppService.Parameter:functionAppName: $functionAppName"
[String]$planId = ''
$plan = Get-AzureRmAppServicePlan -Name $appServicePlanName -ResourceGroupName $resourceGroupName -ErrorAction SilentlyContinue
if(-not $plan) {
throw [System.ArgumentOutOfRangeException] "Missing App Service Plan. (ResourceGroupName='$resourceGroupName', AppServicePlan.Name = '$appServicePlanName')"
}
else {
Write-Host "START AzureRmAppServicePlan Properties"
$plan.PSObject.Properties
Write-Host "END AzureRmAppServicePlan Properties"
#get the planId, so that can be used as the backing-app-service-plan for this AppService
[String]$planId = $plan.Id
}
#wire up the necessary properties for this AppService
$props = @{
ServerFarmId = $planId
}
$functionAppResource = Get-AzureRmResource | Where-Object { $_.ResourceName -eq $functionAppName -And $_.ResourceType -eq 'Microsoft.Web/Sites' }
if ($functionAppResource -eq $null)
{
New-AzureRmResource -ResourceType 'Microsoft.Web/Sites' -ResourceName $functionAppName -kind 'functionapp' -Location $location -ResourceGroupName $resourceGroupName -Properties $props -force
}
}
function SafeCreateStorageAccountToBackConsumptionAzureFunctions(
[Parameter(Mandatory = $true)]
[System.String]$location,
[Parameter(Mandatory = $true)]
[System.String]$resourceGroupName,
[Parameter(Mandatory = $true)]
[String]$storageAccountName
)
{
Write-Host "SafeCreateStorageAccount.Parameter:location: $location"
Write-Host "SafeCreateStorageAccount.Parameter:resourceGroupName: $resourceGroupName"
Write-Host "SafeCreateStorageAccount.Parameter:storageAccountName: $storageAccountName"
$azureRmStorageAccountGetCheck = Get-AzureRmStorageAccount -ResourceGroupName $resourceGroupName -AccountName $storageAccountName -ErrorAction SilentlyContinue
if(-not $azureRmStorageAccountGetCheck)
{
New-AzureRmStorageAccount -ResourceGroupName $resourceGroupName -AccountName $storageAccountName -Location $location -SkuName 'Standard_LRS'
}
else
{
Write-Host "$storageAccountName storage account already exists"
}
}
function MatchStorageSettingsToAppService(
[Parameter(Mandatory = $true)]
[System.String]$location,
[Parameter(Mandatory = $true)]
[System.String]$resourceGroupName,
[Parameter(Mandatory = $true)]
[String]$functionAppName,
[Parameter(Mandatory = $true)]
[String]$storageAccountName
)
{
Write-Host "MatchStorageSettingsToAppService.Parameter:location: $location"
Write-Host "MatchStorageSettingsToAppService.Parameter:resourceGroupName: $resourceGroupName"
Write-Host "MatchStorageSettingsToAppService.Parameter:functionAppName: $functionAppName"
Write-Host "MatchStorageSettingsToAppService.Parameter:storageAccountName: $storageAccountName"
$keys = Get-AzureRmStorageAccountKey -ResourceGroupName $resourceGroupName -AccountName $storageAccountName
$accountKey = $keys | Where-Object { $_.KeyName -eq "Key1" } | Select Value
$storageAccountConnectionString = 'DefaultEndpointsProtocol=https;AccountName=' + $storageAccountName + ';AccountKey=' + $accountKey.Value
$AppSettings = @{}
$AppSettings = @{'AzureWebJobsDashboard' = $storageAccountConnectionString;
'AzureWebJobsStorage' = $storageAccountConnectionString;
'FUNCTIONS_EXTENSION_VERSION' = '~1';
'WEBSITE_CONTENTAZUREFILECONNECTIONSTRING' = $storageAccountConnectionString;
'WEBSITE_CONTENTSHARE' = $storageAccountName;
}
Set-AzureRMWebApp -Name $functionAppName -ResourceGroupName $resourceGroupName -AppSettings $AppSettings
}
I got a few hints from this ARM template as well:
https://github.com/Azure/azure-quickstart-templates/blob/master/101-function-app-create-dynamic/azuredeploy.json
This is not really an answer to your questions, but just some research...
You will notice that in older Microsoft.Web
schemas, there was no support for "Dynamic". Instead, we see a list similar to what you see in the error message.
https://github.com/Azure/azure-resource-manager-schemas/blob/master/schemas/2015-08-01/Microsoft.Web.json#L37
In the newer schema (from 2016-09-01), which is what I'm seeing when I view my Comsumption App Service Plan in resources.azure.com, you'll find "Dynamic" as a valid value under computeMode
: https://github.com/Azure/azure-resource-manager-schemas/blob/master/schemas/2016-09-01/Microsoft.Web.json#L189
I'm not sure how you can set the computeMode
value in PowerShell, since the documentation doesn't show that this is exposed:
https://docs.microsoft.com/en-us/powershell/module/azurerm.websites/new-azurermappserviceplan?view=azurermps-5.0.0