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.
Related
I am trying to create Logic App using ARM Template with existing Vnet and Subnet, but not able to do show, I am getting below error, I am new to ARM templates:
I am also sure whatever, I am doing is the correct way of doing it.
Error :
"code":"PrivateEndpointCreationNotAllowedAsSubnetIsDelegated","message":"Private
endpoint
/subscriptions/f3ffdd01-4400-4ebe-8761-59ecebeba1a2/resourceGroups/logicapp-test-abhishek/providers/Microsoft.Network/privateEndpoints/name
cannot be created as subnet
/subscriptions/f3ffdd01-4400-4ebe-8761-123abdhuue/resourceGroups/my-rg/providers/Microsoft.Network/virtualNetworks/vnet-dev-eastus-edw/subnets/my-vnet
is delegated."}]}
Here is my code :
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"logicAppFEname": {
"type": "String"
},
"appInsightName": {
"type": "String"
},
"privateEndpointName": {
"type": "string"
},
"vnetName": {
"type": "string"
},
"vnetRg": {
"type": "string"
},
"subNetName": {
"type": "string"
},
"use32BitWorkerProcess": {
"type": "Bool"
},
"location": {
"defaultValue": "[resourceGroup().location]",
"type": "String",
"metadata": {
"description": "Location to deploy resources to."
}
},
"hostingPlanFEName": {
"type": "String"
},
"contentStorageAccountName": {
"type": "String"
},
"sku": {
"type": "String"
},
"skuCode": {
"type": "String"
},
"workerSize": {
"type": "String"
},
"workerSizeId": {
"type": "String"
},
"numberOfWorkers": {
"type": "String"
}
},
"variables": {
"fileShareName": "[concat(toLower(parameters('logicAppFEname')), 'b86e')]"
},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2021-04-01",
"name": "[parameters('contentStorageAccountName')]",
"location": "[resourceGroup().location]",
"dependsOn": [],
"sku": {
"name": "Standard_LRS",
"tier": "Standard"
},
"kind": "StorageV2",
"properties": {
"mode": "Incremental",
"networkAcls": {
"bypass": "AzureServices",
"defaultAction": "Allow"
},
"supportsHttpsTrafficOnly": true,
"encryption": {
"services": {
"file": {
"keyType": "Account",
"enabled": true
},
"blob": {
"keyType": "Account",
"enabled": true
}
},
"keySource": "Microsoft.Storage"
}
}
},
{
"type": "Microsoft.Storage/storageAccounts/fileServices/shares",
"apiVersion": "2021-04-01",
"name": "[concat(parameters('contentStorageAccountName'), '/default/', variables('fileShareName'))]",
"dependsOn": [
"[parameters('contentStorageAccountName')]"
]
},
{
"type": "Microsoft.Web/sites",
"apiVersion": "2021-03-01",
"name": "[parameters('vnetName')]",
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.Web/sites/', parameters('logicAppFEname'))]"
],
"properties": {
"subnetRef": "[resourceId('Microsoft.Network/virtualNetworks/subnets',parameters('vnetName'), parameters('subnetName'))]",
"isSwift": true
}
},
{
"type": "Microsoft.Network/privateEndpoints",
"apiVersion": "2021-03-01",
"name": "[parameters('privateEndpointName')]",
"location": "[parameters('location')]",
"tags": {},
"dependsOn": [
"[resourceId('Microsoft.Web/sites', parameters('logicAppFEname'))]"
],
"properties": {
"subnet": {
"id": "[resourceId(parameters('vnetRg'), 'Microsoft.Network/virtualNetworks/subnets', parameters('vnetName'), parameters('subNetName'))]"
},
"privateLinkServiceConnections": [
{
"name": "[parameters('privateEndpointName')]",
"properties": {
"privateLinkServiceId": "[resourceId('Microsoft.Web/sites',parameters('logicAppFEname'))]",
"groupIds": [
"Web/sites"
]
}
}
]
}
},
{
"type": "Microsoft.Insights/components",
"apiVersion": "2020-02-02",
"name": "[parameters('appInsightName')]",
"location": "[resourceGroup().location]",
"kind": "web",
"properties": {
"mode": "Incremental",
"Application_Type": "web"
}
},
{
"type": "Microsoft.Web/sites",
"apiVersion": "2018-11-01",
"name": "[parameters('logicAppFEname')]",
"location": "[resourceGroup().location]",
"dependsOn": [
"[concat('Microsoft.Web/serverfarms/', parameters('hostingPlanFEName'))]"
],
"tags": {},
"kind": "functionapp,workflowapp",
"identity": {
"type": "SystemAssigned"
},
"properties": {
"mode": "Incremental",
"name": "[parameters('logicAppFEname')]",
"siteConfig": {
"appSettings": [
{
"name": "FUNCTIONS_EXTENSION_VERSION",
"value": "~3"
},
{
"name": "FUNCTIONS_WORKER_RUNTIME",
"value": "node"
},
{
"name": "APPINSIGHTS_INSTRUMENTATIONKEY",
"value": "[reference(resourceId('Microsoft.Insights/components', parameters('appInsightName')), '2015-05-01').InstrumentationKey]"
},
{
"name": "APPLICATIONINSIGHTS_CONNECTION_STRING",
"value": "[reference(resourceId('Microsoft.Insights/components', parameters('appInsightName')), '2015-05-01').ConnectionString]"
},
{
"name": "AzureWebJobsStorage",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=',parameters('contentStorageAccountName'),';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('contentStorageAccountName')), '2019-06-01').keys[0].value,';EndpointSuffix=','core.windows.net')]"
},
{
"name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=',parameters('contentStorageAccountName'),';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('contentStorageAccountName')), '2019-06-01').keys[0].value,';EndpointSuffix=','core.windows.net')]"
},
{
"name": "WEBSITE_CONTENTSHARE",
"value": "[variables('fileShareName')]"
},
{
"name": "APP_KIND",
"value": "workflowApp"
},
{
"name": "WEBSITE_DNS_SERVER",
"value": "168.63.129.16"
},
{
"name": "AzureFunctionsJobHost__extensionBundle__id",
"value": "Microsoft.Azure.Functions.ExtensionBundle.Workflows",
"slotSetting": false
},
{
"name": "AzureFunctionsJobHost__extensionBundle__version",
"value": "[1.*, 2.0.0)",
"slotSetting": false
},
{
"name": "WEBSITE_CONTENTOVERVNET",
"value": "1",
"slotSetting": false
},
{
"name": "WEBSITE_VNET_ROUTE_ALL",
"value": "1"
}
],
"use32BitWorkerProcess": "[parameters('use32BitWorkerProcess')]",
"cors": {
"allowedOrigins": [
"https://afd.hosting.portal.azure.net",
"https://afd.hosting-ms.portal.azure.net",
"https://hosting.portal.azure.net",
"https://ms.hosting.portal.azure.net",
"https://ema-ms.hosting.portal.azure.net",
"https://ema.hosting.portal.azure.net",
"https://ema.hosting.portal.azure.net"
]
}
},
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms/', parameters('hostingPlanFEName'))]",
"clientAffinityEnabled": true
},
"resources": []
},
{
"type": "Microsoft.Web/serverfarms",
"apiVersion": "2018-11-01",
"name": "[parameters('hostingPlanFEName')]",
"location": "[resourceGroup().location]",
"dependsOn": [],
"tags": {},
"sku": {
"Tier": "[parameters('sku')]",
"Name": "[parameters('skuCode')]"
},
"kind": "",
"properties": {
"mode": "Incremental",
"name": "[parameters('hostingPlanFEName')]",
"workerSize": "[parameters('workerSize')]",
"workerSizeId": "[parameters('workerSizeId')]",
"numberOfWorkers": "[parameters('numberOfWorkers')]",
"maximumElasticWorkerCount": "20"
}
}
]
}
For AppService the networking is different for inbound and outbound directions.
The template has the outbound set on Vnet subnet, and that subnet will have been delegated to the AppService. (A normal requirement with other AppService SKUs too).
You need to use a different subnet for inbound traffic to your privatelink connection, or look at other options like service endpoint if the sources are in Azure rather on-premises hybrid.
I need a ARM template for Form Recognizer. It would be helpful if anyone can share a working template for this
ARM template for Form Recognizer
We have tried to create form recognizer in Azure and test the deployment using below template.
ARM TEMPLETE:-
sample.json
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"name": {
"type": "string"
},
"location": {
"type": "string"
},
"resourceGroupName": {
"type": "string"
},
"resourceGroupId": {
"type": "string"
},
"sku": {
"type": "string"
},
"tagValues": {
"type": "object"
},
"virtualNetworkType": {
"type": "string"
},
"vnet": {
"type": "object"
},
"ipRules": {
"type": "array"
},
"identity": {
"type": "object"
},
"privateEndpoints": {
"type": "array"
},
"isCommitmentPlanForDisconnectedContainerEnabled": {
"type": "bool"
},
"commitmentPlanForDisconnectedContainer": {
"type": "object"
}
},
"variables": {
"defaultVNetName": "frCSDefaultVNet9901",
"defaultSubnetName": "frCSDefaultSubnet9901",
"defaultAddressPrefix": "13.41.6.0/26"
},
"resources": [
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2017-05-10",
"name": "deployVnet",
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"variables": {},
"resources": [
{
"type": "Microsoft.Network/virtualNetworks",
"apiVersion": "2020-04-01",
"name": "[if(equals(parameters('virtualNetworkType'), 'External'), parameters('vnet').name, variables('defaultVNetName'))]",
"location": "[parameters('location')]",
"properties": {
"addressSpace": {
"addressPrefixes": "[if(equals(parameters('virtualNetworkType'), 'External'), parameters('vnet').addressPrefixes, json(concat('[{\"', variables('defaultAddressPrefix'),'\"}]')))]"
},
"subnets": [
{
"name": "[if(equals(parameters('virtualNetworkType'), 'External'), parameters('vnet').subnets.subnet.name, variables('defaultSubnetName'))]",
"properties": {
"serviceEndpoints": [
{
"service": "Microsoft.CognitiveServices",
"locations": [
"[parameters('location')]"
]
}
],
"addressPrefix": "[if(equals(parameters('virtualNetworkType'), 'External'), parameters('vnet').subnets.subnet.addressPrefix, variables('defaultAddressPrefix'))]"
}
}
]
}
}
]
},
"parameters": {}
},
"condition": "[and(and(not(empty(parameters('vnet'))), equals(parameters('vnet').newOrExisting, 'new')), equals(parameters('virtualNetworkType'), 'External'))]"
},
{
"apiVersion": "2021-04-30",
"name": "[parameters('name')]",
"location": "[parameters('location')]",
"type": "Microsoft.CognitiveServices/accounts",
"kind": "FormRecognizer",
"tags": "[if(contains(parameters('tagValues'), 'Microsoft.CognitiveServices/accounts'), parameters('tagValues')['Microsoft.CognitiveServices/accounts'], json('{}'))]",
"sku": {
"name": "[parameters('sku')]"
},
"identity": "[parameters('identity')]",
"properties": {
"customSubDomainName": "[toLower(parameters('name'))]",
"publicNetworkAccess": "[if(equals(parameters('virtualNetworkType'), 'Internal'), 'Disabled', 'Enabled')]",
"networkAcls": {
"defaultAction": "[if(equals(parameters('virtualNetworkType'), 'External'), 'Deny', 'Allow')]",
"virtualNetworkRules": "[if(equals(parameters('virtualNetworkType'), 'External'), json(concat('[{\"id\": \"', concat(subscription().id, '/resourceGroups/', parameters('vnet').resourceGroup, '/providers/Microsoft.Network/virtualNetworks/', parameters('vnet').name, '/subnets/', parameters('vnet').subnets.subnet.name), '\"}]')), json('[]'))]",
"ipRules": "[if(or(empty(parameters('ipRules')), empty(parameters('ipRules')[0].value)), json('[]'), parameters('ipRules'))]"
}
},
"resources": [
{
"type": "commitmentPlans",
"apiVersion": "2021-10-01",
"name": "DisconnectedContainer-FormRecognizer-1",
"properties": "[parameters('commitmentPlanForDisconnectedContainer')]",
"condition": "[parameters('isCommitmentPlanForDisconnectedContainerEnabled')]",
"dependsOn": [
"[parameters('name')]"
]
}
],
"dependsOn": [
"[concat('Microsoft.Resources/deployments/', 'deployVnet')]"
]
},
{
"apiVersion": "2017-05-10",
"name": "[concat('deployPrivateEndpoint-', parameters('privateEndpoints')[copyIndex()].privateEndpoint.name)]",
"type": "Microsoft.Resources/deployments",
"resourceGroup": "[parameters('privateEndpoints')[copyIndex()].resourceGroup.value.name]",
"subscriptionId": "[parameters('privateEndpoints')[copyIndex()].subscription.subscriptionId]",
"dependsOn": [
"[parameters('name')]"
],
"condition": "[equals(parameters('virtualNetworkType'), 'Internal')]",
"copy": {
"name": "privateendpointscopy",
"count": "[length(parameters('privateEndpoints'))]"
},
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"location": "[parameters('location')]",
"name": "[parameters('privateEndpoints')[copyIndex()].privateEndpoint.name]",
"type": "Microsoft.Network/privateEndpoints",
"apiVersion": "2020-03-01",
"properties": {
"subnet": {
"id": "[parameters('privateEndpoints')[copyIndex()].privateEndpoint.properties.subnet.id]"
},
"privateLinkServiceConnections": [
{
"name": "[parameters('privateEndpoints')[copyIndex()].privateEndpoint.name]",
"properties": {
"privateLinkServiceId": "[concat(parameters('resourceGroupId'), '/providers/Microsoft.CognitiveServices/accounts/', parameters('name'))]",
"groupIds": "[parameters('privateEndpoints')[copyIndex()].privateEndpoint.properties.privateLinkServiceConnections[0].properties.groupIds]"
}
}
]
},
"tags": {}
}
]
}
}
},
{
"apiVersion": "2017-05-10",
"name": "[concat('deployDnsZoneGroup-', parameters('privateEndpoints')[copyIndex()].privateEndpoint.name)]",
"type": "Microsoft.Resources/deployments",
"resourceGroup": "[parameters('privateEndpoints')[copyIndex()].resourceGroup.value.name]",
"subscriptionId": "[parameters('privateEndpoints')[copyIndex()].subscription.subscriptionId]",
"dependsOn": [
"[concat('Microsoft.Resources/deployments/', concat('deployPrivateEndpoint-', parameters('privateEndpoints')[copyIndex()].privateEndpoint.name))]"
],
"condition": "[equals(parameters('virtualNetworkType'), 'Internal')]",
"copy": {
"name": "privateendpointdnscopy",
"count": "[length(parameters('privateEndpoints'))]"
},
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups",
"apiVersion": "2020-03-01",
"name": "[concat(parameters('privateEndpoints')[copyIndex()].privateEndpoint.name, '/', 'default')]",
"location": "[parameters('location')]",
"properties": {
"privateDnsZoneConfigs": [
{
"name": "privatelink-cognitiveservices-azure-com",
"properties": {
"privateDnsZoneId": "[concat(parameters('resourceGroupId'), '/providers/Microsoft.Network/privateDnsZones/privatelink.cognitiveservices.azure.com')]"
}
}
]
}
}
]
}
}
}
]
}
We have Saved the parameters in different file and deploy with referencing deployment file as below.
azuredeploy.parameter.json
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"name":{
"value": "myrecognizer"
},
"location": {
"value": "westus2"
},
"resourceGroupName":{
"value": "my_resource_group"
},
"resourceGroupId": {
"value": "/subscriptions/subscID/resourceGroups/my_resource_group"
},
"sku":{
"value": "S0"
},
"tagValues":{
"value": {}
},
"virtualNetworkType":{
"value": "None"
},
"vnet":{
"value": {}
},
"ipRules":{
"value": []
},
"identity":{
"value": {
"type": "None"
}
},
"privateEndpoints":{
"value":[]
},
"isCommitmentPlanForDisconnectedContainerEnabled":{
"value": false
},
"commitmentPlanForDisconnectedContainer":{
"value": {
"current": {},
"hostingModel": "DisconnectedContainer",
"planType": "CustomInvoice",
"autoRenew": true
}
}
}
}
Deploy using below cmd in terminal :
az deployment group create -n TestDeployment -g myresourcegroup --template-file "C:\locationfile\sample.json" --parameters "C:\locationfile\azuredeploy.parameters.json"
Below are the SCREENSHOT FOR DEPLOYMENT DETAILS:-
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
I can create a Private Endpoint for a Storage Queue through the portal just fine and it works as intended when checking with nameresolver.exe from KUDU. However, I am struggling to find an ARM template that does this in one go.
I have made this template work but I can see that the A record entry does not get generated in the Private DNS Zone that is generated. I don't know how to create that A record entry and cannot seem to find a ARM template online that describes this:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"privateEndpointName": {
"type": "string",
"defaultValue": "privendpoint-sapriv01-queue"
},
"vnetName": {
"type": "string",
"defaultValue": "vn-myvnet01"
},
"subnetName": {
"type": "string",
"defaultValue": "sn-private-endpoints"
},
"groupId": {
"type": "string",
"defaultValue": "queue"
}
},
"variables": {
"privateDNSZone_name": "[concat('privatelink', '.queue.', environment().suffixes.storage)]"
},
"resources": [
{
"apiVersion": "2019-04-01",
"name": "[parameters('privateEndpointName')]",
"type": "Microsoft.Network/privateEndpoints",
"location": "[resourceGroup().Location]",
"properties": {
"privateLinkServiceConnections": [
{
"name": "[parameters('privateEndpointName')]",
"properties": {
"privateLinkServiceId": "[resourceId('Microsoft.Storage/storageAccounts', 'saprivendpointdemo')]",
"groupIds": [
"[parameters('groupId')]"
]
}
}
],
"manualPrivateLinkServiceConnections": [],
"subnet": {
"id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('vnetName'), parameters('subnetName') )]"
}
}
},
{
"type": "Microsoft.Network/privateDnsZones",
"apiVersion": "2018-09-01",
"name": "[variables('privateDNSZone_name')]",
"location": "global",
"tags": {},
"properties": {}
},
{
"type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks",
"apiVersion": "2018-09-01",
"name": "[concat(variables('privateDNSZone_name'), '/', parameters('vnetName'), 'link' )]",
"location": "global",
"dependsOn": [
"[resourceId('Microsoft.Network/privateDnsZones', variables('privateDNSZone_name'))]"
],
"properties": {
"virtualNetwork": {
"id": "[resourceId('Microsoft.Network/virtualNetworks', parameters('vnetName'))]"
},
"registrationEnabled": false
}
}
],
"outputs": {
}
}
I think Microsoft overcomplicated this. The Private IP is auto generated and I don't know how one would reference this IP in the ARM template.
If you want to add A record in your Azure Private DNS Zone, you can define Microsoft.Network/privateEndpoints/privateDnsZoneGroups in your template.
For example
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"privateEndpointName": {
"type": "string",
"defaultValue": "testqueue"
},
"vnetName": {
"type": "string",
"defaultValue": "teststorage"
},
"subnetName": {
"type": "string",
"defaultValue": "default"
},
"groupId": {
"type": "string",
"defaultValue": "queue"
}
},
"variables": {
"privateDNSZone_name": "[concat('privatelink', '.queue.', environment().suffixes.storage)]"
},
"resources": [
{
"apiVersion": "2019-04-01",
"name": "[parameters('privateEndpointName')]",
"type": "Microsoft.Network/privateEndpoints",
"location": "[resourceGroup().Location]",
"properties": {
"privateLinkServiceConnections": [
{
"name": "[parameters('privateEndpointName')]",
"properties": {
"privateLinkServiceId": "[resourceId('Microsoft.Storage/storageAccounts', 'teststorage05')]",
"groupIds": [
"[parameters('groupId')]"
]
}
}
],
"manualPrivateLinkServiceConnections": [],
"subnet": {
"id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('vnetName'), parameters('subnetName') )]"
}
}
},
{
"type": "Microsoft.Network/privateDnsZones",
"apiVersion": "2018-09-01",
"name": "[variables('privateDNSZone_name')]",
"dependsOn": [
"[parameters('privateEndpointName')]"
],
"location": "global",
"tags": {},
"properties": {}
},
{
"type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks",
"apiVersion": "2018-09-01",
"name": "[concat(variables('privateDNSZone_name'), '/', parameters('vnetName'), 'link' )]",
"location": "global",
"dependsOn": [
"[resourceId('Microsoft.Network/privateDnsZones', variables('privateDNSZone_name'))]"
],
"properties": {
"virtualNetwork": {
"id": "[resourceId('Microsoft.Network/virtualNetworks', parameters('vnetName'))]"
},
"registrationEnabled": false
}
},
{
"type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups",
"apiVersion": "2020-03-01",
"name": "[concat(parameters('privateEndpointName'), '/', 'default')]",
"dependsOn": [
"[parameters('privateEndpointName')]",
"[variables('privateDNSZone_name')]"
],
"location": "[resourceGroup().Location]",
"properties": {
"privateDnsZoneConfigs": [
{
"name": "privatelink-queue-core-windows-net",
"properties": {
"privateDnsZoneId": "[resourceId('Microsoft.Network/privateDnsZones',variables('privateDNSZone_name'))]"
}
}
]
}
}
],
"outputs": {
}
}
For more details, please refer to here and here
How can I create a Azure SQL Failover Group in a different deployment to the servers?
We use deployments within deployments to achieve concurrent deployments.
I'm trying to create 2 SQL Servers, one in UK West (primary) and one in UK South (secondary), and then create a Failover group from the Primary to Secondary.
The issue is that when creating the Failover group, I have to reference the primary server to create the FOG under. This is failing and saying that the SQL Server is not defined.
Deployment template validation failed: 'The resource 'Microsoft.Sql/servers/xxxxxx' is not defined in the template. Please see https://aka.ms/arm-template for usage details.'
Is it possible to keep the deployments separate, yet still create the FOG which references the SQL Servers? All examples I can find are using a single template/deployment which makes matters slightly more straightforward.
maindeployment.json
{
"apiVersion": "2018-05-01",
"name": "sqlServerTemplate",
"type": "Microsoft.Resources/deployments",
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[replace(variables('templateLinkUri'), '*', 'sql-server')]",
"contentVersion": "1.0.0.0"
},
"parameters": {
"name": {
"value": "[variables('sqlServerName')]"
},
"location": {
"value": "[parameters('location')]"
},
"adminUsername": {
"value": "[variables('sqlServerAdminUsername')]"
},
"adminPassword": {
"value": "[variables('sqlServerAdminPassword')]"
}
}
}
},
{
"apiVersion": "2018-05-01",
"name": "dbTemplate",
"type": "Microsoft.Resources/deployments",
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[replace(variables('templateLinkUri'), '*', 'sql-database')]",
"contentVersion": "1.0.0.0"
},
"parameters": {
"dbName": {
"value": "[variables('dbName')]"
},
"sqlServerName": {
"value": "[variables('sqlServerName')]"
},
"location": {
"value": "[parameters('location')]"
},
"skuName": {
"value": "[parameters('dbSkuName')]"
},
"dbCapacity": {
"value": "[parameters('dbCapacity')]"
}
}
},
"dependsOn": [
"sqlServerTemplate"
]
},
{
"apiVersion": "2018-05-01",
"name": "failoverSqlServerTemplate",
"type": "Microsoft.Resources/deployments",
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[replace(variables('templateLinkUri'), '*', 'sql-server-failover')]",
"contentVersion": "1.0.0.0"
},
"parameters": {
"name": {
"value": "[variables('failoverSqlServerName')]"
},
"location": {
"value": "[parameters('failoverLocation')]"
},
"adminUsername": {
"value": "[variables('sqlServerAdminUsername')]"
},
"adminPassword": {
"value": "[variables('sqlServerAdminPassword')]"
}
}
}
},
{
"apiVersion": "2018-05-01",
"name": "sqlFailoverGroupTemplate",
"type": "Microsoft.Resources/deployments",
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[replace(variables('templateLinkUri'), '*', 'sql-failovergroup')]",
"contentVersion": "1.0.0.0"
},
"parameters": {
"failoverGroupName": {
"value": "[variables('failoverGroupName')]"
},
"sourceSqlServerName": {
"value": "[reference('sqlServerTemplate').parameters.name.value]"
},
"targetSqlServerName": {
"value": "[reference('failoverSqlServerTemplate').parameters.name.value]"
},
"sqlDatabaseNameToReplicate": {
"value": "[reference('dbTemplate').parameters.dbName.value]"
}
}
}
}
sql-failovergroup.json
{
"$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"failoverGroupName": {
"type": "string"
},
"sourceSqlServerName": {
"type": "string"
},
"targetSqlServerName": {
"type": "string"
},
"sqlDatabaseNameToReplicate": {
"type": "string"
}
},
"variables": {
"TODO": "Figure out how to reference the SQL Server as the below method is failing with... Error: Code=InvalidTemplate; Message=Deployment template validation failed: 'The resource 'Microsoft.Sql/servers/xxxxx' is not defined in the template.",
"sourceServerResourceId": "[resourceId('Microsoft.Sql/servers', parameters('sourceSqlServerName'))]",
"targetServerResourceId": "[resourceId('Microsoft.Sql/servers', parameters('targetSqlServerName'))]",
"databaseResourceId": "[concat(resourceGroup().id, '/providers/Microsoft.Sql/servers/', parameters('sourceSqlServerName'), '/databases/', parameters('sqlDatabaseNameToReplicate'))]"
},
"resources": [
{
"name": "[concat(parameters('sourceSqlServerName'), '/', parameters('failoverGroupName'))]",
"type": "Microsoft.Sql/servers/failoverGroups",
"apiVersion": "2015-05-01-preview",
"properties": {
"readWriteEndpoint": {
"failoverPolicy": "Manual",
"failoverWithDataLossGracePeriodMinutes": 60
},
"readOnlyEndpoint": {
"failoverPolicy": "Disabled"
},
"partnerServers": [
{
"id": "[variables('targetServerResourceId')]"
}
],
"databases": [
"[variables('databaseResourceId')]"
]
},
"dependsOn": [
"[variables('sourceServerResourceId')]",
"[variables('targetServerResourceId')]"
]
}
]
}
sql-server.json
{
"$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"name": {
"type": "string"
},
"location": {
"type": "string"
},
"adminUsername": {
"type": "string"
},
"adminPassword": {
"type": "string"
},
"whitelistStartIpAddress": {
"type": "string"
},
"whitelistEndIpAddress": {
"type": "string"
}
},
"variables": {
"azureStartIpAddress": "0.0.0.0",
"azureEndIpAddress": "0.0.0.0"
},
"resources": [{
"name": "[parameters('name')]",
"type": "Microsoft.Sql/servers",
"apiVersion": "2014-01-01",
"location": "[parameters('location')]",
"properties": {
"administratorLogin": "[parameters('adminUsername')]",
"administratorLoginPassword": "[parameters('adminPassword')]"
}
},
{
"name": "[concat(parameters('name'), '/WindowsAzureIps')]",
"type": "Microsoft.Sql/servers/firewallRules",
"apiVersion": "2014-04-01",
"properties": {
"startIpAddress": "[variables('azureStartIpAddress')]",
"endIpAddress": "[variables('azureEndIpAddress')]"
},
"dependsOn": [
"[resourceId('Microsoft.Sql/servers', parameters('name'))]"
]
}
]
}
Just came across this same problem, and found the answer on this example:
https://github.com/Azure/azure-quickstart-templates/blob/master/101-sql-with-failover-group/azuredeploy.json
The bit you're missing is:
"serverName": "[parameters('sourceSqlServerName')]",
So your full resource:
{
"name": "[concat(parameters('sourceSqlServerName'), '/', parameters('failoverGroupName'))]",
"type": "Microsoft.Sql/servers/failoverGroups",
"apiVersion": "2015-05-01-preview",
"properties": {
"readWriteEndpoint": {
"failoverPolicy": "Manual",
"failoverWithDataLossGracePeriodMinutes": 60
},
"readOnlyEndpoint": {
"failoverPolicy": "Disabled"
},
"serverName": "[parameters('sourceSqlServerName')]",
"partnerServers": [
{
"id": "[variables('targetServerResourceId')]"
}
],
"databases": [
"[variables('databaseResourceId')]"
]
},
"dependsOn": [
"[variables('sourceServerResourceId')]",
"[variables('targetServerResourceId')]"
]
}