0

I have a powershell script like that:

Param(
    [Parameter(Mandatory=$True)]
    [String]
    $NEWPARAMVALUE,

    [Parameter(Mandatory=$True)]
    [String]
    $PARAM_NAME
)
$FILEPATH = “arm_template.json”
$JSON = Get-Content $FILEPATH | Out-String | ConvertFrom-Json
$JSON.$PARAM_NAME = $NEWPARAMVALUE
$JSON | ConvertTo-Json -Depth 10 | Set-Content $FILEPATH

When I used this script without $PARAM_NAME variable (I just put a parameter as a plain text, example: $JSON.resources.properties.parameters.daasServiceBaseUrl.defaultValue) - it worked.

I tried different ways:

  1. $JSON.resources.$PARAM_NAME (where $PARAM_NAME = 'properties.parameters.daasServiceBaseUrl.defaultValue')

  2. $JSON"."$PARAM_NAME"

I think that's because of the point between two env variables. Could please someone help with it?

Update:

Error that I get from Azure DevOps:

The property | 'properties.parameters.parametername.defaultValue' cannot | be found on this object. Verify that the property exists and | can be set.

How I tried it manually:

$env:PARAM_NAME="resources.properties.parameters.daasServiceBaseUrl.defaultValue"


./test.ps1 -NEWPARAMVALUE "[parameters('DaaS_Contract_Daily_Trigger_properties_Daas-UI-to-Contract_parameters_daasServiceBaseUrl')]" -PARAM_NAME $env:PARAM_NAME

What I got:

Line |
  12 |  $JSON.$PARAM_NAME = $NEWPARAMVALUE
     |  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | Exception setting "resources.properties.parameters.daasServiceBaseUrl.defaultValue": "The property
     | 'resources.properties.parameters.daasServiceBaseUrl.defaultValue' cannot be found on this object. Verify that the property exists and can be
     | set."

My JSON:

{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "dataFactoryName": {
            "type": "string",
            "defaultValue": ""
        },
        "location": {
            "type": "string",
            "defaultValue": "[resourceGroup().location]",
            "metadata": {
                "description": "Data Factory location matches Resource group location"
            }
        },
        "project": {
            "type": "string",
            "defaultValue": "ct",
            "metadata": {
                "description": "Azure Tag used to track projects"
            }
        },
        "environment": {
            "type": "string",
            "defaultValue": "default",
            "metadata": {
                "description": "Azure Tag used to track environments"
            }
        },
        "sleepTime": {
            "type": "int",
            "defaultValue": "1"
        },
        "DaaS_Contract_Daily_Trigger_properties_Daas-UI-to-Contract_parameters_daasServiceBaseUrl": {
            "type": "string",
            "defaultValue": "http://digital-daas-service-om-sqa.nplabsusk8s.com/daas"
        }
    },
    "resources": [
        {
            "apiVersion": "2018-06-01",
            "name": "[parameters('dataFactoryName')]",
            "location": "[parameters('location')]",
            "tags": {
                "project": "[parameters('project')]",
                "environment": "[parameters('environment')]"
            },
            "type": "Microsoft.DataFactory/factories",
            "identity": {
                "type": "SystemAssigned"
            },
            "properties": {}
        },
        {
            "name": "[concat(parameters('dataFactoryName'), '/pipeline1')]",
            "type": "Microsoft.DataFactory/factories/pipelines",
            "apiVersion": "2018-06-01",
            "properties": {
                "activities": [
                    {
                        "name": "Wait1",
                        "type": "Wait",
                        "dependsOn": [],
                        "userProperties": [],
                        "typeProperties": {
                            "waitTimeInSeconds": "[parameters('sleepTime')]"
                        }
                    },
                    {
                        "name": "Copy Delivery Request",
                        "type": "Copy",
                        "dependsOn": [
                            {
                                "activity": "Delete old Req File",
                                "dependencyConditions": [
                                    "Succeeded"
                                ]
                            }
                        ],
                        "policy": {
                            "timeout": "7.00:00:00",
                            "retry": 0,
                            "retryIntervalInSeconds": 30,
                            "secureOutput": false,
                            "secureInput": false
                        },
                        "userProperties": [],
                        "typeProperties": {
                            "source": {
                                "type": "RestSource",
                                "httpRequestTimeout": "00:01:40",
                                "requestInterval": "00.00:00:00.010",
                                "requestMethod": "GET"
                            },
                            "sink": {
                                "type": "JsonSink",
                                "storeSettings": {
                                    "type": "AzureBlobFSWriteSettings"
                                },
                                "formatSettings": {
                                    "type": "JsonWriteSettings",
                                    "quoteAllText": true
                                }
                            },
                            "enableStaging": false
                        },
                        "inputs": [
                            {
                                "referenceName": "Rest_Json_File",
                                "type": "DatasetReference",
                                "parameters": {
                                    "relativeURL": {
                                        "value": "@{pipeline().parameters.daasServiceRelURL}/@{variables('createdDate')}",
                                        "type": "Expression"
                                    },
                                    "BaseUrl": {
                                        "value": "@pipeline().parameters.daasServiceBaseUrl",
                                        "type": "Expression"
                                    }
                                }
                            }
                        ]
                    }
                ],
                "parameters": {
                    "deliveryReqFileName": {
                        "type": "string",
                        "defaultValue": "delivery_request.json"
                    },
                    "daasServiceBaseUrl": {
                        "type": "string",
                        "defaultValue": "http://digital-daas-service-om-sqa.nplabsusk8s.com/daas"
                    }
                },
                "annotations": []
            },
            "dependsOn": []
        }
    ]
}

5
  • works for me. only thing i changed: set the $FILEPATH to the full path. what exactly is the error you get? please edit your question and paste the error you get (also maybe try setting the full path). Commented Aug 16, 2020 at 13:59
  • How you address the Script params? Make shure providing parameters by name Commented Aug 16, 2020 at 14:16
  • You are missing te resources. part in $PARAM_NAME = 'properties.parameters.parametername.defaultValue'. As sidenote, don't use curly quoty things like and in code. Change these into straight quotes Commented Aug 16, 2020 at 14:18
  • 1
    Please show us some of the JSON file so we don't have to reinvent what it might look like Commented Aug 16, 2020 at 14:27
  • Whats in your json, what causes property not found? Commented Aug 16, 2020 at 14:29

1 Answer 1

2

When you pass a string "a.b.c.d" as the right-hand operand of the . member access operator, PowerShell will attempt to resolve the exact member name a.b.c.d, not "a, then b, then c, then d".

While this could be solved by executing Invoke-Expression against "${JSON}.${PARAM_NAME}", that also opens your script up to arbitrary execution of whatever the user might pass in as $PARAM_NAME.

To avoid that, you'll need to manually:

  1. Split $PARAM_NAME into individual member names, like $names = $PARAM_NAME.Split('.'), then
  2. Resolve each property name except for the last one manually
  3. Assign to $resolvedObject."$last"

Here's how that might look in a generic helper function that takes care of step 2 and 3:

function Set-PropertyChained
{
  param(
    [Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 0)]
    [ValidateScript({$_ -isnot [ValueType]})]
    [object]$RootObject,
    
    [Parameter(Mandatory = $true, Position = 1)]
    [string[]]$MemberChain,

    [Parameter(Mandatory = $true, Position = 2)]
    [object]$Value,

    [switch]$PassThru
  )

  begin {
    $resolutionChain = @($MemberChain |Select -SkipLast 1)
    $terminalMember  = $($MemberChain |Select -Last 1)
  }

  process {
    $obj = $RootObject

    # Member resolution up until the parent of the last property
    foreach($memberName in $resolutionChain){
      Write-Vebose "Resolving $memberName on $obj"
      $obj = $obj.$memberName
    }

    # Set the value of the last property on its parent
    Write-Vebose "Setting $memberName on $obj to $Value"
    $obj.$terminalMember = $Value

    if($PassThru){
      # Write modified object back if requested
      Write-Output $RootObject -NoEnumerate
    }
  }
}

Then in your script:

Param(
    [Parameter(Mandatory=$True)]
    [String]
    $NEWPARAMVALUE,

    [Parameter(Mandatory=$True)]
    [String]
    $PARAM_NAME
)

$FILEPATH = “arm_template.json”
$JSON = Get-Content $FILEPATH | Out-String | ConvertFrom-Json

# Step 1, split the resolution chain into individual components
$MemberNames = $PARAM_NAME.Split('.')

# Step 2 + 3, resolve n-2 members in chain, then assign to n-1
$JSON | Set-PropertyChained -MemberChain $MemberNames -Value $NEWPARAMVALUE

$JSON | ConvertTo-Json -Depth 10 | Set-Content $FILEPATH
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for your answer! After running the script I got: "defaultValue": "[parameters('DaaS_Contract_Daily_Trigger_properties_Daas-UI-to-Contract_parameters_daasServiceBaseUrl')]" Name of parameter but not the new value
Not sure I understand - the node corresponding to your $NEW_PARAM parameter got updated with the $NEWPARAMVALUE, but that wasn't actually what you wanted?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.