Parameter of Array type in ARM Template - arm-template

I have an ARM Template with a parameter of array type as follows:
How do I set values in 2nd and 3rd position of parameter array? (for instance, "b", "c" in this example)

Method 1: Directly using the array index -
You can use the values of Array parameter by using this expression:
For 1st value: "[parameters('parameter1')[0]]"
For 2nd value: "[parameters('parameter1')[1]]"
For 3rd value: "[parameters('parameter1')[2]]"
You can test this sample template for fetching the values from array and displaying in the output:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"parameter1": {
"defaultValue": [
"value1",
"value2",
"value3"
],
"type": "Array"
}
},
"resources": [],
"outputs": {
"firstValue": {
"type": "String",
"value": "[parameters('parameter1')[0]]"
},
"secondValue": {
"type": "String",
"value": "[parameters('parameter1')[1]]"
},
"thirdValue": {
"type": "String",
"value": "[parameters('parameter1')[2]]"
}
}
}
Update:
Method 2: If you want to use copyIndex. Use the below expression -
"[parameters('parameter1')[copyIndex()]]"
Please check the below example:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"parameter1": {
"defaultValue": [
"strvalue1",
"strvalue2"
],
"type": "Array"
}
},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2019-04-01",
"name": "[parameters('parameter1')[copyIndex()]]",
"location": "[resourceGroup().location]",
"sku": {
"name": "Standard_LRS"
},
"kind": "Storage",
"properties": {},
"copy": {
"name": "storagecopy",
"count": "[length(parameters('parameter1'))]"
}
}
]
}

Related

How can I use dependsOn on copy resources in nested deployment?

I'm trying to deploy a RG tag for saving the roleAssignments version. I want that the tag deployment will be depended on the creation of the roleassignments. the roleassignments are created by using "copy" and the deployment is nested (since I need to change the scope to another RG and subscription).
I'm getting the following error message: {"code":"InvalidTemplate","message":"Deployment template validation failed: 'The template resource '[uniqueString(concat('nonRegionalRoleAssignments-', parameters('resourceId'), variables('roleAssignmentsToCreate')[copyIndex()].roleDefinitionId))]' at line '82' and column '9' is not valid: The template function 'copyIndex' is not expected at this location. The function can only be used in a resource with copy specified. Please see https://aka.ms/arm-copy for usage details.. Please see https://aka.ms/arm-template-expressions for usage details.'."}
How can I resolve it?
The template:
{
"$schema": https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#,
"contentVersion": "1.0.0.0",
"parameters": {
"managedIdentityName": {
"type": "String",
"metadata": {
"description": "The name of the managed identity resource."
}
},
"roleAssignmentsDefinitionIds": {
"type": "Array"
},
"roleAssignmentsVersion": {
"defaultValue": 0,
"type": "Int"
},
"resourceId": {
"type": "String"
},
"rolesAssignmentsResourceGroup": {
"type": "String"
},
"rolesAssignmentSubscriptionID": {
"type": "String"
}
},
"variables": {
"copy": [
{
"name": "roleAssignmentsToCreate",
"count": "[length(parameters('roleAssignmentsDefinitionIds'))]",
"input": {
"name": "[guid(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName')), resourceGroup().id, parameters('roleAssignmentsDefinitionIds')[copyIndex('roleAssignmentsToCreate')])]",
"roleDefinitionId": "[parameters('roleAssignmentsDefinitionIds')[copyIndex('roleAssignmentsToCreate')]]"
}
}
],
"roleAssignmentVersionTagName": "[concat(parameters('managedIdentityName'), 'RoleAssignmentVersion')]",
"roleAssignmentsVersionTags": {
"tags": {
"[variables('roleAssignmentVersionTagName')]": "[parameters('roleAssignmentsVersion')]"
}
},
"updatedResourceGroupTags": "[union(resourceGroup(), variables('roleAssignmentsVersionTags')).tags]",
"roleAssignmentsDefaultVersion": {
"tags": {
"[variables('roleAssignmentVersionTagName')]": 0
}
}
},
"resources": [
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2019-05-01",
"name": "[uniqueString(concat('nonRegionalRoleAssignments-', parameters('resourceId'), variables('roleAssignmentsToCreate')[copyIndex()].roleDefinitionId))]",
"properties": {
"mode": "Incremental",
"parameters": {},
"copy": {
"name": "roleAssignment",
"count": "[length(variables('roleAssignmentsToCreate'))]",
"mode": "serial",
"batchSize": 1
},
"template": {
"$schema": https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#,
"contentVersion": "1.0.0.0",
"variables": {},
"resources": [
{
"name": "[guid(parameters('resourceId'), 'Microsoft.Authorization/roleDefinitions', variables('roleAssignmentsToCreate')[copyIndex()].roleDefinitionId, resourceGroup().id)]",
"type": "Microsoft.Authorization/roleAssignments",
"condition": "[less(int(union(variables('RoleAssignmentsDefaultVersion'), resourceGroup()).tags[variables('roleAssignmentVersionTagName')]), parameters('roleAssignmentsVersion'))]",
"apiVersion": "2020-04-01-preview",
"properties": {
"principalId": "[reference(parameters('resourceId'), '2018-11-30').principalId]",
"roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', variables('roleAssignmentsToCreate')[copyIndex()].roleDefinitionId)]",
"principalType": "ServicePrincipal"
}
}
]
}
},
"subscriptionId": "[parameters('rolesAssignmentSubscriptionID')]",
"resourceGroup": "[parameters('rolesAssignmentsResourceGroup')]"
}
Thanks
Remove:
"dependsOn": [
"roleAssignment"
],
From the tags resource - it's not needed.

Error :The deployment parameters are using case sensitive names. The error parameter name(s): name.(ARM template deployment)

I am creating ARM template for Route table creation. A simple ARM template downloaded from the template deployment is failing. After I run the ARM template, it asks for the name and throws the below error.
I have tried giving names like routeVnet, vnetroute etc.
Saw some posts where giving the combination of lowercase uppercase in name will fix the issue. But it doesn't work here.
The arm template:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.5",
"parameters": {
"name": {
"type": "string"
},
"location": {
"type": "string"
},
"tagsByResource": {
"type": "object",
"defaultValue": {},
"metadata": {
"description": "Optional tags provided by the user via createUiDefinition.json"
}
},
"disableBgpRoutePropagation": {
"type": "bool"
}
},
"variables": {},
"resources": [
{
"apiVersion": "2019-02-01",
"type": "Microsoft.Network/routeTables",
"name": "[parameters('name')]",
"location": "[parameters('location')]",
"tags": "[ if(contains(parameters('tagsByResource'), 'Microsoft.Network/routeTables'), parameters('tagsByResource')['Microsoft.Network/routeTables'], json('{}')) ]",
"properties": {
"disableBgpRoutePropagation": "[parameters('disableBgpRoutePropagation')]"
}
}
],
"outputs": {}
}
The parameter template:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"location": {
"value": "eastus"
},
"Name": {
"value": ""
},
"tagsByResource": {
"value": {}
},
"disableBgpRoutePropagation": {
"value": true
}
}
}
The problem is with your parameter file where you are passing parameter name as "Name", in template your parameter is name while in parameter file you have mentioned it as Name.
The correct parameter file will look like:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"location": {
"value": "eastus"
},
"name": {
"value": "routeVnet12"
},
"tagsByResource": {
"value": {}
},
"disableBgpRoutePropagation": {
"value": true
}
}
}

How to tag Current time as a Tag for an ARM Deployment

I am trying to create a Log Analytics Workspace using an ARM template and a parameter files. I am also thinking to tag currrent time as CreatedOn tag for the resource.
Below is my ARM template-
{
"$schema": "http://schema.management.azure.com/schemas/2014-04-01-preview/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"LAWName": {
"type": "string"
},
"LocationName": {
"type": "string"
},
"SKUName": {
"type": "string"
},
"Tags": {
"type": "object"
}
},
"resources": [
{
"apiVersion": "2017-03-15-preview",
"name": "[parameters('LAWName')]",
"location": "[parameters('LocationName')]",
"tags": "[parameters('Tags')]",
"type": "Microsoft.OperationalInsights/workspaces",
"properties": {
"sku": {
"name": "[parameters('SKUName')]"
}
}
}
]
}
and here is my param file-
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"LAWName": {
"value": "atifmtest1"
},
"LocationName": {
"value": "westeurope"
},
"SKUName": {
"value": "pergb2018"
}
"Tags": {
"value": {
"CreatedBy": "Atif",
"CreatedOn": "[utcNow()]",
"Purpose": "Monitoring"
}
}
}
}
I read here https://learn.microsoft.com/en-us/azure/azure-resource-manager/templates/template-functions-date#utcnow that there is utcNow() function for ARM template but that is being considered as a string here and the current time does not appear as a tag for the resource.
What is the other way using which this can be achieved ?
Thanks in advance !!
Here is a working example:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"utcShort": {
"type": "string",
"defaultValue": "[utcNow('d')]"
},
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]"
}
},
"resources": [
{
"apiVersion": "2019-04-01",
"type": "Microsoft.Storage/storageAccounts",
"name": "[concat('storage', uniqueString(resourceGroup().id))]",
"location": "[parameters('location')]",
"tags": {
"Dept": "Finance",
"Environment": "Production",
"LastDeployed": "[parameters('utcShort')]"
},
"sku": {
"name": "Standard_LRS"
},
"kind": "Storage",
"properties": {}
}
]
}
Source.
Please follow the below steps for better results.
Add the utcShort in parameters and give a default value "[utcNow()]", Its not work from the parameters file. add utcShort into variables to make an object type. Follow the below steps.
"utcShort ": {
"type": "string",
"defaultValue": "[utcNow()]"
},
"resourceTags": {
"type": "object"
}
},
"variables":{
"createdDate": {
"createdDate": "[parameters('utcShort ')]"
}
},
Use this variable in Tags like below..
"tags": "[union(parameters('resourceTags'), variables('createdDate'))]"

Is there a workaround to get an Azure ARM template copy block to accept a zero-length array?

I'm working on an Azure ARM template which will have a string parameter expecting a comma-separated list of email addresses. In the template I want to parse this and copy into an array of the object types required by the emailReceivers property of the Microsoft.Insights/ActionGroups resource type.
The input needs to be a single string because the value will be substituted by Octopus Deploy as part of our deployment pipeline.
The template I have works fine as long as at least one email address is supplied, but I want this value to be optional. Unfortunately when an empty string is supplied I get the following error:
The template 'copy' definition at line '0' and column '0' has an
invalid copy count. The copy count must be postive integer value and
cannot exceed '800'.
Clearly a zero-length array is not supported by these copy blocks so I'm wondering if anyone knows a workaround or cunning hack that will let me achieve what I want.
Here is a stripped down template example:
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"emailAddresses": {
"type": "string",
"defaultValue": "one#email.com, two#email.com",
"metadata": {
"description": "Comma-separated list of email recipients."
}
}
},
"variables": {
"emailArray": "[if(equals(length(parameters('emailAddresses')), 0), json('[]'), split(parameters('emailAddresses'),','))]",
"copy": [
{
"name": "emailReceivers",
"count": "[length(variables('emailArray'))]",
"input": {
"name": "[concat('Email ', trim(variables('emailArray')[copyIndex('emailReceivers')]))]",
"emailAddress": "[trim(variables('emailArray')[copyIndex('emailReceivers')])]"
}
}
]
},
"resources": [],
"outputs": {
"return": {
"type": "array",
"value": "[variables('emailReceivers')]"
}
}
}
Well, not directly, but you could do this:
"copy": [
{
"name": "emailReceivers",
"count": "[if(equals(length(variables('emailArray')), 0), 1, length(variables('emailArray')))]",
"input": {
"name": "[concat('Email ', trim(variables('emailArray')[copyIndex('emailReceivers')]))]",
"emailAddress": "[trim(variables('emailArray')[copyIndex('emailReceivers')])]" << these need the same if to put placeholder value inside
}
}
]
and then,somewhere down the line you would implement a condition if length equals 0 bla-bla-bla
Expanding on what 4c74356b41 posted first - this ARM template will work with zero or more emails:
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"emailAddresses": {
"type": "string",
"defaultValue": "one#email.com, two#email.com",
"metadata": {
"description": "Comma-separated list of email recipients."
}
}
},
"variables": {
"emailArray": "[if(equals(length(parameters('emailAddresses')), 0), json('[]'), split(parameters('emailAddresses'),','))]",
"copy": [
{
"name": "emailReceivers",
"count": "[if(equals(length(variables('emailArray')), 0), 1, length(variables('emailArray')))]",
"input": {
"name": "[concat('Email ', if(equals(length(variables('emailArray')), 0),'',variables('emailArray')[copyIndex('emailReceivers')]) )]",
"emailAddress": "[if(equals(length(variables('emailArray')), 0),'',variables('emailArray')[copyIndex('emailReceivers')])]"
}
}
]
},
"resources": [],
"outputs": {
"return": {
"type": "array",
"value": "[variables('emailReceivers')]"
}
}
}
Using a parameter file either like this:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"emailAddresses": {
"value": "testEmail#mail.com"
}
}
}
or this
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"emailAddresses": {
"value": ""
}
}
}
Accept the answer from 4c74356b41 - this will just have better formatting than the comments.
Note - In my testing, it appears that this doesn't work with Resources:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"DataDisks": {
"type": "array",
"metadata": {
"description": "Combined DataDisk and DataDiskResource array"
},
"defaultValue": [
{
"lun": 0,
"createOption": "attach",
"caching": "None",
"writeAcceleratorEnabled": false,
"id": null,
"name": "cgltest01_DataDisk_0",
"storageAccountType": null,
"diskSizeGB": 31,
"sku": "StandardSSD_LRS",
"creationData": {
"createOption": "empty"
}
}
]
}
},
"variables": {
"Disks": "[parameters('DataDisks')]"
},
"resources": [
{
"name": "[if(equals(length(parameters('DataDisks')),0) ,'BogusName', parameters('DataDisks')[copyIndex()].name)]",
"type": "Microsoft.Compute/disks",
"condition": "[greater(length(parameters('DataDisks')), 0)]",
"apiVersion": "2018-06-01",
"location": "centralus",
"properties": {
"diskSizeGB": "[if(equals(length(parameters('DataDisks')),0) ,'123', parameters('DataDisks')[copyIndex()].diskSizeGB)]",
"creationData": "[if(equals(length(parameters('DataDisks')),0) , json('null'), parameters('DataDisks')[copyIndex()].creationData)]"
},
"sku": {
"name": "[parameters('DataDisks')[copyIndex()].sku]"
},
"copy": {
"name": "managedDiskResources",
"count": "[if(equals(length(parameters('DataDisks')),0), 1 , length(parameters('DataDisks')))]"
}
}
],
"outputs": {
"return": {
"type": "array",
"value": "[variables('Disks')]"
}
}
}
Fails with the same out of bounds array error:
Code : InvalidTemplate
Message : Deployment template validation failed: 'The template resource 'BogusName' at line '34' and column '9' is not valid: The language expression
property array index '0' is out of bounds.. Please see https://aka.ms/arm-template-expressions for usage details.'.
Details :

Azure Template validation failure , expression is not valid

I've exported a resource group that contains some Logic apps that I want to use in Visual Studio but one Logic App is unable to be opened using the designer-view in VS.
I get this error even thou I haven’t modified the code in any way:
The template validation failed: 'The property 'expression' '[concat('#equals(toLower(triggerBody()?['', parameters('workflows_Booking_name'),'s']?['Event']), 'create')')]'
of template action 'Condition_-_Create_or_UpdateBookings' at line '1' and column '1827' is not a valid template language expression.'.
This is what the Logic App looks like in the portal for better understanding.
As Szymon Wylezol mentioned that it seems that it is wrong with the template itself. From the error message we know that expression [concat('#equals(toLower(triggerBody()?['', parameters('workflows_Booking_name'),'s']?['Event']), 'create')')] is incorrect. More detail about expressions please refer to document.
According to your supplied screenshot that we can get the expression as following in the code view:
"actions": {
"Condition_-_Create_or_UpdateBookings": {
"type": "If",
"expression": "#equals(toLower(triggerBody()?['Bookings']?['Event']), 'create')",
"actions": {},
"runAfter": {}
}
}
Please compare the code view in the VS with code view in the Azure portal.
Then it should be ready for view in the Visual Studio. More details about Design, build, and deploy Azure Logic Apps in Visual Studio please refer to the document
Demo code.
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"workflows_testlogic_name": {
"defaultValue": "testlogic",
"type": "string"
},
"workflows_tomtestLogicApp_name": {
"defaultValue": "tomtestLogicApp",
"type": "string"
}
},
"variables": {},
"resources": [
{
"comments": "Generalized from resource: '/subscriptions/ed0caab7-c6d4-45e9-9289-c7e5997c9241/resourceGroups/tomtestlogicApp/providers/Microsoft.Logic/workflows/testlogic'.",
"type": "Microsoft.Logic/workflows",
"name": "[parameters('workflows_testlogic_name')]",
"apiVersion": "2016-06-01",
"location": "eastasia",
"properties": {
"state": "Enabled",
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"triggers": {
"manual": {
"type": "Request",
"kind": "Http",
"inputs": {
"schema": {
"properties": {
"event": {
"type": "string",
"value": ""
},
"name": {
"type": "string",
"value": ""
},
"participants": {
"type": "integer",
"value": ""
}
},
"type": "object"
}
}
}
},
"actions": {
"Condition": {
"actions": {},
"runAfter": {},
"expression": "#equals(toLower(triggerBody()?['name']), 'test')",
"type": "If"
}
},
"outputs": {}
},
"parameters": {}
},
"dependsOn": []
},
{
"comments": "Generalized from resource: '/subscriptions/ed0caab7-c6d4-45e9-9289-c7e5997c9241/resourceGroups/tomtestlogicApp/providers/Microsoft.Logic/workflows/tomtestLogicApp'.",
"type": "Microsoft.Logic/workflows",
"name": "[parameters('workflows_tomtestLogicApp_name')]",
"apiVersion": "2016-06-01",
"location": "eastasia",
"tags": {
"displayName": "LogicApp"
},
"properties": {
"state": "Enabled",
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"triggers": {
"manual": {
"type": "Request",
"kind": "Http",
"inputs": {
"schema": {
"properties": {
"Bookings": {
"properties": {
"BookedByEmail": {
"type": "string"
},
"Event": {
"type": "string"
}
}
}
}
}
}
}
},
"actions": {
"Condition_-_Create_or_UpdateBookings": {
"actions": {},
"runAfter": {},
"expression": "#equals(toLower(triggerBody()?['Bookings']?['Event']), 'create')",
"type": "If"
}
},
"outputs": {}
},
"parameters": {}
},
"dependsOn": []
}
]
}

Resources