How to reference a parameter within a parameter in an ARM template? - azure

I can't seem to find any way to use the value of a parameter as part of another parameter in a parameter file for ARM templates:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"someCustomParam": {
"value": "desired value"
},
"tags": {
"value": {
"tag1": "[parameters('someCustomParam')]",
"tag2": "some tag value"
}
},
}
}
Notice how I want to use the value of a previous parameter for the value of another.
The value for "tag1" is simply the string and the value does not get substituted in from the parameter() function. I've tested this by using the Test-AzResourceGroupDeployment PowerShell cmdlet.
Is there any way I can do this?

You can do this using PowerShell. Before calling Test-AzResourceGroupDeployment you can get content of parameter file in PowerShell variable/object using
$ParameterObject = Get-Content ./ParameterFileName.json
Update required value like:
$ParameterObject.parameters.tags.value.tag1 = #Value to assign
Pass $parameterObject to -TemplateParameterObject parameter of Test-AzResourceGroupDeployment
------OR------
Convert $parameterObject to JSON using ConvertTo-Json and Save as temp.json and pass temp.json to -TemplateParameterFile [reference below]
$TempParameterFile = ( $ParametersObject | ConvertTo-Json -Depth 20 ) -replace "\\u0027", "'" -replace "\\u0026", "&" | Out-File $tmp -Force
and use $TempParameterFile for -TemplateParameterFile

You need to use variables.
In variables, you can use "[parameters('parameterName')]".
And you can use variables in a similar way as parameters : "[variables('variableName')]"
Update:
Here is a sample:
"parameters": {
"someCustomParam": {
"type": "string"
}
},
"variables": {
"tags": {
"tag1": "[parameters('someCustomParam')]",
"tag2": "some tag value"
}
}
And then you can use the variable in the resource of your template.

You can do this just like what you normally do when you reference a parameter, an example as following:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"paramOne": {
"value": "hello"
},
"paramTwo": {
"value": "[concat(parameters('paramOne'), '-', 'world)]"
}
}
}
the output value of 'paramTwo' will be 'hello-world'.
Hope this helps whoever wants to utilize referencing a parameter in a parameter in a parameter file.

Related

Deploying ARM template with Terraform results in datatype mismatch

I am attempting to deploy a resource with Terraform using an ARM template. I will give some simple sample code below that demonstrates the issue. I realize the code below is deploying a storage account and can be done in Terraform without an ARM template, but I am just providing a piece of simple code to demonstrate the problem. My real code is deploying a SQL Managed Instance which is much more complicated and likely just confuses the question.
Here is the main.tf:
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "2.41.0"
}
}
}
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "resourcegroup" {
location = "North Central US"
name = "test"
}
resource "azurerm_resource_group_template_deployment" "deployment" {
name = "test-${formatdate("YYYYMMDDhhmmss", timestamp())}"
resource_group_name = azurerm_resource_group.resourcegroup.name
deployment_mode = "Incremental"
template_content = file("template.json")
parameters_content = templatefile("parameters.json",
{
name = "vwtuvnpplzgelqey"
supportsHttpsTrafficOnly = true
}
)
}
Here is the ARM template.json file:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"name": {
"type": "string"
},
"supportsHttpsTrafficOnly": {
"type": "bool"
}
},
"variables": {},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2019-04-01",
"name": "[parameters('name')]",
"location": "northcentralus",
"sku": {
"name": "Standard_LRS"
},
"kind": "StorageV2",
"properties": {
"supportsHttpsTrafficOnly": "[parameters('supportsHttpsTrafficOnly')]"
}
}
]
}
Here is the ARM parameters.json file:
{
"name": {
"value": "${name}"
},
"supportsHttpsTrafficOnly": {
"value": "${supportsHttpsTrafficOnly}"
}
}
If I run terraform apply on this with just the name as a parameter and hard-code supportsHttpsTrafficOnly to a true value (e.g. "supportsHttpsTrafficOnly": true), it works perfectly and the storage account is successfully deployed. As soon as I change it to use the parameter for supportsHttpsTrafficOnly, it fails with the following error:
: Code="InvalidTemplate" Message="Deployment template validation failed: 'Template parameter JToken type is not valid. Expected 'Boolean'. Actual 'String'. Please see https://aka.ms/resource-manager-parameter-files for usage details.'." AdditionalInfo=[{"info":{"lineNumber":1,"linePosition":213,"path":"properties.template.parameters.supportsHttpsTrafficOnly"},"type":"TemplateViolation"}]
This error indicates that the value for supportsHttpsTrafficOnly is a string when it should be a boolean. I don't understand this error as I am clearly defining the type as bool in the template.json file.
What am I missing so that the value is interpreted as a bool value instead of a string?
It turns out this is actually an easy fix, if not an obvious one.
Apparently all parameters need to be defined as string and then use the ARM template conversion functions to convert to the correct type.
In the template.json, we would have this in the parameters section:
“supportsHttpsTrafficOnly”: {
“type”: “string”
}
And then in the resources section, convert the string to a boolean using a template conversion:
"properties": {
"supportsHttpsTrafficOnly": "[bool(parameters('supportsHttpsTrafficOnly'))]"
}
Then finally in main.tf, pass the value as a string:
parameters_content = templatefile("parameters.json",
{
name = "vwtuvnpplzgelqey"
supportsHttpsTrafficOnly = "true"
}
Per documentation: https://learn.microsoft.com/en-us/azure/azure-resource-manager/templates/template-syntax#data-types
When specifying boolean and integer values in your template, don't
surround the value with quotation marks. Start and end string values
with double quotation marks.
What you have in your code is "value": "${supportsHttpsTrafficOnly}". This probably interpreted as "value": "true" when you pass a var into it.
Switching to "value": ${supportsHttpsTrafficOnly} should fix your issue.
But if I were you, I would go for the heredoc way, which is also the one used in the example of in the provider docs: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/resource_group_template_deployment
So use:
...
template_content = <<TEMPLATE
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"variables": {},
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
...
TEMPLATE
}
instead of using a different .json file.

Concat variable with string in Azure ARM Template

I feel really dump right now but I just can't get this to work. Kind of new to ARM Templates so sorry for my ignorance.
I am trying to use a parameters.json with New-AzResourceGroupDeployment but I want to dynamically feed it in the VMName.
I am trying to use this for the NSG name:
"value": "[concat(variables('vmName'),'-nsg')]"
But I get back an error of:
New-AzResourceGroupDeployment: 6:39:21 AM - Error:
Code=InvalidResourceName; Message=Resource name
[concat(variables('vmName'),'-nsg')] is invalid. The name can be up to
80 characters long. It must begin with a word character, and it must
end with a word character or with ''. The name may contain word
characters or '.', '-', ''.
What am I missing?
Where do you use the Concat function? Because ARM template functions are only available in the ARM template itself, not in the .parameters.json file.
Edit as a response:
It really depends on the use case but I would do something like this in the main ARM template if the 'nsg' value does not change for the given ARM template. If it does then define a second parameter 'vmsuffix' and concat both parameters into the full VMname.
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"VmName": {
"type": "string",
"defaultValue": ""
}
},
"variables": {
"FullVmName": "[concat(parameters('VmName'), 'nsg')]"
},
"resources": [
{
...
## Use the [variables('FullVmName') somewhere here
}
]
}

ARM deployment multi-line string with escaped quotes

I am trying to deploy this ARM template
/* example_template.json */
{
"$schema": "https://schema.management.azure.com/schemas/2019-08-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"var": {
"type": "string",
"defaultValue": "
echo ${VARIABLE}
",
"metadata": {
"description": "some description"
}
}
},
"resources": [],
"outputs": {
"ouput": {
"type": "string",
"value": "[string(parameters('var'))]"
}
}
}
which successfully outputs what I want:
"outputs": {
"ouput": {
"type": "String",
"value": "\n echo ${VARIABLE}\n "
}
}
The problem is, if I am trying to use this in a bash script, $VARIABLE may have a space in it, hence I need to output to be
"outputs": {
"ouput": {
"type": "String",
"value": "\n echo \"${USER}\"\n "
}
}
to prevent argument splitting.
So, I have tried to edit my template to include the quotes
/* example_template.json */
{
"$schema": "https://schema.management.azure.com/schemas/2019-08-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"var": {
"type": "string",
"defaultValue": "
echo \"${VARIABLE}\"
",
"metadata": {
"description": "some description"
}
}
},
"resources": [],
"outputs": {
"ouput": {
"type": "string",
"value": "[string(parameters('var'))]"
}
}
}
Which gives me a validate and create error:
> az deployment group validate -f example_template.json -g resource-group-name
Failed to parse 'example_template.json', please check whether it is a valid JSON format
This seems to only happen with the multi-line string - if I put the whole defaultValue on a single line i.e.,
"defaultValue": "echo \"${VARIABLE}\""
it is successful again.
I need to use a multiline string as this variable is for a long deployment script which would be infeasible to put on one-line.
I believe this is a bug due to the parser only failing with the multiline string, but am unsure where to report it!
Does anyone know what a possible solution to this could be?
Thanks,
Akhil
Actually there is no significance to do multi-line manually like you did.
As you can see, the type of this "var" parameter is "string", so it should be a string in "defaultValue", thus the reason you got the error message. Even it worked without error when using PowerShell command like "New-AzDeployment" ,but the result is same.
As you want to "use a multiline string as this variable is for a long deployment script", you can try do this to make the defaultValue to be a string:
"parameters": {
"var": {
"type": "string",
"defaultValue": "VARIABLE={value1}\n echo \"${VARIABLE}\"",
"metadata": {
"description": "some description"
}
}
},
The output should be:
VARIABLE={value1}
echo "${VARIABLE}"
Actually az command is based on python, Power Shell command is based on c#, which made them parse json differently.
About how Azure CLI parse json, it starts reading defaultValue string with ", and cannot find the opposite " in the same line, then the error occurs.
About how Power Shell parse json, it starts reading defaultValue string with :, and read the whole content included in that :.
Deploy ARM template with Power Shell.

Template output evaluation skipped

If I try to deploy my arm Template (Something like this)
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"variables": {
"AAS": "TestAAS",
"AFU": "TestAFU",
},
"resources": [
//define some resource here
],
"outputs": {
"asName": {
"type": "string",
"value": "[variables('AAS')]"
},
"azureFunctionName": {
"type": "string",
"value": "[variables('AFU')]"
}}
}
if for any reason this isn't going well, I can not read output in Powershell. and I get the following message:
Template output evaluation skipped: at least one resource deployment operation failed. Please list deployment operations for details
what should I do so that the output parameters are passed to powershell script despite faulty execution
My Powershell code:
//Standard PowerShell code for Deploying ARM Template
try
{
Stop-AzureRmWebApp -ResourceGroupName $ResourceGroupName -Name $deployment.Outputs.item("AFU").value
Suspend-AzureRmAnalysisServicesServer -Name $deployment.Outputs.item("AAS").value -ResourceGroupName $ResourceGroupName
}
catch
{
Write-Host "error here"
}
You cant do anything here. Outputs are only being generated if there were no errors in the ARM Template flow. So you need your ARM Template to succeed to be able to retrieve those (doesn't matter which tool you use, API behind those is always the same one).

Pass hashtable as parametwr to ARM template from PowerShell

I would like to replace my parameter file and just give the parameter with powershell. My parameters file looks like this:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"subnets": {
"value": {
"settings": [
{
"name": "firstSubnet",
"addressPrefix": "10.0.0.0/24"
},
{
"name": "secondSubnet",
"addressPrefix": "10.0.1.0/24"
}
]
}
}
}
}
Which I try to override with:
-subnets {"settings":[{"name": "firstSubnet","addressPrefix": "10.0.0.0/24"},{"name": "secondSubnet","addressPrefix": "10.0.1.0/24"]}}
But I keep getting errors. What is the correct syntax for using hash table as parameter?
Your example is not a hash table. It's just an unquoted JSON string.
Hash tables are defined in PowerShell as
#{}
and arrays are
#()
So you'd be looking at constructing something that looks like this:
-subnets #{
settings = #(
#{
name = 'foo'
address = 'bar'
}
)
}
and so on.
You can use ConvertFrom-Json and ConvertTo-Json to convert JSON to/from PowerShell hash tables and arrays.

Resources