Related
In most Azure resource private endpoints, I can configure them using a bicep script by calling 'Microsoft.Network/privateEndpoints'. With Purview, it has two kinds of private endpoints: the regular private endpoint and Ingestion private endpoint. When using the mentioned library, although I can create an endpoint, it is not shown under the Ingestion private endpoint connection name. If you do it through the portal, you will see that endpoint connection created there.
I also notice that there is another API named 'Microsoft.Purview/accounts/privateEndpointConnections' however, it only exposes two properties privateEndpoint.id and privateLinkServiceConnectionState - so this does not look like it will be appropriate to use either?
Therefore I wonder if anyone has tried to use Bicep to do the above? I realize that Purview Private endpoint is still under public preview so maybe there is no way to configure using Bicep yet. I also notice that we cannot export a Purview resource as an ARM template from the Azure Portal, so it leads me even more to believe that Bicep is not available for Purview? Just want to confirm with someone more knowledgeable in this before I decide to give up on it.
As Azure Purview is still In preview it is an evolving tool .
Below I am providing two ARM template one for Account and Portal endpoints and one for ingestion endpoints ( I have pasted here two ARM templates and there parametrized file)
Note :- Portal, Account and ingestion endpoint should be in same vnet and subnet
1-ARM template for Portal and account endpoint
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"location": {
"type": "String"
},
"privateEndpointName-account": {
"type": "String"
},
"privateEndpointName-portal": {
"type": "String"
},
"purview_account_externalid": {
"type": "String"
},
"targetSubResource-account": {
"type": "Array"
},
"targetSubResource-portal": {
"type": "Array"
},
"subnet": {
"type": "String"
},
"virtualNetworkName": {
"type": "String"
},
"privateDnsDeploymentName": {
"type": "String"
},
"virtualNetworkLinkName": {
"type": "String"
},
"privateDNS": {
"type": "String"
}
},
"resources": [
{
"type": "Microsoft.Network/privateEndpoints",
"apiVersion": "2020-03-01",
"name": "[parameters('privateEndpointName-account')]",
"location": "[parameters('location')]",
"tags": {
},
"properties": {
"subnet": {
"id": "[concat(resourceGroup().id, '/providers/Microsoft.Network/virtualNetworks/', parameters('virtualNetworkName'), '/subnets/', parameters('subnet'))]"
},
"privateLinkServiceConnections": [
{
"name": "[parameters('privateEndpointName-account')]",
"properties": {
"privateLinkServiceId": "[parameters('purview_account_externalid')]",
"groupIds": "[parameters('targetSubResource-account')]"
}
}
]
}
},
{
"type": "Microsoft.Network/privateEndpoints",
"apiVersion": "2020-03-01",
"name": "[parameters('privateEndpointName-portal')]",
"location": "[parameters('location')]",
"tags": {
},
"properties": {
"subnet": {
"id": "[concat(resourceGroup().id, '/providers/Microsoft.Network/virtualNetworks/', parameters('virtualNetworkName'), '/subnets/', parameters('subnet'))]"
},
"privateLinkServiceConnections": [
{
"name": "[parameters('privateEndpointName-portal')]",
"properties": {
"privateLinkServiceId": "[parameters('purview_account_externalid')]",
"groupIds": "[parameters('targetSubResource-portal')]"
}
}
]
}
},
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2017-05-10",
"name": "[parameters('privateDnsDeploymentName')]",
"dependsOn": [
"[parameters('privateEndpointName-portal')]",
"[parameters('privateEndpointName-account')]"
],
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"apiVersion": "2017-05-10",
"name": "[concat(parameters('privateDnsDeploymentName'), '-zone')]",
"type": "Microsoft.Resources/deployments",
"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/privateDnsZones",
"apiVersion": "2018-09-01",
"name": "[parameters('privateDNS')]",
"location": "global",
"tags": {
},
"properties": {
}
}
]
}
}
}
]
}
}
},
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2017-05-10",
"name": "[parameters('virtualNetworkLinkName')]",
"dependsOn": [
"[parameters('privateDnsDeploymentName')]"
],
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"apiVersion": "2017-05-10",
"name": "[concat(parameters('virtualNetworkLinkName'), '-link')]",
"type": "Microsoft.Resources/deployments",
"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/privateDnsZones/virtualNetworkLinks",
"apiVersion": "2018-09-01",
"name": "[concat(parameters('privateDNS'), '/', uniqueString(parameters('virtualNetworkName')))]",
"location": "global",
"properties": {
"virtualNetwork": {
"id": "[concat(resourceGroup().id, '/providers/Microsoft.Network/virtualNetworks/', parameters('virtualNetworkName'))]"
},
"registrationEnabled": false
}
}
]
}
}
}
]
}
}
},
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2017-05-10",
"name": "[concat(parameters('privateEndpointName-account'), '-', 'default')]",
"dependsOn": [
"[parameters('privateEndpointName-account')]",
"[parameters('privateDnsDeploymentName')]"
],
"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('privateEndpointName-account'), '/', 'default')]",
"location": "[parameters('location')]",
"properties": {
"privateDnsZoneConfigs": [
{
"name": "[parameters('privateDNS')]",
"properties": {
"privateDnsZoneId": "[concat(resourceGroup().id, '/providers/Microsoft.Network/privateDnsZones/', parameters('privateDNS'))]"
}
}
]
}
}
]
}
}
},
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2017-05-10",
"name": "[concat(parameters('privateEndpointName-portal'), '-', 'default')]",
"dependsOn": [
"[parameters('privateEndpointName-portal')]",
"[parameters('privateDnsDeploymentName')]"
],
"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('privateEndpointName-portal'), '/', 'default')]",
"location": "[parameters('location')]",
"properties": {
"privateDnsZoneConfigs": [
{
"name": "[parameters('privateDNS')]",
"properties": {
"privateDnsZoneId": "[concat(resourceGroup().id, '/providers/Microsoft.Network/privateDnsZones/', parameters('privateDNS'))]"
}
}
]
}
}
]
}
}
}
]}
2- Parameterized file for Account and Portal Endpoints
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"location": {
"value": "Type the location of endpoint here"
},
"privateEndpointName-account": {
"value": "Type the name of Account endpoint here"
},
"privateEndpointName-portal": {
"value": "Type the name of Portal Endpoint here"
},
"purview_account_externalid": {
"value": "Go to azure portal > Purview >Properties >Resource Id,This is resource ID of the Purview "
},
"targetSubResource-account": {
"value": [
"account"
]
},
"targetSubResource-portal": {
"value": [
"portal"
]
},
"subnet": {
"value": "Type the name subnet here "
},
"virtualNetworkName": {
"value": "Type the name of the virtual network here "
},
"privateDnsDeploymentName": {
"value": "privatelink.purview.azure.com"
},
"virtualNetworkLinkName": {
"value": ""
},
"privateDNS": {
"value": "privatelink.purview.azure.com"
}
}}
3-ARM Template for Ingestion Endpoint
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"ingestionEndpointName": {
"type": "String"
},
"purviewManagedRGId": {
"type": "String"
},
"virtualNetworksName": {
"type": "String"
},
"purviewManagedRGEventHubsNamespaceId": {
"type": "String"
},
"managedStorageAccountName": {
"type": "string"
},
"resourceGroupId": {
"type": "string"
},
"subnet": {
"type": "String"
},
"privateDnsZonesLinkBlob": {
"defaultValue": "privatelink.blob.core.windows.net",
"type": "String"
},
"privateDnsZonesLinkServicebus": {
"defaultValue": "privatelink.servicebus.windows.net",
"type": "String"
},
"privateDnsZonesLinkQueue": {
"defaultValue": "privatelink.queue.core.windows.net",
"type": "String"
}
},
"variables": {},
"resources": [
{
"type": "Microsoft.Network/privateEndpoints",
"apiVersion": "2020-11-01",
"name": "[concat(parameters('ingestionEndpointName'),'-blob')]",
"location": "eastus",
"tags": {
"ContactEmail": "<not defined, please set>",
"ContactName": "<not defined, please set>",
"Department": "<not defined, please set>",
"Environment": "SANDBOX",
"OwnerName": "<not defined, please set>",
"Project": "<not defined, please set>"
},
"properties": {
"privateLinkServiceConnections": [
{
"name": "[concat(parameters('ingestionEndpointName'),'-blob')]",
"properties": {
"privateLinkServiceId": "[concat(parameters('purviewManagedRGId'),'/providers/Microsoft.Storage/storageAccounts/',parameters('managedStorageAccountName'))]",
"groupIds": [
"blob"
],
"privateLinkServiceConnectionState": {
"status": "Approved",
"description": "Auto-Approved",
"actionsRequired": "None"
}
}
}
],
"manualPrivateLinkServiceConnections": [],
"subnet": {
"id": "[concat(parameters('resourceGroupId'),'/providers/Microsoft.Network/virtualNetworks/',parameters('virtualNetworksName'), '/subnets/',parameters('subnet'))]"
},
"customDnsConfigs": []
}
},
{
"type": "Microsoft.Network/privateEndpoints",
"apiVersion": "2020-11-01",
"name": "[concat(parameters('ingestionEndpointName'),'-namespace')]",
"location": "eastus",
"tags": {
"ContactEmail": "<not defined, please set>",
"ContactName": "<not defined, please set>",
"Department": "<not defined, please set>",
"Environment": "SANDBOX",
"OwnerName": "<not defined, please set>",
"Project": "<not defined, please set>"
},
"properties": {
"privateLinkServiceConnections": [
{
"name": "[concat(parameters('ingestionEndpointName'),'-namespace')]",
"properties": {
"privateLinkServiceId": "[parameters('purviewManagedRGEventHubsNamespaceId')]",
"groupIds": [
"namespace"
],
"privateLinkServiceConnectionState": {
"status": "Approved",
"description": "Auto-Approved",
"actionsRequired": "None"
}
}
}
],
"manualPrivateLinkServiceConnections": [],
"subnet": {
"id": "[concat(parameters('resourceGroupId'), '/providers/Microsoft.Network/virtualNetworks/',parameters('virtualNetworksName'), '/subnets/',parameters('subnet'))]"
},
"customDnsConfigs": []
}
},
{
"type": "Microsoft.Network/privateEndpoints",
"apiVersion": "2020-11-01",
"name": "[concat(parameters('ingestionEndpointName'),'-queue')]",
"location": "eastus",
"tags": {
"ContactEmail": "<not defined, please set>",
"ContactName": "<not defined, please set>",
"Department": "<not defined, please set>",
"Environment": "SANDBOX",
"OwnerName": "<not defined, please set>",
"Project": "<not defined, please set>"
},
"properties": {
"privateLinkServiceConnections": [
{
"name": "[concat(parameters('ingestionEndpointName'),'-queue')]",
"properties": {
"privateLinkServiceId": "[concat(parameters('purviewManagedRGId'),'/providers/Microsoft.Storage/storageAccounts/',parameters('managedStorageAccountName'))]",
"groupIds": [
"queue"
],
"privateLinkServiceConnectionState": {
"status": "Approved",
"description": "Auto-Approved",
"actionsRequired": "None"
}
}
}
],
"manualPrivateLinkServiceConnections": [],
"subnet": {
"id": "[concat(parameters('resourceGroupId'), '/providers/Microsoft.Network/virtualNetworks/',parameters('virtualNetworksName'), '/subnets/',parameters('subnet'))]"
},
"customDnsConfigs": []
}
},
{
"type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups",
"apiVersion": "2020-11-01",
"name": "[concat(parameters('ingestionEndpointName'),'-blob','/default')]",
"dependsOn": [
"[resourceId('Microsoft.Network/privateEndpoints', concat(parameters('ingestionEndpointName'),'-blob'))]"
],
"properties": {
"privateDnsZoneConfigs": [
{
"name": "privatelink-blob-core-windows-net",
"properties": {
"privateDnsZoneId": "[concat(parameters('resourceGroupId'),'/providers/Microsoft.Network/privateDnsZones/',parameters('privateDnsZonesLinkBlob'))]"
}
}
]
}
},
{
"type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups",
"apiVersion": "2020-11-01",
"name": "[concat(parameters('ingestionEndpointName'),'-namespace','/default')]",
"dependsOn": [
"[resourceId('Microsoft.Network/privateEndpoints', concat(parameters('ingestionEndpointName'),'-namespace'))]"
],
"properties": {
"privateDnsZoneConfigs": [
{
"name": "privatelink-servicebus-windows-net",
"properties": {
"privateDnsZoneId": "[concat(parameters('resourceGroupId'),'/providers/Microsoft.Network/privateDnsZones/',parameters('privateDnsZonesLinkServicebus'))]"
}
}
]
}
},
{
"type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups",
"apiVersion": "2020-11-01",
"name": "[concat(parameters('ingestionEndpointName'),'-queue','/default')]",
"dependsOn": [
"[resourceId('Microsoft.Network/privateEndpoints', concat(parameters('ingestionEndpointName'),'-queue'))]"
],
"properties": {
"privateDnsZoneConfigs": [
{
"name": "privatelink-queue-core-windows-net",
"properties": {
"privateDnsZoneId": "[concat(parameters('resourceGroupId'),'/providers/Microsoft.Network/privateDnsZones/',parameters('privateDnsZonesLinkQueue'))]"
}
}
]
}
}
]}
4- Parameterized file for Ingestion Endpoint template
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"ingestionEndpointName": {
"value": "Type the name of Ingestion Endpoint here"
},
"purviewManagedRGId": {
"value": "Go to azure portal > Purview> ManagedResource > Properties> Resource id This is the Resources ID of purview managed resource group"
},
"virtualNetworkName": {
"value": "Give the name of the Virtual network here"
},
"purviewManagedRGEventHubsNamespaceId": {
"value": "Go to azure portal > Purview>Managed Resource > Event Hubs namespace name>properties >Resource IDThis is Purview managed Event hub name space resources Id "
},
"managedStorageAccountName": {
"value": "Go to azure portal > Purview>Managed Resource > Storage Account"
},
"resourceGroupId": {
"value": "Go to azure portal > Purview> overview >resourceGroup"
},
"subnet": {
"value": "Give the name the subnet"
}
}}
I have an existing Event Grid Topic and want to add an Event Subscription to it, with an existing Azure Function endpoint.
To achieve this I am using Linked Templates. ARM Template validation passes, but deployment fails, with quite a peculiar error:
"InvalidResourceNamespace: "The resource namespace 'subscriptions' is invalid. (Code: InvalidResourceNamespace)"
Here's the raw error:
{
"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": "InvalidContentLink",
"message": "Unable to download deployment content from 'https://storagearmtpl.blob.core.windows.net/arm-tpl-service-cd-11111-artifacts/nestedtemplates/eventGridSubscriptionTemplate.json?sv=sasartifactsstring'. The tracking Id is '11111111'. Please see https://aka.ms/arm-deploy for usage details."
},
{
"code": "InvalidResourceNamespace",
"message": "The resource namespace 'subscriptions' is invalid."
}
]
}
Where sasartifactsstring is a valid artifacts locations sas token. (I'm assuming, it looks correct)
I understand that this error stems from the "type" of the resource in the template being invalid, but as you can see below, it's simply Microsoft.EventGrid/topics/providers/eventSubscriptions.
/nestedtemplates/eventGridSubscriptionTemplate.json
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"subscriptionName": {
"type": "string",
"metadata": {
"description": "Name of the event grid subscription"
}
},
"topicName": {
"type": "string",
"metadata": {
"description": "Event grid Topic Name to Subscribe."
}
},
"functionResourceGroupName": {
"type": "string",
"metadata": {
"description": "Resource group name for functionapp"
}
},
"functionAppName": {
"type": "string",
"metadata": {
"description": "function app name"
}
},
"subscriptionId": {
"type": "string",
"metadata": {
"description": "The id string of the Azure subscription"
}
},
"topicResourceGroupName": {
"type": "string",
"metadata": {
"description": "The name of the topic resource group"
}
}
},
"variables": {},
"resources": [
{
"name": "[concat(parameters('topicName'), '/Microsoft.EventGrid/', parameters('subscriptionName'))]",
"type": "Microsoft.EventGrid/topics/providers/eventSubscriptions",
"location": "[resourceGroup().location]",
"apiVersion": "2020-06-01",
"properties": {
"topic": "[concat('/subscriptions/', parameters('subscriptionId'), '/resourceGroups/', parameters('topicResourceGroupName'), 'providers/Microsoft.EventGrid/topics/', parameters('topicName'))]",
"destination": {
"endpointType": "AzureFunction",
"properties": {
"resourceId": "[concat('/subscriptions/', parameters('subscriptionId'), '/resourceGroups/', parameters('functionResourceGroupName'), '/providers/Microsoft.Web/sites/', parameters('functionAppName'), '/functions/HelloWorld')]",
"maxEventsPerBatch": 1,
"preferredBatchSizeInKilobytes": 64
}
},
}
},
"dependsOn": [
]
}
],
"outputs": {}
}
/azuredeploy.json
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"_artifactsLocation": {
"type": "string"
},
"_artifactsLocationSasToken": {
"type": "securestring"
},
"functionResourceGroupName": {
"type": "string"
},
"functionAppName": {
"type": "string"
},
"topicName": {
"type": "string"
},
"topicResourceGroupName": {
"type": "string"
},
"subscriptionId": {
"type": "string"
}
},
"variables": {
"templateFolder": "nestedtemplates",
"subscriptionTemplateFileName": "eventGridSubscriptionTemplate.json"
},
"resources": [
{
"name": "functionsubscription"
"type": "Microsoft.Resources/deployments",
"apiVersion": "2017-05-10"
"resourceGroup": "[parameters('topicResourceGroupName')]",
"dependsOn": [ ],
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[concat(parameters('_artifactsLocation'), '/', variables('templateFolder'), '/', variables('subscriptionTemplateFileName'), parameters('_artifactsLocationSasToken'))]",
"contentVersion": "1.0.0.0"
},
"parameters": {
"subscriptionName": {
"value": "FunctionSubscription"
},
"topicName": {
"value": "[parameters('topicName')]"
},
"functionResourceGroupName": {
"value": "[parameters('functionResourceGroupName')]"
},
"functionAppName": {
"value": "[parameters('functionAppName')]"
},
"topicResourceGroupName": {
"value": "[parameters('topicResourceGroupName')]"
},
"subscriptionId": {
"value": "[parameters('subscriptionId')]"
}
}
}
}
]
}
azure deploy parameters file
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
,
"functionResourceGroupName": {
"value": "functionResourceGroup"
},
"functionAppName": {
"value": "functionAppName"
},
"subscriptionId": {
"value": "1111111111"
},
"topicName": {
"value": "topicName"
},
"topicResourceGroupName": {
"value": "topicResourceGroup"
}
}
Really not sure what I'm doing wrong here. Worth noting that the first error is annoying as well and I'm not sure why it can't download the deployment content...
update/edit:
It's worth noting that the release is using Classic Azure Release Pipelines. And the error comes up during the release.
Looking into the deployment logs for the resource group, I was able to see that the deployment was trying to deploy an invalid resource, with the type starting "subscriptions/.....", so at least I know where the error is coming from. Still investigating what is causing this misread...
The cause of the odd 'subscriptions' error was due to the fact that I inserted a new resource into my resources list in my deployment (parent) ARM template, but not at the end of the list.
Once I put the deployment resource that references the new event grid subscription at the end of the resources list, the error did not show up.
azuredeploy.json
resources: [
{all other existing deployment resources ....},
{
"name": "functionsubscription"
"type": "Microsoft.Resources/deployments",
"apiVersion": "2017-05-10"
"resourceGroup": "[parameters('topicResourceGroupName')]",
"dependsOn": [ ],
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[concat(parameters('_artifactsLocation'), '/', variables('templateFolder'), '/', variables('subscriptionTemplateFileName'), parameters('_artifactsLocationSasToken'))]",
"contentVersion": "1.0.0.0"
},
"parameters": {
"subscriptionName": {
"value": "FunctionSubscription"
},
"topicName": {
"value": "[parameters('topicName')]"
},
"functionResourceGroupName": {
"value": "[parameters('functionResourceGroupName')]"
},
"functionAppName": {
"value": "[parameters('functionAppName')]"
},
"topicResourceGroupName": {
"value": "[parameters('topicResourceGroupName')]"
},
"subscriptionId": {
"value": "[parameters('subscriptionId')]"
}
}
}
}
]
However, I am still dealing with the InvalidContentLink error, the main problem of the question has been resolved.
I am trying to create a Log Analytics Workspace using an ARM template and a parameter files. I am also thinking to tag currrent time as CreatedOn tag for the resource.
Below is my ARM template-
{
"$schema": "http://schema.management.azure.com/schemas/2014-04-01-preview/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"LAWName": {
"type": "string"
},
"LocationName": {
"type": "string"
},
"SKUName": {
"type": "string"
},
"Tags": {
"type": "object"
}
},
"resources": [
{
"apiVersion": "2017-03-15-preview",
"name": "[parameters('LAWName')]",
"location": "[parameters('LocationName')]",
"tags": "[parameters('Tags')]",
"type": "Microsoft.OperationalInsights/workspaces",
"properties": {
"sku": {
"name": "[parameters('SKUName')]"
}
}
}
]
}
and here is my param file-
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"LAWName": {
"value": "atifmtest1"
},
"LocationName": {
"value": "westeurope"
},
"SKUName": {
"value": "pergb2018"
}
"Tags": {
"value": {
"CreatedBy": "Atif",
"CreatedOn": "[utcNow()]",
"Purpose": "Monitoring"
}
}
}
}
I read here https://learn.microsoft.com/en-us/azure/azure-resource-manager/templates/template-functions-date#utcnow that there is utcNow() function for ARM template but that is being considered as a string here and the current time does not appear as a tag for the resource.
What is the other way using which this can be achieved ?
Thanks in advance !!
Here is a working example:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"utcShort": {
"type": "string",
"defaultValue": "[utcNow('d')]"
},
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]"
}
},
"resources": [
{
"apiVersion": "2019-04-01",
"type": "Microsoft.Storage/storageAccounts",
"name": "[concat('storage', uniqueString(resourceGroup().id))]",
"location": "[parameters('location')]",
"tags": {
"Dept": "Finance",
"Environment": "Production",
"LastDeployed": "[parameters('utcShort')]"
},
"sku": {
"name": "Standard_LRS"
},
"kind": "Storage",
"properties": {}
}
]
}
Source.
Please follow the below steps for better results.
Add the utcShort in parameters and give a default value "[utcNow()]", Its not work from the parameters file. add utcShort into variables to make an object type. Follow the below steps.
"utcShort ": {
"type": "string",
"defaultValue": "[utcNow()]"
},
"resourceTags": {
"type": "object"
}
},
"variables":{
"createdDate": {
"createdDate": "[parameters('utcShort ')]"
}
},
Use this variable in Tags like below..
"tags": "[union(parameters('resourceTags'), variables('createdDate'))]"
I'm currently facing an issue with nested template.
When I'm applying my template (detail below), I get this answer from Azure:
Azure Error: InvalidTemplate
Message: Deployment template validation failed: 'The template reference 'sandbox.test.portal' is not valid: could not find template resource or resource copy with this name. Please see https://aka.ms/arm-template-expressions/#reference for usage details.'.
However, I don't really understand why I get this issue, because for the content inside the nested template, I used what they provide in the documentation here: https://github.com/Azure/azure-quickstart-templates/blob/master/101-azure-dns-new-zone/azuredeploy.json
My ARM template:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]",
"metadata": {
"description": "Location for all resources."
}
},
"newZoneName": {
"type": "string",
"defaultValue": "sandbox.test.portal",
"metadata": {
"description": "The name of the DNS zone to be created. Must have at least 2 segements, e.g. hostname.org"
}
},
"newRecordName": {
"type": "string",
"defaultValue": "www",
"metadata": {
"description": "The name of the DNS record to be created. The name is relative to the zone, not the FQDN."
}
}
},
"variables": {
"publicIPAddressName": "[concat(resourceGroup().name, '-pip')]",
},
"resources": [
{
"apiVersion": "2015-06-15",
"type": "Microsoft.Network/publicIPAddresses",
"name": "[variables('publicIPAddressName')]",
"location": "[parameters('location')]",
"properties": {
"publicIPAllocationMethod": "Dynamic",
"dnsSettings": {
"domainNameLabel": "[parameters('dnsLabelPrefix')]"
}
}
},
{
"apiVersion": "2017-05-10",
"name": "nestedTemplate",
"type": "Microsoft.Resources/deployments",
"resourceGroup": "my-rg",
"subscriptionId": "[subscription().subscriptionId]",
"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/dnszones",
"name": "[parameters('newZoneName')]",
"apiVersion": "2016-04-01",
"location": "global",
"properties": {
}
},
{
"type": "Microsoft.Network/dnszones/a",
"name": "[concat(parameters('newZoneName'), '/', parameters('newRecordName'))]",
"apiVersion": "2016-04-01",
"location": "global",
"dependsOn": [
"[parameters('newZoneName')]"
],
"properties": {
"TTL": 3600,
"ARecords": [
{
"ipv4Address": "1.2.3.4"
},
{
"ipv4Address": "1.2.3.5"
}
]
}
}
],
"outputs": {
"nameServers": {
"type": "array",
"value": "[reference(parameters('newZoneName')).nameServers]"
}
}
}
}
}
]
}
basically, you need to remove the outputs from the nested inline template, so remove this bit:
"outputs": {
"nameServers": {
"type": "array",
"value": "[reference(parameters('newZoneName')).nameServers]"
}
}
long story short, nested inline deployments are bad. dont use them.
alternatively move those to the parent template and do a real lookup:
reference(resourceId('Microsoft.Network/dnszones', parameters('newZoneName')))
You have several minor mistakes in your template:
Comma in variables '-pip')]",
Undefined parameter dnsLabelPrefix
The general mistake in nested outputs. When you use nested templates azure don't find it in your main template. Therefore you must use a reference function with identifier and API: "[reference(resourceId('Microsoft.Network/dnszones', parameters('newZoneName')), '2016-04-01').nameServers]".
I modified your template and validate in my subscription.
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"newZoneName": {
"type": "string",
"defaultValue": "sandbox.test.portal",
"metadata": {
"description": "The name of the DNS zone to be created. Must have at least 2 segements, e.g. hostname.org"
}
},
"newRecordName": {
"type": "string",
"defaultValue": "www",
"metadata": {
"description": "The name of the DNS record to be created. The name is relative to the zone, not the FQDN."
}
},
"dnsLabelPrefix": {
"type": "string",
"defaultValue": "[concat('dns',uniqueString(resourceGroup().name))]"
},
"nestedResourceGroup": {
"type": "string",
"defaultValue": "my-rg",
"metadata": {
"description": "my-rg"
}
}
},
"variables": {
"publicIPAddressName": "[concat(resourceGroup().name, '-pip')]"
},
"resources": [
{
"apiVersion": "2015-06-15",
"type": "Microsoft.Network/publicIPAddresses",
"name": "[variables('publicIPAddressName')]",
"location": "[resourceGroup().location]",
"properties": {
"publicIPAllocationMethod": "Dynamic",
"dnsSettings": {
"domainNameLabel": "[parameters('dnsLabelPrefix')]"
}
}
},
{
"apiVersion": "2017-05-10",
"name": "nestedTemplate",
"type": "Microsoft.Resources/deployments",
"resourceGroup": "[parameters('nestedResourceGroup')]",
"subscriptionId": "[subscription().subscriptionId]",
"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/dnszones",
"name": "[parameters('newZoneName')]",
"apiVersion": "2016-04-01",
"location": "global",
"properties": {
}
},
{
"type": "Microsoft.Network/dnszones/a",
"name": "[concat(parameters('newZoneName'), '/', parameters('newRecordName'))]",
"apiVersion": "2016-04-01",
"location": "global",
"dependsOn": [
"[resourceId('Microsoft.Network/dnszones', parameters('newZoneName'))]"
],
"properties": {
"TTL": 3600,
"ARecords": [
{
"ipv4Address": "1.2.3.4"
},
{
"ipv4Address": "1.2.3.5"
}
]
}
}
],
"outputs": {
"nameServers": {
"type": "array",
"value": "[reference(resourceId('Microsoft.Network/dnszones', parameters('newZoneName')), '2016-04-01').nameServers]"
}
}
}
}
}
]
}
Have a nice day!
I am using maintemplate and linked template for deployment. I want to print the output of linked template after deployment.
When I deploy the below template. I am getting the below error,
The template output 'vmpublicIPName' is not valid: The language
expression property 'publicIPName' doesn't exist, available properties
are ''.. (Code: DeploymentOutputEvaluationFailed)
How can I print the output of variables present in linked template?
Is there any way to print all the linked template deployment parameters values in main template?
storage.json
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"storageAccountName": {
"type": "string"
},
"storageAccountType": {
"type": "string",
"defaultValue": "Standard_LRS"
}
},
"variables": {
"location": "[resourceGroup().location]",
"resourceGroupName": "[resourceGroup().name]",
"subscriptionId": "[subscription().subscriptionId]"
},
"resources": [
{
"name": "[concat(parameters('storageAccountName'), '1rmtest')]",
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2015-06-15",
"location": "[variables('location')]",
"properties": {
"accountType": "[parameters('storageAccountType')]"
},
"tags": {
"BuildName": "StorageARM"
}
},
{
"apiVersion": "2017-03-01",
"name": "TestTemplate",
"type": "Microsoft.Resources/deployments",
"properties": {
"mode": "incremental",
"templateLink": {
"uri":"https://gist.githubusercontent.com/public-ip-template.json",
"contentVersion":"1.0.0.0"
},
"parameters": {
"publicIpAddressName": {
"value": "public-ip-test"
}
}
}
}
],
"outputs": {
"vmpublicIPName": {
"type": "object",
"value": "[reference('TestTemplate').outputs.publicIPName]"
},
"vmlocation": {
"type": "object",
"value": "[reference('TestTemplate').outputs.location]"
}
}
}
Linked template:-
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"publicIpAddressName": {
"type": "string"
}
},
"variables": {
"location": "[resourceGroup().location]",
"resourceGroupName": "[resourceGroup().name]"
},
"resources": [
{
"name": "[parameters('publicIpAddressName')]",
"type": "Microsoft.Network/publicIpAddresses",
"apiVersion": "2016-09-01",
"location": "[variables('location')]",
"properties": {
"publicIpAllocationMethod": "Static"
}
}
],
"outputs": {
"publicIPName": {
"type": "string",
"value": "[parameters('publicIpAddressName')]"
},
"location": {
"type": "string",
"value": "[variables('location')]"
}
}
}
Do you ensure your linked template URI is correct and accessible? According to this official document
The URI value for the linked parameter file cannot be a local file,
and must include either http or https.
I test in my lab, I only replace your URI such as below:
"templateLink": {
"uri":"https://gist.githubusercontent.com/Walter-Shui/d5387c0fc92f2e8df1c7157a2d5e54aa/raw/722d4a58107b2f617996ae237ceae445ef4342d9/test.json",
"contentVersion":"1.0.0.0"
},
Your template works for me.
How can I print the output of variables present in linked template?
Yes, this is possible. Just like your template.
Is there any way to print all the linked template deployment
parameters values in main template?
You could use Azure cli 2.0 to get linked parameter values.
az group deployment create --name shuitest1 --resource-group shuitest --template-file test.json --parameters '{"storageAccountName":{"value":"shuitest"}}'
{
"id": "/subscriptions/********/resourceGroups/shuitest/providers/Microsoft.Resources/deployments/shuitest1",
"name": "shuitest1",
"properties": {
"correlationId": "dbe16f35-0807-4627-b4b5-86c0a25c49ba",
"debugSetting": null,
"dependencies": [],
"mode": "Incremental",
"outputs": {
"vmlocation": {
"type": "Object",
"value": {
"type": "String",
"value": "centralus"
}
},
"vmpublicIPName": {
"type": "Object",
"value": {
"type": "String",
"value": "public-ip-test"
}
}
},
"parameters": {
"storageAccountName": {
"type": "String",
"value": "shuitest"
},
"storageAccountType": {
"type": "String",
"value": "Standard_LRS"
}
},
"parametersLink": null,
"providers": [
{
"id": null,
"namespace": "Microsoft.Storage",
"registrationState": null,
"resourceTypes": [
{
"aliases": null,
"apiVersions": null,
"locations": [
"centralus"
],
"properties": null,
"resourceType": "storageAccounts"
}
]
},
{
"id": null,
"namespace": "Microsoft.Resources",
"registrationState": null,
"resourceTypes": [
{
"aliases": null,
"apiVersions": null,
"locations": [
null
],
"properties": null,
"resourceType": "deployments"
}
]
}
],
"provisioningState": "Succeeded",
"template": null,
"templateLink": null,
"timestamp": "2017-04-19T02:09:55.064156+00:00"
},
"resourceGroup": "shuitest"
}
"someName": {
"type": "string",
"value": "[variables('somevar')]"
},
The same way you are outputting parameters.
No there is no way of doing that.
So what is the question, your template looks good. I've tested it and it works
ps. the link on your template is wrong, that's the only thing that doesn't work