Related
I have an ARM template that creates Event Hub namespaces in two regions (eastus and westus2) with a event hub and multiple auth rules (on the even hub). This was working until ~16-Nov-2020 12:00PM.
Arm template:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"location-region1": {
"type": "string",
"defaultValue": "eastus",
"metadata": {
"description": "Name of an azure region"
}
},
"location-region2": {
"type": "string",
"defaultValue": "westus2",
"metadata": {
"description": "Name of an Azure region"
}
},
"appName": {
"type": "string",
"defaultValue": "jklm",
"metadata": {
"description": "Short name of the app or service"
}
},
"uniqueSuffix": {
"type": "string",
"defaultValue": "tst",
"metadata": {
"description": "Unique Suffix to use for the azure resources of the app or service"
}
},
"environment": {
"type": "string",
"defaultValue": "int",
"allowedValues": [
"poc",
"dev",
"int",
"uat",
"prod"
],
"metadata": {
"description": "The name of the environment"
}
},
"progressRecordsEventHubName": {
"type": "string",
"defaultValue": "progressrecords"
}
},
"variables": {
"eventHubNMApiVersion": "2018-01-01-preview",
"eventHubApiVersion": "2017-04-01",
"parentResourceGroupName": "[resourceGroup().name]",
"regionCount": 2,
"location": [
"[parameters('location-region1')]",
"[parameters('location-region2')]"
],
"appName": "[concat(parameters('appName'),'-',parameters('uniqueSuffix'),'-')]",
"copy": [
{
"name": "regionSuffix",
"count": "[variables('regionCount')]",
"input": "[concat('r',copyIndex('regionSuffix',1))]"
},
{
"name": "eventHubName",
"count": "[variables('regionCount')]",
"input": "[concat(variables('appName'),'ehub-',variables('regionSuffix')[copyIndex('eventHubName')],'-',parameters('environment'))]"
}
]
},
"resources": [
{
"type": "Microsoft.EventHub/namespaces",
"apiVersion": "[variables('eventHubNMApiVersion')]",
"name": "[variables('eventHubName')[copyIndex()]]",
"copy": {
"name": "resourceLoop",
"count": "[variables('regionCount')]"
},
"location": "[variables('location')[copyIndex()]]",
"sku": {
"name": "Standard",
"tier": "Standard",
"capacity": 1
},
"properties": {
"zoneRedundant": false,
"isAutoInflateEnabled": true,
"maximumThroughputUnits": 1,
"kafkaEnabled": true
},
"resources": [
{
"type": "Microsoft.EventHub/namespaces/eventhubs",
"apiVersion": "[variables('eventHubApiVersion')]",
"name": "[concat(variables('eventHubName')[copyIndex()], '/',parameters('progressRecordsEventHubName'))]",
"location": "[variables('location')[copyIndex()]]",
"dependsOn": [
"[resourceId('Microsoft.EventHub/namespaces', variables('eventHubName')[copyIndex()])]"
],
"properties": {
"messageRetentionInDays": 3,
"partitionCount": 1,
"status": "Active"
},
"resources": [
{
"type": "Microsoft.EventHub/namespaces/eventhubs/authorizationRules",
"apiVersion": "[variables('eventHubApiVersion')]",
"name": "[concat(variables('eventHubName')[copyIndex('resourceLoop')], '/',parameters('progressRecordsEventHubName'),'/Listen')]",
"location": "[variables('location')[copyIndex()]]",
"dependsOn": [
"[resourceId('Microsoft.EventHub/namespaces/eventhubs', variables('eventHubName')[copyIndex()],parameters('progressRecordsEventHubName'))]"
],
"properties": {
"rights": [
"Listen"
]
}
},
{
"type": "Microsoft.EventHub/namespaces/eventhubs/authorizationRules",
"apiVersion": "[variables('eventHubApiVersion')]",
"name": "[concat(variables('eventHubName')[copyIndex('resourceLoop')], '/',parameters('progressRecordsEventHubName'),'/Send')]",
"location": "[variables('location')[copyIndex()]]",
"dependsOn": [
"[resourceId('Microsoft.EventHub/namespaces/eventhubs', variables('eventHubName')[copyIndex()], parameters('progressRecordsEventHubName'))]"
],
"properties": {
"rights": [
"Send"
]
}
}
]
}
]
}
],
"functions": [
],
"outputs": {}
}
Now this template fails when I run Test-AzureRmResourceGroupDeployment (add -Debug to see real error)
Error:
Test-AzureRmResourceGroupDeployment : Encountered internal server error. Diagnostic information: timestamp '20201119T072227Z' ......
After some troubleshooting I identified that removing the second auth rule in the template fixes the issue.
I actually need more than 1 auth rule. What could be causing the above template to fail? I can't seem to find anything wrong with it.
Below you can find successful template - With 1 auth rule on the Event Hub
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"location-region1": {
"type": "string",
"defaultValue": "eastus"
},
"location-region2": {
"type": "string",
"defaultValue": "westus2"
},
"appName": {
"type": "string",
"defaultValue": "jklm",
"metadata": {
"description": "Short name of the app or service"
}
},
"uniqueSuffix": {
"type": "string",
"defaultValue": "tst",
"metadata": {
"description": "Unique Suffix to use for the azure resources of the app or service"
}
},
"environment": {
"type": "string",
"defaultValue": "int",
"allowedValues": [
"poc",
"dev",
"int",
"uat",
"prod"
],
"metadata": {
"description": "The name of the environment"
}
},
"progressRecordsEventHubName": {
"type": "string",
"defaultValue": "progressrecords"
}
},
"variables": {
"eventHubNMApiVersion": "2018-01-01-preview",
"eventHubApiVersion": "2017-04-01",
"parentResourceGroupName": "[resourceGroup().name]",
"regionCount": 2,
"location": [
"[parameters('location-region1')]",
"[parameters('location-region2')]"
],
"appName": "[concat(parameters('appName'),'-',parameters('uniqueSuffix'),'-')]",
"copy": [
{
"name": "regionSuffix",
"count": "[variables('regionCount')]",
"input": "[concat('r',copyIndex('regionSuffix',1))]"
},
{
"name": "eventHubName",
"count": "[variables('regionCount')]",
"input": "[concat(variables('appName'),'ehub-',variables('regionSuffix')[copyIndex('eventHubName')],'-',parameters('environment'))]"
}
]
},
"resources": [
{
"type": "Microsoft.EventHub/namespaces",
"apiVersion": "[variables('eventHubNMApiVersion')]",
"name": "[variables('eventHubName')[copyIndex()]]",
"copy": {
"name": "resourceLoop",
"count": "[variables('regionCount')]"
},
"location": "[variables('location')[copyIndex()]]",
"sku": {
"name": "Standard",
"tier": "Standard",
"capacity": 1
},
"properties": {
"zoneRedundant": false,
"isAutoInflateEnabled": true,
"maximumThroughputUnits": 1,
"kafkaEnabled": true
},
"resources": [
{
"type": "Microsoft.EventHub/namespaces/eventhubs",
"apiVersion": "[variables('eventHubApiVersion')]",
"name": "[concat(variables('eventHubName')[copyIndex()], '/',parameters('progressRecordsEventHubName'))]",
"location": "[variables('location')[copyIndex()]]",
"dependsOn": [
"[resourceId('Microsoft.EventHub/namespaces', variables('eventHubName')[copyIndex()])]"
],
"properties": {
"messageRetentionInDays": 3,
"partitionCount": 1,
"status": "Active"
},
"resources": [
{
"type": "Microsoft.EventHub/namespaces/eventhubs/authorizationRules",
"apiVersion": "[variables('eventHubApiVersion')]",
"name": "[concat(variables('eventHubName')[copyIndex('resourceLoop')], '/',parameters('progressRecordsEventHubName'),'/Listen')]",
"location": "[variables('location')[copyIndex()]]",
"dependsOn": [
"[resourceId('Microsoft.EventHub/namespaces/eventhubs', variables('eventHubName')[copyIndex()],parameters('progressRecordsEventHubName'))]"
],
"properties": {
"rights": [
"Listen"
]
}
}
]
}
]
}
],
"functions": [
],
"outputs": {}
}
Worked with Azure support on this. There was an issue on the Azure side. It auto resolved today (11/19/2020). Template no longer fails with multiple auth rules.
This article may be useful: https://www.rickvandenbosch.net/blog/error-creating-service-bus-authorization-rules-using-arm/.
I think the template is not expecting the same resource twice, because these Listen, Send authorization rules can be combined like below:
"resources": [
{
"type": "Microsoft.EventHub/namespaces/eventhubs/authorizationRules",
"apiVersion": "[variables('eventHubApiVersion')]",
"name": "[concat(variables('eventHubName')[copyIndex('resourceLoop')], '/',parameters('progressRecordsEventHubName'),'/Listen')]",
"location": "[variables('location')[copyIndex()]]",
"dependsOn": [
"[resourceId('Microsoft.EventHub/namespaces/eventhubs', variables('eventHubName')[copyIndex()],parameters('progressRecordsEventHubName'))]"
],
"properties": {
"rights": [
"Listen",
"Send"
]
}
},
I started Infrastructure as Code with ARM Template and previously all my deployment was made with Powershell. Hope you can help me to fix this issue.
I would like to deploy {2 app services + Azure FrontDoor]. In FrontDoor-Backendpool I want to define the 2 appservices. Below my code:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"location": {
"type": "array",
"metadata": {
"description": "array of region"
},
"defaultValue": [
"centralus",
"eastus"
]
},
"Stage": {
"type": "string",
"metadata": {
"description": "Stage dev, prod"
},
"allowedValues": [
"Dev",
"Prod"
],
"defaultValue": "Dev"
}
},
"functions": [],
"variables": {
"appServicePlanName": "[concat('AppServicePlan-', parameters('Stage'),'-')]",
"appServiceName": "[concat('AppService-', parameters('Stage'), '-')]",
"frontDoorName": "[concat('FrontDoor-', parameters('Stage'), uniqueString(resourceGroup().id))]"
},
"resources": [
{ // App Service Plan
"type": "Microsoft.Web/serverfarms",
"name": "[concat(variables('appServicePlanName'),parameters('location')[copyIndex()])]",
"apiVersion": "2018-02-01",
"copy": {
"count": "[length(parameters('location'))]",
"name": "copy multiple"
},
"location": "[parameters('location')[copyIndex()]]",
"sku": {
"name": "F1",
"capacity": 1
},
"tags": {
"cost": "[parameters('Stage')]"
},
"properties": {
"name": "[concat(variables('appServicePlanName'),parameters('location')[copyIndex()])]"
}
},
{ // App Services
"type": "Microsoft.Web/sites",
"name": "[concat(variables('appServiceName'), parameters('location')[copyIndex()])]",
"apiVersion": "2018-11-01",
"copy": {
"name": "Copy website",
"count": "[length(parameters('location'))]"
},
"location": "[parameters('location')[copyIndex()]]",
"tags": {
"cost": "[parameters('Stage')]"
},
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms', concat(variables('appServicePlanName'),parameters('location')[copyIndex()]))]"
],
"properties": {
"name": "[concat(variables('appServiceName'), parameters('location')[copyIndex()])]",
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', concat(variables('appServicePlanName'),parameters('location')[copyIndex()]))]"
}
},
{ // Front Door
"type": "Microsoft.Network/frontDoors",
"apiVersion": "2020-05-01",
"name": "[variables('frontDoorName')]",
"location": "global",
"properties": {
"routingRules": [
{
"name": "routingRule1",
"properties": {
"frontendEndpoints": [
{
"id": "[resourceId('Microsoft.Network/frontDoors/frontendEndpoints', variables('frontDoorName'), 'frontendEndpoint1')]"
}
],
"acceptedProtocols": [
"Http",
"Https"
],
"patternsToMatch": [
"/*"
],
"routeConfiguration": {
"#odata.type": "#Microsoft.Azure.FrontDoor.Models.FrontdoorForwardingConfiguration",
"forwardingProtocol": "MatchRequest",
"backendPool": {
"id": "[resourceId('Microsoft.Network/frontDoors/backendPools', variables('frontDoorName'), 'backendPool1')]"
}
},
"enabledState": "Enabled"
}
}
],
"healthProbeSettings": [
{
"name": "healthProbeSettings1",
"properties": {
"path": "/",
"protocol": "Http",
"intervalInSeconds": 120
}
}
],
"loadBalancingSettings": [
{
"name": "loadBalancingSettings1",
"properties": {
"sampleSize": 4,
"successfulSamplesRequired": 2
}
}
],
"backendPools": [
{
"id": "backendPool1",
"name": "backendPool1",
"properties": {
"copy": [
{
"name": "backends",
"count": "[length(parameters('location'))]",
"input": {
"address": "[concat(variables('appServiceName'), parameters('location')[copyIndex()], '.azurewebsites.net') ]",
"httpPort": 80,
"httpsPort": 443,
"weight": 50,
"priority": 1,
"enabledState": "Enabled"
}
}
],
"loadBalancingSettings": {
"id": "[resourceId('Microsoft.Network/frontDoors/loadBalancingSettings', variables('frontDoorName'), 'loadBalancingSettings1')]"
},
"healthProbeSettings": {
"id": "[resourceId('Microsoft.Network/frontDoors/healthProbeSettings', variables('frontDoorName'), 'healthProbeSettings1')]"
}
}
}
],
"frontendEndpoints": [
{
"name": "frontendEndpoint1",
"properties": {
"hostName": "[concat(variables('frontDoorName'), '.azurefd.net')]",
"sessionAffinityEnabledState": "Enabled"
}
}
],
"enabledState": "Enabled"
}
}
],
"outputs": {}
}
As you can see i iterate on paramater location to create my AppService Plan and AppService and it worked well. So I thought to do same for BackEndpool.
Here part of code which break my head
address": "[concat(variables('appServiceName'), parameters('location')[copyIndex()], '.azurewebsites.net') ]",
Something is wrong inside but I have no idea why.
Error retuned is:
Error: Code=InvalidTemplate; Message=Deployment template language expression evaluation
failed: 'The template language function 'copyIndex' has an invalid argument. The provided copy name '' doesn't exist in the resource.
Please see https://aka.ms/arm-copy for usage details.'. Please see https://aka.ms/arm-template-expressions for usage details.
I take my inspiration from official MS documentation link from MS
Any idea on how I can fix it ?
Thx
You need to include the copy name property in the call to copyIndex in the backendPools part. That is why is says "The provided copy name '' doesn't exist". The property copy is treated a little differently than the resource copy.
"The loopName property enables you to specify whether copyIndex is referring to a resource iteration or property iteration. If no value is provided for loopName, the current resource type iteration is used. Provide a value for loopName when iterating on a property."
Source: https://learn.microsoft.com/en-us/azure/azure-resource-manager/templates/template-functions-numeric#copyindex
parameters('location')[copyIndex('backends')]
I'm attempting to deploy to a new resource group containing an existing app service plan in Azure using an ARM script. If I run the deployment through the Azure Portal UI, it is successful. The issue happens when I try to download the template ARM script for the deployment and use that.
I'm attempting to create a Web app and associated application insights instance.
Here is my template.json
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"subscriptionId": {
"type": "string"
},
"name": {
"type": "string"
},
"location": {
"type": "string"
},
"hostingEnvironment": {
"type": "string"
},
"hostingPlanName": {
"type": "string"
},
"serverFarmResourceGroup": {
"type": "string"
},
"alwaysOn": {
"type": "bool"
},
"currentStack": {
"type": "string"
}
},
"resources": [
{
"apiVersion": "2018-02-01",
"name": "[parameters('name')]",
"type": "Microsoft.Web/sites",
"location": "[parameters('location')]",
"tags": {},
"dependsOn": [
"microsoft.insights/components/LicensingService-API"
],
"properties": {
"name": "[parameters('name')]",
"siteConfig": {
"appSettings": [
{
"name": "APPINSIGHTS_INSTRUMENTATIONKEY",
"value": "[reference('microsoft.insights/components/LicensingService-API', '2015-05-01').InstrumentationKey]"
},
{
"name": "ApplicationInsightsAgent_EXTENSION_VERSION",
"value": "~2"
},
{
"name": "XDT_MicrosoftApplicationInsights_Mode",
"value": "default"
},
{
"name": "DiagnosticServices_EXTENSION_VERSION",
"value": "disabled"
},
{
"name": "APPINSIGHTS_PROFILERFEATURE_VERSION",
"value": "disabled"
},
{
"name": "APPINSIGHTS_SNAPSHOTFEATURE_VERSION",
"value": "disabled"
},
{
"name": "InstrumentationEngine_EXTENSION_VERSION",
"value": "disabled"
},
{
"name": "SnapshotDebugger_EXTENSION_VERSION",
"value": "disabled"
},
{
"name": "XDT_MicrosoftApplicationInsights_BaseExtensions",
"value": "disabled"
}
],
"metadata": [
{
"name": "CURRENT_STACK",
"value": "[parameters('currentStack')]"
}
],
"alwaysOn": "[parameters('alwaysOn')]"
},
"serverFarmId": "[concat('/subscriptions/', parameters('subscriptionId'),'/resourcegroups/', parameters('serverFarmResourceGroup'), '/providers/Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]",
"hostingEnvironment": "[parameters('hostingEnvironment')]",
"clientAffinityEnabled": true
}
},
{
"apiVersion": "2015-05-01",
"name": "LicensingService-API",
"type": "microsoft.insights/components",
"location": "westus2",
"tags": {},
"properties": {
"ApplicationId": "[parameters('name')]",
"Request_Source": "IbizaWebAppExtensionCreate"
}
}
]
}
And my parameters.json
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"subscriptionId": {
"value": "REMOVED"
},
"name": {
"value": "LicensingService-API"
},
"location": {
"value": "West US 2"
},
"hostingEnvironment": {
"value": ""
},
"hostingPlanName": {
"value": "LicensingServiceProductionAppServicePlan"
},
"serverFarmResourceGroup": {
"value": "LicensingServicePROD"
},
"alwaysOn": {
"value": true
},
"currentStack": {
"value": "dotnetcore"
}
}
}
There is one particular parameter that I'm having issues with. It is the "hostingEnvironment" parameter. I am unable to determine what should be placed in that field, as the default template provided by Azure leaves this blank. If I enter a value here (LicensingServiceProductionAppServicePlan for example), I get an error on the deployment of the web app that reads:
{
"Code": "NotFound",
"Message": "Cannot find Stamp with name LicensingServiceProductionAppServicePlan.",
"Target": null,
"Details": [
{
"Message": "Cannot find Stamp with name LicensingServiceProductionAppServicePlan."
},
{
"Code": "NotFound"
},
{
"ErrorEntity": {
"ExtendedCode": "51004",
"MessageTemplate": "Cannot find {0} with name {1}.",
"Parameters": [
"Stamp",
"LicensingServiceProductionAppServicePlan"
],
"Code": "NotFound",
"Message": "Cannot find Stamp with name LicensingServiceProductionAppServicePlan."
}
}
],
"Innererror": null
}
If I instead remove the parameter from both the template and the parameters files, as suggested in this answer, I get a BadRequest error that reads:
{
"error": {
"code": "InvalidTemplate",
"message": "Unable to process template language expressions for resource '/subscriptions/REMOVED/resourceGroups/LicensingServicePROD/providers/Microsoft.Web/serverfarms/LicensingServicePROD' at line '151' and column '9'. 'The template parameter 'hostingEnvironment' is not found. Please see https://aka.ms/arm-template/#parameters for usage details.'",
"additionalInfo": [
{
"type": "TemplateViolation",
"info": {
"lineNumber": 151,
"linePosition": 9,
"path": ""
}
}
]
}
}
Likely this is because I can see that the "hostingEnvironment" parameter is used in the template script.
So I'm left wondering why this works when done through the Azure UI but not from the script generated from the UI. My final question that I'm looking to solve is what is the value that should be provided for the "hostingEnvironment" parameter?
First hostingEnvironment is not required. It is required if you have an App Service Environment and you want to deploy the site on it.
You can leave it empty the value or remove it from the template.
See the details from the template reference site Web Site template reference
The solution is to make the following changes:
template.json:
"hostingEnvironment": {
"type": "string",
"defaultValue": ""
},
parameters.json
"hostingEnvironment": {
"value": ""
},
I am trying to send array of email values as parameters and trying to deploy 'Action group' using 'Copy' in the resource template .My Action group template is getting deployed without errors but email fields are empty. I was passing two email values as parameters. I'm stuck with this for a day. It would be great if someone throw some lights on where i am going wrong.
Template.json:
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"actionGroupName": {
"type": "string",
"defaultValue": "newActionGroup",
"metadata": {
"description": "Unique name (within the Resource Group) for the Action group."
}
},
"actionGroupShortName": {
"type": "string",
"defaultValue": "newActionGroup",
"metadata": {
"description": "Short name (maximum 12 characters) for the Action group."
}
},
"emailReceiverName": {
"type": "array",
"metadata": {
"description": "email receiver service Name."
}
},
"emailReceiverAddress": {
"type": "array",
"metadata": {
"description": "email receiver address."
}
}
},
"variables": {
"customemailReceiverName": "[array(parameters('emailReceiverName'))]",
"customemailReceiverAddress": "[parameters('emailReceiverAddress')]"
},
"resources": [
{
"type": "Microsoft.Insights/actionGroups",
"name": "[parameters('actionGroupName')]",
"apiVersion": "2018-03-01",
"location": "Global",
"properties": {
"groupShortName": "[parameters('actionGroupShortName')]",
"copy": [
{
"name": "counts",
"count": "[length(parameters('emailReceiverName'))]",
"input": {
"emailReceivers": [
{
"name": "[parameters('emailReceiverName')[copyIndex('counts')]",
"emailAddress": "[parameters('emailReceiverAddress')[copyIndex('counts')]]"
}
]
}
}
]
}
}
] }
Parameter.json:
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"actionGroupName": {
"value": "actiongroupslb"
},
"actionGroupShortName": {
"value": "agSLB"
},
"emailReceiverName": {
"value": ["siva","siva1"]
},
"emailReceiverAddress": {
"value": ["siva#gmail.com","svaji#gmail.com"]
}
}
}
Action group created with missing email values
Here's whats working for me:
{
"type": "Microsoft.Insights/actionGroups",
"apiVersion": "2018-03-01",
"name": "[variables('actionGroups')[copyIndex()].Name]",
"copy": {
"name": "ActionGroupCopy",
"count": "[length(parameters('emailReceiverName'))]"
},
"location": "Global",
"properties": {
"groupShortName": "[variables('actionGroups')[copyIndex()].Name]",
"enabled": true,
"emailReceivers": [
{
"name": "[variables('actionGroups')[copyIndex()].EmailName]",
"emailAddress": "[variables('actionGroups')[copyIndex()].EmailAddress]"
}
]
}
},
Here's the variable:
"actionGroups": [
{
"Name": "teamname",
"EmailAddress": "email#domain.com",
"EmailName": "emailname"
},
{
"Name": "teamname1",
"EmailAddress": "email1#domain.com",
"EmailName": "emailname1"
}
],
If you need multiple receivers, use the resource property copy function, not resource:
{
"type": "Microsoft.Insights/actionGroups",
"apiVersion": "2018-03-01",
"name": "name",
"location": "Global",
"properties": {
"groupShortName": "name",
"enabled": true,
"copy": [
{
"name": "emailReceivers",
"count": "[length(parameters('emailReceiverName'))]",
"input": {
"name": "[parameters('emailReceiverName')[copyIndex('emailReceivers')]]",
"emailAddress": "[parameters('emailReceiverAddress')[copyIndex('emailReceivers')]]"
}
}
]
}
},
this is assuming they map 1-to-1
I wrote an ARM template to script the deploy and configuration of ServiceBus. One of the goals of the script was to make it easy to manage topics and subscriptions. In order to accomplish this, the script uses variables that are arrays.
This all works fine, but I'm seeing an issue whenever I try to use the same subscription name for two different topics. Now, I understand that a subscription can only be mapped to a single topic. The script attempts to account for that by joining the subscription name to the topic.
I should also note that the Azure UI will allow you to use the same subscription name beneath two topics. This script was derived from setting up this scenario via the azure console then exporting the ARM.
I have been over this script several dozen times and I'm not seeing the cause. Hoping new eyes will help.
Here is the script:
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"envType": {
"type": "string",
"allowedValues": [ "dev", "prod" ],
"defaultValue": "dev",
"metadata": { "description": "The environment type being created" }
},
"sbSku": {
"type": "string",
"allowedValues": [ "Standard", "Premium" ],
"defaultValue": "Standard",
"metadata": { "description": "The messaging tier for service Bus namespace" }
}
},
"variables": {
"defaultSASKeyName": "RootManageSharedAccessKey",
"authRuleResourceId": "[resourceId('Microsoft.ServiceBus/namespaces/authorizationRules', variables('sbNamespaceName'), variables('defaultSASKeyName'))]",
"sbNamespaceName": "[concat(parameters('envType'), 'eventbus')]",
"sbVersion": "2017-04-01",
"sbTopics": [
"mytopic1",
"mytopic2",
"mytopic3",
"mytopic4"
],
"sbSubscriptions": [
{ "Name": "mysubA", "Topic": "mytopic1" },
{ "Name": "mysubB", "Topic": "mytopic2" },
{ "Name": "mysubB", "Topic": "mytopic3" },
{ "Name": "mysubC", "Topic": "mytopic4" }
]
},
"resources": [
{
"apiVersion": "[variables('sbVersion')]",
"location": "[resourceGroup().location]",
"name": "[variables('sbNamespaceName')]",
"properties": {},
"sku": {
"name": "[parameters('sbSku')]"
},
"tags": {},
"type": "Microsoft.ServiceBus/Namespaces"
},
{
"type": "Microsoft.ServiceBus/namespaces/topics",
"name": "[concat(variables('sbNamespaceName'), '/', variables('sbTopics')[copyIndex()])]",
"apiVersion": "[variables('sbVersion')]",
"location": "[resourceGroup().location]",
"dependsOn": [
"[concat('Microsoft.ServiceBus/namespaces/', variables('sbNamespaceName'))]"
],
"properties": {
"defaultMessageTimeToLive": "P14D",
"maxSizeInMegabytes": 1024,
"requiresDuplicateDetection": false,
"enablePartitioning": true
},
"copy": {
"name": "topiccopy",
"count": "[length(variables('sbTopics'))]",
"mode": "Serial",
"batchSize": 3
}
},
{
"type": "Microsoft.ServiceBus/namespaces/topics/subscriptions",
"name": "[concat(variables('sbNamespaceName'), '/', variables('sbSubscriptions')[copyIndex()].Topic, '/', variables('sbSubscriptions')[copyIndex()].Name)]",
"apiVersion": "2017-04-01",
"location": "East US",
"dependsOn": [
"[resourceId('Microsoft.ServiceBus/namespaces', variables('sbNamespaceName'))]",
"[resourceId('Microsoft.ServiceBus/namespaces/topics', variables('sbNamespaceName'), variables('sbSubscriptions')[copyIndex()].Topic)]"
],
"properties": {
"maxDeliveryCount": 10
},
"copy": {
"name": "subscriptioncopy",
"count": "[length(variables('sbSubscriptions'))]",
"mode": "Serial",
"batchSize": 1
}
}
],
"outputs": {
"NamespaceConnectionString": {
"type": "string",
"value": "[listkeys(variables('authRuleResourceId'), variables('sbVersion')).primaryConnectionString]"
},
"SharedAccessPolicyPrimaryKey": {
"type": "string",
"value": "[listkeys(variables('authRuleResourceId'), variables('sbVersion')).primaryKey]"
},
"Topics": {
"type": "array",
"value": "[concat(variables('sbTopics'))]"
},
"Subscriptionss": {
"type": "array",
"value": "[concat(variables('sbSubscriptions'))]"
}
}
}
When executed with:
New-AzureRmResourceGroupDeployment -ResourceGroupName {xxx} -TemplateFile arm.servicebus.example.json
It returns:
New-AzureRmResourceGroupDeployment : 2:58:05 PM - Error: Code=InvalidTemplate; Message=Deployment template validation
failed: 'The template resource 'Microsoft.ServiceBus/namespaces/deveventbus/topics/mytopic3/subscriptions/mysubB'
cannot reference itself. Please see https://aka.ms/arm-template-expressions/#reference for usage details.'.
At line:1 char:1
+ New-AzureRmResourceGroupDeployment -ResourceGroupName Wiretappers_Ste ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [New-AzureRmResourceGroupDeployment], Exception
+ FullyQualifiedErrorId : Microsoft.Azure.Commands.ResourceManager.Cmdlets.Implementation.NewAzureResourceGroupDep
loymentCmdlet
New-AzureRmResourceGroupDeployment : The deployment validation failed
At line:1 char:1
+ New-AzureRmResourceGroupDeployment -ResourceGroupName Wiretappers_Ste ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : CloseError: (:) [New-AzureRmResourceGroupDeployment], InvalidOperationException
+ FullyQualifiedErrorId : Microsoft.Azure.Commands.ResourceManager.Cmdlets.Implementation.NewAzureResourceGroupDep
loymentCmdlet
The issue is caused by the third entry in the 'sbSubscriptions' array (mysubB/mytopic3). This is being processed in the third object beneath 'resources'.
If anyone can see my oversight, it would be appreciated.
PS. If anyone knows how to get the Azure tools to output the template json after it has expanded the "copy" node and the functions (resourceId, concat) that would be helpful as well.
UPDATE:2018-03-01
Here is a working template for future reference. See all comments below for details.
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"envType": {
"type": "string",
"allowedValues": [ "dev", "prod" ],
"defaultValue": "dev",
"metadata": { "description": "The environment type being created" }
},
"sbSku": {
"type": "string",
"allowedValues": [ "Standard", "Premium" ],
"defaultValue": "Standard",
"metadata": { "description": "The messaging tier for service Bus namespace" }
}
},
"variables": {
"sbNamespaceName": "[concat(parameters('envType'), 'eventbus')]",
"sbVersion": "2017-04-01",
"sbTopics": [
"mytopic1",
"mytopic2",
"mytopic3",
"mytopic4"
],
"sbSubscriptions": [
{ "Name": "mysubA", "Topic": "mytopic1" },
{ "Name": "mysubB", "Topic": "mytopic2" },
{ "Name": "mysubB", "Topic": "mytopic3" },
{ "Name": "mysubC", "Topic": "mytopic4" }
]
},
"resources": [
{
"apiVersion": "[variables('sbVersion')]",
"location": "[resourceGroup().location]",
"name": "[variables('sbNamespaceName')]",
"properties": {},
"sku": {
"name": "[parameters('sbSku')]"
},
"tags": {},
"type": "Microsoft.ServiceBus/Namespaces"
},
{
"type": "Microsoft.ServiceBus/namespaces/topics",
"name": "[concat(variables('sbNamespaceName'), '/', variables('sbTopics')[copyIndex()])]",
"apiVersion": "[variables('sbVersion')]",
"location": "[resourceGroup().location]",
"dependsOn": [
"[variables('sbNamespaceName')]"
],
"properties": {
"defaultMessageTimeToLive": "P14D",
"maxSizeInMegabytes": 1024,
"requiresDuplicateDetection": false,
"enablePartitioning": true
},
"copy": {
"name": "topiccopy",
"count": "[length(variables('sbTopics'))]",
"mode": "Serial",
"batchSize": 3
}
},
{
"type": "Microsoft.ServiceBus/namespaces/topics/subscriptions",
"name": "[concat(variables('sbNamespaceName'), '/', variables('sbSubscriptions')[copyIndex()].Topic, '/', variables('sbSubscriptions')[copyIndex()].Name)]",
"apiVersion": "[variables('sbVersion')]",
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.ServiceBus/namespaces', variables('sbNamespaceName'))]",
"[resourceId('Microsoft.ServiceBus/namespaces/topics', variables('sbNamespaceName'), variables('sbSubscriptions')[copyIndex()].Topic)]"
],
"properties": {
"maxDeliveryCount": 10
},
"copy": {
"name": "subscriptioncopy",
"count": "[length(variables('sbSubscriptions'))]"
}
}
],
"outputs": {
"Topics": {
"type": "array",
"value": "[concat(variables('sbTopics'))]"
},
"Subscriptionss": {
"type": "array",
"value": "[concat(variables('sbSubscriptions'))]"
}
}
}
Ok, i dont know what the issue is\was, but this works:
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"envType": {
"type": "string",
"allowedValues": [
"dev",
"prod",
"zlp"
],
"defaultValue": "zlp",
"metadata": {
"description": "The environment type being created"
}
},
"sbSku": {
"type": "string",
"allowedValues": [
"Standard",
"Premium"
],
"defaultValue": "Standard",
"metadata": {
"description": "The messaging tier for service Bus namespace"
}
}
},
"variables": {
"sbNamespaceName": "[concat(parameters('envType'), 'eventbus')]",
"sbVersion": "2017-04-01",
"sbTopics": [
"mytopic1",
"mytopic2",
"mytopic3",
"mytopic4"
],
"sbSubscriptions": [
{
"Name": "mysubA",
"Topic": "mytopic1"
},
{
"Name": "mysubB",
"Topic": "mytopic2"
},
{
"Name": "mysubB",
"Topic": "mytopic3"
},
{
"Name": "mysubC",
"Topic": "mytopic4"
}
]
},
"resources": [
{
"apiVersion": "[variables('sbVersion')]",
"location": "[resourceGroup().location]",
"name": "[variables('sbNamespaceName')]",
"properties": {},
"sku": {
"name": "[parameters('sbSku')]"
},
"tags": {},
"type": "Microsoft.ServiceBus/Namespaces"
},
{
"type": "Microsoft.ServiceBus/namespaces/topics",
"name": "[concat(variables('sbNamespaceName'), '/', variables('sbTopics')[copyIndex()])]",
"apiVersion": "[variables('sbVersion')]",
"location": "[resourceGroup().location]",
"dependsOn": [
"[variables('sbNamespaceName')]"
],
"properties": {
"defaultMessageTimeToLive": "P14D",
"maxSizeInMegabytes": 1024,
"requiresDuplicateDetection": false,
"enablePartitioning": true
},
"copy": {
"name": "topiccopy",
"count": "[length(variables('sbTopics'))]"
}
},
{
"type": "Microsoft.ServiceBus/namespaces/topics/subscriptions",
"name": "[concat(variables('sbNamespaceName'), '/', variables('sbSubscriptions')[copyIndex()].Topic, '/', variables('sbSubscriptions')[copyIndex()].Name)]",
"apiVersion": "[variables('sbVersion')]",
"location": "[resourceGroup().location]",
"dependsOn": [
"topiccopy"
],
"properties": {
"maxDeliveryCount": 10
},
"copy": {
"name": "subscriptioncopy",
"count": "[length(variables('sbSubscriptions'))]"
}
}
]
}
You can also use this to debug:
Test-AzureRmResourceGroupDeployment -verbose or -debug