How to check if output from command contains "error"? - powershell

I have 2 powershell scripts
script1.ps1 contains REST calls to Vault, which returns a json response containing some keys/values.
Function getValues($token) {
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("X-Vault-Token", $token)
$response = Invoke-RestMethod -method GET -uri "https://vault.com:8243/v1/secret/vault/development" -ContentType 'application/json' -headers $headers
$response.data| ConvertTo-Json -depth 100
}
getValues $token
As you can see, the method requires a $token.
I have that token saved in a system variable.
Now i call script1 in script2 to get the keys/values like this:
$resp = & ".\script1.ps1" | convertfrom-json
that works great and i get values as i need.
however, i am testing when if there is errors in the future, for example by removing the token from the system variable.
This $resp returned:
errors
------
{missing client token}
great. now i want to exit the script should that happen.
I tried a check like this:
if($resp.tostring().contains("error"))
{
write-output "error!"
exit 1
}
but it never exited nor did it return the output error!
how am i suppose to look for a match in this case?

Related

Is there a Powershell equivalent to JavaScript Console Log?

I have a powershell script, which is calling a third party API and getting some response data back. I'd like to just log the response object to see what exactly is returning. I've tried
Write-Host ($item | Format-List | Out-String)
But that doesn't seem to be working. The API says it will return JSON but I'm not sure how to verify the return at all.
Full script is something like this.
$queryURL = "xyz"
$apiResponse = Invoke-RestMethod -Uri $queryURL -Method Get -ContentType "application/json" -Headers $header
You can pipe the Invoke-RestMethod to the ConvertFrom-Json cmdlet, this will convert the output into an object you can easily query:
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/convertfrom-json?view=powershell-7.1
$j = Invoke-WebRequest 'https://api.github.com/repos/PowerShell/PowerShell/issues' | ConvertFrom-Json
Calling $j will output the object created from the JSON.

Powershell API Data Extraction

I'm getting data back from an API for a system of ours using Powershell but it doesn't quite return it correctly. It is putting the data all under one header as seen below. I'm trying to extract the downloadLink part only
Tried converting to JSON to see if I could get anywhere else with it.
$token = ".."
$web = Invoke-RestMethod -uri $url -Method Get -Headers #{'Authorization' = $token}
echo $web
I get this as the outcome:
documents
---------
{#{documentName=Name.docx.pdf; downloadLink=https://app.xxx.com/api/docs/employees/111/shared/111}, {#{documentName=Name.docx.pdf; downloadLink=https://app.xxx.com/api/docs/employees/111/shared/111} ...
What I need to get is the downloadLink, but as it's all coming under the documents header I can't do a simple select or get on it.
Have you tried converting the results from JSON using ConvertFrom-Json? See the code example below.
Please note the change I made to the ContentType to the Invoke-RestMethod as well.
$token = ".."
$web = Invoke-RestMethod -uri $url -Method Get -ContentType "application/json" -Headers #{'Authorization' = $token}
$webResults = $web | ConvertFrom-Json
echo ($json | ConvertFrom-Json).downloadLink

Using powershell's Invoke-RestMethod cmdlet is only returning the word "success" as a result

I have written 2 scripts. One in python and one in powershell. Python is able to call a rest api and is returned the string "JSESSIONID=8kfv0fi1bc84gtw2xvnqsrt4;Path=/;Secure;HttpOnly ". When I use the following code in powershell, it returns "success". What am I doing wrong?
$getEncCode = "Er6TmdhXn09Y9C1I"
$dataPart1 = #{EncCode=$getEncCode}
$dataPart = $dataPart1 | ConvertTo-Json
$uri = "https://10.164.42.77:8092/getEnc/2252953/login"
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
$result = Invoke-RestMethod -Method Post -Body $dataPart -uri $uri -ContentType "application/json"
Write-Host $result
Write-Host $result uses the $result.ToString() method to display that object as a string.
Likely there is more data there to show. Simply remove Write-Host to see it. Or do something like Get-Member -InputObject $result to see all immediate properties, methods etc.
Have a look at Printing object properties in Powershell to see other ways to deal with this.

Can I save result from invoke-restmethod as variable instead of an -outfile in powershell?

I have a Invoke-Restmethod API script that creates a new mailinglist and returns the following
Code Message Result
---- ------- ------
1 Mailing list successfully created 12345678
I need the result (ID for the new mailnglist) for the next operation.
I know I can use -outfile to save the result to txt\xml\json and import it using get-contents, but it strikes me as more efficient and clean to just save the result in a variable without having to save an outfile and importing it back in. Is there a way to do this?
My complete code:
Invoke-RestMethod $url -Method $method -Headers $headers -Body (ConvertTo-json $body) -ContentType "$outform"
Sure, yes. Add -PassThru switch to your Invoke-RestMethod call, and assign the output to a variable as normal.
$result = Invoke-RestMethod #args -PassThru # when there's "outfile" in args
In fact, if you don't use -outfile, your results should already be available for saving as a variable.
$result = Invoke-RestMethod #args # when there's no "outfile" in args
EDIT: If you need only one field out of the total result (so you don't need code,message etc), you can save only the result's result field like so:
$result = (Invoke-RestMethod #args).result

Error Handling for Invoke-RestMethod - Powershell

I have a powershell script using the Skytap API (REST). I would like to catch the error, if there is one, and try to display it.
For example, we are changing the IP:
Invoke-RestMethod -Uri https://cloud.skytap.com/configurations/XXXXXX/vms/YYYYYY/interfaces/ZZZZZZ?ip=10.0.0.1 -Method PUT -Headers $headers
If the IP is used somewhere else, I will get the 409 Conflict Error (Request is well-formed but conflicts with another resource or permission).
I would like to check if the error is 409 and then tell it to do something else about it.
This is somewhat awkward but the only way to do it as far as I know without doing something more complicated like using .NET's WebRequest and ConvertFrom-Json (or whatever data format you are expecting).
try {
Invoke-RestMethod ... your parameters here ...
} catch {
# Dig into the exception to get the Response details.
# Note that value__ is not a typo.
Write-Host "StatusCode:" $_.Exception.Response.StatusCode.value__
Write-Host "StatusDescription:" $_.Exception.Response.StatusDescription
}
I know you asked for Powershellv4, but since v6/v7 :
Try {
$WebRequestResult = Invoke-RestMethod -Uri $URL -Headers $Headers -Body $BodyJSON -Method $Method -ContentType $ContentType -SkipCertificateCheck
} Catch {
if($_.ErrorDetails.Message) {
Write-Host $_.ErrorDetails.Message
} else {
Write-Host $_
}
}
The Special Variable $? will solve this. It stands for $LASTEXITCODE = 0 (everything ok). It will ask for the Result Code from the previous Command.
Invoke-RestMethod -Uri https://cloud.skytap.com/configurations/XXXXXX/vms/YYYYYY/interfaces/ZZZZZZ?ip=10.0.0.1 -Method PUT -Headers $headers
if (!$?) {
throw $_.ErrorDetails.Message
}
Powershell 7 introduces the -SkipHttpErrorCheck parameter. This instructs the cmdlet to behave in a similar way to web requests in programming frameworks (i.e. where 404, 409, etc. are valid responses - the web request is successful but the server returned an error code).
This can be combined with the -StatusCodeVariable parameter. This instructs the cmdlet to insert the response code into a variable. However, the variable name is passed as a string (not as a reference). For example:
$scv = $null
Invoke-RestMethod ... -SkipHttpErrorCheck -StatusCodeVariable "scv"