Azure Resource Manager (ARM) template to deploy SQL along with tables - azure

I have an ARM template to deploy a sql.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
......
"resources": [
{
"type": "Microsoft.Sql/servers",
"apiVersion": "2021-05-01-preview",
"name": "[parameters('serverName')]",
"location": "[parameters('location')]",
"properties": {
"administratorLogin": "[parameters('administratorLogin')]",
"administratorLoginPassword": "[parameters('administratorLoginPassword')]"
}
},
{
"type": "Microsoft.Sql/servers/databases",
"apiVersion": "2021-05-01-preview",
"name": "[format('{0}/{1}', parameters('serverName'), parameters('sqlDBName'))]",
"location": "[parameters('location')]",
"sku": {
"name": "Standard",
"tier": "Standard"
},
"dependsOn": [
"[resourceId('Microsoft.Sql/servers', parameters('serverName'))]"
]
}
]
}
When deployed it creates an empty sql database. How do we deploy the corresponding schema, tables, procedures?

We tested the below ARM template in our local environment it is working fine, Below statements are based on our analysis.
Here is the ARM template we have used to create a new SQL database, a table that is exported from the existing database.
Here is our template.json file:
{
"$schema": "http://schema.management.azure.com/schemas/2014-04-01-preview/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters":
{
"administratorLogin":
{
"type": "string"
},
"administratorLoginPassword":
{
"type": "securestring"
},
"databaseName":
{
"type": "string"
},
"location":
{
"type": "string"
},
"_artifactsLocationSasToken":
{
"type": "securestring"
}
},
"variables":
{
"collation": "SQL_Latin1_General_CP1_CI_AS",
"edition": "Premium",
"maxSizeBytes": "1073741824",
"requestedServiceObjectiveName": "P1",
"storageKeyType": "SharedAccessKey",
"version": "12.0",
"serverName": "[concat('sqldemo', uniqueString(resourceGroup().id))]"
},
"resources":
[
{
"name": "[variables('serverName')]",
"type": "Microsoft.Sql/servers",
"apiVersion": "2015-05-01-preview",
"location": "[parameters('location')]",
"properties":
{
"administratorLogin": "[parameters('administratorLogin')]",
"administratorLoginPassword": "[parameters('administratorLoginPassword')]",
"version": "[variables('version')]"
},
"resources":
[
{
"name": "AllowAllWindowsAzureIps",
"type": "firewallrules",
"apiVersion": "2015-05-01-preview",
"location": "[parameters('location')]",
"dependsOn":
[
"[concat('Microsoft.Sql/servers/', variables('serverName'))]"
],
"properties":
{
"endIpAddress": "0.0.0.0",
"startIpAddress": "0.0.0.0"
}
},
{
"name": "[parameters('databaseName')]",
"type": "databases",
"apiVersion": "2017-03-01-preview",
"location": "[parameters('location')]",
"dependsOn":
[
"[concat('Microsoft.Sql/servers/', variables('serverName'))]"
],
"properties":
{
"collation": "[variables('collation')]",
"edition": "[variables('edition')]",
"maxSizeBytes": "[variables('maxSizeBytes')]",
"requestedServiceObjectiveName": "[variables('requestedServiceObjectiveName')]"
},
"resources":
[
{
"name": "Import",
"type": "extensions",
"apiVersion": "2014-04-01-preview",
"dependsOn":
[
"[concat('Microsoft.Sql/servers/', variables('serverName'), '/databases/', parameters('databaseName'))]"
],
"properties":
{
"storageKeyType": "[variables('storageKeyType')]",
"storageKey": "[parameters('_artifactsLocationSasToken')]",
"storageUri": "<Storageuri_of_exported_bacpacfile>", ##pass the bloburi of the bacpac file
"administratorLogin": "[parameters('administratorLogin')]",
"administratorLoginPassword": "[parameters('administratorLoginPassword')]",
"operationMode": "Import"
}
}
]
}
]
}
],
"outputs":
{
"serverName":
{
"type": "object",
"value": "[reference(variables('serverName'))]"
}
}
}
Here is the template.parameters.json file :
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters":
{
"administratorLogin":
{
"value": "<sqlserverusername>"
},
"databaseName":
{
"value": "<dbtablename>"
},
"location":
{
"value": "<location>"
},
"_artifactsLocationSasToken":{
"value": "<SAS token of the exported bacpacfile>"
}
}
}
Here is the sample output for reference:
Note:
You need to create a firewall rule with your Public IP in the SQL database post-creating sql DB with a table using the above ARM template.

Related

ARM Template to create SQL Database with a privatendpoint

I'm having errors while trying to deploy an ARM deploy with an SQL Database and its private endpoint.
here is the code below
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"sqlAdministratorLogin": {
"type": "string",
"metadata": {
"description": "The administrator username of the SQL logical server"
}
},
"sqlAdministratorLoginPassword": {
"type": "securestring",
"metadata": {
"description": "The administrator password of the SQL logical server."
}
},
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]",
"metadata": {
"description": "Location for all resources."
}
}
},
"variables": {
"vnetName": "powerStateManagement-vnet",
"subnet1Name": "default",
"sqlServerName": "[concat('sqlserver', uniqueString(resourceGroup().id))]",
"databaseName": "[concat(variables('sqlServerName'),'/sample-db')]",
"privateEndpointName": "myPrivateEndpoint",
"privateDnsZoneName": "[concat('privatelink', environment().suffixes.sqlServerHostname)]",
"pvtendpointdnsgroupname": "[concat(variables('privateEndpointName'),'/mydnsgroupname')]",
"vnetResourceGroup":"powerStateManagement"
},
"resources": [
{
"type": "Microsoft.Sql/servers",
"apiVersion": "2020-02-02-preview",
"name": "[variables('sqlServerName')]",
"location": "[parameters('location')]",
"kind": "v12.0",
"tags": {
"displayName": "[variables('sqlServerName')]"
},
"properties": {
"administratorLogin": "[parameters('sqlAdministratorLogin')]",
"administratorLoginPassword": "[parameters('sqlAdministratorLoginPassword')]",
"version": "12.0",
"publicNetworkAccess": "Disabled"
},
"resources": [
]
},
{
"type": "Microsoft.Sql/servers/databases",
"apiVersion": "2020-02-02-preview",
"name": "[variables('databaseName')]",
"location": "[parameters('location')]",
"sku": {
"name": "Basic",
"tier": "Basic",
"capacity": 5
},
"dependsOn": [
"[resourceId('Microsoft.Sql/servers', variables('sqlServerName'))]"
],
"tags": {
"displayName": "[variables('databaseName')]"
},
"properties": {
"collation": "SQL_Latin1_General_CP1_CI_AS",
"edition": "Basic",
"maxSizeBytes": 104857600,
"requestedServiceObjectiveName": "Basic",
"sampleName": "AdventureWorksLT"
}
},
{
"type": "Microsoft.Network/privateEndpoints",
"apiVersion": "2020-06-01",
"name": "[variables('privateEndpointName')]",
"location": "[parameters('location')]",
"dependsOn": [
"[variables('vnetName')]",
"[variables('sqlServerName')]"
],
"properties": {
"subnet": {
"id": "[resourceId(variables('vnetResourceGroup'),'/','Microsoft.Network/virtualNetworks','/',variables('vnetName'),'/',variables('subnet1Name'))]"
},
"privateLinkServiceConnections": [
{
"name": "[variables('privateEndpointName')]",
"properties": {
"privateLinkServiceId": "[resourceId('Microsoft.Sql/servers',variables('sqlServerName'))]",
"groupIds": [
"sqlServer"
]
}
}
]
}
},
{
"type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks",
"apiVersion": "2020-01-01",
"name": "[concat(variables('privateDnsZoneName'), '/', variables('privateDnsZoneName'), '-link')]",
"location": "global",
"dependsOn": [
"[resourceId('Microsoft.Network/privateDnsZones', variables('privateDnsZoneName'))]",
"[resourceId(variables('vnetResourceGroup'),'Microsoft.Network/virtualNetworks',variables('vnetName'))]"
],
"properties": {
"registrationEnabled": false,
"virtualNetwork": {
"id": "/subscriptions/*****/resourceGroups/powerStateManagement/providers/Microsoft.Network/virtualNetworks/powerStateManagement-vnet"
}
}
},
{
"type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups",
"apiVersion": "2020-06-01",
"name": "[variables('pvtendpointdnsgroupname')]",
"location": "[parameters('location')]",
"dependsOn": [
"[resourceId('Microsoft.Network/privateDnsZones', variables('privateDnsZoneName'))]",
"[variables('privateEndpointName')]"
],
"properties": {
"privateDnsZoneConfigs": [
{
"name": "config1",
"properties": {
"privateDnsZoneId": "[resourceId('Microsoft.Network/privateDnsZones', variables('privateDnsZoneName'))]"
}
}
]
}
}
]
}
The challenge here is that when I try to run this code I always get this error
Deployment template validation failed: 'The template reference 'powerStateManagement-vnet' is not valid: could not find template resource or resource copy with this name.
The ''powerStateManagement-vnet' is an existing Virtual Network which has been referenced below
{
"type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks",
"apiVersion": "2020-01-01",
"name": "[concat(variables('privateDnsZoneName'), '/', variables('privateDnsZoneName'), '-link')]",
"location": "global",
"dependsOn": [
"[resourceId('Microsoft.Network/privateDnsZones', variables('privateDnsZoneName'))]",
"[resourceId(variables('vnetResourceGroup'),'Microsoft.Network/virtualNetworks',variables('vnetName'))]"
],
"properties": {
"registrationEnabled": false,
"virtualNetwork": {
"id": "/subscriptions/*****/resourceGroups/powerStateManagement/providers/Microsoft.Network/virtualNetworks/powerStateManagement-vnet"
}
}
}
Please help
There is something wrong with your dependsOn param of Microsoft.Network/privateEndpoints. And seems there are some other issues in your template, I did some modification based on your template,just try it below:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"sqlAdministratorLogin": {
"type": "string",
"metadata": {
"description": "The administrator username of the SQL logical server"
}
},
"sqlAdministratorLoginPassword": {
"type": "securestring",
"metadata": {
"description": "The administrator password of the SQL logical server."
}
},
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]",
"metadata": {
"description": "Location for all resources."
}
}
},
"variables": {
"vnetName": "powerStateManagement-vnet",
"subnet1Name": "default",
"sqlServerName": "[concat('sqlserver', uniqueString(resourceGroup().id))]",
"databaseName": "[concat(variables('sqlServerName'),'/sample-db')]",
"privateEndpointName": "myPrivateEndpoint",
"privateDnsZoneName": "testdns.com",
"pvtendpointdnsgroupname": "[concat(variables('privateEndpointName'),'/mydnsgroupname')]",
"vnetResourceGroup": "powerStateManagement"
},
"resources": [{
"type": "Microsoft.Sql/servers",
"apiVersion": "2020-02-02-preview",
"name": "[variables('sqlServerName')]",
"location": "[parameters('location')]",
"kind": "v12.0",
"tags": {
"displayName": "[variables('sqlServerName')]"
},
"properties": {
"administratorLogin": "[parameters('sqlAdministratorLogin')]",
"administratorLoginPassword": "[parameters('sqlAdministratorLoginPassword')]",
"version": "12.0",
"publicNetworkAccess": "Disabled"
},
"resources": [
]
}, {
"type": "Microsoft.Sql/servers/databases",
"apiVersion": "2020-02-02-preview",
"name": "[variables('databaseName')]",
"location": "[parameters('location')]",
"sku": {
"name": "Basic",
"tier": "Basic",
"capacity": 5
},
"dependsOn": [
"[resourceId('Microsoft.Sql/servers', variables('sqlServerName'))]"
],
"tags": {
"displayName": "[variables('databaseName')]"
},
"properties": {
"collation": "SQL_Latin1_General_CP1_CI_AS",
"edition": "Basic",
"maxSizeBytes": 104857600,
"requestedServiceObjectiveName": "Basic",
"sampleName": "AdventureWorksLT"
}
}, {
"type": "Microsoft.Network/privateEndpoints",
"apiVersion": "2020-06-01",
"name": "[variables('privateEndpointName')]",
"location": "[parameters('location')]",
"dependsOn": [
"[resourceId('Microsoft.Network/virtualNetworks', variables('vnetName'))]",
"[resourceId('Microsoft.Sql/servers', variables('sqlServerName'))]"
],
"properties": {
"subnet": {
"id": "[concat(resourceId('Microsoft.Network/virtualNetworks', variables('vnetName')),'/subnets/default')]"
},
"privateLinkServiceConnections": [{
"name": "[variables('privateEndpointName')]",
"properties": {
"privateLinkServiceId": "[resourceId('Microsoft.Sql/servers',variables('sqlServerName'))]",
"groupIds": [
"sqlServer"
]
}
}
]
}
}, {
"type": "Microsoft.Network/virtualNetworks",
"apiVersion": "2020-05-01",
"name": "[variables('vnetName')]",
"location": "[resourceGroup().location]",
"properties": {
"addressSpace": {
"addressPrefixes": [
"172.22.0.0/16"
]
}
},
"resources": [{
"type": "subnets",
"apiVersion": "2020-05-01",
"location": "[resourceGroup().location]",
"name": "default",
"dependsOn": [
"[variables('vnetName')]"
],
"properties": {
"addressPrefix": "172.22.0.0/24",
"privateEndpointNetworkPolicies": "Disabled"
}
}
]
}, {
"type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks",
"apiVersion": "2020-01-01",
"name": "[concat(variables('privateDnsZoneName'), '/', variables('privateDnsZoneName'), '-link')]",
"location": "global",
"dependsOn": [
"[resourceId('Microsoft.Network/virtualNetworks', variables('vnetName'))]"
],
"properties": {
"registrationEnabled": false,
"virtualNetwork": {
"id":"[resourceId('Microsoft.Network/virtualNetworks', variables('vnetName'))]"
}
}
}, {
"type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups",
"apiVersion": "2020-06-01",
"name": "[variables('pvtendpointdnsgroupname')]",
"location": "[parameters('location')]",
"dependsOn": [
"[resourceId('Microsoft.Network/privateEndpoints', variables('privateEndpointName'))]"
],
"properties": {
"privateDnsZoneConfigs": [{
"name": "config1",
"properties": {
"privateDnsZoneId": "[resourceId('Microsoft.Network/privateDnsZones', variables('privateDnsZoneName'))]"
}
}
]
}
}
]
}
This template creates a new virtual network with a default subnet together, I use my own private DNS zone named : testdns.com. I have tested on my side by powershell and it works for me.
Result

Creation of Microsoft.Network/networkInterfaces resource fails with Bad request in nested arm template

I am trying to deploy to a nested template, in which I am creating a virtual network with two subnets and a network interface card. Though the virtual network is created successfully but the network interface card creation fails and deployment errors out with following message.
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"rgPrefix": {
"type": "string"
},
"location": {
"type": "string"
}
},
"variables": {
"rgName": "[parameters('rgPrefix')]",
"VNet": "[concat(variables('rgName'), '-Vnet')]",
"vmName": "[concat(variables('rgName'), 'Vm1')]",
"networkInterfaceName": "[concat(variables('vmName'), 'nic1')]"
},
"resources": [
{
"type": "Microsoft.Resources/resourceGroups",
"apiVersion": "2018-05-01",
"location": "[parameters('location')]",
"name": "[variables('rgName')]",
"properties": {
}
},
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2017-05-10",
"name": "vmDeployment",
"resourceGroup": "[variables('rgName')]",
"dependsOn": [
"[resourceId('Microsoft.Resources/resourceGroups/', variables('rgName'))]"
],
"properties": {
"expressionEvaluationOptions": {
"scope": "outer"
},
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"type": "Microsoft.Network/virtualNetworks",
"name": "[variables('VNet')]",
"apiVersion": "2019-11-01",
"location": "[parameters('location')]",
"tags": {
"displayName": "[variables('VNet')]"
},
"properties": {
"addressSpace": {
"addressPrefixes": [
"10.0.0.0/16"
]
},
"subnets": [
{
"name": "subnet-1",
"properties": {
"addressPrefix": "10.0.0.0/24"
}
},
{
"name": "subnet-2",
"properties": {
"addressPrefix": "10.0.1.0/24"
}
}
]
},
"resources": [
{
"type": "subnets",
"apiVersion": "2019-11-01",
"name": "subnet-1",
"dependsOn": [
"[resourceId('Microsoft.Network/virtualNetworks', variables('VNet'))]"
],
"properties": {
"addressPrefix": "10.0.0.0/24",
"delegations": [
],
"privateEndpointNetworkPolicies": "Enabled",
"privateLinkServiceNetworkPolicies": "Enabled"
}
},
{
"type": "subnets",
"apiVersion": "2019-11-01",
"name": "subnet-2",
"dependsOn": [
"[resourceId('Microsoft.Network/virtualNetworks', variables('VNet'))]"
],
"properties": {
"addressPrefix": "10.0.1.0/24",
"delegations": [
],
"privateEndpointNetworkPolicies": "Enabled",
"privateLinkServiceNetworkPolicies": "Enabled"
}
}
]
},
{
"name": "[variables('networkInterfaceName')]",
"type": "Microsoft.Network/networkInterfaces",
"apiVersion": "2019-07-01",
"location": "[parameters('location')]",
"dependsOn": [
],
"properties": {
"ipConfigurations": [
{
"name": "ipconfig1",
"properties": {
"privateIpAddressVersion": "IPv4",
"privateIPAllocationMethod": "Dynamic",
"subnet": {
"id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('VNet'), 'subnet-1')]"
}
}
}
]
}
}
],
"outputs": {
}
}
}
}
],
"outputs": {
}
}
When I run the deployment, I get the following error
Resource Microsoft.Network/networkInterfaces 'vssRGVm1nic1' failed with message '{ "error": { "code": "InvalidRequestFormat",
| "message": "Cannot parse the request.
the error comes from the usage of resourceId() function. It behaves differently on the subscription level deployment. You should replace it with concat functions:
"[concat(subscription().id, '/resourceGroups/', variables('rgName'), '/providers/Microsoft.Network/virtualNetworks/', variables('VNet'), '/subnets/subnet-1')]"
https://learn.microsoft.com/en-us/azure/azure-resource-manager/templates/template-functions-resource#return-value-5

ARM - Add multiple VM to Recovery Services Vault (copyIndex)

I'm trying to use the Recovery Services where I can automatically add a VM to Azure Backup via ARM template. I have successfully done this on a single machine deploy, but I'm trying to import it for when multiple VMs are deployed.
Here is where I had help from:
https://www.francoisdelport.com/2017/03/automating-azure-vm-backups-using-arm-templates/
and
Azure ARM JSON template - Add VM to Recovery Services Vault in different Resource Group
Here is a snippet from a single deploy I had working
{
"apiVersion": "2017-05-10",
"name": "nestedTemplate",
"type": "Microsoft.Resources/deployments",
"resourceGroup": "Env1",
"dependsOn": [
"[concat('Microsoft.Compute/virtualMachines/', variables('vmName'))]"
],
"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": "2016-06-01",
"name": "[concat( parameters('recoveryVault'), '/Azure/', 'iaasvmcontainer;iaasvmcontainerv2;', parameters('vmRsg') , ';', parameters('vmPrefix'), '/vm;iaasvmcontainerv2;', parameters('vmRsg'),';', parameters('vmPrefix'))]",
"location": "[resourceGroup().location]",
"type": "Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems",
"properties": {
"protectedItemType": "Microsoft.Compute/virtualMachines",
"policyId": "[resourceId('Microsoft.RecoveryServices/vaults/backupPolicies', parameters('recoveryVault'), parameters('recoveryPolicy'))]",
"sourceResourceId": "[resourceId(subscription().subscriptionId, parameters('vmRsg'), 'Microsoft.Compute/virtualMachines', parameters('vmPrefix'))]"
}
}
]
}
}
}
Now I'm trying to use that in a copyIndex form for VM deploy, and here is the code I've been testing with:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"adminUsername": {
"type": "string",
"minLength": 1,
"metadata": {
"description": "Username for the Virtual Machine."
}
},
"adminPassword": {
"type": "securestring",
"metadata": {
"description": "Password for the Virtual Machine."
}
},
"dnsNameForPublicIP": {
"type": "string",
"minLength": 1,
"metadata": {
"description": "Globally unique DNS Name for the Public IP used to access the Virtual Machine."
}
},
"windowsOSVersion": {
"type": "string",
"defaultValue": "2012-R2-Datacenter",
"allowedValues": [
"2008-R2-SP1",
"2012-Datacenter",
"2012-R2-Datacenter"
],
"metadata": {
"description": "The Windows version for the VM. This will pick a fully patched image of this given Windows version. Allowed values: 2008-R2-SP1, 2012-Datacenter, 2012-R2-Datacenter."
}
},
"vmCount": {
"type": "int",
"defaultValue": 1
},
"virtualNetworkName": {
"type": "string"
},
"dataDiskCount": {
"type": "int",
"defaultValue": 1
},
"recoveryVault": {
"type": "string",
"metadata": {
"description": "Backup vault name"
}
},
"recoveryPolicy": {
"type": "string",
"metadata": {
"description": "Backcup policy name"
}
},
"vmPrefix": {
"type": "string",
"metadata": {
"description": "Prefix for VM names, used with vmCount to build the VM names"
}
},
"vmRsg": {
"type": "string",
"metadata": {
"description": "Resource group where VMs reside"
}
}
},
"variables": {
"imagePublisher": "MicrosoftWindowsServer",
"imageOffer": "WindowsServer",
"OSDiskName": "osdiskforwindowssimple",
"nicName": "myVMNic",
"subnetName": "Subnet",
"vhdStorageType": "Standard_LRS",
"publicIPAddressName": "myPublicIP",
"publicIPAddressType": "Dynamic",
"vhdStorageContainerName": "vhds",
"vmName": "MWindowsVM",
"vmSize": "Standard_A2",
"virtualNetworkName": "MyVNET",
"vnetId": "[resourceId(resourceGroup().name, 'Microsoft.Network/virtualNetworks', parameters('virtualNetworkName'))]",
"subnetRef": "[concat(variables('vnetId'), '/subnets/', variables('subnetName'))]"
},
"resources": [
{
"apiVersion": "2016-03-30",
"type": "Microsoft.Network/publicIPAddresses",
"name": "[concat(variables('publicIPAddressName'), copyIndex(1))]",
"location": "[resourceGroup().location]",
"tags": {
"displayName": "PublicIPAddress"
},
"properties": {
"publicIPAllocationMethod": "[variables('publicIPAddressType')]",
"dnsSettings": {
"domainNameLabel": "[concat(parameters('dnsNameForPublicIP'), copyIndex(1))]"
}
},
"copy": {
"name": "publicIpCopy",
"count": "[parameters('vmCount')]"
}
},
{
"apiVersion": "2016-03-30",
"type": "Microsoft.Network/networkInterfaces",
"name": "[concat(variables('nicName'), copyIndex(1))]",
"location": "[resourceGroup().location]",
"tags": {
"displayName": "NetworkInterface"
},
"dependsOn": [
"[concat('Microsoft.Network/publicIPAddresses/', concat(variables('publicIPAddressName'), copyIndex(1)))]"
],
"properties": {
"ipConfigurations": [
{
"name": "[concat('ipconfig', copyIndex(1))]",
"properties": {
"privateIPAllocationMethod": "Dynamic",
"publicIPAddress": {
"id": "[resourceId('Microsoft.Network/publicIPAddresses', concat(variables('publicIPAddressName'), copyIndex(1)))]"
},
"subnet": {
"id": "[variables('subnetRef')]"
}
}
}
]
},
"copy": {
"name": "nicCopy",
"count": "[parameters('vmCount')]"
}
},
{
"apiVersion": "2017-03-30",
"copy": {
"name": "nodeCopy",
"count": "[parameters('vmCount')]"
},
"type": "Microsoft.Compute/virtualMachines",
"name": "[concat(variables('vmName'), copyIndex(1))]",
"location": "[resourceGroup().location]",
"tags": {
"displayName": "VirtualMachine"
},
"dependsOn": [
"[resourceId('Microsoft.Network/networkInterfaces/', concat(variables('nicName'), copyIndex(1)))]"
],
"properties": {
"hardwareProfile": {
"vmSize": "[variables('vmSize')]"
},
"osProfile": {
"computerName": "[concat(variables('vmName'), copyIndex(1))]",
"adminUsername": "[parameters('adminUsername')]",
"adminPassword": "[parameters('adminPassword')]"
},
"storageProfile": {
"imageReference": {
"publisher": "[variables('imagePublisher')]",
"offer": "[variables('imageOffer')]",
"sku": "[parameters('windowsOSVersion')]",
"version": "latest"
},
"osDisk": {
"createOption": "FromImage"
},
"copy": [
{
"name": "dataDisks",
"count": "[parameters('dataDiskCount')]",
"input": {
"diskSizeGB": 1023,
"lun": "[copyIndex('dataDisks')]",
"createOption": "Empty"
}
}
]
},
"networkProfile": {
"networkInterfaces": [
{
"id": "[resourceId('Microsoft.Network/networkInterfaces', concat(variables('nicName'), copyIndex(1)))]"
}
]
}
}
},
{
"apiVersion": "2017-05-10",
"name": "nestedTemplate",
"type": "Microsoft.Resources/deployments",
"resourceGroup": "Env1",
"dependsOn": [
"[concat('Microsoft.Compute/virtualMachines/', concat(variables('vmName'), copyIndex(1)))]"
],
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"variables": {},
"resources": [
{
"copy": {
"name": "protectedItemsCopy",
"count": "[parameters('vmCount')]"
},
"apiVersion": "2017-03-30",
"name": "[concat( parameters('recoveryVault'), '/Azure/', 'iaasvmcontainer;iaasvmcontainerv2;', parameters('vmRsg') , ';', parameters('vmPrefix'), copyIndex(1), '/vm;iaasvmcontainerv2;', parameters('vmRsg'),';', parameters('vmPrefix'), copyIndex(1))]",
"location": "[resourceGroup().location]",
"type": "Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems",
"properties": {
"protectedItemType": "Microsoft.Compute/virtualMachines",
"policyId": "[resourceId('Microsoft.RecoveryServices/vaults/backupPolicies', parameters('recoveryVault'), parameters('recoveryPolicy'))]",
"sourceResourceId": "[resourceId(subscription().subscriptionId ,parameters('vmRsg'),'Microsoft.Compute/virtualMachines', concat(parameters('vmPrefix'), copyIndex(1)) )]"
}
}
]
}
}
}
]
}
Sadly it reports an error when trying to deploy, which I can't figure out why because it seems to be correct.
Error: Code=InvalidTemplate; Message=Deployment template validation failed: 'The template resource 'nestedTemplate' at line '198' and column '10' 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.'.
The deployment validation failed
FYI, line 198 is "name": "nestedTemplate",
Any ideas, please?
To expand upon #4c74356b41 answer I was missing the all important "index":{ "value": "[copyIndex()]" within "Microsoft.Resources/deployments" on the parent template.
For those wanting to know more, have a look at: https://learn.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-multiple
Ensure you have the ('index') parameter next to those items which need to be duplicated, such as "[concat(parameters('WHATEVER'), parameters('index'))]"
I also ended up having a nested source within my linked template for the overall design I was looking for.
So my parent template had a linked (child) template (to another file) with:
name": "[concat('nestings', copyIndex(1))]",
"type": "Microsoft.Resources/deployments", ...
My child template had all the usual buildings of a VM with the parameters ('index') to ensure the items which are duplicated are named correctly.
And finally at the bottom of the child template I had a nested template source so I could back the VM up to another resource group (had to be nested, otherwise you can't do multiple resource groups), which looked like this:
{
"apiVersion": "2017-05-10",
"name": "[concat('nestedTemplate', parameters('index'))]",
"type": "Microsoft.Resources/deployments",
"resourceGroup": "Env1",
"dependsOn": [
"[concat('Microsoft.Compute/virtualMachines/', concat(variables('vmName'), parameters('index')))]"
],
"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": "2016-06-01",
"name": "[concat( parameters('recoveryVault'), '/Azure/', 'iaasvmcontainer;iaasvmcontainerv2;', parameters('vmRsg') , ';', concat(parameters('vmPrefix'), parameters('index')), '/vm;iaasvmcontainerv2;', parameters('vmRsg'),';', concat(parameters('vmPrefix'), parameters('index')))]",
"location": "[resourceGroup().location]",
"type": "Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems",
"properties": {
"protectedItemType": "Microsoft.Compute/virtualMachines",
"policyId": "[resourceId('Microsoft.RecoveryServices/vaults/backupPolicies', parameters('recoveryVault'), parameters('recoveryPolicy'))]",
"sourceResourceId": "[resourceId(subscription().subscriptionId, parameters('vmRsg'), 'Microsoft.Compute/virtualMachines', concat(parameters('vmPrefix'), parameters('index')))]"
}
}
]
}
}
}
So what its telling you that you are not supposed to use copyIndex() function in that place. Now why exactly this is happening I don't know, but I do know that inline templates are a mess (for instance they use parent template paremeters, not nested template), I'm pretty sure if you convert that template to a real nested template (so a linked template, completely separate file) the above syntax will work.
Also, I'm handling this in a separate manner. I'm using 1 single nested deployment for each VM I have, so I'm using copy on the deployment resource, not backup resource.

How to use a DocumentDB(MongoDB) connection string as an Environment variable in an Azure Resource Management Template

I want to use a DocumentDB(MongoDB) connection string as an environment variable in an Azure Resource Management Template. Forexample i have a resource group which has a wep app and a DocumentDB(MongoDB) database.
"siteConfig": {
"appSettings": [
{
"name": "db",
"value": "connection string"
}
]
}
How can i assign an environment variable to a connection string in template?
ARM template supports listKeys and list{Value} function, more details we can refer to ARM template function.
We can find DocumentDB list connection strings API, so we can use listconnectionstrings function to get documentdb connection string in the ARM template.
"appSettings": [
{
"name": "db",
"value": " [listConnectionStrings(resourceId('Microsoft.DocumentDb/databaseAccounts', parameters('documentdb')), '2015-04-08').connectionStrings[0].connectionString]"
}
It works correct on my side. If we want to add appsetting for WebApp, we also can do with following code
"resources": [
{
"name": "appsettings",
"type": "config",
"apiVersion": "2015-08-01",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', variables('webSiteName'))]"
],
"tags": {
"displayName": "appsetting"
},
"properties": {
"db": "[listConnectionStrings(resourceId('Microsoft.DocumentDb/databaseAccounts', parameters('documentdb')), '2015-04-08').connectionStrings[0].connectionString]"
}
}
]
Check the result from the Azure portal.
Update:
ARM template demo code
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"hostingPlanName": {
"type": "string",
"minLength": 1
},
"documentdb": {
"type": "string",
"minLength": 1
},
"skuName": {
"type": "string",
"defaultValue": "S1",
"allowedValues": [
"F1",
"D1",
"B1",
"B2",
"B3",
"S1",
"S2",
"S3",
"P1",
"P2",
"P3",
"P4"
],
"metadata": {
"description": "Describes plan's pricing tier and instance size. Check details at https://azure.microsoft.com/en-us/pricing/details/app-service/"
}
},
"skuCapacity": {
"type": "int",
"defaultValue": 1,
"minValue": 1,
"metadata": {
"description": "Describes plan's instance count"
}
}
},
"variables": {
"webSiteName": "[concat('webSite', uniqueString(resourceGroup().id))]",
"docDbName": "tomdocumentdb",
"storageAccountId": "[concat(resourceGroup().id,'/providers/Microsoft.Storage/storageAccounts/', parameters('storageAccountName'))]"
},
"resources": [
{
"apiVersion": "2015-08-01",
"name": "[parameters('hostingPlanName')]",
"type": "Microsoft.Web/serverfarms",
"location": "[resourceGroup().location]",
"tags": {
"displayName": "HostingPlan"
},
"sku": {
"name": "[parameters('skuName')]",
"capacity": "[parameters('skuCapacity')]"
},
"properties": {
"name": "[parameters('hostingPlanName')]"
}
},
{
"apiVersion": "2015-08-01",
"name": "[variables('webSiteName')]",
"type": "Microsoft.Web/sites",
"location": "[resourceGroup().location]",
"tags": {
"[concat('hidden-related:', resourceGroup().id, '/providers/Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]": "Resource",
"displayName": "Website"
},
"dependsOn": [
"[concat('Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]"
],
"properties": {
"name": "[variables('webSiteName')]",
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', parameters('hostingPlanName'))]"
},
"resources": [
{
"name": "appsettings",
"type": "config",
"apiVersion": "2015-08-01",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', variables('webSiteName'))]"
],
"tags": {
"displayName": "appsetting"
},
"properties": {
"db": "[listConnectionStrings(resourceId('Microsoft.DocumentDb/databaseAccounts', parameters('documentdb')), '2015-04-08').connectionStrings[0].connectionString]"
}
}
]
}
]
}
Paramter file
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"hostingPlanName": {
"value": "tomtest" //your hostingplan name
},
"skuName": {
"value": "B1"
},
"documentdb": {
"value": "tomdocument" // your documentdb name
}
}
}
After a bit of a struggle:
"appSettings": [{
"Name": "DOCUMENTDB_ENDPOINT",
"Value": "[reference(concat('Microsoft.DocumentDb/databaseAccounts/', parameters('databaseAccountName'))).documentEndpoint]"
}, {
"Name": "DOCUMENTDB_PRIMARY_KEY",
"Value": "[listKeys(resourceId('Microsoft.DocumentDb/databaseAccounts', parameters('databaseAccountName')), '2015-04-08').primaryMasterKey]"
}]

Reference the same linked template in different parent templates

I want to deploy resources for storage account, service bus, azure function and web app using ARM templates. Also I want to write storage and service bus connections strings to both function and web app application settings.
So I created a main template which references 2 child templates: one for function and one for web app. Both child templates reference same linked templates for service bus and storage account.
My composite template is validated successfully but when I'm trying to deploy I've got errors like this:
Unable to edit or replace deployment serviceBus: previous deployment
from [datetime] is still active
It seems like Azure tries to deploy service bus and storage account twice. How can I tell ARM to use the same serviceBus deployment for both web app and function?
Current simplified schema:
Main ARM template(azuredeploy.json)
/ \
Web App(nestedtemplates/webApp.json) Function App(nestedtemplates/functions/resourceAllocationFunction.json)
\ /
Service Bus(nestedtemplates/serviceBus.json)
Templates:
azuredeploy.json
"resources": [
{
"name": "webApp",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2016-09-01",
"dependsOn": [],
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[concat(parameters('_artifactsLocation'), '/', variables('webAppTemplateFolder'), '/', variables('webAppTemplateFileName'), parameters('_artifactsLocationSasToken'))]",
"contentVersion": "1.0.0.0"
},
"parameters": {
"mainStorageAccountType": { "value": "[parameters('mainStorageAccountType')]" },
"location": { "value": "[parameters('location')]" },
"_artifactsLocation": { "value": "[parameters('_artifactsLocation')]" },
"_artifactsLocationSasToken": { "value": "[parameters('_artifactsLocationSasToken')]" }
}
}
},
{
"name": "resourceAllocationFunction",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2016-09-01",
"dependsOn": [],
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[concat(parameters('_artifactsLocation'), '/', variables('resourceAllocationFunctionTemplateFolder'), '/', variables('resourceAllocationFunctionTemplateFileName'), parameters('_artifactsLocationSasToken'))]",
"contentVersion": "1.0.0.0"
},
"parameters": {
"mainStorageAccountType": { "value": "[parameters('mainStorageAccountType')]" },
"location": { "value": "[parameters('location')]" },
"_artifactsLocation": { "value": "[parameters('_artifactsLocation')]" },
"_artifactsLocationSasToken": { "value": "[parameters('_artifactsLocationSasToken')]" }
}
}
}
],
nestedtemplates/webApp.json
"resources": [
{
"name": "[parameters('servicePlanName')]",
"type": "Microsoft.Web/serverfarms",
"location": "[resourceGroup().location]",
"apiVersion": "2015-08-01",
"sku": {
"name": "[parameters('servicePlanSkuName')]"
},
"dependsOn": [],
"properties": {
"name": "[parameters('servicePlanName')]",
"numberOfWorkers": 1
}
},
{
"name": "[variables('webAppName')]",
"type": "Microsoft.Web/sites",
"location": "[parameters('location')]",
"apiVersion": "2015-08-01",
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms', parameters('servicePlanName'))]"
],
"properties": {
"name": "[variables('webAppName')]",
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', parameters('servicePlanName'))]"
},
"resources": [
{
"name": "appsettings",
"type": "config",
"apiVersion": "2015-08-01",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', variables('webAppName'))]",
"[resourceId('microsoft.insights/components/', variables('appInsightsName'))]"
],
"properties": {
"ServiceBus:ConnectionString": "[reference('serviceBus').outputs.connectionString.value]",
"ServiceBus:QueueName": "[reference('serviceBus').outputs.queueName.value]",
"StorageAccounts:WritableAccountName": "[reference('mainStorage').outputs.storageAccountName.value]",
"StorageAccounts:ConnectionString": "[reference('mainStorage').outputs.storageAccountConnString.value]",
}
}
]
},
{
"name": "serviceBus",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2016-09-01",
"dependsOn": [ ],
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[concat(parameters('_artifactsLocation'), '/', variables('serviceBusTemplateFolder'), '/', variables('serviceBusTemplateFileName'), parameters('_artifactsLocationSasToken'))]",
"contentVersion": "1.0.0.0"
},
"parameters": {
"location": { "value": "[parameters('location')]" }
}
}
},
{
"name": "mainStorage",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2016-09-01",
"dependsOn": [ ],
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[concat(parameters('_artifactsLocation'), '/', variables('mainStorageTemplateFolder'), '/', variables('mainStorageTemplateFileName'), parameters('_artifactsLocationSasToken'))]",
"contentVersion": "1.0.0.0"
},
"parameters": {
"location": { "value": "[parameters('location')]" },
"mainStorageAccountType": { "value": "[parameters('mainStorageAccountType')]" }
}
}
}
]
nestedtemplates/functions/resourceAllocationFunction.json
"resources": [
{
"name": "functionStorageAccount",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2016-09-01",
"dependsOn": [],
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[concat(parameters('_artifactsLocation'), '/', variables('functionStorageAccountTemplateFolder'), '/', variables('functionStorageAccountTemplateFileName'), parameters('_artifactsLocationSasToken'))]",
"contentVersion": "1.0.0.0"
},
"parameters": {
"location": { "value": "[parameters('location')]" }
}
}
},
{
"name": "consumptionPlan",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2016-09-01",
"dependsOn": [],
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[concat(parameters('_artifactsLocation'), '/', variables('consumptionPlanTemplateFolder'), '/', variables('consumptionPlanTemplateFileName'), parameters('_artifactsLocationSasToken'))]",
"contentVersion": "1.0.0.0"
},
"parameters": {
"location": { "value": "[parameters('location')]" }
}
}
},
{
"apiVersion": "2016-08-01",
"type": "Microsoft.Web/sites",
"name": "[variables('functionAppName')]",
"location": "[parameters('location')]",
"kind": "functionapp",
"dependsOn": [
"[resourceId('microsoft.insights/components', variables('appInsightsName'))]"
],
"properties": {
"name": "[variables('functionAppName')]",
"serverFarmId": "[reference('consumptionPlan').outputs.resourceID.value]",
"siteConfig": {
"appSettings": [
{
"name": "AzureWebJobsDashboard",
"value": "[reference('functionStorageAccount').outputs.storageAccountConnString.value]"
},
{
"name": "AzureWebJobsStorage",
"value": "[reference('functionStorageAccount').outputs.storageAccountConnString.value]"
},
{
"name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
"value": "[reference('functionStorageAccount').outputs.storageAccountConnString.value]"
},
{
"name": "WEBSITE_CONTENTSHARE",
"value": "[toLower(variables('functionAppName'))]"
},
{
"name": "FUNCTIONS_WORKER_RUNTIME",
"value": "dotnet"
},
{
"name": "AccoutLogin",
"value": "[reference('mainStorage').outputs.storageAccountName.value]"
},
{
"name": "AccountConnString",
"value": "[reference('mainStorage').outputs.storageAccountConnString.value]"
},
{
"name": "ServiceBusConnectionString",
"value": "[reference('serviceBus').outputs.connectionString.value]"
},
{
"name": "QueueName",
"value": "[reference('serviceBus').outputs.queueName.value]"
}
]
}
}
},
{
"name": "serviceBus",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2016-09-01",
"dependsOn": [],
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[concat(parameters('_artifactsLocation'), '/', variables('serviceBusTemplateFolder'), '/', variables('serviceBusTemplateFileName'), parameters('_artifactsLocationSasToken'))]",
"contentVersion": "1.0.0.0"
},
"parameters": {
"location": { "value": "[parameters('location')]" }
}
}
},
{
"name": "mainStorage",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2016-09-01",
"dependsOn": [],
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[concat(parameters('_artifactsLocation'), '/', variables('mainStorageTemplateFolder'), '/', variables('mainStorageTemplateFileName'), parameters('_artifactsLocationSasToken'))]",
"contentVersion": "1.0.0.0"
},
"parameters": {
"location": { "value": "[parameters('location')]" },
"mainStorageAccountType": { "value": "[parameters('mainStorageAccountType')]" }
}
}
}
],
nestedtemplates/mainStorage.json
"resources": [
{
"name": "[variables('mainStorageAccountName')]",
"type": "Microsoft.Storage/storageAccounts",
"location": "[parameters('location')]",
"apiVersion": "2018-02-01",
"sku": {
"name": "[parameters('mainStorageAccountType')]"
},
"dependsOn": [],
"kind": "StorageV2",
"resources": [
{
"name": "[concat('default/', variables('containerName'))]",
"type": "blobServices/containers",
"apiVersion": "2018-03-01-preview",
"dependsOn": [
"[variables('mainStorageAccountName')]"
]
}
]
}
],
"outputs": {
"resourceID": {
"type": "string",
"value": "[resourceId('Microsoft.Storage/storageAccounts', variables('mainStorageAccountName'))]"
},
"storageAccountName": {
"type": "string",
"value": "[variables('mainStorageAccountName')]"
},
"storageAccountContainer": {
"type": "string",
"value": "[variables('containerName')]"
},
"storageAccountConnString": {
"type": "string",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('mainStorageAccountName'), ';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('mainStorageAccountName')),'2015-05-01-preview').key1)]"
}
}
nestedtemplates/serviceBus.json
"resources": [
{
"type": "Microsoft.ServiceBus/namespaces",
"name": "[variables('serviceBusNamespaceName')]",
"apiVersion": "2017-04-01",
"location": "[parameters('location')]",
"sku": {
"name": "Standard"
},
"properties": {},
"resources": [
{
"apiVersion": "2017-04-01",
"name": "[parameters('serviceBusQueueName1')]",
"type": "Queues",
"dependsOn": [
"[concat('Microsoft.ServiceBus/namespaces/', variables('serviceBusNamespaceName'))]"
],
"properties": {
"lockDuration": "PT5M",
"maxSizeInMegabytes": "1024",
"requiresDuplicateDetection": "false",
"requiresSession": "false",
"defaultMessageTimeToLive": "P10675199DT2H48M5.4775807S",
"deadLetteringOnMessageExpiration": "false",
"duplicateDetectionHistoryTimeWindow": "PT10M",
"maxDeliveryCount": "10",
"autoDeleteOnIdle": "P10675199DT2H48M5.4775807S",
"enablePartitioning": "false",
"enableExpress": "false"
}
}
]
}
],
"outputs": {
"resourceID": {
"type": "string",
"value": "[resourceId('Microsoft.ServiceBus/namespaces', variables('serviceBusNamespaceName'))]"
},
"connectionString": {
"type": "string",
"value": "[listkeys(variables('authRuleResourceId'), '2017-04-01').primaryConnectionString]"
},
"sharedAccessPolicyPrimaryKey": {
"type": "string",
"value": "[listkeys(variables('authRuleResourceId'), '2017-04-01').primaryKey]"
},
"queueName": {
"type": "string",
"value": "[parameters('serviceBusQueueName1')]"
}
}
ok, this makes very little sense. why do you deploy same thing two times if you only need it one time? answer is - you dont deploy it two times. so move it as a separate resource\separate template and deploy only one. just get its keys into web app\function app.
move these deployment to the main template: mainStorage and serviceBus. remove outputs from them, outputs are not secure.
replace "[reference('mainStorage').outputs.storageAccountConnString.value]" with appropriate value from the outputs: "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('mainStorageAccountName'), ';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('mainStorageAccountName')),'2015-05-01-preview').key1)]". repeat for all outputs.
you also need dependsOn on the webapp\function app to wait until service bus\storage are actually created
ps. makes no sense to create a nested deployment for 1 resource. I'd rework your template into a flat template. it makes no sense to use nested deployment here.

Resources