【问题标题】:PowerShell Replace value in JSONPowerShell 替换 JSON 中的值
【发布时间】:2022-11-17 20:03:55
【问题描述】:

在我们的 Azure CICD 管道中,我们有一个尝试部署策略的元素。我们在 repo 中有每个策略的 JSON 文件,我们将所有这些 json 文件放在一个文件中作为 CI 的一部分,稍后通过 CD 部署。 PowerShell 不是我写的,而是几年前在现场的一位 Microsoft 顾问写的。

问题是当所有的 JSON 放在一起时,我们会得到一个非法的语法,例如

将代码更改为可以工作并部署,但这意味着我们必须手动检查所有文件,将 [ 替换为 [[:

总之,PowerShell 将所有这些结合在一起,进行一些操作并输出到 artifacts 文件夹中的文件。

这只是 json 的一个小 sn-p,但突出显示了该区域,并且在整个 json 中有很多这样的区域需要替换:

{
"functions": [

],
"variables": {
    "location": "UK South"
},
"resources": [{
    "properties": {
        "displayName": "Allowed Locations for Resources",
        "policyType": "Custom",
        "mode": "Indexed",
        "description": "description.",
        "metadata": {
            "version": "1.0.0",
            "category": "General"
        },
        "parameters": {
            "listOfAllowedLocations": {
                "type": "Array",
                "metadata": {
                    "description": "The list of locations that can be specified when deploying resources.",
                    "strongType": "location",
                    "displayName": "Allowed locations"
                },
                "allowedValues": [
                    "uksouth",
                    "ukwest"
                ],
                "defaultValue": [
                    "uksouth",
                    "ukwest"
                ]
            }
        },
        "policyRule": {
            "if": {
                "allOf": [{
                        "field": "location",
                        "notIn": "[parameters('listOfAllowedLocations')]"
                    },
                    {
                        "field": "location",
                        "notEquals": "global"
                    },
                    {
                        "field": "type",
                        "notEquals": "Microsoft.Resources/subscriptions/resourceGroups"
                    },
                    {
                        "field": "type",
                        "notEquals": "Microsoft.Resources/b2cDirectories"
                    }
                ]
            },
            "then": {
                "effect": "audit"
            }
        }
    },
    "name": "Policy1",
    "apiVersion": "2019-01-01",
    "type": "Microsoft.Authorization/policyDefinitions",
    "location": "[variables('location')]"
}]

}

我的 PowerShell 充其量只是入门级的,所以我正在努力让替代品正常工作。

我可以获得有问题的区域并将其替换为Write-Host,但我不知道如何在不把事情弄得一团糟的情况下写回原始对象:

        if ($content.properties.policyRule.if.allOf -ne $null){
        foreach ($param in $content.properties.policyRule.if.allOf){
            Write-Host "were here..................."
            #$param = ($param | ConvertTo-Json -Depth 100 | % { [System.Text.RegularExpressions.Regex]::Unescape($_) })

            if ($param.notIn -ne $null){
                $param.notIn.replace('[', '[[')
                Write-Host $param.notIn
            }    
        }

任何建议将不胜感激。

【问题讨论】:

    标签: powershell


    【解决方案1】:

    重点是 allOf 节点包含一个数组。由于member-access enumeration 功能,您将能够轻松notIn 属性但是为此,您需要具体说明 allOf 节点中的索引 ([0]):

    $Data = ConvertFrom-Json $Json # $Json contains your $Json snippet
    $Data.resources.properties.policyRule.if.allOf[0].notIn = "[[parameters('listOfAllowedLocations')]"
    $Data |ConvertTo-Json -Depth 9
    

    如果您想基于例如递归查找您的项目来自特定属性级别的特定名称和值格式,您可以使用这个常见的可重用函数递归地寻找(和代替) 复杂 PowerShell 对象中的一个节点:

    function Get-Node {
        [CmdletBinding()][OutputType([Object[]])] param(
            [ScriptBlock]$Where,
            [Parameter(ValueFromPipeLine = $True, Mandatory = $True)]$InputObject,
            [Int]$Depth = 9
        )
        process {
            if ($_ -isnot [String] -and $Depth -gt 0) {
                if ($_ -is [Collections.IDictionary]) {
                    if (& $Where) { $_ }
                    $_.get_Values() |Get-Node -Where $Where -Depth ($Depth -1)
                }
                elseif  ($_ -is [Collections.IEnumerable]) {
                    for ($i = 0; $i -lt $_.get_Count(); $i++) { $_[$i] |Get-Node -Where $Where -Depth ($Depth -1) }
                }
                elseif ( $Nodes = $_.PSObject.Properties.Where{ $_.MemberType -eq 'NoteProperty'} ) {
                    $Nodes.ForEach{
                        if (& $Where) { $_ }
                        $_.Value |Get-Node -Where $Where -Depth ($Depth -1)
                    }
                }
            }
        }
    }
    

    用法

    发现具体节点的值:

    $Node = $Data.resources.properties.policyRule.if |Get-Node -Where {
        $_.name -eq 'notIn' -and $_.value -Match "[parameters('w+')]"
    }
    $Node
    
    Value           : [parameters('listOfAllowedLocations')]
    MemberType      : NoteProperty
    IsSettable      : True
    IsGettable      : True
    TypeNameOfValue : System.String
    Name            : notIn
    IsInstance      : True
    

    更换相关节点的所有值:

    $Node |ForEach-Object {
        $_.Value  = '[' + $_.Value
    }
    $Data |ConvertTo-Json -Depth 9
    

    结果

    {
      "functions": [],
      "variables": {
    "location": "UK South"
      },
      "resources": [
    {
      "properties": {
        "displayName": "Allowed Locations for Resources",
        "policyType": "Custom",
        "mode": "Indexed",
        "description": "description.",
        "metadata": {
          "version": "1.0.0",
          "category": "General"
        },
        "parameters": {
          "listOfAllowedLocations": {
            "type": "Array",
            "metadata": {
              "description": "The list of locations that can be specified when deploying resources.",
              "strongType": "location",
              "displayName": "Allowed locations"
            },
            "allowedValues": [
              "uksouth",
              "ukwest"
            ],
            "defaultValue": [
              "uksouth",
              "ukwest"
            ]
          }
        },
        "policyRule": {
          "if": {
            "allOf": [
              {
                "field": "location",
                "notIn": "[[parameters('listOfAllowedLocations')]"
              },
              {
                "field": "location",
                "notEquals": "global"
              },
              {
                "field": "type",
                "notEquals": "Microsoft.Resources/subscriptions/resourceGroups"
              },
              {
                "field": "type",
                "notEquals": "Microsoft.Resources/b2cDirectories"
              }
            ]
          },
          "then": {
            "effect": "audit"
          }
        }
      },
      "name": "Policy1",
      "apiVersion": "2019-01-01",
      "type": "Microsoft.Authorization/policyDefinitions",
      "location": "[variables('location')]"
    }
      ]
    }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-18
      • 2021-01-19
      相关资源
      最近更新 更多