Azure ARM Templates - How to pass output variable from linked template as parameters to another template? - azure-resource-manager

Lets say we have 2 linked arm templates with their associated *.params.json files:
createAppServiceTemplate.json
createAppServiceTemplate.params.json
createSqlDbTemplate.json
createSqlDbTemplate.params.json
The second template createSqlDbTemplate.json has outputs:
"outputs": {
"connectionString": {
"type": "string",
"value": "[concat('Database=', parameters('databaseName'), ';Server=', reference(resourceId('Microsoft.DBforPostgreSQL/servers',parameters('serverName')), '2017-12-01').fullyQualifiedDomainName, ';User Id=', parameters('administratorLogin'),'#', parameters('serverName'),';Password=', parameters('administratorPassword'))]"
}
}
I wan't to extract this output variable and pass it as parameter to createAppServiceTemplate.params.json.
I have tried to add this to my :
"parameters": {
"usersDbConnectionString": {
"value": "[reference('createSqlDbTemplate').outputs.connectionString.value]"
}
}
But I think parameters can't evaluate expressions? How can I achieve the desired behaviour ?

Assuming you had the linked createSqlServerTemplate.json template below:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"variables": {},
"resources": [],
"outputs": {
"greetingMessage": {
"value": "Hello World",
"type" : "string"
}
}
}
The main template deploys the linked template and gets the returned value. Notice that it references the deployment resource by name, and it uses the name of the property returned by the linked template.
main-template.json:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"variables": {},
"resources": [
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2019-10-01",
"name": "createAppServiceTemplate",
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[uri(deployment().properties.templateLink.uri, 'createAppServiceTemplate.json')]",
"contentVersion": "1.0.0.0"
},
"parameters": {
"userDbConnectionString: {
value: "[reference('createSqlServerTemplate').outputs.greetingMessage.value]"
}
}
}
},
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2019-10-01",
"name": "createSqlServerTemplate",
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[uri(deployment().properties.templateLink.uri, 'createSqlServerTemplate.json')]",
"contentVersion": "1.0.0.0"
}
}
}
]
}
Reference

Related

How to create and attach a new disk to an existing Windows Virtual Machine using ARM template?

I have already created VM in my resource group Now I want to add a new Data Disk to my existing VM so Can someone provide me any GitHub URL template link which I can refer to for this requirement. Below Link, I have already gone.
https://learn.microsoft.com/en-us/azure/virtual-machines/using-managed-disks-template-deployments
If you want to create a new data disk and append to a new created VM by ARM template, try the template below:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"vmName": {
"type": "String"
},
"diskName": {
"type": "String"
}
},
"resources": [{
"type": "Microsoft.Compute/virtualMachines",
"apiVersion": "2019-07-01",
"name": "[parameters('vmName')]",
"location": "[resourceGroup().location]",
"properties": {
"storageProfile": {
"dataDisks": [{
"lun": 0,
"name": "[parameters('diskName')]",
"createOption": "attach",
"managedDisk": {
"id": "[resourceId('Microsoft.Compute/disks/', parameters('diskName'))]"
}
}
]
}
},
"dependsOn": ["[resourceId('Microsoft.Compute/disks/', parameters('diskName'))]"]
}, {
"type": "Microsoft.Compute/disks",
"apiVersion": "2018-06-01",
"name": "[parameters('diskName')]",
"location": "[resourceGroup().location]",
"sku": {
"name": "Standard_LRS"
},
"properties": {
"creationData": {
"createOption": "Empty"
},
"diskSizeGB": 1023
}
}
]
}
I use PowerShell to deploy. Result:
UPDATE
If your VM has 1 data disk already, you want to keep it and append a new data disk to it, you need specify both of this 2 disks in dataDisks, for a quick test, the template below is based on the previous one: This vm has been appended a disk : test6-disk and append a new one and keep them two:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"vmName": {
"type": "String"
},
"diskName": {
"type": "String"
}
},
"resources": [{
"type": "Microsoft.Compute/virtualMachines",
"apiVersion": "2019-07-01",
"name": "[parameters('vmName')]",
"location": "[resourceGroup().location]",
"properties": {
"storageProfile": {
"dataDisks": [{
"lun": 0,
"name": "test6-disk",
"createOption": "attach",
"managedDisk": {
"id": "[resourceId('Microsoft.Compute/disks/','test6-disk')]"
}
}, {
"lun": 1,
"name": "[parameters('diskName')]",
"createOption": "attach",
"managedDisk": {
"id": "[resourceId('Microsoft.Compute/disks/', parameters('diskName'))]"
}
}
]
}
},
"dependsOn": ["[resourceId('Microsoft.Compute/disks/', parameters('diskName'))]"]
}, {
"type": "Microsoft.Compute/disks",
"apiVersion": "2018-06-01",
"name": "[parameters('diskName')]",
"location": "[resourceGroup().location]",
"sku": {
"name": "Standard_LRS"
},
"properties": {
"creationData": {
"createOption": "Empty"
},
"diskSizeGB": 1023
}
}
]
}
Result:

How to deploy ARM template with user managed identity and assign a subscription level role?

The ARM template below is supposed to create the following resources:
resource group
- user managed identity
- subscription level Contributor role assignment
Currently the deployment is failing with the error "error": { "code": "ResourceGroupNotFound", "message": "Resource group 'rg-myproject-deploy' could not be found." } apparently because the role assignment step seem to not be respecting the dependsOn statements that should enforce that it should only happen after the resource group is created. Is there a way to deploy all these resources in a single ARM template?
{
"$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"projectName": {
"type": "string",
"defaultValue": "myproject",
"maxLength": 11,
"metadata": {
"description": "The name of the project"
}
},
"location": {
"type": "string",
"defaultValue": "westus2",
"metadata": {
"description": "The region were to deploy assets"
}
}
},
"variables": {
"resourceGroupName": "[concat('rg-', parameters('projectName'), '-deploy')]",
"managedIdentityName": "[concat('msi-', parameters('projectName'), '-deploy')]",
"bootstrapRoleAssignmentId": "[guid(subscription().id, 'contributor')]",
"contributorRoleDefinitionId": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]",
"managedIdentityId": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', variables('resourceGroupName'), '/providers/Microsoft.ManagedIdentity/userAssignedIdentities/', variables('managedIdentityName'))]"
},
"resources": [
{
"type": "Microsoft.Resources/resourceGroups",
"apiVersion": "2019-10-01",
"name": "[variables('resourceGroupName')]",
"location": "[parameters('location')]",
"properties": {}
},
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2019-10-01",
"name": "deployment-assets-except-role-assignment",
"resourceGroup": "[variables('resourceGroupName')]",
"dependsOn": [
"[resourceId('Microsoft.Resources/resourceGroups/', variables('resourceGroupName'))]"
],
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"variables": {},
"resources": [
{
"type": "Microsoft.ManagedIdentity/userAssignedIdentities",
"name": "[variables('managedIdentityName')]",
"apiVersion": "2018-11-30",
"location": "[parameters('location')]"
}
],
"outputs": {}
}
}
}
,
{
"type": "Microsoft.Authorization/roleAssignments",
"apiVersion": "2017-09-01",
"name": "[variables('bootstrapRoleAssignmentId')]",
"dependsOn": [
"[subscriptionResourceId('Microsoft.Resources/resourceGroups', variables('resourceGroupName'))]",
"deployment-assets-except-role-assignment"
],
"properties": {
"roleDefinitionId": "[variables('contributorRoleDefinitionId')]",
"principalId": "[reference(variables('managedIdentityId'), '2018-11-30').principalId]",
"principalType": "ServicePrincipal",
"scope": "[subscription().id]"
}
}
],
"outputs": {}
}
I think you're running into this:
https://bmoore-msft.blog/2020/07/26/resource-not-found-dependson-is-not-working/
The fix was a little more involved than I thought, but to summarize:
the nested deployment that provisions the MI must be set to inner scope evaluation
output the principalId from that deployment and use that in your reference (i.e. don't directly reference)
Due to #1 I moved some stuff around (params/vars)
{
"$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"projectName": {
"type": "string",
"defaultValue": "myproject",
"maxLength": 11,
"metadata": {
"description": "The name of the project"
}
},
"location": {
"type": "string",
"defaultValue": "westus2",
"metadata": {
"description": "The region were to deploy assets"
}
}
},
"variables": {
"identityDeploymentName": "deployment-assets-except-role-assignment",
"resourceGroupName": "[concat('rg-', parameters('projectName'), '-deploy')]",
"managedIdentityName": "[concat('msi-', parameters('projectName'), '-deploy')]",
"managedIdentityId": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', variables('resourceGroupName'), '/providers/Microsoft.ManagedIdentity/userAssignedIdentities/', variables('managedIdentityName'))]",
"bootstrapRoleAssignmentId": "[guid(subscription().id, variables('contributorRoleDefinitionId'),variables('managedIdentityId'))]",
"contributorRoleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]",
},
"resources": [
{
"type": "Microsoft.Resources/resourceGroups",
"apiVersion": "2019-10-01",
"name": "[variables('resourceGroupName')]",
"location": "[parameters('location')]",
"properties": {}
},
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2019-10-01",
"name": "[variables('identityDeploymentName')]",
"resourceGroup": "[variables('resourceGroupName')]",
"dependsOn": [
"[resourceId('Microsoft.Resources/resourceGroups', variables('resourceGroupName'))]"
],
"properties": {
"mode": "Incremental",
"expressionEvaluationOptions":{
"scope": "inner"
},
"parameters": {
"location": {
"value": "[parameters('location')]"
},
"managedIdentityName": {
"value": "[variables('managedIdentityName')]"
}
},
"template": {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"location": {
"type": "string"
},
"managedIdentityName": {
"type": "string"
}
},
"variables": {},
"resources": [
{
"type": "Microsoft.ManagedIdentity/userAssignedIdentities",
"name": "[parameters('managedIdentityName')]",
"apiVersion": "2018-11-30",
"location": "[parameters('location')]"
}
],
"outputs": {
"principalId": {
"type": "string",
"value": "[reference(parameters('managedIdentityName')).principalId]"
}
}
}
}
}
,
{
"type": "Microsoft.Authorization/roleAssignments",
"apiVersion": "2020-04-01-preview",
"name": "[variables('bootstrapRoleAssignmentId')]",
"dependsOn": [
"[subscriptionResourceId('Microsoft.Resources/resourceGroups', variables('resourceGroupName'))]",
"[variables('identityDeploymentName')]"
],
"properties": {
"roleDefinitionId": "[variables('contributorRoleDefinitionId')]",
"principalId": "[reference(variables('identityDeploymentName')).outputs.principalId.value]",
"principalType": "ServicePrincipal",
"scope": "[subscription().id]"
}
}
]
}

How to use "jagged" objects in Azure Resource Manger templates to iterate over them?

I have object with not equal number of properties (and would like to keep it like this), i.e. second object is missing property "routeTable" and properties repeat i.e. "NSG-AllowAll"
"value": [
{
"name": "GatewaySubnet",
"addressPrefix": "10.2.0.0/24",
"networkSecurityGroup": "NSG-AllowAll",
"routeTable": "UDR-Default"
},
{
"name": "UnTrusted",
"addressPrefix": "10.2.1.0/24",
"networkSecurityGroup": "NSG-AllowAll"
},
{
"name": "routed",
"addressPrefix": "10.2.2.0/24",
"routeTable": "UDR-Default1"
}
]
The solution to create vnet works fine but only if exisiting properties don't repeat i.e. the second NSG above has different name from the first one. In my scenario there will be a lot of repeating property names
In that case you just need to remove nsg\udr from that template I've created. I think thats what I've told you there as well. check the ps in my previous answer.
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"deploymentPrefix": {
"type": "string"
},
"subnets": {
"type": "array",
"defaultValue": [
{
"name": "GatewaySubnet",
"addressPrefix": "10.2.0.0/24",
"networkSecurityGroup": "NSG-AllowAll",
"routeTable": "UDR-Default"
},
{
"name": "UnTrusted",
"addressPrefix": "10.2.1.0/24",
"networkSecurityGroup": "NSG-AllowAll"
},
{
"name": "routed",
"addressPrefix": "10.2.2.0/24",
"routeTable": "UDR-Default"
}
]
}
},
"variables": {
"copy": [
{
"name": "subnetsBase",
"count": "[length(parameters('subnets'))]",
"input": {
"name": "[concat('subnet-', parameters('subnets')[copyIndex('subnetsBase')].name)]",
"properties": {
"addressPrefix": "[parameters('subnets')[copyIndex('subnetsBase')].addressPrefix]"
}
}
},
{
"name": "subnetsUDR",
"count": "[length(parameters('subnets'))]",
"input": {
"routeTable": {
"id": "[if(contains(parameters('subnets')[copyIndex('subnetsUDR')], 'routeTable'), resourceId('Microsoft.Network/routeTables', parameters('subnets')[copyIndex('subnetsUDR')].routeTable), 'skip')]"
}
}
},
{
"name": "subnetsNSG",
"count": "[length(parameters('subnets'))]",
"input": {
"networkSecurityGroup": {
"id": "[if(contains(parameters('subnets')[copyIndex('subnetsNSG')], 'networkSecurityGroup'), resourceId('Microsoft.Network/networkSecurityGroups', parameters('subnets')[copyIndex('subnetsNSG')].networkSecurityGroup), 'skip')]"
}
}
}
]
},
"resources": [
{
"apiVersion": "2017-06-01",
"type": "Microsoft.Network/virtualNetworks",
"name": "[concat(parameters('deploymentPrefix'), '-vNet')]",
"location": "[resourceGroup().location]",
"properties": {
"addressSpace": {
"addressPrefixes": [
"10.2.0.0/16"
]
},
"copy": [
{
"name": "subnets",
"count": "[length(parameters('subnets'))]",
"input": {
"name": "[concat('subnet-', parameters('subnets')[copyIndex('subnets')].name)]",
"properties": "[union(variables('subnetsBase')[copyIndex('subnets')].properties, if(equals(variables('subnetsUDR')[copyIndex('subnets')].routetable.id, 'skip'), variables('subnetsBase')[copyIndex('subnets')].properties, variables('subnetsUDR')[copyIndex('subnets')]), if(equals(variables('subnetsNSG')[copyIndex('subnets')].networkSecurityGroup.id, 'skip'), variables('subnetsBase')[copyIndex('subnets')].properties, variables('subnetsNSG')[copyIndex('subnets')]))]"
}
}
]
}
}
]
}
I dont see any reason why this wont work if you have nsg\udr in place

How do I troubleshoot "InternalServerError" returned by ARM deployment

Trying to deploy custom module to Azure Automation account and getting error during deployment.
So there are 2 issues:
1. Deployment instead of failing ending up indefinetely stack with InternalServerError
2. Failure itself is non-descriptive and impossible to troubleshoot
Error
{
"code": "InternalServerError",
"message": "{\"Message\":\"An error has occurred.\"}"
}
Template
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"Automation Account Name": {
"type": "string"
}
},
"resources": [
{
"apiVersion": "2015-10-31",
"location": "southcentralus",
"name": "[parameters('Automation Account Name')]",
"type": "Microsoft.Automation/automationAccounts",
"properties": {
"sku": {
"name": "Basic"
}
},
"tags": {},
"resources": [
{
"name": "cdscdockerswarm",
"type": "modules",
"apiVersion": "2015-10-31",
"properties": {
"contentLink": {
"uri": "https://github.com/artisticcheese/dockerswarmarm/raw/master/modules/cdscdockerswarm.zip"
}
},
"dependsOn": [
"[concat('Microsoft.Automation/automationAccounts/', parameters('Automation Account Name'))]"
]
}
]
}
],
"outputs": {}
}

Provide request header for Microsoft.Scheduler/jobCollections/jobs

I want to know how to provide from my Azure WebApp the user/password to provide header for my webjob
{
"name": "[concat('TraitementTableAzure-', parameters('HeliosEnvironnementName'), '-js')]",
"type": "jobs",
"apiVersion": "2016-03-01",
"location": "[resourceGroup().location]",
"properties": {
"action": {
"request": {
"method": "Post",
"uri": "[concat('https://', parameters('AzureWebAppWebJobs'), '.scm.azurewebsites.net/api/triggeredwebjobs/', parameters('HeliosEnvironnementName'), '_TraitementTableAzure/run')]",
"headers": {
"authorization": "[concat('Basic ', reference('???').???)]" }
},
"type": "Http",
"retryPolicy": {
"retryType": "Fixed"
}
},
"startTime": "[parameters('SchedulesStartTime').SchedulerTraitementTableAzureStartTime]",
"recurrence": {
"frequency": "Day",
"interval": 1
},
"state": "Enabled"
},
"dependsOn": [
"[resourceId('Microsoft.Scheduler/jobCollections', variables('AzureSchedulerName'))]"
],
"tags": {
"displayName": "Cedule_TraitementTableAzure"
}
},
I found information over Azure Portal but not in ARM Template under webjob Properties. How can reference information on the blue arrow over my ARM template ?
How can reference information on the blue arrow over my ARM template ?
If we want to get the publishingPassword, then we could use ListPublishingCredentials API in the ARM template via list function, list(concat('Microsoft.Web/sites/', parameters('websisteName') ,'/config/publishingcredentials'), '2016-08-01').properties.publishingPassword
According to your template, it seems the that you want to call WebJob REST API, If it is that case, the authorization header is base64(publishusername:publishpassword).
base64(concat(list(concat('Microsoft.Web/sites/', parameters('websisteName'),'/config/publishingcredentials'), '2016-08-01').properties.publishingUserName,':',list(concat('Microsoft.Web/sites/', parameters('websisteName') ,'/config/publishingcredentials'), '2016-08-01').properties.publishingPassword))
I write a demo to test it on my side, it works correctly .
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"websisteName": {
"type": "string"
}
},
"resources": [],
"outputs": {
"base64Output": {
"type": "string",
"value": "[base64(concat(list(concat('Microsoft.Web/sites/', parameters('websisteName'),'/config/publishingcredentials'), '2016-08-01').properties.publishingUserName,':',list(concat('Microsoft.Web/sites/', parameters('websisteName') ,'/config/publishingcredentials'), '2016-08-01').properties.publishingPassword))]"
}
}
}

Resources