Azure ARM getting Values from variable - azure

i have to create an ARM template an currently im stucked in using the variables with extendend values.
I define the variables
"variables": {
"NetWorkID": "[resourceId('Microsoft.Network/virtualNetworks', parameters('virtualNetworkName'))]",
}
And now i want to get the first subnet of the virtual Network.
I don´t know how to get the value.
i tested this but this doesn´t work:
"subnet": {
"id": "[variables('NetWorkID().subnet.ID')]"
}
Can i get a hint how to work with these variables?

usually you refer to subnets using the syntax bellow.
What you can do is pass the virtualNetworkName and subnet1Name as parameters and use the resourceid() expression.
"subnet": {
"id": "[resourceId(parameters('virtualNetworkResourceGroup'), 'Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworkName'), parameters('subnet1Name'))]"
}
Another way to do this, if you refer to the same subnet accross the arm template, is to build this resourceid in the variables instead of the resources and then use the variable in the resources properties.
Example:
"variables": {
"subnetId": "[resourceId(parameters('virtualNetworkResourceGroup'), 'Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworkName'), parameters('subnet1Name'))]"
},
"resources": [
{
"type": "Microsoft.Network/privateEndpoints",
"apiVersion": "xxxx",
"name": "xxxxx",
"location": "xxxxx",
"properties": {
"privateLinkServiceConnections": [
{
"name": "xxxxx",
"properties": {
"privateLinkServiceId": "xxxxx",
"groupIds": [
"blob"
]
}
}
],
**"subnet": {
"id": "[variables('subnetId')]"
}**,
"customDnsConfigs": [
{
"fqdn": "xxxxxx"
}
]
}
}
]
You can also try to list the existing subnets using the reference() function
"subnetId":"[reference(resourceId('Microsoft.Network/virtualNetworks', variables('vnetName')), '2022-01-01', 'Full').properties.subnets]"

Related

Look up settings by key/name in Bicep?

I have a list of subnets defined in my *.parameter.json file.
"subnetAddressPrefixes": {
"value": [
{
"name": "primary",
"addressPrefix": "10.2.0.0/17"
},
{
"name": "APIManagementSubnet",
"addressPrefix": "10.2.246.0/24"
},
{
"name": "ApplicationGatewaySubnet",
"addressPrefix": "10.2.251.0/24"
}
]
}
I want to look this up inside my bicep using the name.
To access the value 'primary', I'm using a syntax like this one: subnetAddressPrefixes[0].name
I want to be able to look the value up by name using this or any other mechanism in Bicep.
subnetAddressPrefixes['primary']

Use of ARM template function "reference" in "dependsOn" fails with error: The template function 'reference' is not expected at this location

I am using output from a linked template in my ARM template for deployment below are my templates :
Link template :
"resources": [
{
"name": "[variables('clusterName')]",
"type": "Microsoft.Kusto/clusters",
"sku": {
"name": "Standard_D13_v2",
"tier": "Standard",
"capacity": 2
},
"apiVersion": "2020-09-18",
"location": "[parameters('location')]",
"properties": {
"trustedExternalTenants": [],
"optimizedAutoscale": {
"version": 1,
"isEnabled": true,
"minimum": 2,
"maximum": 10
},
"enableDiskEncryption": false,
"enableStreamingIngest": true,
"enablePurge": false,
"enableDoubleEncryption": false,
"engineType": "V3"
}
}
],
"outputs": {
"clusterNameResult": {
"type": "string",
"value": "[variables('clusterName')]"
}
}
Template using this linked template:
"resources": [
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2021-04-01",
"name": "linkedTemplate",
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[concat(uri(deployment().properties.templateLink.uri, 'Dataexplorer_Deployment_Template.json'))]",
"contentVersion": "1.0.0.0"
}
},
"copy": {
"name": "databasecopy",
"count": "[length(parameters('databaseNameList'))]"
}
},
{
"type": "Microsoft.Kusto/Clusters/Databases",
"apiVersion": "2020-09-18",
"name": "[variables('databaseNameList').databaseNames[copyIndex()]]",
"location": "[parameters('location')]",
"dependsOn": [
"[resourceId('Microsoft.Kusto/Clusters', reference('linkedTemplate').outputs['clusterNameResult'].value)]"
],
"kind": "ReadWrite",
"properties": {
"softDeletePeriod": "P5D",
"hotCachePeriod": "P1D"
},
"copy": {
"name": "databasecopy",
"count": "[length(parameters('databaseNameList'))]"
}
},
{
"type": "Microsoft.Kusto/Clusters/Databases/PrincipalAssignments",
"apiVersion": "2020-09-18",
"name": "[variables('databaseNameList').databaseNames[copyIndex()]]",
"dependsOn": [
"[resourceId('Microsoft.Kusto/Clusters/Databases', variables('databaseNameList').databaseNames[copyIndex()])]",
"[resourceId('Microsoft.Kusto/Clusters', reference('linkedTemplate').outputs['clusterNameResult'].value)]"
],
"properties": {
"principalId": "abc.def#gmail.com",
"role": "Viewer",
"principalType": "User",
"tenantId": "523547f7-9d12-45c5-9g15-2ysb44a3r2m4"
},
"copy": {
"name": "databasecopy",
"count": "[length(parameters('databaseNameList'))]"
}
}
]
I am refering to the cluster name deployed through template 1 in template 2 , specified at "dependsOn" but it fails with error The template resource 'adx-jtcjiot-dev-sea-adxdb001' at line '84' and column '9' is not valid: The template function 'reference' is not expected at this location.
Has anyone used reference functions for deployment like this, I want to keep cluster and database deployment separately as database creation might occur often at the same time i don't want to hardcode the clustername in the database template. Is there any other way to do it or to resolve this error.
Thanks in advance!
I'm not sure I understand why you want to keep those separate in the first place.
What about simply putting them together as in the example here: https://learn.microsoft.com/en-us/azure/data-explorer/automated-deploy-overview#step-3-create-an-arm-template-to-deploy-the-cluster?
Ultimately, dependsOn doesn't accept reference functions as appeared in the error message. My second thought was to find out resource name using resourceID function, but apparently that's not supported. So, instead I have defined the server name in variables and used it for database "name field"
Because you're depending on a resource being deployed in the same deployment, you don't need to define a resource id, or use a reference. You can just use the name of the resource deployment (as defined in the arm template), like this:
{
"type": "Microsoft.Resources/deployments",
"name": "linkedTemplate",
etc
},
{
"type": "Microsoft.Kusto/Clusters/Databases",
etc
"dependsOn": [
"linkedTemplate"
]
}
That will ensure that the deployment of the database will not start until the deployment of the Kusto cluster has been completed.

Where to see all possible properties for the resources for Azure Resource Manager templates?

In ARM templates, we configure multiple properties for a resource.
For example for AKS - (taken from AKS Quickstart template)
"resources": [
{
"type": "Microsoft.ContainerService/managedClusters",
"apiVersion": "2020-03-01",
"name": "[parameters('clusterName')]",
"location": "[parameters('location')]",
"properties": {
"dnsPrefix": "[parameters('dnsPrefix')]",
"agentPoolProfiles": [
{
"name": "agentpool",
"osDiskSizeGB": "[parameters('osDiskSizeGB')]",
"count": "[parameters('agentCount')]",
"vmSize": "[parameters('agentVMSize')]",
"osType": "[parameters('osType')]",
"storageProfile": "ManagedDisks"
}
],
"linuxProfile": {
"adminUsername": "[parameters('linuxAdminUsername')]",
"ssh": {
"publicKeys": [
{
"keyData": "[parameters('sshRSAPublicKey')]"
}
]
}
}
},
"identity": {
"type": "SystemAssigned"
}
}
]
As you can see, there are properties like dnsPrefix, agentPoolProfiles (and its sub properties like osDiskSizeGB), linuxProfile, etc
Where are these properties documented? Where can I find the list of all possible properties that I can configure for a resource?
You can find the relevant documentation in the ManagedClusterProperties object
The trick here is to get the resource name and you can find the relevant documentation from the ARM documentation by mapping the reosurce

Using secret from Azure KeyVault in Azure ARM Template

I have a template of container instance with container in azurecr.io
Is it possible to use an Azure Key Vault secret in an ARM Template?
The following examples do not work:
"imageRegistryCredentials": [
{
"server": "***.azurecr.io",
"username": "***",
"password": {
"reference": {
"keyVault": {
"id": "[resourceId(parameters('vaultSubscription'), parameters('vaultResourceGroupName'), 'Microsoft.KeyVault/vaults', parameters('vaultName'))]"
},
"secretName": "[parameters('secretName')]"
}
}
}
],
I have tried it with:
"resources": [
{
...
"properties": {
"parameters":{
"secretPassword": {
"type": "securestring",
"reference": {
"keyVault": {
"id": "[resourceId(parameters('vaultSubscription'), parameters('vaultResourceGroupName'), 'Microsoft.KeyVault/vaults', parameters('vaultName'))]"
},
"secretName": "[parameters('secretName')]"
}
}
},
And:
"imageRegistryCredentials": [
{
"server": "**.azurecr.io",
"username": "**",
"password": "[parameters('secretPassword')]"
}
],
Result:
"error": {
"code": "InvalidTemplate",
"message": "Unable to process template language expressions for resource '/subscriptions/**/resourceGroups/**/providers/Microsoft.ContainerInstance/containerGroups/**' at line '28' and co
lumn '9'. 'The template parameter 'secretPassword' is not found. Please see https://aka.ms/arm-template/#parameters for
usage details.'"
}
}'
So, I've created a workaround, which enables you to relatively simply use any keyvault secret in your template by using a publicly available template on github. See https://github.com/bobvandevijver/azure-arm-keyvault-secret-output for the example.
It would obviously be better if Microsoft just fixed this implementation, but it's something!
You can only use key vault reference in the parameters of the template (or nested template).
so you either need to move this part to the parameters section or move it to the nested template and use this as a parameter to the nested template. here is the sample to pass values from the kv to the nested template:
{
"apiVersion": "2017-05-10",
"name": "[concat('kvReference-', copyIndex())]",
"type": "Microsoft.Resources/deployments",
"copy": {
"name": "kvReference",
"count": 2
},
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "nested_template_uri"
},
"parameters": {
"cer": {
"reference": {
"keyVault": {
"id": "keyvaultId"
},
"secretName": "secretname"
}
}
}
}
},
and you can just use those inputs as parameters inside nested template

Azure ARM Template with VM and subnet

I have a resource group called network-rg containing a virtual network. I am trying to deploy a Virual Machine in a new resource group vm-rg. The VM should be connected to a new subnet on the vnet in network-rg. I am using one single ARM template with both the subnet and the VM and deploying to vm-rg. How do I specify the subnet in the ARM template when its vnet is in another resource group than the primary/default group for the deployment?
I would need to explicitly reference the vnet with the resource group. This would be similar to how a Network Interface deploy is referencing the subnet ID in its ipConfigurations properties list:
"apiVersion": "2015-05-01-preview",
"type": "Microsoft.Network/networkInterfaces",
"name": "[parameters('nicName')]",
"location": "[parameters('location')]",
"properties": {
"ipConfigurations": [{
"name": "ipconfig1",
"properties": {
"subnet": {
"id": "[variables('subnet1Ref')]"
}
}
}]
}
It seems you cannot create a subnet in another resource group in one template when you create a new resource group with resources. There no property for you to refer to the Vnet in another group.
If you really want to create a new subnet in another group in one template, you could take a look at linked and nested template. Hope this will help you.
You will need to add a variables (Resource in the template that references the parameter file) example below:
In the main.JSON file:
{
"name": "[parameters('networkInterfaceName')]",
"type": "Microsoft.Network/networkInterfaces",
"apiVersion": "2018-04-01",
"location": "[parameters('location')]",
"dependsOn": [
"[concat('Microsoft.Network/publicIpAddresses/', parameters('publicIpAddressName'))]"
],
"properties": {
"ipConfigurations": [
{
"name": "ipconfig1",
"properties": {
"subnet": {
"id": "[variables('subnetRef')]"
},
"privateIPAllocationMethod": "Dynamic",
"publicIpAddress": {
"id": "[resourceId(parameters('resourceGroupName'),'Microsoft.Network/publicIpAddresses', parameters('publicIpAddressName'))]"
}
}
}
],
"enableAcceleratedNetworking": true,
"networkSecurityGroup": {
"id": "[resourceId(parameters('nsgResourceGroupName'), 'Microsoft.Network/networkSecurityGroups', parameters('networkSecurityGroupName'))]"
}
}
}
Add the following variables in main.JSON:
{
"name": "[parameters('networkInterfaceName')]",
"type": "Microsoft.Network/networkInterfaces",
"apiVersion": "2018-04-01",
"location": "[parameters('location')]",
"dependsOn": [
"[concat('Microsoft.Network/publicIpAddresses/', parameters('publicIpAddressName'))]"
],
"properties": {
"ipConfigurations": [
{
"name": "ipconfig1",
"properties": {
"subnet": {
"id": "[variables('subnetRef')]"
},
"privateIPAllocationMethod": "Dynamic",
}
}
],
}
}
Then add the following parameters in the main.JSON file:
"parameters": {
"virtualNetworkName": {
"type": "string"
},
"subnetName": {
"type": "string"
},
In the main.parameters.json add the variable information:
"virtualNetworkName": {
"value": "<vnet name>"
},
"resourceGroupName": {
"value": "<whatever the rg is for the Network>"
},
"subnetName": {
"value": "<subnet name>"
},
Hope that helps.

Resources