TL; DR Как мне программно найти объект, который может не находиться в одном и том же месте для каждого файла, и удалить его?
Хорошо, если я точно знаю, где объект будет находиться внутри JSON, но если он меняет местоположение, это сложно написать в сценарии. На данный момент мы программно создаем шаблон ARM и отправляем его в Azure, но прежде чем мы это сделаем, мы сравниваем его, чтобы увидеть, что версия в облаке отличается от только что сгенерированного файла, и если это так, либо заменяем его, либо создаем новый на основе по его версии.
Проблема заключается в том, что спецификация шаблона создается с новой версией Bicep, которая затем вводит эту информацию в файл JSON, который затем корректирует значения version
и templateHash
. К сожалению, я не могу предотвратить это.
"metadata": {
"_generator": {
"name": "bicep",
"version": "0.4.1008.15138",
"templateHash": "17593852815978663805"
}
Раньше я делал Compare-Object
для сравнения двух файлов после превращения их в объекты PowerShell, но когда пришло бинарное изменение, эта идея была отброшена. Затем я начал искать более сложное сравнение PowerShell, где оно будет игнорировать строки на основе шаблонов, но сегодня утром это не удалось из-за какой-то случайной ошибки, которую я не могу диагностировать, потому что она находится в конвейере Azure DevOps.
Write-Host "`n`n##[debug]?`tLooking for changes ?"
$bicepAlteredLines = @()
$templateSpecChange = $false
$patterns = @(
'\"version\"'
'\"templateHash\"'
)
# newFile (${currentDir}.json) goes into old oldFile (portal.json)
$compare = Compare-Object `
-ReferenceObject $(Get-Content -Path "./portal.json") `
-DifferenceObject $(Get-Content -Path "./${currentDir}.json")
# find the values where new goes into old
foreach($result in ($compare | Where-Object { $_.SideIndicator -eq "=>" })) {
# loop over patterns that should be excluded because of bicep binary update
foreach($pattern in $patterns) {
# for each bicep binary metadata pattern, check to see if the difference line matches that pattern
if ($result.InputObject -match $pattern) {
# create variable of old oldFile which is referenced on the same line
$comparedResult = $compare |
Where-Object {
($_.SideIndicator -eq "< = ") -and
($_.InputObject.ReadCount -eq $result.InputObject.Readcount)
}
# check to see if the variable also contains the pattern that should be excluded
if ($comparedResult.InputObject -match $pattern) {
$selectSearch = Select-String -Path "./${currentDir}.json" -Pattern $pattern -Context 2 |
Where-Object {
$_.LineNumber -eq $result.InputObject.Readcount
}
# validate if the pattern relates to bicep and not just random string that looks like what we want
foreach($item in $selectSearch) {
# we do this by checking the lines above the pattern, as this will contain the word 'bicep':
# "metadata": {
# "_generator": {
# "name": "bicep",
# "version": "0.4.1008.15138", <- if this line was the pattern, 1 up contains 'bicep'
# "templateHash": "9914162448113979868" <- if this line was the pattern, 2 up contains 'bicep'
# }
foreach($bicepCheck in $item.Context.PreContext) {
if ($bicepCheck -match "bicep") {
# if 'bicep' has been found, add array for readout later
$bicepAlteredLines += $item.LineNumber
Write-Host "Bicep binary change found at line $($item.LineNumber) for pattern ${pattern}. Adding to ignore list."
}
else {
# if the variable doesn't contain 'bicep', then obviously there's been a change in the JSON layout
$templateSpecChange = $true
}
}
}
}
else {
# if the variable doesn't contain the pattern, then obviously there's been a change in the JSON layout
$templateSpecChange = $true
}
}
else {
# if the variable doesn't contain the pattern, then obviously there's been a change in the JSON layout
$templateSpecChange = $true
}
}
}
Write-Host "`nThe following lines are ignored due Bicep binary change:"
$bicepAlteredLines | Sort-Object -Unique
Write-Host "`n`n##[debug]?`tDifference found in file comparison = ${templateSpecChange}"
Так что я хотел бы либо;
{
"$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"metadata": {
"_generator": {
"name": "bicep",
"version": "0.4.1111.15138",
"templateHash": "asdfasdfasdf"
}
},
"parameters": {
"p_vnetPeeringsCompute": {
"type": "array",
"metadata": {
"description": "List of peerings to the virtual network."
}
},
"p_vnetPeeringsStorage": {
"type": "array",
"metadata": {
"description": "List of peerings to the virtual network."
}
},
"p_vnetPeeringsLinkFile": {
"type": "array",
"metadata": {
"description": "List of peerings to the virtual network."
}
},
"p_tags": {
"type": "object",
"defaultValue": {},
"metadata": {
"description": "List of tags applied to resources."
}
}
},
"functions": [],
"variables": {
"v_longLocation": "uksouth",
"v_shortLocation": "uks",
"v_templateDescription": "Azure Private DNS Template Spec",
"v_templateDisplayName": "privateDns",
"v_templateName": "privateDns",
"v_templateVersion": "2.0.0",
"v_templateTags": {
"tsName": "[variables('v_templateName')]",
"tsVersion": "[variables('v_templateVersion')]"
},
"v_tags": "[union(parameters('p_tags'), variables('v_templateTags'))]"
},
"resources": [
{
"type": "Microsoft.Resources/resourceGroups",
"apiVersion": "2021-01-01",
"name": "[format('{0}-{1}-compute-rsg', variables('v_shortLocation'), subscription().displayName)]",
"location": "[variables('v_longLocation')]",
"tags": "[variables('v_tags')]"
},
{
"type": "Microsoft.Resources/resourceGroups",
"apiVersion": "2021-01-01",
"name": "[format('{0}-{1}-link-rsg', variables('v_shortLocation'), subscription().displayName)]",
"location": "[variables('v_longLocation')]",
"tags": "[variables('v_tags')]"
},
{
"type": "Microsoft.Resources/resourceGroups",
"apiVersion": "2021-01-01",
"name": "[format('{0}-{1}-storage-rsg', variables('v_shortLocation'), subscription().displayName)]",
"location": "[variables('v_longLocation')]",
"tags": "[variables('v_tags')]"
},
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2020-06-01",
"name": "privateCompute",
"resourceGroup": "[format('{0}-{1}-compute-rsg', variables('v_shortLocation'), subscription().displayName)]",
"properties": {
"expressionEvaluationOptions": {
"scope": "inner"
},
"mode": "Incremental",
"parameters": {
"p_tags": {
"value": "[variables('v_tags')]"
},
"p_vnetPeeringsCompute": {
"value": "[parameters('p_vnetPeeringsCompute')]"
}
},
"template": {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"metadata": {
"_generator": {
"name": "bicep",
"version": "0.4.1008.15138",
"templateHash": "17593852815978663805"
}
},
"parameters": {
"p_tags": {
"type": "object",
"defaultValue": {},
"metadata": {
"description": "List of tags applied to resources."
}
},
"p_vnetPeeringsCompute": {
"type": "array",
"metadata": {
"description": "List of peerings to the virtual network."
}
}
},
"functions": [],
"resources": [
{
"type": "Microsoft.Network/privateDnsZones",
"apiVersion": "2020-06-01",
"name": "compute.bld.local",
"tags": "[parameters('p_tags')]",
"location": "Global"
},
{
"copy": {
"name": "vnl",
"count": "[length(parameters('p_vnetPeeringsCompute'))]"
},
"type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks",
"apiVersion": "2020-06-01",
"name": "[format('{0}/{1}', 'compute.bld.local', last(split(parameters('p_vnetPeeringsCompute')[copyIndex()].id, '/')))]",
"tags": "[parameters('p_tags')]",
"location": "Global",
"properties": {
"virtualNetwork": {
"id": "[parameters('p_vnetPeeringsCompute')[copyIndex()].id]"
},
"registrationEnabled": false
},
"dependsOn": [
"[resourceId('Microsoft.Network/privateDnsZones', 'compute.bld.local')]"
]
}
]
}
},
"dependsOn": [
"[subscriptionResourceId('Microsoft.Resources/resourceGroups', format('{0}-{1}-compute-rsg', variables('v_shortLocation'), subscription().displayName))]"
]
},
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2020-06-01",
"name": "privateLink",
"resourceGroup": "[format('{0}-{1}-link-rsg', variables('v_shortLocation'), subscription().displayName)]",
"properties": {
"expressionEvaluationOptions": {
"scope": "inner"
},
"mode": "Incremental",
"parameters": {
"p_vnetPeeringsLinkFile": {
"value": "[parameters('p_vnetPeeringsLinkFile')]"
},
"p_tags": {
"value": "[variables('v_tags')]"
}
},
"template": {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"metadata": {
"_generator": {
"name": "bicep",
"version": "0.4.1008.15138",
"templateHash": "14603239311913824090"
}
},
"parameters": {
"p_vnetPeeringsLinkFile": {
"type": "array",
"metadata": {
"description": "List of peerings to the virtual network."
}
},
"p_tags": {
"type": "object",
"defaultValue": {},
"metadata": {
"description": "List of tags applied to resources."
}
}
},
"functions": [],
"resources": [
{
"type": "Microsoft.Network/privateDnsZones",
"apiVersion": "2020-06-01",
"name": "[format('privatelink.file.{0}', environment().suffixes.storage)]",
"tags": "[parameters('p_tags')]",
"location": "Global"
},
{
"copy": {
"name": "vnl",
"count": "[length(parameters('p_vnetPeeringsLinkFile'))]"
},
"type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks",
"apiVersion": "2020-06-01",
"name": "[format('{0}/{1}', format('privatelink.file.{0}', environment().suffixes.storage), last(split(parameters('p_vnetPeeringsLinkFile')[copyIndex()].id, '/')))]",
"tags": "[parameters('p_tags')]",
"location": "Global",
"properties": {
"virtualNetwork": {
"id": "[parameters('p_vnetPeeringsLinkFile')[copyIndex()].id]"
},
"registrationEnabled": false
},
"dependsOn": [
"[resourceId('Microsoft.Network/privateDnsZones', format('privatelink.file.{0}', environment().suffixes.storage))]"
]
},
{
"type": "Microsoft.Network/privateDnsZones",
"apiVersion": "2020-06-01",
"name": "[format('privatelink{0}', environment().suffixes.sqlServerHostname)]",
"tags": "[parameters('p_tags')]",
"location": "Global"
}
]
}
},
"dependsOn": [
"[subscriptionResourceId('Microsoft.Resources/resourceGroups', format('{0}-{1}-link-rsg', variables('v_shortLocation'), subscription().displayName))]"
]
},
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2020-06-01",
"name": "privateStorage",
"resourceGroup": "[format('{0}-{1}-storage-rsg', variables('v_shortLocation'), subscription().displayName)]",
"properties": {
"expressionEvaluationOptions": {
"scope": "inner"
},
"mode": "Incremental",
"parameters": {
"p_tags": {
"value": "[variables('v_tags')]"
},
"p_vnetPeeringsStorage": {
"value": "[parameters('p_vnetPeeringsStorage')]"
}
},
"template": {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"metadata": {
"_generator": {
"name": "bicep",
"version": "0.4.1008.15138",
"templateHash": "12131108274222647600"
}
},
"parameters": {
"p_tags": {
"type": "object",
"defaultValue": {},
"metadata": {
"description": "List of tags applied to resources."
}
},
"p_vnetPeeringsStorage": {
"type": "array",
"metadata": {
"description": "List of peerings to the virtual network."
}
}
},
"functions": [],
"resources": [
{
"type": "Microsoft.Network/privateDnsZones",
"apiVersion": "2020-06-01",
"name": "storage.bld.local",
"tags": "[parameters('p_tags')]",
"location": "Global"
},
{
"copy": {
"name": "vnl",
"count": "[length(parameters('p_vnetPeeringsStorage'))]"
},
"type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks",
"apiVersion": "2020-06-01",
"name": "[format('{0}/{1}', 'storage.bld.local', last(split(parameters('p_vnetPeeringsStorage')[copyIndex()].id, '/')))]",
"tags": "[parameters('p_tags')]",
"location": "Global",
"properties": {
"virtualNetwork": {
"id": "[parameters('p_vnetPeeringsStorage')[copyIndex()].id]"
},
"registrationEnabled": false
},
"dependsOn": [
"[resourceId('Microsoft.Network/privateDnsZones', 'storage.bld.local')]"
]
}
]
}
},
"dependsOn": [
"[subscriptionResourceId('Microsoft.Resources/resourceGroups', format('{0}-{1}-storage-rsg', variables('v_shortLocation'), subscription().displayName))]"
]
}
]
}
На данный момент я знаю, что он находится в 2 стандартных местах, но я не уверен, появится ли он в других.
➜ $asdf.resources.properties.template.metadata
_generator
----------
@{name=bicep; version=0.4.1008.15138; templateHash=17593852815978663805}
@{name=bicep; version=0.4.1008.15138; templateHash=14603239311913824090}
@{name=bicep; version=0.4.1008.15138; templateHash=12131108274222647600}
compare
➜ $asdf.metadata
_generator
----------
@{name=bicep; version=0.4.1111.15138; templateHash=asdfasdfasdf}
Было бы лучше, если бы в PowerShell была возможность найти все экземпляры объектов с именем metadata
и удалить их, но я не могу найти такую опцию в PowerShell. Любые мысли/идеи были бы замечательны.
Прежде чем кто-либо упомянет, что я должен просто удалить все экземпляры $asdf.resources.properties.template.metadata
и $asdf.metadata
, мне интересно, как искать любые экземпляры *.metadata
, которые могут быть/могут быть в других местах, которые могут появиться или не появиться. Скорее «искать все *.metadata
и удалять из объекта, где бы он ни находился».
Либо PowerShell, либо JQ. Не JQuery.
Поскольку jq
помечен, вы можете использовать walk
для обхода документа JSON, и если он встречает объект, применить del
для удаления любого поля .metadata
:
jq 'walk(if type == "object" then del(.metadata) else . end)' file.json
{
"$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"p_vnetPeeringsCompute": {
"type": "array"
},
"p_vnetPeeringsStorage": {
"type": "array"
},
"p_vnetPeeringsLinkFile": {
"type": "array"
},
"p_tags": {
"type": "object",
"defaultValue": {}
}
},
"functions": [],
"variables": {
"v_longLocation": "uksouth",
"v_shortLocation": "uks",
"v_templateDescription": "Azure Private DNS Template Spec",
"v_templateDisplayName": "privateDns",
"v_templateName": "privateDns",
"v_templateVersion": "2.0.0",
"v_templateTags": {
"tsName": "[variables('v_templateName')]",
"tsVersion": "[variables('v_templateVersion')]"
},
"v_tags": "[union(parameters('p_tags'), variables('v_templateTags'))]"
},
"resources": [
{
"type": "Microsoft.Resources/resourceGroups",
"apiVersion": "2021-01-01",
"name": "[format('{0}-{1}-compute-rsg', variables('v_shortLocation'), subscription().displayName)]",
"location": "[variables('v_longLocation')]",
"tags": "[variables('v_tags')]"
},
{
"type": "Microsoft.Resources/resourceGroups",
"apiVersion": "2021-01-01",
"name": "[format('{0}-{1}-link-rsg', variables('v_shortLocation'), subscription().displayName)]",
"location": "[variables('v_longLocation')]",
"tags": "[variables('v_tags')]"
},
{
"type": "Microsoft.Resources/resourceGroups",
"apiVersion": "2021-01-01",
"name": "[format('{0}-{1}-storage-rsg', variables('v_shortLocation'), subscription().displayName)]",
"location": "[variables('v_longLocation')]",
"tags": "[variables('v_tags')]"
},
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2020-06-01",
"name": "privateCompute",
"resourceGroup": "[format('{0}-{1}-compute-rsg', variables('v_shortLocation'), subscription().displayName)]",
"properties": {
"expressionEvaluationOptions": {
"scope": "inner"
},
"mode": "Incremental",
"parameters": {
"p_tags": {
"value": "[variables('v_tags')]"
},
"p_vnetPeeringsCompute": {
"value": "[parameters('p_vnetPeeringsCompute')]"
}
},
"template": {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"p_tags": {
"type": "object",
"defaultValue": {}
},
"p_vnetPeeringsCompute": {
"type": "array"
}
},
"functions": [],
"resources": [
{
"type": "Microsoft.Network/privateDnsZones",
"apiVersion": "2020-06-01",
"name": "compute.bld.local",
"tags": "[parameters('p_tags')]",
"location": "Global"
},
{
"copy": {
"name": "vnl",
"count": "[length(parameters('p_vnetPeeringsCompute'))]"
},
"type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks",
"apiVersion": "2020-06-01",
"name": "[format('{0}/{1}', 'compute.bld.local', last(split(parameters('p_vnetPeeringsCompute')[copyIndex()].id, '/')))]",
"tags": "[parameters('p_tags')]",
"location": "Global",
"properties": {
"virtualNetwork": {
"id": "[parameters('p_vnetPeeringsCompute')[copyIndex()].id]"
},
"registrationEnabled": false
},
"dependsOn": [
"[resourceId('Microsoft.Network/privateDnsZones', 'compute.bld.local')]"
]
}
]
}
},
"dependsOn": [
"[subscriptionResourceId('Microsoft.Resources/resourceGroups', format('{0}-{1}-compute-rsg', variables('v_shortLocation'), subscription().displayName))]"
]
},
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2020-06-01",
"name": "privateLink",
"resourceGroup": "[format('{0}-{1}-link-rsg', variables('v_shortLocation'), subscription().displayName)]",
"properties": {
"expressionEvaluationOptions": {
"scope": "inner"
},
"mode": "Incremental",
"parameters": {
"p_vnetPeeringsLinkFile": {
"value": "[parameters('p_vnetPeeringsLinkFile')]"
},
"p_tags": {
"value": "[variables('v_tags')]"
}
},
"template": {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"p_vnetPeeringsLinkFile": {
"type": "array"
},
"p_tags": {
"type": "object",
"defaultValue": {}
}
},
"functions": [],
"resources": [
{
"type": "Microsoft.Network/privateDnsZones",
"apiVersion": "2020-06-01",
"name": "[format('privatelink.file.{0}', environment().suffixes.storage)]",
"tags": "[parameters('p_tags')]",
"location": "Global"
},
{
"copy": {
"name": "vnl",
"count": "[length(parameters('p_vnetPeeringsLinkFile'))]"
},
"type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks",
"apiVersion": "2020-06-01",
"name": "[format('{0}/{1}', format('privatelink.file.{0}', environment().suffixes.storage), last(split(parameters('p_vnetPeeringsLinkFile')[copyIndex()].id, '/')))]",
"tags": "[parameters('p_tags')]",
"location": "Global",
"properties": {
"virtualNetwork": {
"id": "[parameters('p_vnetPeeringsLinkFile')[copyIndex()].id]"
},
"registrationEnabled": false
},
"dependsOn": [
"[resourceId('Microsoft.Network/privateDnsZones', format('privatelink.file.{0}', environment().suffixes.storage))]"
]
},
{
"type": "Microsoft.Network/privateDnsZones",
"apiVersion": "2020-06-01",
"name": "[format('privatelink{0}', environment().suffixes.sqlServerHostname)]",
"tags": "[parameters('p_tags')]",
"location": "Global"
}
]
}
},
"dependsOn": [
"[subscriptionResourceId('Microsoft.Resources/resourceGroups', format('{0}-{1}-link-rsg', variables('v_shortLocation'), subscription().displayName))]"
]
},
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2020-06-01",
"name": "privateStorage",
"resourceGroup": "[format('{0}-{1}-storage-rsg', variables('v_shortLocation'), subscription().displayName)]",
"properties": {
"expressionEvaluationOptions": {
"scope": "inner"
},
"mode": "Incremental",
"parameters": {
"p_tags": {
"value": "[variables('v_tags')]"
},
"p_vnetPeeringsStorage": {
"value": "[parameters('p_vnetPeeringsStorage')]"
}
},
"template": {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"p_tags": {
"type": "object",
"defaultValue": {}
},
"p_vnetPeeringsStorage": {
"type": "array"
}
},
"functions": [],
"resources": [
{
"type": "Microsoft.Network/privateDnsZones",
"apiVersion": "2020-06-01",
"name": "storage.bld.local",
"tags": "[parameters('p_tags')]",
"location": "Global"
},
{
"copy": {
"name": "vnl",
"count": "[length(parameters('p_vnetPeeringsStorage'))]"
},
"type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks",
"apiVersion": "2020-06-01",
"name": "[format('{0}/{1}', 'storage.bld.local', last(split(parameters('p_vnetPeeringsStorage')[copyIndex()].id, '/')))]",
"tags": "[parameters('p_tags')]",
"location": "Global",
"properties": {
"virtualNetwork": {
"id": "[parameters('p_vnetPeeringsStorage')[copyIndex()].id]"
},
"registrationEnabled": false
},
"dependsOn": [
"[resourceId('Microsoft.Network/privateDnsZones', 'storage.bld.local')]"
]
}
]
}
},
"dependsOn": [
"[subscriptionResourceId('Microsoft.Resources/resourceGroups', format('{0}-{1}-storage-rsg', variables('v_shortLocation'), subscription().displayName))]"
]
}
]
}
Это действительно полезно. JQ — это мой запасной вариант, если PowerShell не может делать то, что я хочу, только из-за используемых нами агентов и того, как работают конвейеры. Сначала я буду болтаться, если кто-нибудь предложит исправление для PS.
В чистом PowerShell вы можете использовать рекурсивную функцию для очистки любого свойства "metadata"
от объектов на любой глубине вложенности.
function StripMetadata {
param($node)
if ($node -is [pscustomobject]) {
foreach ($prop in $node.PSObject.Properties) {
if ($prop.Name -eq "metadata") {
$node.PSObject.Properties.Remove($prop.Name)
} else {
StripMetadata $prop.Value
}
}
} elseif ($node -is [array]) {
foreach ($item in $node) {
StripMetadata $item
}
}
}
Обратите внимание, что это изменяет объект на месте, значение результата отсутствует.
$data = $yourJson | ConvertFrom-Json
StripMetadata $data
$result = $data | ConvertTo-Json -Depth 100 -Compress
$result
это (отформатировано):
{
"$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"p_vnetPeeringsCompute": {
"type": "array"
},
"p_vnetPeeringsStorage": {
"type": "array"
},
"p_vnetPeeringsLinkFile": {
"type": "array"
},
"p_tags": {
"type": "object",
"defaultValue": {}
}
},
"functions": [],
"variables": {
"v_longLocation": "uksouth",
"v_shortLocation": "uks",
"v_templateDescription": "Azure Private DNS Template Spec",
"v_templateDisplayName": "privateDns",
"v_templateName": "privateDns",
"v_templateVersion": "2.0.0",
"v_templateTags": {
"tsName": "[variables(\u0027v_templateName\u0027)]",
"tsVersion": "[variables(\u0027v_templateVersion\u0027)]"
},
"v_tags": "[union(parameters(\u0027p_tags\u0027), variables(\u0027v_templateTags\u0027))]"
},
"resources": [{
"type": "Microsoft.Resources/resourceGroups",
"apiVersion": "2021-01-01",
"name": "[format(\u0027{0}-{1}-compute-rsg\u0027, variables(\u0027v_shortLocation\u0027), subscription().displayName)]",
"location": "[variables(\u0027v_longLocation\u0027)]",
"tags": "[variables(\u0027v_tags\u0027)]"
}, {
"type": "Microsoft.Resources/resourceGroups",
"apiVersion": "2021-01-01",
"name": "[format(\u0027{0}-{1}-link-rsg\u0027, variables(\u0027v_shortLocation\u0027), subscription().displayName)]",
"location": "[variables(\u0027v_longLocation\u0027)]",
"tags": "[variables(\u0027v_tags\u0027)]"
}, {
"type": "Microsoft.Resources/resourceGroups",
"apiVersion": "2021-01-01",
"name": "[format(\u0027{0}-{1}-storage-rsg\u0027, variables(\u0027v_shortLocation\u0027), subscription().displayName)]",
"location": "[variables(\u0027v_longLocation\u0027)]",
"tags": "[variables(\u0027v_tags\u0027)]"
}, {
"type": "Microsoft.Resources/deployments",
"apiVersion": "2020-06-01",
"name": "privateCompute",
"resourceGroup": "[format(\u0027{0}-{1}-compute-rsg\u0027, variables(\u0027v_shortLocation\u0027), subscription().displayName)]",
"properties": {
"expressionEvaluationOptions": {
"scope": "inner"
},
"mode": "Incremental",
"parameters": {
"p_tags": {
"value": "[variables(\u0027v_tags\u0027)]"
},
"p_vnetPeeringsCompute": {
"value": "[parameters(\u0027p_vnetPeeringsCompute\u0027)]"
}
},
"template": {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"p_tags": {
"type": "object",
"defaultValue": {}
},
"p_vnetPeeringsCompute": {
"type": "array"
}
},
"functions": [],
"resources": [{
"type": "Microsoft.Network/privateDnsZones",
"apiVersion": "2020-06-01",
"name": "compute.bld.local",
"tags": "[parameters(\u0027p_tags\u0027)]",
"location": "Global"
}, {
"copy": {
"name": "vnl",
"count": "[length(parameters(\u0027p_vnetPeeringsCompute\u0027))]"
},
"type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks",
"apiVersion": "2020-06-01",
"name": "[format(\u0027{0}/{1}\u0027, \u0027compute.bld.local\u0027, last(split(parameters(\u0027p_vnetPeeringsCompute\u0027)[copyIndex()].id, \u0027/\u0027)))]",
"tags": "[parameters(\u0027p_tags\u0027)]",
"location": "Global",
"properties": {
"virtualNetwork": {
"id": "[parameters(\u0027p_vnetPeeringsCompute\u0027)[copyIndex()].id]"
},
"registrationEnabled": false
},
"dependsOn": ["[resourceId(\u0027Microsoft.Network/privateDnsZones\u0027, \u0027compute.bld.local\u0027)]"]
}]
}
},
"dependsOn": ["[subscriptionResourceId(\u0027Microsoft.Resources/resourceGroups\u0027, format(\u0027{0}-{1}-compute-rsg\u0027, variables(\u0027v_shortLocation\u0027), subscription().displayName))]"]
}, {
"type": "Microsoft.Resources/deployments",
"apiVersion": "2020-06-01",
"name": "privateLink",
"resourceGroup": "[format(\u0027{0}-{1}-link-rsg\u0027, variables(\u0027v_shortLocation\u0027), subscription().displayName)]",
"properties": {
"expressionEvaluationOptions": {
"scope": "inner"
},
"mode": "Incremental",
"parameters": {
"p_vnetPeeringsLinkFile": {
"value": "[parameters(\u0027p_vnetPeeringsLinkFile\u0027)]"
},
"p_tags": {
"value": "[variables(\u0027v_tags\u0027)]"
}
},
"template": {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"p_vnetPeeringsLinkFile": {
"type": "array"
},
"p_tags": {
"type": "object",
"defaultValue": {}
}
},
"functions": [],
"resources": [{
"type": "Microsoft.Network/privateDnsZones",
"apiVersion": "2020-06-01",
"name": "[format(\u0027privatelink.file.{0}\u0027, environment().suffixes.storage)]",
"tags": "[parameters(\u0027p_tags\u0027)]",
"location": "Global"
}, {
"copy": {
"name": "vnl",
"count": "[length(parameters(\u0027p_vnetPeeringsLinkFile\u0027))]"
},
"type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks",
"apiVersion": "2020-06-01",
"name": "[format(\u0027{0}/{1}\u0027, format(\u0027privatelink.file.{0}\u0027, environment().suffixes.storage), last(split(parameters(\u0027p_vnetPeeringsLinkFile\u0027)[copyIndex()].id, \u0027/\u0027)))]",
"tags": "[parameters(\u0027p_tags\u0027)]",
"location": "Global",
"properties": {
"virtualNetwork": {
"id": "[parameters(\u0027p_vnetPeeringsLinkFile\u0027)[copyIndex()].id]"
},
"registrationEnabled": false
},
"dependsOn": ["[resourceId(\u0027Microsoft.Network/privateDnsZones\u0027, format(\u0027privatelink.file.{0}\u0027, environment().suffixes.storage))]"]
}, {
"type": "Microsoft.Network/privateDnsZones",
"apiVersion": "2020-06-01",
"name": "[format(\u0027privatelink{0}\u0027, environment().suffixes.sqlServerHostname)]",
"tags": "[parameters(\u0027p_tags\u0027)]",
"location": "Global"
}]
}
},
"dependsOn": ["[subscriptionResourceId(\u0027Microsoft.Resources/resourceGroups\u0027, format(\u0027{0}-{1}-link-rsg\u0027, variables(\u0027v_shortLocation\u0027), subscription().displayName))]"]
}, {
"type": "Microsoft.Resources/deployments",
"apiVersion": "2020-06-01",
"name": "privateStorage",
"resourceGroup": "[format(\u0027{0}-{1}-storage-rsg\u0027, variables(\u0027v_shortLocation\u0027), subscription().displayName)]",
"properties": {
"expressionEvaluationOptions": {
"scope": "inner"
},
"mode": "Incremental",
"parameters": {
"p_tags": {
"value": "[variables(\u0027v_tags\u0027)]"
},
"p_vnetPeeringsStorage": {
"value": "[parameters(\u0027p_vnetPeeringsStorage\u0027)]"
}
},
"template": {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"p_tags": {
"type": "object",
"defaultValue": {}
},
"p_vnetPeeringsStorage": {
"type": "array"
}
},
"functions": [],
"resources": [{
"type": "Microsoft.Network/privateDnsZones",
"apiVersion": "2020-06-01",
"name": "storage.bld.local",
"tags": "[parameters(\u0027p_tags\u0027)]",
"location": "Global"
}, {
"copy": {
"name": "vnl",
"count": "[length(parameters(\u0027p_vnetPeeringsStorage\u0027))]"
},
"type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks",
"apiVersion": "2020-06-01",
"name": "[format(\u0027{0}/{1}\u0027, \u0027storage.bld.local\u0027, last(split(parameters(\u0027p_vnetPeeringsStorage\u0027)[copyIndex()].id, \u0027/\u0027)))]",
"tags": "[parameters(\u0027p_tags\u0027)]",
"location": "Global",
"properties": {
"virtualNetwork": {
"id": "[parameters(\u0027p_vnetPeeringsStorage\u0027)[copyIndex()].id]"
},
"registrationEnabled": false
},
"dependsOn": ["[resourceId(\u0027Microsoft.Network/privateDnsZones\u0027, \u0027storage.bld.local\u0027)]"]
}]
}
},
"dependsOn": ["[subscriptionResourceId(\u0027Microsoft.Resources/resourceGroups\u0027, format(\u0027{0}-{1}-storage-rsg\u0027, variables(\u0027v_shortLocation\u0027), subscription().displayName))]"]
}]
}
Это именно то, что я ищу. Магия, спасибо. Хотя оба решения — это то, что я ищу, я предпочитаю PowerShell для того, что я делаю.
@Beefcake, вероятно, работает немного лучше, чем запуск дополнительного процесса для этого, и у него нет внешней зависимости, что приятно.
Вы ищете решение с использованием процессора JSON командной строки jq или библиотеки JavaScript jQuery?