以编程方式查找并删除 JSON 对象中的对象
Programmatically find and remove object in JSON object
TL;DR 如何以编程方式搜索每个文件可能不在同一位置的对象并将其删除?
如果我确切知道对象在 JSON 中的位置就好了,但如果它改变了位置,就很难编写脚本。目前我们以编程方式构建一个 ARM 模板并将其推送到 Azure,但在我们这样做之前我们比较它以查看云中的版本与新生成的文件不同,如果不同,则替换它或创建一个新的基于关于它的版本。
问题是当模板规格是用新版本的 Bicep 构建时,然后将该信息注入 JSON 文件,然后调整 version
和 templateHash
值.可悲的是,我无法阻止这种情况发生。
"metadata": {
"_generator": {
"name": "bicep",
"version": "0.4.1008.15138",
"templateHash": "17593852815978663805"
}
在将两个文件转换为 PowerShell 对象后,我曾经做过 Compare-Object
比较这两个文件,但是当二进制更改出现时,我就放弃了这个想法。然后我开始研究更复杂的 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 中找不到这样的选项。任何 thoughts/ideas 都会很棒。
在有人提到我应该只删除 $asdf.resources.properties.template.metadata
和 $asdf.metadata
的所有实例之前,我想知道如何搜索 would/could 的任何 *.metadata
实例在可能会或可能不会出现的其他位置。更多的是“寻找所有 *.metadata
并从对象中删除,无论它在哪里”。
由于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))]"
]
}
]
}
在纯 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
}
}
}
注意这里修改了对象in-place,没有结果值
$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))]"]
}]
}
TL;DR 如何以编程方式搜索每个文件可能不在同一位置的对象并将其删除?
如果我确切知道对象在 JSON 中的位置就好了,但如果它改变了位置,就很难编写脚本。目前我们以编程方式构建一个 ARM 模板并将其推送到 Azure,但在我们这样做之前我们比较它以查看云中的版本与新生成的文件不同,如果不同,则替换它或创建一个新的基于关于它的版本。
问题是当模板规格是用新版本的 Bicep 构建时,然后将该信息注入 JSON 文件,然后调整 version
和 templateHash
值.可悲的是,我无法阻止这种情况发生。
"metadata": {
"_generator": {
"name": "bicep",
"version": "0.4.1008.15138",
"templateHash": "17593852815978663805"
}
在将两个文件转换为 PowerShell 对象后,我曾经做过 Compare-Object
比较这两个文件,但是当二进制更改出现时,我就放弃了这个想法。然后我开始研究更复杂的 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 中找不到这样的选项。任何 thoughts/ideas 都会很棒。
在有人提到我应该只删除 $asdf.resources.properties.template.metadata
和 $asdf.metadata
的所有实例之前,我想知道如何搜索 would/could 的任何 *.metadata
实例在可能会或可能不会出现的其他位置。更多的是“寻找所有 *.metadata
并从对象中删除,无论它在哪里”。
由于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))]"
]
}
]
}
在纯 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
}
}
}
注意这里修改了对象in-place,没有结果值
$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))]"]
}]
}