We are having a deployment error in working deployments since last Thursday AEST.
When we run an ARM deployment DocumentDb fails with the message:
Resource Microsoft.DocumentDB/databaseAccounts 'xxx' failed with message 'Document service name 'xxx' already exists.
{
"apiVersion": "2015-04-08",
"type": "Microsoft.DocumentDB/databaseAccounts",
"name": "[parameters('databaseAccountName')]",
"location": "[resourceGroup().location]",
"properties": {
"name": "[parameters('databaseAccountName')]",
"databaseAccountOfferType": "Standard"
}
In the snippet [parameters('databaseAccountName')] = 'xxx'
We are guessing that something underlying has happened to cause this. Can you please let us know the new properties into the ARM template that we need to include for the DocumentDb instance to be found again?
Update: We have updated our documentation to cover ARM deployment for multi-region enabled accounts. https://azure.microsoft.com/documentation/articles/documentdb-automation-resource-manager-cli/#create-multi-documentdb-account
We are in the process of enabling multi-region accoutns for all accounts. As a part of this effort, there is a change in the ARM template. A few accounts are seeing errors when using the currently published template in certain scenarios.
We will be updating our documentation very soon. In the meantime, the below template should get you going. Your old template will also start working in a couple of days.
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"databaseAccountName": {
"type": "string"
},
"locationName1": {
"type": "string"
}
},
"variables": { },
"resources": [
{
"apiVersion": "2015-04-08",
“kind”: “GlobalDocumentDB”,
"type": "Microsoft.DocumentDb/databaseAccounts",
"name": "[parameters('databaseAccountName')]",
"location": "[resourceGroup().location]",
"properties": {
"databaseAccountOfferType": "Standard",
"locations": [
{
"id": "[concat(parameters('databaseAccountName'), '-', resourceGroup().location)]",
"failoverPriority": 0,
"locationName": "[parameters('locationName1')]"
}]
}
}]
}
Edit:
locationName1 should be in the format of the "Azure Regions" column on this page: https://azure.microsoft.com/en-us/regions/
Related
My goal is to deploy a logic app with a system managed identity and a role assignment for that identity. Preferably, this is done in one ARM template.
I have a setup that fails the first run, but succeeds successive runs. Correct me if I'm wrong, but I think that the reason for this is that the deployment of the role assignment happens before the managed identity of the logic app is "ready", hence the following error I get the first time that I deploy the template. I don't get this error the second time I deploy the template, probably because the Identity already exists at that time.
{
"code": "DeploymentFailed",
"message": "At least one resource deployment operation failed. Please list deployment operations for details. Please see https://aka.ms/DeployOperations for usage details.",
"details": [
{
"code": "PrincipalNotFound",
"message": "Principal *** does not exist in the directory ***."
}
]
}
My template (removed logic app definition for brevity). In this case the identity of the logic app requires access to a storage account which is located in another resource group.
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"logicAppName": {
"type": "string"
},
"storageAccountResourceGroup": {
"type": "String"
},
"storageAccountName": {
"type": "String"
}
},
"variables": {
"logicAppResourceId": "[resourceId('Microsoft.Logic/workflows', parameters('logicAppName'))]",
"Storage Blob Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')]"
},
"resources": [
{
"type": "Microsoft.Logic/workflows",
"apiVersion": "2017-07-01",
"name": "[parameters('logicAppName')]",
"location": "[resourceGroup().location]",
"identity": {
"type": "SystemAssigned"
},
"properties": {
"state": "Enabled",
"definition": {
...
}
}
},
{
"type": "Microsoft.Resources/deployments",
"name": "[concat('RoleAssignment-', parameters('logicAppName'))]",
"apiVersion": "2020-06-01",
"resourceGroup": "[parameters('storageAccountResourceGroup')]",
"subscriptionId": "[subscription().subscriptionId]",
"dependsOn": [
"[parameters('logicAppName')]"
],
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"apiVersion": "2018-09-01-preview",
"type": "Microsoft.Storage/storageAccounts/providers/roleAssignments",
"name": "[concat(parameters('storageAccountName'), '/Microsoft.Authorization/', guid(subscription().subscriptionId, parameters('logicAppName')))]",
"properties": {
"roleDefinitionId": "[variables('Storage Blob Data Contributor')]",
"principalId": "[reference(variables('logicAppResourceId'), '2019-05-01', 'Full').identity.principalId]"
}
}
]
}
}
}
]
}
As you can see in the template, I added a dependsOn on the logic app itself. However that doesn't seem to be sufficient.
Does anyone have a solution for this?
Thank you!
I found the answer here: https://learn.microsoft.com/en-us/azure/role-based-access-control/role-assignments-template#new-service-principal
Deployment works consistently after adding "principalType": "ServicePrincipal"
I have prepared an ARM template for deploying an Azure Eventhub instance and wonder how to access the both connection keys for returning them as output?
I would like to return a string in the form:
Endpoint=sb://my-eventhub.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=ojZMQcJD7uYifxJyGeXG6tNDdZyaC1/h5tmX6ODVfmY=
Here is my current template:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"clusterName": {
"type": "string",
"defaultValue": "eventhub",
"metadata": {
"description": "Name for the Event Hub cluster."
}
},
"namespaceName": {
"type": "string",
"defaultValue": "namespace",
"metadata": {
"description": "Name for the Namespace to be created in cluster."
}
}
},
"variables": {
"clusterName": "[concat(resourceGroup().name, '-', parameters('clusterName'))]",
"namespaceName": "[concat(resourceGroup().name, '-', parameters('namespaceName'))]"
},
"outputs": {
"MyClusterName": {
"type": "string",
"value": "[variables('clusterName')]"
},
"PrimaryConnectionString": {
"type": "string",
"value": "WHAT TO USE HERE PLEASE?"
},
"SecondaryConnectionString": {
"type": "string",
"value": "WHAT TO USE HERE PLEASE?"
}
},
"resources": [
{
"type": "Microsoft.EventHub/clusters",
"apiVersion": "2018-01-01-preview",
"name": "[variables('clusterName')]",
"location": "[resourceGroup().location]",
"sku": {
"name": "Dedicated",
"capacity": 1
}
},
{
"type": "Microsoft.EventHub/namespaces",
"apiVersion": "2018-01-01-preview",
"name": "[variables('namespaceName')]",
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.EventHub/clusters', variables('clusterName'))]"
],
"sku": {
"name": "Standard",
"tier": "Standard",
"capacity": 1
},
"properties": {
"isAutoInflateEnabled": false,
"maximumThroughputUnits": 0,
"clusterArmId": "[resourceId('Microsoft.EventHub/clusters', variables('clusterName'))]"
}
}
]
}
I have tried the following:
"value": "[listKeys(resourceId(concat('Microsoft.ServiceBus/namespaces/AuthorizationRules'), variables('namespaceName'), 'RootManageSharedAccessKey'),'2018-01-01-preview').primaryConnectionString]"
but get deployment error:
[error]ParentResourceNotFound: Can not perform requested operation on nested resource. Parent resource 'my-rg-namespace' not found.
UPDATE:
The following has worked for me as suggested by Jesse (thank you!):
"variables": {
"clusterName": "[concat(resourceGroup().name, '-', parameters('clusterName'))]",
"namespaceName": "[concat(resourceGroup().name, '-', parameters('namespaceName'))]",
"defaultSASKeyName": "RootManageSharedAccessKey",
"authRuleResourceId": "[resourceId('Microsoft.EventHub/namespaces/authorizationRules', variables('namespaceName'), variables('defaultSASKeyName'))]"
},
"outputs": {
"MyClusterName": {
"type": "string",
"value": "[variables('clusterName')]"
},
"PrimaryConnectionString": {
"type": "string",
"value": "[listkeys(variables('authRuleResourceId'), '2015-08-01').primaryConnectionString]"
},
"SecondaryConnectionString": {
"type": "string",
"value": "[listkeys(variables('authRuleResourceId'), '2015-08-01').secondaryConnectionString]"
}
},
UPDATE 2:
Also, Jesse has noticed that my ARM template is wrong in 2 ways, because it does not create an Event Hub, but a cluster and it is outside my namespace and provided this valuable comment:
The Event Hubs cluster is basically a way of reserving dedicated compute. It's not something that most scenarios need and it is... not cheap. Think of something on the scale of Xbox Live where you're seeing nearly 5 millions of events per second and which have higher performance needs. If you're not looking at that kind of scale or that sensitivity around timing, you probably want to rethink the need for a dedicated cluster.
Normally, you'd just provision an Event Hubs namespace which will use shared infrastructure with certain guarantees to minimize noisy neighbors and similar. This is adequate for the majority of scenarios, even those with high throughput needs. If you're not sure, this is probably the place that you want to start and then upgrade to a dedicated cluster if your needs justify the cost.
An Event Hubs namespace is the container for a set of Event Hub instances grouped together by a unique endpoint. Each Event Hub is made of a set of partitions. When you're publishing or consuming events, the partitions of an Event Hub are where the actual data is. When you're working with one of the SDKs, you'll start by telling it about the endpoint of your namespace and the Event Hub that you're interested in. You'll need a general awareness of partitions, but most of the "Getting Started" scenarios handle that detail for you, as do a fair portion of the real-world ones.... but, the concept is an important one.
It looks like you may be using an incorrect resource id, pulling from Microsoft.ServiceBus rather than Microsoft.EventHub where the failure is because there is no Service Bus namespace with the correct name.
You may want to try using a form similar to the following to identify your resource:
"variables": {
"location": "[resourceGroup().location]",
"apiVersion": "2015-08-01",
"defaultSASKeyName": "RootManageSharedAccessKey",
"authRuleResourceId": "[resourceId('Microsoft.EventHub/namespaces/authorizationRules', parameters('namespaceName'), variables('defaultSASKeyName'))]"
},
Which should allow it to be returned using listkeys as you you detailed above:
"outputs": {
"NamespaceConnectionString": {
"type": "string",
"value": "[listkeys(variables('authRuleResourceId'), variables('apiVersion')).primaryConnectionString]"
}
}
A full example for a simple deployment can be found in the Event Hubs sample template.
I'm trying to create Application Insights API keys from ARM template. I need to have the API key for write annotations created during resource deployment to have release annotations working during application deployment from Azure Devops.
I've tried to find information on how to get this working, but I can only find examples on how to use PowerShell or Azure REST API to create the keys.
What I need to get working is to create the API keys using the ARM template.
I have tried numerous attempts with json similar to this without success;
{
"name": "[variables('applicationInsightsName')]",
"type": "Microsoft.Insights/components",
"location": "[resourceGroup().location]",
"apiVersion": "2014-04-01",
"tags": {
"displayName": "[concat('Component ', variables('applicationInsightsName'))]"
},
"properties": {
"applicationId": "[variables('applicationInsightsName')]"
},
"resources": [
{
"name": "action",
"type": "apikeys",
"location": "[resourceGroup().location]",
"apiVersion": "2015-05-01",
"properties": {
"name": "Azure Devops Release Annotations",
"linkedWriteProperties": [
"[concat(resourceId('Microsoft.Insights/components', variables('applicationName')), '/annotations')]"
],
"linkedReadProperties": []
},
"dependsOn": [
"[resourceId('Microsoft.Insights/components', variables('applicationInsightsName'))]"
]
}
]
}
The best information I've found so far is this, but it isn't much help.
Is it possible to have the API keys created using ARM templates?
No this is not possible, ARM Templates only mimic PUT requests, whereas the Microsoft.Insights/Components/ApiKeys/Action is a POST request.
I suggest an easy way. You are able to use outputs with reference InstrumentationKey. Then you able to use it everywhere: another resource, linked template or use outputs for the next steps by Azure DevOps.
{
"$schema": "http://schema.management.azure.com/schemas/2014-04-01-preview/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"name": {
"type": "string",
"defaultValue": "[concat('stackoverflow-', uniqueString(resourceGroup().name))]"
},
"type": {
"type": "string",
"defaultValue": "web"
},
"requestSource": {
"type": "string",
"defaultValue": "IbizaAIExtension"
}
},
"resources": [
{
"name": "[parameters('name')]",
"type": "microsoft.insights/components",
"location": "[resourceGroup().location]",
"apiVersion": "2014-08-01",
"properties": {
"ApplicationId": "[parameters('name')]",
"Application_Type": "[parameters('type')]",
"Flow_Type": "Redfield",
"Request_Source": "[parameters('requestSource')]"
}
}
],
"outputs":{
"APPINSIGHTS_INSTRUMENTATIONKEY":{
"type": "string",
"value": "[reference(resourceId('Microsoft.Insights/components', parameters('name')), '2014-08-01').InstrumentationKey]"
}
}
}
I used it many times.
I have developed an azure timer trigger function. I am taking timer schedule from appSettings of the function app as following.
function.json
This is working fine for given static schedule. But this schedule should be able to change as per the user requirement from another web application, when user need to change the schedule.
I am struggling to change schedule parameter from external application dynamically. What i was tried is deploy an ARM templatere injecting new schedule values from following ARM template.
{
"$schema": "http://schema.management.azure.com/schemas/2014-04-01-preview/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"name": {
"type": "String"
},
"location": {
"type": "String"
},
"subscriptionId": {
"type": "String"
},
"schedule1": {
"type": "String"
},
"schedule2": {
"type": "String"
}
},
"resources": [
{
"type": "Microsoft.Web/sites",
"kind": "functionapp",
"name": "[parameters('name')]",
"apiVersion": "2016-03-01",
"location": "[parameters('location')]",
"properties": {
"name": "[parameters('name')]",
"siteConfig": {
"appSettings": [
{
"name": "schedule1",
"value": "[parameters('schedule1')]"
},
{
"name": "schedule2",
"value": "[parameters('schedule2')]"
}
]
},
"clientAffinityEnabled": false,
"reserved": false
}
}
]
}
However, this is not overriding existing appSettings. Instead, it returns an error "Web site already exists"
Is there any method to override appSettings as explained above and restart the function app in order to affect new appSettings parameters.
Per my test, your template works fine on my side.
Just some information for you to refer.
This is my function app:
Test the template in the portal:
Deploy result:
Check in the portal:
Note: It will overwrite all the settings of the app, before the deployment, there were other settings in my app, currently, there are just two settings.
Besides, instead of using ARM template, I recommend you to use REST API, essentially, the template is also calling API. You could also use powershell to do it, here is a similar post, you could refer to it.
For anyone coming across this, it is possible to override the Microsoft.Web/sites resource's app settings with an arm template (might be important for some buildout situations, to avoid having to use scripts in addition to arm templates):
Create the app settings as an outer child resource:
"resources": [
{
"type": "Microsoft.Web/sites",
"kind": "functionapp",
"name": "[parameters('name')]",
"apiVersion": "2016-03-01",
"location": "[parameters('location')]",
"properties": {
"name": "[parameters('name')]",
"clientAffinityEnabled": false,
"reserved": false
}
},
{
"name": "[concat(parameters('name'), '/', 'appsettings')]",
"type": "Microsoft.Web/sites/config",
"apiVersion": "2018-11-01",
"dependsOn": [
"[resourceId('Microsoft.Web/sites',parameters('name'))]"
],
"properties": {
"schedule1": "[parameters('schedule1')]",
"schedule2": "[parameters('schedule2')]"
}
}
]
That way it isn't detected as an override to the website and thus allowed to be deployed.
I have an existing Service Bus with one queue and event hub deployed using Azure Resource Manager.
Now I am interested to retrieve the primary key and connection string using Azure PowerShell wiithout using the ServiceBus.dll. Is it possible??
As a workaround I have created an ARM template which does not deploy anything but just query the existing resource and retrieve the information I need. The below template retrieves the connection string and primary key of an event hub/queue for a specific service bus namespace
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"serviceBusNamespace": {
"type": "string",
"minLength": 1,
"metadata": {
"description": "The name of the service bus namespace to create."
}
},
"resourceName": {
"type": "string",
"minLength": 1,
"metadata": {
"description": "The name of the resource to be retreived."
}
},
"resourceType": {
"type": "string",
"minLength": 1,
"allowedValues": [
"queues",
"eventhubs"
],
"metadata": {
"description": "The type of the resource"
}
},
"policy": {
"type": "string",
"minLength": 1,
"defaultValue": "ManagePolicy",
"allowedValues": [
"ManagePolicy",
"SendPolicy",
"ListenPolicy"
],
"metadata": {
"description": "The type of the resource"
}
}
},
"variables": {
},
"resources": [ ],
"outputs": {
"connectionString": {
"type": "string",
"value": "[listKeys(resourceId(concat('Microsoft.ServiceBus/namespaces/',parameters('resourceType'),'/authorizationRules'),parameters('serviceBusNamespace'),parameters('resourceName'),parameters('policy')),'2015-08-01').primaryConnectionString]"
},
"primaryKey": {
"type": "string",
"value": "[listKeys(resourceId(concat('Microsoft.ServiceBus/namespaces/',parameters('resourceType'),'/authorizationRules'),parameters('serviceBusNamespace'),parameters('resourceName'),parameters('policy')),'2015-08-01').primaryKey]"
}
}
}
Is it abusing to use ARM template to query for a resource and not actually deploy anything?
EDIT
To capture the output of the ARM template within PowerShell use the below code
$ep = New-AzureRmResourceGroupDeployment -Name "getEventHub" -ResourceGroupName myResourceGroup -Mode Incremental -TemplateFile getEventHub.json -TemplateParameterFile getEventHub.param.json
$RuleConnString = $ep.Outputs.connectionString.value
$RulePrimaryKey = $ep.Outputs.primaryKey.value
Note that the property names connectionString and primaryKey are same as defined in my template file
EDIT 2
If I re-run the ARM template to deploy the event hub second time I get the below error.
I din't find any option other than to use the ARM template to query the details.
I don’t see what’s wrong with what you’re doing. In my view Resource Manager templates in their nature are incremental. So you could author a template to create your existing service bus with the same resources. If the properties are the same then it will leave the existing resources intact and return you the connection string and primary key of the relevant resource.
I have a need to automate the creation of a service bus and queue and separate send/listen shared access policies. You can retrieve the connection string on the service bus itself using PowerShell natively without using the .Net ServiceBus.dll assembly by using Get-AzureSBAuthorizationRule but due to a still current bug this doesn’t work at the queue level.
I tried using the ServiceBus.dll to create the shared access policies but sometimes it would randomly fail but subsequently work if you ran it a second time immediately afterwards. I also tried Resource Manager templates but previously you had to pass in the keys you’d generated yourself. Now I see Microsoft generate those for you but you’re still left trying to get the key in an automated fashion so I like your solution.
One question though, can you capture the Resource Manager template outputs and pass them back to a PowerShell script, do you know?
Cheers
Rob
{ "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": {
"servicebusNamespace": {
"type": "string",
"metadata": {
"description": "The service bus namespace"
}
},
"notificationssmsqueue": {
"type": "string",
"metadata": {
"description": "Notifications SMS queue"
}
} }, "variables": {
"location": "[resourceGroup().location]", }, "resources": [
{
"apiVersion": "2015-08-01",
"name": "[parameters('servicebusNamespace')]",
"type": "Microsoft.ServiceBus/namespaces",
"location": "[variables('location')]",
"properties": {
"messagingSku": 2
},
"resources": [
{
"apiVersion": "2015-08-01",
"name": "[parameters('notificationssmsqueue')]",
"type": "Queues",
"dependsOn": [
"[concat('Microsoft.ServiceBus/namespaces/', parameters('servicebusNamespace'))]"
],
"properties": {
"path": "[parameters('notificationssmsqueue')]"
},
"resources": [
{
"apiVersion": "2015-08-01",
"name": "[concat(parameters('notificationssmsqueue'),'.listen')]",
"type": "AuthorizationRules",
"dependsOn": [
"[parameters('notificationssmsqueue')]"
],
"properties": {
"keyName": "[concat(parameters('notificationssmsqueue'),'.listen')]",
"claimType": "SharedAccessKey",
"claimValue": "None",
"rights": [ "Listen" ],
"revision": -1
}
},
{
"apiVersion": "2015-08-01",
"name": "[concat(parameters('notificationssmsqueue'),'.send')]",
"type": "AuthorizationRules",
"dependsOn": [
"[parameters('notificationssmsqueue')]"
],
"properties": {
"keyName": "[concat(parameters('notificationssmsqueue'),'.send')]",
"claimType": "SharedAccessKey",
"claimValue": "None",
"rights": [ "Send" ],
"revision": -1
}
}
]
}
]
} ], "outputs": {
"connectionString": {
"type": "string",
"value": "[listKeys(resourceId(concat('Microsoft.ServiceBus/namespaces/AuthorizationRules'),parameters('serviceBusNamespace'),'RootManageSharedAccessKey'),'2015-08-01').primaryConnectionString]"
},
"smsSendPrimaryKey": {
"type": "string",
"value": "[listKeys(resourceId(concat('Microsoft.ServiceBus/namespaces/Queues/AuthorizationRules'),parameters('serviceBusNamespace'),parameters('notificationssmsqueue'),concat(parameters('notificationssmsqueue'),'.send')),'2015-08-01').PrimaryKey]"
},
"smsListenPrimaryKey": {
"type": "string",
"value": "[listKeys(resourceId(concat('Microsoft.ServiceBus/namespaces/Queues/AuthorizationRules'),parameters('serviceBusNamespace'),parameters('notificationssmsqueue'),concat(parameters('notificationssmsqueue'),'.listen')),'2015-08-01').PrimaryKey]"
} } }
But I call my templates like this:
New-AzureRMResourceGroupDeployment -ResourceGroupName $ResourceGroupName -TemplateFile "$scripts_folder$SB_create_script" -TemplateParameterObject `
#{ servicebusNamespace = $servicebusNamespace;
notificationssmsqueue = $NotificationSMSqueue }
This is the correct way to get the information you are seeking. The Resource Manager provides a common interface to interact with all the services. It is how the Portal access the services, and each of the language SDKs are just wrappers for similar requests to the one you have created.
I usually use the Python or java SDKs, but I have been told that NodeJS is a very easy way to wrap the Web APIs that ARM calls to construct similar calls like the one you made, if you are looking for a none ARM way to do this.