How to parse a response from Invoke-WebRequest - powershell

I fairly new to powershell, so I'm hoping someone may be able to help me out! I am trying to parse version numbers out of a webrequest and not sure of the best way to go about it. Basically, I'm using a website to store a package, and want to be able to call to a URL and download the file. The URL unfortunately only downloads the latest package, so I need to specify the version in the URL.
The goal is to pull the version list from the site, and then take the version number, and loop through, appending it to the download url for each version.
Currently to get the version, I have the following:
$api = 'http://localhost/package/NameOfProject/Packages()?
$format=json&$filter=id%20eq%20%27NameOfPackaget%27%20&$select=Version'
$response = Invoke-WebRequest -Uri $api | select-object Content
This will output
Content
-------
{"d":{"results":[{"Version":"3.3.14.2"},{"Version":"3.3.14.5"}],"count":0}}
Basically, I want it to just give me the versions (3.3.14.2), so that I can then use Invoke-WebRequest again with an -OutFile tag to save the files.
I'm probably approaching this in a completely incorrect way, so any guidance is appreciated!

You need to convert JSON in the Content property to the object and get all values of the the Version properties:
($response | ConvertFrom-Json).d.results.Version
Result:
3.3.14.2
3.3.14.5

beatcracker's helpful answer shows how to solve your problem with the Invoke-WebRequest cmdlet.
However, the Invoke-RestMethod cmdlet offers a simpler solution, because it automatically parses JSON text into objects ([pscustomobject] instances) that you can drill into with dot notation:
(Invoke-RestMethod $api).d.results.Version # add `[0]` to only extract the first version
If you need to exclude versions that match a pattern, such as those that have a --based suffix (e.g., 3.3.14.2-Test)):
#((Invoke-RestMethod $api).d.results.Version) -notmatch '-'

Related

Invoke-WebRequest not returning results as expected

I am running this code and its not returning the data to my $response variable as I expected.
$targetUrl = "https://www.tigerrunresort.com/vacation-rentals-homes-search.asp?txtStartDate=8%2F1%2F2022&txtEndDate=8%2F7%2F2022&categoryid=11317&destinationID=0&communityID=0&amenBedrooms=-1&maxPersons=0&advs=&sort=0&currentPage=1&flexibleDates=0&flexibleDatesThreshold=&searchAmenities=&showOnlySpecials=0"
$Response = Invoke-WebRequest -Uri $targetUrl
In rawcontent I should expect to see the string "Sorry" which does not show. What do I need to do to get it to return the values as I would see interactively?
Thanks!
You are not seeing it because it is not actually in the response. It is probably created and appended to the DOM by Javascript. Due to the Invoke-WebRequest not executing Javascript, it is never part of the response. If you are looking to orchestrate browsers (which do execute Javascript and offer access to the DOM) maybe you can try taking a look at Selenium (https://www.selenium.dev/)
For lauching a web request you can use for example start-process like this : start-process microsoft-edge:http://google.com/

Powershell Invoke-Response Where Clause

I have the following Powershell script that runs without issue. I am being told that I need to add "&onlyCurrent=false" to get it to pull information for employees with a future start date. I have no idea how to do this....
$response = Invoke-RestMethod 'https://api._________.com/api/gateway.php/gemco/v1/reports/120' -Method 'GET' -Headers $headers
When I add this to the end, I get invalid parameter error message:
-Where-Object onlyCurrent eq "false"
The support for they system I'm pulling this from has no information on how to do this. Absolutely any help would be very greatly appreciated.
&onlyCurrent=false is probably a query string. You can append it at the end of the URL after ?. Note that & is used to separate multiple parameters, since you have just one it's not needed. Try changing the URL to:
https://api._________.com/api/gateway.php/gemco/v1/reports/120?onlyCurrent=false
Figured it out. You have to add ?onlyCurrent=false after the 120 (inside the single quote).

Azure DevOps Rest API in Powershell saying no parameters matching

I am starting to use PowerShell to call the Azure DevOps REST API. But it seems like when I try to add parameters it tell me:
A parameter cannot be found that matches parameter name
'repositoryId'
Here is what my call looks like in PowerShell. If I take out the parameter it works. What am I doing wrong?
Invoke-RestMethod -Uri 'https://dev.azure.com/{organization}/{project}/_apis/build/builds?api-version=5.1' -repositoryId $repoId -Headers (my authentication) -Method Get
Per Microsoft's documentation this should work.
https://learn.microsoft.com/en-us/rest/api/azure/devops/build/builds/list?view=azure-devops-rest-5.1
repositoryId should be url parameter as Booga Roo mentioned. The error indicated that Repository type is missing.
You should add another parameter to your uri repositoryType={repositoryType}.So the uri should be like below.
Please check here for all repositoryTypes
https://dev.azure.com/{Organization}/{Project}/_apis/build/builds?repositoryId={id}&repositoryType=TfsGit&api-version=5.1
Addition:
You can get your repositoryId from URL of Repositories page under Repos in the Project Settings. Check below screentshot.
The Invoke-RestMethod cmdlet does not have a -repositoryId parameter. The phrasing and examples on the help page are for "URI Parameters" instead of PowerShell parameters. It means you need to build it into -Uri value instead of trying to use it directly.
I suggest using this:
Invoke-RestMethod -Uri "https://dev.azure.com/{organization}/{project}/_apis/build/builds?repositoryId={$repoId}&api-version=5.1" -Headers (my authentication) -Method Get
Side note: There are double quotes around this example URI. This is so the variable expansion for $repoId will occur and be properly interpreted as part of the URI. Using single quotes as in the original example will prevent this and treat it as a literal string value and won't perform any subsitutions.

How do I get the newest tag with Azure devops Rest Api?

I would like to recover the newest tag in azure devops, for that I am using this Uri:
https://dev.azure.com/{organization}/_apis/git/repositories/{repositoryId}/refs?filter=tags/&api-version=5.1
This returns all tags.
If I set the $top=1 parameter it returns the first label found which is the oldest.
So the question is;
Is there any way to get the newest one?
Or do I have to download everything and get the last one by hand?
Is there another way to retrieve the tags?
Edit with my work around in PowerShell (I accept suggestions):
$uriGetTags = 'https://dev.azure.com/{organization}/_apis/git/repositories/{repositoryId}/refs?filter=tags/&api-version=5.1'
$tags = Invoke-WebRequest -Uri $uriGetTags -Headers $Headers | ConvertFrom-Json
#I Only wants the last element (the newest)
$tag = $tags.value.Get($tags.count-1)
As far as I know, currently there is no out-of-the-box rest api to get the newest tag directly. The tags returned are sorted by the oldest at the top. Even in the Tags manage in the UI, it is also sorted by the oldest at the top. And there is no such parameter to get the newest one.
As a workaround , you can write a powershell script to traverse these returned results and then write host the last result.

GoDaddy DNS API - Building a module with numerous commands

EDIT: I am looking for assistance on the GoDaddy API and how to form the request so I can delete a record. I can replace records and add new records and, of course, read records. I do not need assistance on building the module. Just having a problem figuring out the REST API piece for doing a delete on GoDaddy with the API.
I found this: Error 422 When Using Powershell to Update DNS Records on GoDaddy API
This gave me a good start. I have a number of functions I have already written to create or modify various different types of record. I have learned a lot along the way. Something that I have been unable to figure out so far is how to use the API to delete an existing record that is no longer needed.
I discovered that if I had an existing record of the same name and type and I tried to create a new, it would replace what was there with the new value. If it is just an A record and that is your desire, that's great. But if it is an MX or NS record, that is probably not the desired result. I am working on the helper functions to make sure that I don't blow away existing records before I publish to my module.
I am relatively new to reading API documentation and working with REST API's so I am probably just missing something basic, but if anyone could provide me with some guidance on how to configure my call so that I can clean up records that are no longer needed.
I am also having some issues formatting the SRV record properly so that it doesn't error out when I make the call. I am not sure where my problem is and I am not seeing anything in the documentation of allowed/expected values for Protocol, Service, etc.
Here is an excerpt of my code where I am calling:
try{
$ret = Invoke-WebRequest https://api.godaddy.com/v1/domains/domain/records/$type/$alias -method put -headers $headers -Body $json -ContentType "application/json"
if ($ret.StatusCode -eq 200) { Write-Verbose -Message "Success!" }
else { Write-Warning -Message "ERROR" }
} catch {
$result = $_.Exception.Response.GetResponseStream()
$reader = New-Object System.IO.StreamReader($result)
$reader.BaseStream.Position = 0
$reader.DiscardBufferedData()
$responseBody = $reader.ReadToEnd();
$responseBody = $responseBody | ConvertFrom-Json | Format-Custom | Out-String
Write-Warning -Message "ERROR: $responseBody"
}
You will recognize this code block as it is largely taken intact from the aforementioned post. I am passing in $type as a valid record type (A, CNAME, etc.). $alias is the name of an existing record. $headers is a properly formatted header with a valid key/secret pair (I am able to Get and Put other records). I have tried omitting the body altogether to delete a value and that fails. I have tried doing the body with a JSON empty set ([], [{}]) as well as passing in data and TTL values with no value in the JSON. I can't get a successful query to work. I am testing with the following:
Invoke-WebRequest "https://api.godaddy.com/v1/domains/mydomain/records/A/test2" -method put -headers $header -ContentType "application/json" -Body '[{}]'
Any guidance or pointers to documentation that I haven't found would be greatly appreciated.
I had the same problem, it's about JSON encoding. I will show you a PHP example you can adapt to anything. The format that GoDaddy will provide is like this:
[{"":"","":"","":"",.....}]
I don't know from where comes the [] but I remove them, the parse json with regular PHP functions:
$json = str_replace("]","",$json);
//print_r($json);
$json = json_decode($json,true);
Now you will get the usable object to work with.
When send data to GoDaddy, do the same (I use curl)
$data = '[{"type":"'.$type.'","name":"'.$name.'","data":"'.$data.'","ttl":'.$ttl.'}]';
A full example that I build for updating my home server dynamic IP :) Check the functions Update() and get()
https://github.com/yo3hcv/Dynamic-DNS-hosting-home-or-mobile-with-GoDaddy/blob/master/pip.php
This maybe useful for others as I ran into the same unclarity about deleting a DNS record from a Godaddy domain using their API.
Godaddy doesn't support deleting an individual record.
From their support on the question whether it was possible to delete a record:
Dear Sir/Madam,
This API call does not exist at this time and it is something on our backlog to build out but there is no ETA to have it created. Current you can use the Put endpoint on the record type to replace all but the one you do not want to keep or you may go into our UI to remove it that way.
See their api documentation for what is available (at this date July 2020).
However, what you can do is replace all the existing records with a new set.
So suppose you have three A records with subdomain SD1, SD2 and SD3 and you want to remove SD2. You could sent an update command using:
curl -X PUT "https://api.godaddy.com/v1/domains/<yourdomain>/records/A" -H "accept: application/json" -H "Content-Type: application/json" -H "Authorization: <yourAPIKEY>" -d "[ { \"data\": \"<IP for SD1>\", \"name\": \"SD1\", \"ttl\": 3600 }, { \"data\": \"<IP for SD3>\", \"name\": \"SD3\", \"ttl\": 3600 }]"
Which will result in two A records one for SD1 and one for SD3. As long as you have at least one recordtype left (this also works for MX, MS, TXT) you will be able to remove others.
If you want to remove the last you have to go back to the Godaddy GUI, unfortunately.