I'm getting the following response through an API and I'm trying to pull data out of the JSON response. I'm interested in only pulling the clone.href when clone.name = ssh.
response: {
"links": {
"clone": [
"#{href=ssh://sampleurl.com; name=ssh}",
"#{href=https://sampleurl.com; name=http}"
],
"self": [
"#{href=https://sampleurl.com}"
]
}
}
I'm using the following to call the API:
Invoke-RestMethod -Uri $uri -Headers $Header -Method POST -Body $Body|ConvertTo-Json
You can do this:
$result = Invoke-RestMethod -Uri $uri -Headers $Header -Method POST -Body $Body|ConvertTo-Json
$href = $result.links.clone | Where-Object Name -eq ssh | ForEach-Object href
$href # Output to console
This uses Where-Object to filter the clone array and ForEach-Object to extract the href property, using short form of ForEach-Object -MemberName href.
Alternatively you can use the following syntax:
$href = $result.links.clone.Where{ $_.Name -eq 'ssh' }.href
It uses PowerShell intrinsic method Where for filtering.
Related
I am running Invoke-RestMethod to get a response from an API. That response is in JSON format and I am trying to figure out how to get access to the individual properties in my Powershell code.
Given these two lines:
$response = Invoke-RestMethod -Uri $paymentJournalUri -Method 'GET' -Headers $headers | ConvertTo-Json
Write-Host $response
my output looks like this:
{
"#odata.context": "https://api....yments",
"value": [
{
"#odata.etag": "W/\"JzI....Dsn\"",
"id": "b86ac....8fab",
"journalId": "59....b3ca",
"journalDisplayName": "EFT",
"lineNumber": 30000,
"vendorId": "a4c...552",
...
So how can I loop over the 'value' array and get access to each of those properties?
I have tried something like this:
$PSObj = $response | ConvertTo-Json
#Write-Host $PSObj
$PSObj.value | ForEach-Object {
Write-Host $_.journalDisplayName
}
Trying to do a bulk rename of device when they haven't been logged on for a long time.
I have managed to gather the information I need it and pipe it, so it comes out correctly.
But for some reason, I get Bad request and my formating is some how wrong, but can't figure out what. Tried every type of modification to the URI, but no luck.
This should work according to Microsoft's Doc about SetDevicename action
$date = (Get-date (Get-date).adddays(-316) -format "yyy-MM-ddTHH:mm:ssZ")
$devices | where {$_.lastSyncDateTime -le $date} | ForEach-Object {
$newname = "Test-$($_.Devicename)"
$deviceID = "$($_.ID)"
$URI = "https://graph.microsoft.com/beta/deviceManagement/managedDevices/$deviceID/setDeviceName"
$Body = #{ "deviceName" = "$NewName" } | ConvertTo-Json
$Method = "POST"
Invoke-RestMethod -Uri $URI -Method $Method -Headers $appauthToken -body $body -ContentType "application/json"
}
Any Idea what I'm doing wrong?
There is another method of renaming of bulk devices:
Document reference: https://learn.microsoft.com/en-us/mem/intune/remote-actions/device-rename#bulk-rename-devices.
I am trying to use a REST API to configure some alerts in RecoverPoint for Virtual Machines (RP4VM). I am trying to enter multiple filters at the same using json. The json file looks like this:
[
{
"JsonSubType": "SystemEventLogsFilter",
"level": "WARNING",
"scope": "NORMAL",
"eventsIDs": [],
"filterUID": {
"id": 1570417688566256135
},
"name": "RPA_issue",
"topic": "RPA",
"groupsToInclude": null
},
{
"JsonSubType": "SystemEventLogsFilter",
"level": "WARNING",
"scope": "ADVANCED",
"eventsIDs": [],
"filterUID": {
"id": -1728986321682574312
},
"name": "cluster_events",
"topic": "CLUSTER",
"groupsToInclude": null
}
]
When I try to run the script I get an error:
Unexpected token (START_ARRAY), expected START_OBJECT: need JSON Object to contain As.PROPERTY type information (for class com.emc.fapi.version5_2.commons.SystemEventLogsFilter)
at [Source: org.apache.catalina.connector.CoyoteInputStream#75b592c2; line: 1, column: 1]
If I remove the square brackets it does the first value but not the second. Is this an issue with my code or an issue with theirs?
The script:
$rp4vmcl = import-csv -Path .\test_clusters.csv
$credential = Get-Credential
$username = $credential.GetNetworkCredential().UserName
$password = $credential.GetNetworkCredential().password
$credPair = "$($username):$($password)"
$encodedCredentials = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($credPair))
$headers = #{
Authorization = "Basic $encodedCredentials";
"Accept" = "application/json";
"Content-Type" = "application/json"
}
$comp = "/system/event_logs_filters"
$json = Get-Content .\event_log_filter.json -Raw
foreach ($s in $rp4vmcl) {
$cluster = $s.cluster_name
$uid = $s.cluster_uid
$curl = $s.cluster_url
$url = "$curl$comp"
$cluster
$results = Invoke-RestMethod -Method POST -uri $url -SkipCertificateCheck -Headers $headers -Body $json
}
If the recipient expect one Call per Json Object it will not be able to handle arrays. It's totally dependant from the implementation of the webservice. Btw, better change the body:
$results = Invoke-RestMethod -Method POST -uri $url -SkipCertificateCheck -Headers $headers -Body ([System.Text.Encoding]::UTF8.GetBytes($json))
Try this first, and if this is doesnt help, loop through the elemnts and call the webservice individual:
$jsonObject = $json | ConvertFrom-Json
$results = #()
$jsonObject | foreach {
$json = $_ | ConvertTo-Json -Depth 99
$results += Invoke-RestMethod -Method POST -uri $url -SkipCertificateCheck -Headers $headers -Body ([System.Text.Encoding]::UTF8.GetBytes($json))
}
Btw, the invoke-restmethod is buggy in powershell < 6 Version, so if youre will with the standard V5 Windows Version, check the response headers via invoke-webservice, and if the response header is:
"application/json"
and not
"application/json; charset=utf-8"
powershell will misinterpret this as a windows encoding. So if youree experiencing encoding issues, you have four options:
1.) if you can modify the webservice, change the response header
2.) switch to a newer powershell version (v7 is recommended)
3.) build your own webservice call directly via the .net cmdlets
4.) use the invoke-webservice, write the answer directly into a file with the OutFile Paramater
see also:
Powershell Invoke-RestMethod incorrect character
$person = #{
"Username"="Test3";
"Password"="Test3";
}
$json = $person | ConvertTo-Json
Invoke-RestMethod -Method POST -Header $Header -ContentType "application/json" -uri "http://testa.katest.com/CreateUsers/api/v1.0/Users" -Body $json
Above powershell script works perfect and also creates the username Test3 in the system:
But If I would like to call this Invoke-RestMethod for creating multiple users at the same time - What command should I use?
Since I can only assume information about your API, I can offer two potential ways to do this.
If the POST supports a JSON array, you can do the following:
$persons = #{
"Username"="Test3";
"Password"="Test3";
},#{
"Username"="Test4";
"Password"="Test4";
}
$json = $persons | ConvertTo-Json
Invoke-RestMethod -Method POST -Header $Header -ContentType "application/json" -uri "http://testa.katest.com/CreateUsers/api/v1.0/Users" -Body $json
If POST only supports one json with one user, you can do the following:
$persons = #{
"Username"="Test3";
"Password"="Test3";
},#{
"Username"="Test4";
"Password"="Test4";
}
foreach ($person in $persons) {
$json = $person | ConvertTo-Json
Invoke-RestMethod -Method POST -Header $Header -ContentType "application/json" -uri "http://testa.katest.com/CreateUsers/api/v1.0/Users" -Body $json
}
Each method centers around creating an array of hash tables. Each hash table has a key-value pair for Username and Password. Then you can choose to either iterate or not before converting to JSON.
I am trying to change a value - specifically a variable - of one of my TFS 2017 builds. To my understanding, Patch is not supported at all. I can successfully queue a build with the Post method and I am trying to use the same command change a value as well.
When I run the Get method, I have:
*A bunch of text*
"variables": {
"system.debug": {
"value": "false",
"allowOverride": true
},
"BuildVersion": {
"value": "ValueIWantToChange"
}
},
*A bunch of text*
I need to change the Build Version and everything else will stay the same. My body in Postman looks like:
{
"Variables":
{
"BuildVersion":
{
"value": NewValue
}
}
}
When I run this in Postman, I get this error:
"Value cannot be null.\r\nParameter name: definition.Repository"
Could anyone tell me where I am going wrong or if this is possible using another method?
Seems you want to update the build definition base on you description.
To update the build definition with the REST API you need to use PUT method, please see Definitions - Update Definition for details.
Get the build definition first:
GET http://server:8080/tfs/DefaultCollection/ScrumProject/_apis/build/definitions/6?api-version=3.2
Copy all the json response from the first step as the request body,
then change the value of the specific variable which you want to be
modified.
PUT http://SERVER:8080/tfs/DefaultCollection/ScrumProject/_apis/build/definitions/6?api-version=3.2
Content-Type: application/json
Note that you need to provide the latest revision in request body:
UPDATE:
You can also use PowerShell by calling the REST API to update the specific variable value, just try below sample: (the variable name is lctest in below sample, you just need to replace it with your own variable name.)
Param(
[string]$collectionurl = "http://server:8080/tfs/DefaultCollection",
[string]$project = "ProjectName",
[string]$definitionid = "6",
[string]$user = "username",
[string]$token = "password"
)
# Base64-encodes the Personal Access Token (PAT) appropriately
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))
#Get build definition
$defurl = "$collectionurl/$project/_apis/build/definitions/$($definitionid)?api-version=3.2"
$definition = Invoke-RestMethod -Uri $defurl -Method Get -UseDefaultCredential -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}
#Set new value for the specific variable
$definition.variables.lctest.value = "1.0.0.4"
$json = #($definition) | ConvertTo-Json -Depth 99
#Update the definition
$updatedef = Invoke-RestMethod -Uri $defurl -Method Put -Body $json -ContentType "application/json" -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}
write-host $definition.variables.lctest.value
I figured out my problem awhile back and forgot to update. My initial task was to get the API for octopus so this is the long version. If youre only interested in the REST commands, refer to the last section of code. Just wanted to add the rest in for extra context.
#Create a folder
if(test-Path C:\Test){}
else{
new-item -path "C:\" -name "Test" -ItemType "directory"}
$encodedPAT = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes(":$TFSAPIKeyForAutomatedBuild"))
$GetURI = "$MyURI"
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Authorization", "Basic $encodedPAT")
[string]$Global:ChangeVersion = [version]$OctopusParameters["Octopus.Action[Deploy Package].Package.NuGetPackageVersion"]
write-host $ChangeVersion
$GetBuildresponse = Invoke-RestMethod -Method Get -header $headers -ContentType "application/json" -Uri $GetUri
write-host $GetBuildResponse
$y = convertTo-json $GetBuildresponse -depth 99 | Out-file -FilePath "C:\test\FromPostmanCopy.json"
$z = (get-content "C:\test\FromPostmanCopy.json") | select-string -pattern '(?<=value": "2.)(.*)(?=")' | % { $_.Matches} | % { $_.value }
Write-Host $z
$Content = (Get-Content "C:\Test\FromPostmanCopy.json")
$content -replace "2.$z", $changeVersion | out-file "C:\Test\FromPostmanCopy.json"
$Content = (Get-Content "C:\Test\FromPostmanCopy.json")
$Buildresponse = Invoke-RestMethod -URI $GetURI -Method Put -header $headers -Body $content -ContentType application/json