ARM Template: how to read output result in array format - azure

I posted some question on stackoverflow and would like to thanks those who take time to answer.
Although it exists documentation, i still face an issue related to output feature.
Basically I understand how to retrieve data when format is string.
Unfortunately when data is on array format it looks more difficult for me.
"outputs": {
"keyVaultName": {
"type": "string",
"value": "[variables('keyVaultName')]"
},
"websitesname": {
"type": "array",
"copy": {
"count": "[length(variables('webSitesName'))]",
"input": {
"name": "[variables('webSitesName')[copyIndex()].name]"
}
}
}
}
Then i do this:
$deploymentResult = New-AzResourceGroupDeployment -Name $deploymentName -ResourceGroupName
$ResourceGroupName-TemplateFile $TemplateFile
$vaultName = $deploymentResult.Outputs.keyVaultName.Value
$arrayWebsitesName = $deploymentResult.Outputs.websitesname.Value
I need to extract value from returned array. In powershell i expected to use something like
$arrayWebsitesName[0] to get AppService-Prod-CentralUS
$arrayWebsitesName[\1] to get AppService-Prod-EastUS
I believe there is something related to conversion and I tried convertto-json without success.
Your help is appreciated !

The variable type returned from the deployment for websitesname is a JArray.
PS> $deploymentResult.Outputs.websitesname.Value.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True False JArray Newtonsoft.Json.Linq.JContainer
In order to get at the values, you would make the call like:
$arrayWebsitesName = $deploymentResult.Outputs.websitesname.Value
$ids = $arrayWebsitesName.ToString() | ConvertFrom-Json
$ids[0].name
$ids[1].name
Converting the JArray to a JSON string, and then converting the JSON string to a PowerShell array may not be most efficient but I don't typically deal with large arrays and performance is not a concern (gets the job done).

Related

How to assign json file's content to a variable using powershell

I trying to run below PowerShell script to add azure data factory data sets. But im getting motioned error.
Json File
{
"name": "DSNAME",
"properties": {
"linkedServiceName": {
"referenceName": "REGNAME1",
"type": "LinkedServiceReference"
},
"annotations": [],
"type": "AzureDataExplorerTable",
"schema": [],
"typeProperties": {
"table": "TABLE_TEST"
}
},
"type": "Microsoft.DataFactory/factories/datasets"
}
Powershell
az config set extension.use_dynamic_install=yes_without_prompt
Get-ChildItem "ADF_DATASETS/" -Filter *.json |
Foreach-Object {
$content = Get-Content $_.FullName
az datafactory dataset create --properties $content --name "DATASETNAME" --factory-name "ADFNAME" --resource-group "RG_TEST"
}
Error:
Error detail: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
Please provide a valid JSON file path or JSON string.
The provided JSON string may have been parsed by the shell. See https://docs.microsoft.com/cli/azure/use-cli-effectively#use-quotation-marks-in-arguments
ERROR: Failed to parse string as JSON:
What kind of text --properties expect?
It is expecting JSON string in double quotation marks. So you have to put the value of $content inside the double quotation mark.
az datafactory dataset create --properties "{\"type\":\"AzureBlob\",\"linkedServiceName\":{\"type\":\"LinkedServiceReference\",\"referenceName\":\"exampleLinkedService\"},\"parameters\":{\"MyFileName\":{\"type\":\"String\"},\"MyFolderPath\":{\"type\":\"String\"}},\"typeProperties\":{\"format\":{\"type\":\"TextFormat\"},\"fileName\":{\"type\":\"Expression\",\"value\":\"#dataset().MyFileName\"},\"folderPath\":{\"type\":\"Expression\",\"value\":\"#dataset().MyFolderPath\"}}}" --name "exampleDataset" --factory-name "exampleFactoryName" --resource-group "exampleResourceGroup"

Reference Azure ARM template output variable from same deployment in another output variable

In an ARM Template, I have two output variables which are built by concating some strings. So, for the sake of it, let's just say it looks like this
"outputs": {
"firstKey": {
"type": "string",
"value": "[concat('first', 'Key')]"
},
"secondKey": {
"type": "string",
"value": "[concat('second', 'Key')]"
}
}
I now want to introduce a variable that concats these strings, like this
"bothKeys": {
"type": "string",
"value": "[concat('FirstKey=', outputs(firstKey), ';', 'SecondKey=', outputs(secondKey)]"
}
so I basically get these outputs
firstKey = firstKey
secondKey = secondKey
bothKeys = FirstKey=firstKey;SecondKey=secondKey
How would I do this?
I found various solutions to reference output variables from different deployments like [reference('deploymentName').outputs.propertyName.value] or [reference(resourceId('randomResource', variables('ResourceName'))).downloadLocation], but these are for referncing the outputs of OTHER deployments, where I want it from the same deployment.
Of course I could just copy paste the concat string but when I would edit one, I'd have to edit others as well. Is there a better way?
I couldn't find how to reference other output variables in the documentation listed here
https://learn.microsoft.com/en-us/azure/azure-resource-manager/templates/outputs?tabs=azure-powershell
https://learn.microsoft.com/en-us/azure/azure-resource-manager/templates/syntax#outputs

Azure resource graph query re-write default tag response

I am trying to alter the default response of Azure Resource graph query into similar that Azure portal uses. My query is:
resourcecontainers | where type == "microsoft.resources/subscriptions" | project name, tags
From where the response for tags is:
"tags": {
"TagA": "TeamA",
"TagB": "TeamB",
"TagC": "TeamC"
},
I would like to alter this into:
"tags": [
{
"name": "TagA",
"value": "TeamA"
},
{
"name": "TagB",
"value": "TeamB"
},
{
"name": "TagC",
"value": "TeamC"
}
]
How to do it? All examples I have found are either for only one tag or static set of tags. Mine would need to support dynamic amount of tags.
As you have confirmed to achieve the above requirement we can do it using the below query
resourcecontainers
| where type =~ 'microsoft.resources/subscriptions'
| mvexpand parsejson(tags)
| extend tagname = tostring(bag_keys(tags)[0])
| extend tagvalue = tostring(tags[tagname])
| project name, tagname, tagvalue
Output:-
For more information please refer this BLOG

Error in ARM template function in Release-Pipeline

I have an issue with a ARM template in which I replace a certain part with a template function. This happens during the execution of the release pipeline. The ARM template is installed by a Azure Powershell Script which I added to the release pipeline.
Here is the relevant part throwing the error:
"parameters": {
"connections_office365_externalid": {
"defaultValue": "[concat(resourceGroup().id,'/providers')]/Microsoft.Web/connections/office365",
"type": "String"
},
"connections_sql_externalid": {
"defaultValue": "[concat(resourceGroup().id, '/providers')]/Microsoft.Web/connections/sql25",
"type": "String"
}
},
When it comes to the deployment of the ARM template I get the following error:
> Status Message: Property id '[concat(resourceGroup().id,
> '/providers')]/Microsoft.Web/connections/office365' at path
> 'properties.parameters.$connections.value.office365.connectionId' is
> invalid. Expect fully qualified resource Id that start with
> '/subscriptions/{subscriptionId}' or
> '/providers/{resourceProviderNamespace}/'.
> (Code:LinkedInvalidPropertyId)
It seems that the part with the template function is not executed because the function is not translated into the appropriate value.Does anybody know what could be the issue that this template function is not executed on runtime of the release pipeline?`
UPDATE:
This is how the DefaultValue Part is replaced prior deployment:
I replace a particular part of the string (regex) to have it dynamic
(Get-Content $file.FullName -Raw) -replace "\/subscriptions\/(.*?)\/resourceGroups\/customerPrefix(.*?)\/providers","[concat(resourceGroup().id, '/providers')]" | Set-Content $file.FullName
If you are setting up Connections through ARM templates for Logic Apps, go ahad and use this piece:
"office365_1": {
"id": "[concat(subscription().id, '/providers/Microsoft.Web/locations/', parameters('logicAppLocation'), '/managedApis/', 'office365')]",
"connectionId": "[resourceId('Microsoft.Web/connections', parameters('office365_1_Connection_Name'))]",
"connectionName": "[parameters('office365_1_Connection_Name')]"
}
You just need to change your replacing script a little bit to make it work. See below:
I have tested and found the expression [concat(resourceGroup().id,'/providers')]/Microsoft.Web/connections/office365 cannot be evaluated in the template.
The correct expression should be like below:
"defaultValue": "[concat(resourceGroup().id, '/providers', '/Microsoft.Web/connections/office365')]"
Since you want to replace a particular part of the string (regex) to have it dynamic. You can change your replacing script like:
(Get-Content $file.FullName -Raw) -replace "\/subscriptions\/(.*?)\/resourceGroups\/(.*?)\/providers(\/.*)`"",'[concat(resourceGroup().id, ''/providers'', ''$3'')]"' | Set-Content $file.FullName
Above script will replace relevant string to be like this "[concat(resourceGroup().id, '/providers', '/Microsoft.Web/connections/sql25')]",

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

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.

Resources