Error when calling Azure Powershell New-AzResource: request content invalid - azure

I am stuck on this Azure PowerShell error when calling New-AzResource:
new-azresource : InvalidRequestContent : The request content was invalid and could not be deserialized: 'Could not find member 'dependsOn' on object of type 'ResourceProxyDefinition'. Path 'dependsOn'.'.
The object I pass into the -property argument of New-AzResource is indeed an object with a dependsOn property. So the message is a decoy. And, of course, it works just fine in the CLI.
Interestingly, you cannot even find that message, or the substring ResourceProxyDefinition in any of the code for the Az PS module (https://github.com/Azure/azure-powershell). I have researched this to the extent I can think of, like looking at the underlyzing Azure API and source code. Try a Google search for ResourceProxyDefinition (no spaces) and you will mostly land on a GitHub issue I hijacked.
For the property object, I start from a json template (given below, partially). That JSON works directly in the CLI. However, for the azure powershell module, I use ConvertFrom-Json on the file contents and pass the resulting object as the argument.
{
"type": "Microsoft.VirtualMachineImages/imageTemplates",
"apiVersion": "2019-05-01-preview",
"location": "eastus2",
"dependsOn": [],
"tags": {
"imagebuilderTemplate": "My.WindowsServer.2019-Datacenter-1910020354.tpl"
},
"properties": {
"buildTimeoutInMinutes": 100,
"source": {
"type": "PlatformImage",
"publisher": "MicrosoftWindowsServer",
"offer": "WindowsServer",
"sku": "2019-Datacenter",
"version": "2019.0.20190603"
},

With some changes to your template to be like this:
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"name": "My.WindowsServer.2019-Datacenter-1910030425.tpl",
"type": "Microsoft.VirtualMachineImages/imageTemplates",
"apiVersion": "2019-05-01-preview",
"location": "eastus2",
"dependsOn": [],
"tags": {
"imagebuilderTemplate": "My.WindowsServer.2019-Datacenter-1910030425.tpl"
},
"properties": {
"buildTimeoutInMinutes": 100,
"source": {
"type": "PlatformImage",
"publisher": "MicrosoftWindowsServer",
"offer": "WindowsServer",
"sku": "2019-Datacenter",
"version": "2019.0.20190603"
which includes adding an extra level (nesting the previous template under "resources" and adding a "$schema" and "contentVersion" you are set for deployment.
Now, use:
New-AzResourceGroupDeployment -ResourceGroupName $imageResourceGroup `
-TemplateFile $imageTemplateFile
which will read in the JSON file and it works! Don't use New-AzResource.

Related

ARM template for Azure Function ignores preWarmedInstanceCount setting

I'm deploying Azure function into Premium Function Plan (Elastic) using Azure powershell script:
New-AzResourceGroupDeployment -ResourceGroupName $RESOURCE_GROUP -TemplateFile "function-app.json" -TemplateParameterObject $params -Name $APP_SERVICE_NAME -Mode Incremental > $null
And deployment ignores my preWarmedInstanceCount setting. Newly created function has Always Ready Instances = 0 (see screenshot)
ARM template of function:
{
"apiVersion": "2020-06-01",
"name": "[parameters('siteName')]",
"type": "Microsoft.Web/sites",
"identity": {
"type": "systemAssigned"
},
"kind": "functionapp",
"location": "[resourceGroup().location]",
"properties": {
"name": "[parameters('siteName')]",
"serverFarmId": "[resourceId(parameters('appServicePlanRg'),'Microsoft.Web/serverfarms',parameters('appServicePlanName'))]",
"clientAffinityEnabled": false,
"siteConfig": {
"use32BitWorkerProcess": false,
"preWarmedInstanceCount": 2,
"appSettings": [
{
"name": "FUNCTIONS_EXTENSION_VERSION",
"value": "~3"
},
{
"name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
"value": "DefaultEndpointsProtocol=https;AccountName=xxx..."
},
{
"name": "WEBSITE_CONTENTSHARE",
"value": "asggas"
}
]
}
}
}
It seems to me few days ago it did worked properly and I managed to set that value via arm template and now I can only update it via Azure portal.
Here is ARM template of my hosting plan:
{
"type": "Microsoft.Web/serverfarms",
"apiVersion": "2018-02-01",
"name": "[parameters('appServicePlanName')]",
"location": "[resourceGroup().location]",
"properties": {
"name": "[parameters('appServicePlanName')]",
"workerSize": "1",
"numberOfWorkers": "1",
"maximumElasticWorkerCount": 20
},
"sku": {
"Tier": "ElasticPremium",
"Name": "EP2"
}
}
After some investigation I've come to "Activity Log" (after manual update on portal) screen and was surprised that my desired property is named as "minimumElasticInstanceCount" (it is not documented anywhere in either ARM API version https://learn.microsoft.com/en-us/azure/templates/microsoft.web/sites)
Then I added this field to my ARM template and all looks good for now. Also some explanation and difference between "Always Ready Instances"(minimumElasticInstanceCount) and "Pre-warmed instances"(preWarmedInstanceCount) are posted here: https://learn.microsoft.com/uk-ua/azure/azure-functions/functions-premium-plan
So in Azure Portal Pre-warmed instance setting is not displayed. And I was looking for another setting.
I have tried to replicate the issue and was able to figure out the issue here.
Instead of "preWarmedInstanceCount" try "reservedInstanceCount".
You can check from the Azure portal itself. Once you have updated the reserved instance count from the portal you can export the template :
Then compare your previous template with the exported one, you will be able to see the difference.

Azure ARM template resourceId problem with nested deployments on subscription level

I'm working on an ARM template to
A. deploy a resource group
B. deploy an ASE env.
To do both, as I understand I need to run a deployment on scope subscription level
New-AzDeployment -Name TestingASE -TemplateFile $HOME/azuredeploy.json -TemplateParameterFile $HOME/parameters.json -Location 'West Europe'
My template is pretty long already - so here are the most important parts (I think).
{
"$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
"contentVersion": "1.0.0.1",
"parameters": {
....
"resources": [
// Resource Group
{
"type": "Microsoft.Resources/resourceGroups",
"apiVersion": "2018-05-01",
"location": "[parameters('Location')]",
"name": "[parameters('rgName')]",
"properties": {}
},
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2019-05-01",
"name": "storageDeployment",
"resourceGroup": "[parameters('rgName')]",
"dependsOn": [
"[resourceId('Microsoft.Resources/resourceGroups/', parameters('rgName'))]"
],
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"variables": {},
"resources": [
....
{
"apiVersion": "2019-04-01",
"name": "[parameters('asevnetname')]",
"type": "Microsoft.Network/virtualNetworks",
"location": "[parameters('Location')]",
"properties": {
"addressSpace": {
"addressPrefixes": [
"[parameters('addressPrefix')]"
]
},
"subnets": [
{
"name": "[parameters('subnetName')]",
...
{
"apiVersion": "2019-02-01",
"type": "Microsoft.Web/hostingEnvironments",
"name": "[parameters('aseName')]",
"kind": "ASEV2",
"location": "[parameters('Location')]",
"properties": {
"name": "[parameters('aseName')]",
"location": "[parameters('Location')]",
"InternalLoadBalancingMode": "[parameters('ilbMode')]",
"virtualNetwork": {
"Id": "[resourceId(subscription().id, resourceGroup().Id, 'Microsoft.Network/virtualNetworks/subnets',parameters('asevnetname'),parameters('subnetName'))]"
}
....
This give me an output "The template function 'RESOURCEGROUP' is not expected at thislocation"
As far as I understand I'm following the guidelines
https://learn.microsoft.com/en-gb/azure/azure-resource-manager/templates/template-functions-resource#resourcegroup
The resourceGroup() function can't be used in a template that is deployed at the subscription level. It can only be used in templates that are deployed to a resource group. You can use the resourceGroup() function in a linked or nested template (with inner scope) that targets a resource group, even when the parent template is deployed to the subscription. In that scenario, the linked or nested template is deployed at the resource group level.
Thanks for helping with this.
The error happened at the resourceId format, it should be
resourceId([subscriptionId], [resourceGroupName], resourceType, resourceName1, [resourceName2], ...)
To get the resource ID for a resource in the same subscription but a
different resource group, provide the resource group name.
"[resourceId('otherResourceGroup', 'Microsoft.Storage/storageAccounts', 'examplestorage')]"
So, in this case, the virtualNetwork ID in the properties of Microsoft.Web/hostingEnvironments should be
"virtualNetwork": {
"Id": "[resourceId(parameters('rgName'), 'Microsoft.Network/virtualNetworks/subnets',parameters('asevnetname'),parameters('subnetName'))]"
}
or
"Id": "[resourceId(resourceGroup().name, 'Microsoft.Network/virtualNetworks/subnets',parameters('asevnetname'),parameters('subnetName'))]"
For more information, you could get more references to deploy an ASE within a subnet from this template.
Your deployment schema is subscriptionDeploymentTemplate and the New-AzDeployment cmdlet creates a deployment at the subscription scope. As per the docs you can't use that function when deploying at the subscription scope. You'll also encounter problems with the resourceId() function that wraps around it. The subscriptionResourceId() function should solve your problem.
"virtualNetwork": {
"Id": "[subscriptionResourceId('Microsoft.Network/virtualNetworks/subnets',parameters('asevnetname'),parameters('subnetName'))]"
}
The resource id will be returned in the subscription format as described here, if that isn't an acceptable format for the virtualNetwork.Id property of the Microsoft.Web/hostingEnvironments resource you're trying to deploy you might need to construct the resource id using the concat() function instead.

Deploy nested resources separately

Due to separation of duty I need to split an existing ARM template into two single templates - one for the resource and one for the logging
the original templates looks like this:
"resources": [
{ // https://learn.microsoft.com/en-us/azure/templates/microsoft.datafactory/factories
"type": "Microsoft.DataFactory/factories",
"name": "[variables('dataFactoryName')]",
"apiVersion": "[variables('apiVersion')]",
"location": "[resourceGroup().location]",
"tags": {},
"identity": {
"type": "SystemAssigned"
},
"properties": {},
"resources": [
{
"type": "providers/diagnosticSettings",
"name": "[concat('Microsoft.Insights/', variables('logSettingName'))]",
"dependsOn": [
"[resourceId('Microsoft.DataFactory/factories', variables('dataFactoryName'))]"
],
"apiVersion": "2017-05-01-preview",
"location": "[resourceGroup().location]",
"tags": {},
"properties": {
"name": "[variables('logSettingName')]",
"workspaceId": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', parameters('logAnalyticsObject').resourceGroup, '//providers/Microsoft.OperationalInsights/workspaces/', parameters('logAnalyticsObject').name)]",
"logs": "[parameters('logAnalyticsObject').adfv2.logs]",
"metrics": "[parameters('logAnalyticsObject').adfv2.metrics]"
}
}
]
}
The first part is quite easy, I just remove the sub-resource but how to get the second part (resource with "type": "providers/diagnosticSettings") correctly so it can be deployed from a different template?
Is this possible at all or are these strongly tied together?
I already tried different things like
"type": "Microsoft.DataFactory/factories/providers/diagnosticSettings",
"name": "[concat('Microsoft.Insights/', variables('name'))]",
but ended up with error messages like this:
Unable to process template language expressions for resource '/subscriptions/fb1e20c4-0878-4949-ac10-f92a9ac35db4/resourceGroups/swe-sdp-dv0
-rgp-adp/providers/Microsoft.Resources/deployments/DataFactory_LogAnalytics_Resource' at line '67' and column '5'. 'Unable to evaluate template language
function 'resourceId': function requires exactly one multi-segmented argument which must be resource type including resource provider namespace. Current
function arguments 'fb1e20c4-0878-4949-ac10-f92a9ac35db4,swe-sdp-dv0-rgp-anl,Microsoft.Insights,swe-sdp-dv0-oms-001'. Please see
https://aka.ms/arm-template-expressions/#resourceid for usage details.
I think to make it work I would need the right combination of "type", "name" and probably also "dependsOn"
ok, according to this, you would need to do this:
"type": "Microsoft.DataFactory/factories/providers/diagnosticSettings",
"name": "[concat(variables('dataFactoryName'), '/Microsoft.Insights/', variables('name'))]",
you dont need dependsOn, because resources are under different templates.

arm template virtualNetworkName creation appendix issue

I am trying to get a arm template running and have hit an issue with the virtualnetwork creation.
azuredeploy.json
"virtualNetworkName": {
"type": "string",
"metadata": {
"description": "Name of virtual network to be created"
},
"defaultValue": "autohav2VNET"
},
vnet-net.json
"resources": [
{
"name": "[parameters('virtualNetworkName')]",
"type": "Microsoft.Network/virtualNetworks",
"location": "[parameters('location')]",
"apiVersion": "2015-06-15",
"properties": {
"addressSpace": {
"addressPrefixes": [
"[parameters('virtualNetworkAddressRange')]"
]
},
"subnets": "[parameters('subnets')]"
}
}
]
The issue I am getting is that the vnet gets created with an appendix such as this: autohav2VNETl5g
So when this gets used to create a loadblancer, the names doe not match the defined parameter and the creation fails.
..../virtualNetworks/AUTOHAV2VNET referenced by resource .... /Microsoft.Network/loadBalancers/sqlLoadBalancer was not found.
Any suggestions?
with the data given it impossible to be sure why this is happening. you are probably passing in a value to the parameter virtualNetworkName. because if you wouldn't, than the vnet name would be: autohav2VNET.
ARM templates do not append anything anywhere just because they are arm templates. they only do what you designed them to do.
to help with debugging: how you are invoking the template and full template + full parameters file.

Azure Automation DSC compilation job failing with 404 from ARM template

I have created an ARM template which successfully creates an Automation Account in Azure and then creates a module and DSC configuration in that account.
When I add a Microsoft.Automation/automationAccounts/Compilationjobs resource to compile the DSC configuration, the template deployment fails at this step with 404 - File or directory not found.
The Compilationjobs resource exists as a top level resource in the template as follows:
{
"apiVersion": "2015-10-31",
"type": "Microsoft.Automation/automationAccounts/Compilationjobs",
"name": "automationAccountName/jobId123",
"location": "[variables('location')]",
"tags": {
},
"dependsOn": [
"Microsoft.Automation/automationAccounts/automationAccountName",
"modulesResourceLoop"
],
"properties": {
"configuration": {
"name": "DSCConfigurationName"
}
}
}
When I call Start-AzureRmAutomationDscCompilationJob with the same details the compilation job is created and completes successfully.
Compiling the configuration involves creating a compliationJob. Under the hood it's a PUT call to /CompiliationJobs/{guid}. so the trick here is to pass a new guid into the arm template when invoking compilation job.
Something like the following, you will need to define the parameter compilationJobGuid:
{
"name": "[parameters('compilationJobGuid')]",
"apiVersion": "2015-10-31",
"type": "Microsoft.Automation/automationAccounts/Compilationjobs",
"location": "[variables('location')]",
"tags": {
},
"dependsOn": [
"Microsoft.Automation/automationAccounts/automationAccountName",
"modulesResourceLoop"
],
"properties": {
"configuration": {
"name": "DSCConfigurationName"
}
}
}

Resources