fetch value from json using powershell - powershell

I have the below JSON which I am getting after executing certain commands
cluster.status()
{
"clusterName": "ICluster",
"defaultReplicaSet": {
"name": "default",
"primary": "?",
"ssl": "REQUIRED",
"status": "ERROR",
"statusText": "Cluster has no quorum as visible from 'X92A1DB:3306' and no ONLINE members that can be used to restore it. 3 members are not active.",
"topology": {
"X92A1DB:3306": {
"address": "X92A1DB:3306",
"instanceErrors": [
"ERROR: group_replication has stopped with an error."
],
"memberRole": "SECONDARY",
"mode": "R/O",
"readReplicas": {},
"role": "HA",
"status": "ERROR",
"version": "5.7.36"
},
"X92A2DB:3306": {
"address": "X92A2DB:3306",
"instanceErrors": [
"ERROR: split-brain! Instance is not part of the majority group, but has state ONLINE"
],
"memberRole": "SECONDARY",
"memberState": "ONLINE",
"mode": "R/O",
"readReplicas": {},
"role": "HA",
"status": "(MISSING)",
"version": "5.7.36"
},
"X92A3DB:3306": {
"address": "X92A3DB:3306",
"instanceErrors": [
"ERROR: split-brain! Instance is not part of the majority group, but has state ONLINE",
"WARNING: Instance is NOT a PRIMARY but super_read_only option is OFF."
],
"memberRole": "SECONDARY",
"memberState": "ONLINE",
"mode": "R/O",
"readReplicas": {},
"role": "HA",
"status": "(MISSING)",
"version": "5.7.36"
}
},
"topologyMode": "Single-Primary",
"warning": "The cluster description may be inaccurate as it was generated from an instance in Error state"
},
"groupInformationSourceMember": "X921DB:3306"
}
I need to identify the node name X92A1DB:3306 and having "status": "ERROR" or have to get "ERROR: group_replication has stopped with an error."
Based on which I need to execute further commands.
Below is the code using which I am getting the above output (output of Cluster.status())
$NewServerList=#()
$GetServerData = #(Import-Csv -Path "E:\MySQL_Cluster\NONPRODServerDetails.csv")
foreach($S_List in $GetServerData)
{
$S_1 = $S_List.IP
$session = New-SSHSession -ComputerName $S_1 -Credential $Mysqlcred
$Strem = New-SSHShellStream -SSHSession $Session
$cmd_1 = $Strem.WriteLine("sudo su - mysql")
sleep -Seconds 5
$Strem.read()
$cmd_5 = $Strem.WriteLine("var cluster = dba.getCluster('ICluster')")
sleep -Seconds 5
$IBCL = $Strem.read()
Write-Host $IBCL
$statustowrite = $Strem.WriteLine("cluster.status()")
sleep -Seconds 5
"Initial Cluster Status"| Out-File -FilePath $OutputFile -Force -Append
"==============================================="|Out-File -FilePath $OutputFile -Force -Append
$Strem.Read() | Out-File -FilePath $OutputFile -Force -Append
"==============================================="| Out-File -FilePath $OutputFile -Force -Append
}
Please let me know how to get it.

This should work
(Get-Content "path_to_json" | Select-Object -Skip 1) | ConvertFrom-Json

Related

PowerShell Replace value in JSON

In our Azure CICD Pipeline, we have an element where we are trying to deploy Policies. We have JSON file per policy in the repo and we bring all these json files together into one file as part of CI which later is deployed via the CD. The PowerShell wasn't written by me, but a Microsoft consultant who was on site a few years back.
The problem is that when all the JSON comes together, we get an illegal syntax e.g.
Altering the code to this works and deploys, but means we have to go through all our files manually replace [ with [[:
In summary the PowerShell bring all of this together, does some manipulation and outputs to a file in the artifacts folder.
This is just a small snippet of the json, but highlights the area and there are many areas like this in the total json that need replacing:
{
"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')]"
}]
}
My PowerShell is intro level at best, so I am struggling to get a replace working.
I can obtain the offending area and replace it in a Write-Host, but I don't know how to write the back to the originating object with without making a right mess of things:
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
}
}
Any suggestions would be grateful.
The point is that the allOf node contains an array. Due to the member-access enumeration feature you will be able to conveniently read the notIn property but to write to it, you will need to be specific on the index ([0]) in the allOf node:
$Data = ConvertFrom-Json $Json # $Json contains your $Json snippet
$Data.resources.properties.policyRule.if.allOf[0].notIn = "[[parameters('listOfAllowedLocations')]"
$Data |ConvertTo-Json -Depth 9
In case you want to recursively find your items based on e.g. a specific name and value format from a specific property level, you might use this common reusable function to recursively find (and replace) a node in a complex PowerShell object:
function Get-Node {
[CmdletBinding()][OutputType([Object[]])] param(
[ScriptBlock]$Where,
[AllowNull()][Parameter(ValueFromPipeLine = $True, Mandatory = $True)]$InputObject,
[Int]$Depth = 10
)
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)
}
}
}
}
}
Usage
Finding node(s) with a specific name and value (-format):
$Node = $Data.resources.properties.policyRule.if |Get-Node -Where {
$_.name -eq 'notIn' -and $_.value -Match "^\[\w+\('\w+'\)\]$"
}
$Node
Value : [parameters('listOfAllowedLocations')]
MemberType : NoteProperty
IsSettable : True
IsGettable : True
TypeNameOfValue : System.String
Name : notIn
IsInstance : True
Replacing the value of the found node(s):
$Node |ForEach-Object {
$_.Value = '[' + $_.Value
}
$Data |ConvertTo-Json -Depth 9
Results
{
"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')]"
}
]
}
Update 2022-11-21
Resolved an issue with $Null values in the Get-Node function, see also: PowerShell FilterScript error with some JSON Files (thanks
mklement0).

Extract data from json using powershell

I executing below command using strem from powershell and I am getting response in form of json using the below code
$session = New-SSHSession -ComputerName $S_1 -Credential $cred
$Strem = New-SSHShellStream -SSHSession $Session
$cmd_4 = $Strem.WriteLine("shell.connect('USER#X92SL224XXX2XX:3306')")
sleep -Seconds 5
$Strem.read()
$pass = $Strem.WriteLine("password")
sleep -Seconds 5
$Strem.read()
$cmd_5 = $Strem.WriteLine("var cluster = dba.getCluster('IBDCluster')")
sleep -Seconds 5
$Strem.read()
$cmd_6 = $Strem.WriteLine("cluster.status()")
sleep -Seconds 5
$ClusterStatus = $Strem.read()
[DBG]: PS C:\Windows\system32>>
cluster.status()
{
"clusterName": "IBDCluster",
"defaultReplicaSet": {
"name": "default",
"primary": "X92SL224XXX2XX:3306",
"ssl": "REQUIRED",
"status": "OK_NO_TOLERANCE",
"statusText": "Cluster is NOT tolerant to any failures. 1 member is not active.",
"topology": {
"X92SL224XXX1XX:3306": {
"address": "X92SL224XXXXXXX:3306",
"memberRole": "SECONDARY",
"mode": "R/O",
"readReplicas": {},
"role": "HA",
"status": "ONLINE",
"version": "5.7.36"
},
"X92SL224XXX2XX:3306": {
"address": "X92SL224XXX2XX:3306",
"memberRole": "PRIMARY",
"mode": "R/W",
"readReplicas": {},
"role": "HA",
"status": "ONLINE",
"version": "5.7.36"
},
"X92SL224XXXX3XX:3306": {
"address": "X92SL224XXX3XX:3306",
"instanceErrors": [
"ERROR: group_replication has stopped with an error."
],
"memberRole": "SECONDARY",
"memberState": "ERROR",
"mode": "R/O",
"readReplicas": {},
"role": "HA",
"status": "(MISSING)",
"version": "5.7.36"
}
},
"topologyMode": "Single-Primary"
},
"groupInformationSourceMember": "X92SL224XXXXXXX:3306"
}
[48;5;254m[38;5;23m My[0m[48;5;254m[38;5;166mSQL [0m[48;5;237m[38;5;15m X92SL224QDBA2DB:3306 ssl [0m[48;5;221m[38;5;0m JS [0m[48;5;0m> [0m
I need to fetch all the address, memberRole, memberState from the above data.
I was trying to convert from Json but getting error like
ConvertFrom-Json : Invalid JSON primitive: cluster.status.
Please let me know how to get the data from above
It looks like you simply need to remove the cluster.status() line that precedes the JSON text in the multi-line string that $Strem.Read() returns, as well as the extra line that follows it:
$ClusterStatus = $Strem.Read() -replace '^.+|.+$' | ConvertFrom-Json
Note: -replace '^.+|.+$' removes the first and last line from the input string, without also trying to remove a newline that follows / precedes them; however, these newlines are incidental whitespace that doesn't affect the operation of ConvertFrom-Json.

delete a object from the json file using a powershell

In this Question i want to accomplish is that i am trying to delete a specific object in the json file.
But while doing so i am experiencing some difficulties i tried to refer article Iterate over JSON and remove JSON element in PowerShell
and implement the same but however it is deleting the entire element but i want to delete a specific object in the element not the entire element following are the required things
1. json file
{
"name": "JourneyPack",
"description": "Details of the journey across india",
"author": "Sachin",
"version": "1.0.0",
"main": "main.js",
"build": {
"applicationID": "desktop",
"Necessaryfiles": [
"main.js",
"package.json",
],
"Storage": {
"output": "./reunited"
},
"DeatilsOfJourney": [
{
"from": "../Pune",
"to": "../travel/Pune",
"filter": [
"**/*
]
},
{
"from": "../Delhi",
"to": "../travel/Delhi",
"filter": [
"**/*"
]
},
{
"from": "../Jharkhand",
"to": "../travel/Jharkhand",
"filter": [
"**/*"
]
},
],
"IOS": {
"category": "desktop"
},
"Windows": {
"icon": "images/desktopicons/icons.ico",
"target": [
"divfrieght"
],
"publisherName": [
"Sachin"
]
},
"divfrieght": {
"PointClick": true,
"standaloneMachine": true,
"allowrise": true,
"allowinstdir": true,
"menu": "JourneyPack"
}
},
"private": true,
}
following is the tried code again this is that i have referred from Iterate over JSON and remove JSON element in PowerShell
2. tried code
$inputFile = '<THE FULL PATH AND FILENAME TO YOUR JSON FILE>'
$outputFile = '<THE FULL PATH AND FILENAME FOR THE OUTPUT JSON FILE>'
$apijson = Get-Content -Path $inputFile -Raw | ConvertFrom-Json
# for safety, first make a copy of the original .paths object
$newPaths = $apijson.paths
foreach ($element in $newPaths.PSObject.Properties) {
$objName = $element.Name
$objValue = $element.Value
$objProperties = $objValue.PSObject.Properties
foreach ($prop in $objProperties) {
if ($prop.Value.'from' -eq 'Jharkhand') {
$propName = $prop.Name
$objProperties.Remove($propName)
Write-Host "Removed object $objName -- $propName"
}
}
}
# now overwrite the $apijson.paths with this cleaned up version
$apijson.paths = $newPaths
# I assume you want to convert it back to a .JSON file??
$apijson | ConvertTo-Json -Depth 100 | Set-Content -Path $outputFile -Force
i want to delete the object where "from" is equal to "../Jharkhand/"
Desired Output
{
"name": "JourneyPack",
"description": "Details of the journey across india",
"author": "Sachin",
"version": "1.0.0",
"main": "main.js",
"build": {
"applicationID": "desktop",
"Necessaryfiles": [
"main.js",
"package.json",
],
"Storage": {
"output": "./reunited"
},
"DeatilsOfJourney": [
{
"from": "../Pune",
"to": "../travel/Pune",
"filter": [
"**/*
]
},
{
"from": "../Delhi",
"to": "../travel/Delhi",
"filter": [
"**/*"
]
},
],
"IOS": {
"category": "desktop"
},
"Windows": {
"icon": "images/desktopicons/icons.ico",
"target": [
"divfrieght"
],
"publisherName": [
"Sachin"
]
},
"divfrieght": {
"PointClick": true,
"standaloneMachine": true,
"allowrise": true,
"allowinstdir": true,
"menu": "JourneyPack"
}
},
"private": true,
}
if anyone could help that would be really helpful
".paths" property does not belong to you json file, so removed this part of your script.
# for safety, first make a copy of the original .paths object
$newPaths = $apijson.paths
Try this code:
$inputFile = 'input.json'
$outputFile = 'output.json'
$apijson = Get-Content -Path $inputFile -Raw | ConvertFrom-Json
foreach ($element in $apijson.PSObject.Properties) {
$objName = $element.Name
$objValue = $element.Value
$objProperties = $objValue.PSObject.Properties
foreach ($prop in $objProperties) {
# Your object lies in this array
if ($prop.Name -eq 'DeatilsOfJourney') {
[System.Collections.ArrayList]$arr = $prop.Value
#Iterate over your array and find that object which you want to remove
for ($i = 0; $i -lt $arr.count; $i++) {
if ($arr[$i].'from' -eq '../Jharkhand')
{
$arr.RemoveAt($i)
$i--
}
}
$prop.Value = $arr
}
}
}
$apijson | ConvertTo-Json -Depth 100 | Set-Content -Path $outputFile -Force

Cannot pass an array type parameter in ARM template via Powershell

I have an ARM Template with the following parameters:
"parameters": {
"projectName": {
"type": "string",
"metadata": {
"description": "Name of the project"
}
},
"environmentName": {
"type": "string",
"defaultValue": "testing",
"metadata": {
"description": "Name/Type of the environment"
}
},
"vmResourceGroupName": {
"type": "string",
"metadata": {
"description": "Resource Group in which VMs wil be deployed"
}
},
"vmName": {
"type": "string",
"metadata": {
"description": "Name of the Virtual Machine"
}
},
"vmIPAddress": {
"type": "string",
"metadata": {
"description": "IP Address of the Virtual Machine"
}
},
"osDiskVhdUri": {
"type": "string",
"metadata": {
"description": "Uri of the existing VHD in ARM standard or premium storage"
}
},
"dataDiskVhdUri": {
"type": "array",
"metadata": {
"description": "Uri of the existing VHD in ARM standard or premium storage"
}
},
"vmSize": {
"type": "string",
"metadata": {
"description": "Size of the Virtual Machine"
}
},
"osType": {
"type": "string",
"allowedValues": [
"Windows",
"Linux"
],
"metadata": {
"description": "OS of the VM - Typically Windows or Linux"
}
},
"ManagedDisk": {
"type": "string",
"allowedValues": [
"Yes",
"No"
],
"metadata": {
"description": "Yes for Managed Disks, No for VHDs"
}
}
As evident, $dataDiskVHDURI is of type:array and I am trying to deploy the template using -TemplateParameterObject with New-AzureRMresourceGroupDeployment cmdlet in Powershell using the following code:
{
$vmWithDDTemplate = 'azuredeploy.json'
$vmWithoutDDTemplate = 'azuredeploy-withoutdd.json'
$dataDiskVhdUri = New-Object -TypeName System.Collections.ArrayList
$dataDiskVhdUri.Add("$VM.dataDiskVhduri")
#Creating VM param object
$VMTemplateObject = #{"projectname" = $projectName; `
"environmentname" = $environmentName; `
"vmResourceGroupName" = $vmResourceGroupName; `
"vmName" = $VM.vmName; `
"vmIPAddress" = $VM.vmIPAddress; `
"osDiskVhdUri" = $VM.osDiskVhdUri; `
"dataDiskVhdUri" = ,$dataDiskVhdUri; `
"vmSize" = $VM.vmSize; `
"osType" = $VM.osType; `
"ManagedDisk" = $VM.ManagedDisk
}
#$VMTemplateObject
# Checking if VM contains a data disk
if($VM.dataDiskVhdUri -ne $null)
{
Write Output "$VM contains data disk"
New-AzureRmResourceGroupDeployment -Name ('vmwithdd' + '-' + ((Get-Date).ToUniversalTime()).ToString('MMdd-HHmm')) `
-ResourceGroupName $ResourceGroupName `
-TemplateParameterObject $VMTemplateObject `
-TemplateFile $vmWithDDTemplate `
-Force -Verbose -ErrorVariable ErrorMessages `
-ErrorAction Stop -DefaultProfile $azureCred
}
else
{
Write-output '$VM does not contain data disk'
}
}
However, I get the following error every time:
Microsoft.PowerShell.Utility\Write-Error : 4:46:14 PM - Error:
Code=InvalidTemplate; Message=Deployment template validation failed:
'The provided value for the template parameter 'dataDiskVhdUri' at
line '44' and column '27' is not valid.'. At Create-Environment:73
char:73
+
+ CategoryInfo : NotSpecified: (:) [Write-Error], RemoteException
+ FullyQualifiedErrorId : System.Management.Automation.RemoteException,Microsoft.PowerShell.Commands.WriteErrorCommand
+ PSComputerName : [localhost]
Does anyone know how to resolve this?
Not sure, but maybe feeding it with an ArrayList object wrapped in an array by use of the preceeding , is not what it wants. If i lookup examples, i see only single values added there like "dataDiskVhdUri" = $VM.dataDiskVhduri;
Try this:
$OptionalParameters = New-Object -TypeName Hashtable
$OptionalParameters.Add("aParam", #(1,2,3))
New-AzureRmResourceGroupDeployment -ResourceGroupName $ResourceGroupName `
-TemplateFile azuredeply.json `
#OptionalParameters
With:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"aParam": {
"type": "array"
}
},
"variables": { },
"resources": [ ],
"outputs": {
"dump": {
"type": "array",
"value": "[parameters('aParam')]"
}
}
}

Is Powershell command available for retrieving Azure Document Database account key?

I am creating DocumentDB Account using ARM Template. Now want to get the Account Key once DocumentDB Account is created.
I know we can get these details from https://portal.azure.com but I want a command which will give context ( ex. with Get-AzureStorageAccountKey command we get key for storage account)
$ScriptPath = split-path -parent $MyInvocation.MyCommand.Definition
$ResourceGroupName = "ResGrp"
$Location = "South Central US"
$DocDBAccountName = "testdocdbaccount"
$TemplateFilePath = "DocumentDBJson\DocumentDB.json"
$ParameterFilePath = "DocumentDBJson\DocumentDB.param.dev.json"
$PSOutputFolder= "$ScriptPath\PowerShellOutput"
$NewParameterFilePath = $ParameterFilePath.Replace(".json",".Deploy.json")
(Get-Content "$ParameterFilePath") | Foreach-object {
$_ -replace '\$Location\$', $Location `
-replace '\$DocDBAccountName\$', $DocDBAccountName
} |Set-Content "$NewParameterFilePath" -Force
New-AzureRmResourceGroupDeployment -Name $DocDBAccountName -ResourceGroupName $ResourceGroupName -Mode Complete -Force -TemplateFile "$ScriptPath\$TemplateFilePath" -location $Location -TemplateParameterFile "$NewParameterFilePath" | ConvertTo-Json | Out-File "$PSOutputFolder\DocumentDB_$DocDBAccountName.json"
$DocDBFile = "$PSOutputFolder\DocumentDB_$DocumentDbAccount.json"
$docdbjson = Get-Content $DocDBFile | Out-String | ConvertFrom-Json
foreach ($v in $docdbjson.Outputs.keys.Value.Replace('" "','"|"').Split("|"))
{
if($v -match "primaryMasterKey")
{
$DocumentDbKey= ($v.Split(":")[-1]).Replace('"','')
}
}
--------------------- DocumentDB.Json File -----------------------
{
"$schema": "http://schema.management.azure.com/schemas/2014-04-01-preview/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"databaseAccountName": {
"type": "string"
},
"location": {
"type": "string"
}
},
"resources": [
{
"apiVersion": "2015-04-08",
"type": "Microsoft.DocumentDb/databaseAccounts",
"name": "[parameters('databaseAccountName')]",
"location": "[parameters('location')]",
"properties": {
"name": "[parameters('databaseAccountName')]",
"databaseAccountOfferType": "Standard"
}
}
],
"outputs": {
"Keys": {
"type": "object",
"value": "[listKeys(resourceId('Microsoft.DocumentDb/databaseAccounts', parameters('databaseAccountName')), '2015-04-08')]"
}
}
}
------------------ DocumentDB.param.dev.json File -----------------
{
"$schema": "http://schema.management.azure.com/schemas/2014-04-01-preview/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"databaseAccountName": {
"value": "$DocDBAccountName$"
},
"location": {
"value": "$Location$"
}
}
}