Unable to update or scope deployment target at project variable

Hi,

Problem: Need help with updating or scoping deployment target in exiting project variable set.

Reference Points: I have download the project variable json and using PowerShell I am converting it using “ConvertFrom-Json” method and using loops & conditions I am able to add “Environment Variable”. However, While adding “Machines” as an nested array under “Variables.Scope” property hash table, I am not having expected result. I am putting expected & in-correct json content along with power shell script.

Expected Json Content:

"Variables": [
		{
			"Id": "",
			"Name": "FullName",
			"Value": "A",
			"Description": null,
			"Scope": {
				"Environment": [
					"Environments-1",
					"Environments-2",
					"Environments-3",
					"Environments-4"
				],
				"Role": [
					"Demo-1"
				],
				"Machines": [
					"Machines-61",
					"Machines-41"
				]
			},
			"IsEditable": true,
			"Prompt": null,
			"Type": "String",
			"IsSensitive": false
		},
		{
			"Id": "",
			"Name": "LastName",
			"Value": "B",
			"Description": null,
			"Scope": {
				"Environment": [
					"Environments-1"
				],
				"Role": [
					"Demo-2"
				]
			},
			"IsEditable": true,
			"Prompt": null,
			"Type": "String",
			"IsSensitive": false
		}
	],

In-Correct Json

"Variables": [
		{
			"Id": "",
			"Name": "FullName",
			"Value": "",
			"Description": null,
			"Scope": [
				{
					"Environment": [
						"Environments-1",
						"Environments-2",
						"Environments-3",
						"Environments-4"
					],
					"Role": [
						"Demo-2"
					]
				},
				{
					"Machines": [
						"Machines-61"
					]
				},
				{
					"Machines": [
						"Machines-41"
					]
				}
			],
			"IsEditable": true,
			"Prompt": null,
			"Type": "String",
			"IsSensitive": false
		},
		{
			"Id": "",
			"Name": "LastName",
			"Value": "",
			"Description": null,
			"Scope": {
				"Environment": [
					"Environments-1"
				],
				"Role": [
					"Demo-1"
				]
			},
			"IsEditable": true,
			"Prompt": null,
			"Type": "String",
			"IsSensitive": false
		}		
	],

PowerShell Code

# Global Variable
$VariableJsonFile = "D:\Scripts\variables.json"
$VariableName = "FullName"
$EnvironmentList = ("Environments-3", "Environments-4")
$MachinesList = ("Machines-61", "Machines-41")

# Get Content Of File & Construct Array As An List Type
$VariableSet = Get-Content -Path $($VariableJsonFile) | ConvertFrom-Json


foreach ($Variable in $($VariableSet.Variables)) {
    
    
    ########################################## WORKING ####################################################

    # Adding New Environment In Scope        
    if ($Variable.Name -eq $($VariableName)) {                                
        [System.Collections.Generic.List[System.Object]]$AddEnvironmentObject = $Variable.Scope.Environment
        if ($($EnvironmentList) -is [array]) {
            foreach ($Environment in $($EnvironmentList)) {
                if ($($AddEnvironmentObject) -contains $($Environment) ) {
                    # Wanted to remove variable first becasue of there is chance off that variable is already holding multiple value's.
                    [void]$AddEnvironmentObject.Remove($($Environment)) 
                    # Add the variable post removal.
                    [void]$AddEnvironmentObject.Add($($Environment))                     
                }
                else {
                    # Add the new variable
                    [void]$AddEnvironmentObject.Add($($Environment))                     
                }
            }
        }
        else {
            if ($($AddEnvironmentObject) -contains $($EnvironmentList) ) {
                # Wanted to remove variable first becasue of there is chance off that variable is already holding multiple value's.
                [void]$AddEnvironmentObject.Remove($($EnvironmentList))
                # Add the variable post removal.
                [void]$AddEnvironmentObject.Add($($EnvironmentList))                 
            }
            else {
                # Add the new variable
                [void]$AddEnvironmentObject.Add($($EnvironmentList))                 
            }
        }        
        $Variable.Scope.Environment = $AddEnvironmentObject


        ##################################### NOT WORKING ##############################################


        # Add Target Machines In Scope    
        [System.Collections.Generic.List[System.Object]]$AddScopeObject = $Variable.Scope

        if ($($MachinesList) -is [array]) {
            foreach ($Machine in $($MachinesList)) {

                # Construct PSCustomObject
                $MachineObject = [PsCustomObject]@{
                    Machines = @($Machine)
                }
                $AddScopeObject.Add($MachineObject)
                $Variable.Scope = $AddScopeObject
            }        
        }    
        else {
            # Construct PSCustomObject
            $MachineObject = [PsCustomObject]@{
                Machines = @($MachinesList)
            }
            $AddScopeObject.Add($MachineObject)
            $Variable.Scope = $AddScopeObject
        }    
    }
}

    
$VariableSet | ConvertTo-Json -Depth 10 | Set-Content -Path $VariableJsonFile

@jeremy.miller or @paul.calvert : Tagging You Guys For Quick Response.

Thanks
Vivek Singh

Hi Vivek,

Thanks for posting your question to the forum.

The following is the code that worked for me on my side - I commented out your machine scoping code and wrote some fresh code.

        # Add Target Machines In Scope    
        [System.Collections.Generic.List[System.Object]]$AddScopeObject = $Variable.Scope
        <#
        if ($($MachinesList) -is [array]) {
            foreach ($Machine in $($MachinesList)) {

                # Construct PSCustomObject
                $MachineObject = [PsCustomObject]@{
                    Machines = @($Machine)
                }
                $AddScopeObject.Add($MachineObject)
                $Variable.Scope = $AddScopeObject
            }        
        }    
        else {
            # Construct PSCustomObject
            $MachineObject = [PsCustomObject]@{
                Machines = @($MachinesList)
            }
            $AddScopeObject.Add($MachineObject)
            $Variable.Scope = $AddScopeObject
        }    
        #>
        if ($variable.scope.machine -eq $null){
             $variable.scope | Add-Member -MemberType NoteProperty -Name Machine -Value @()
        }
        foreach ($machine in $MachinesList){
            $variable.scope.Machine+=$machine
        }

Just to explain what’s going on here, I kept it simple with the following process:

  • Check if there is an existing Machine scoping, and if not add it
  • Iterate through the supplied machine list and add it to the new scoping array

In your if-else, I believe it might have been redundant as foreach iteration will work even if it’s only a 1 item array for instance $MachinesList = ("Machines-61").

The way I went about solving this was by pulling the variableset into a Powershell variable, then exploring the variableset by navigating all of the items to figure out where the data was missing. For instance, I could run $variableset.Variables[0].Scope in the bottom portion of the Powershell ISE to get an idea of how a variable should look data wise.

Finally, I went to the portal and looked at the JSON from a variableset and the results of the above command and compared it to the JSON like this:

Then, looking at a variable with machine scoping already on it, I can see that the data structure should be Scope.Machine, but you can also see Scope.Role, and Scope.Environment, etc. The best way is to just check one that already exists and work backward to get to that place.

image

The last item we need to account for are variables that don’t have a machine scoping, so we check if that’s null, and if it is, we create it. Then we iterate and add to that data structure.

Hopefully that helps explain how I got to my solution and gives you some background on how this all fits together. Let me know if you have any questions about that process. Please test this script thoroughly as I just did some very quick high-level tests.

Best.
Patrick

Hi @patrick.smergut ,

Thanks for helping out. Yes that worked, adding “NoteProperty” of “MemberType” of [PSCustomObject] as an array of objects under nested hash table. This logic also can also apply for other “NoteProperty” in the “Variables” array of objects in project json.

Thanks
Vivek Singh

1 Like

Hi Vivek,

Glad to hear you were able to get it working, and thanks for letting me know. Let me know if you have any other questions.

Best,
Patrick

This topic was automatically closed 31 days after the last reply. New replies are no longer allowed.