Reputation: 56
I've been trying to extract usage cost using Azure Cost Management API, i ran the API through Postman to test the URI's before injecting them into the powershell script. this is the POST method I used:
POST https://management.azure.com/subscriptions/0000000-0000-0000-0000-00000000/providers/Microsoft.CostManagement/generateCostDetailsReport?api-version=2022-10-01
{
"metric": "ActualCost",
"timePeriod": {
"start": "2020-03-01",
"end": "2020-03-15"
}
}
I used this Microsoft API link as a reference : Generate Cost Details Report - Create Operation
according to Microsoft the result (cost management report) should be in an another URI that comes in this POST response within the Headers (Location), see first screenshot:
the link highlighted should be the one that I will be using to get the results for a signle subscriptions and it worked perfectly fine using Postman. However, now I want to use both methods (POST and GET) and rund them in a PS script that goes through subscriptions and generate/download the file automatically. this is the script that I was able to come up with :
# Step 1: Get mandatory parameters from the user
$startDate = Read-Host "Enter the start date (YYYY-MM-DD):"
$endDate = Read-Host "Enter the end date (YYYY-MM-DD):"
# Step 2: Connect to Azure and get subscriptions
Connect-AzAccount
$subscriptions = Get-AzSubscription | Select-Object -ExpandProperty SubscriptionId
# Step 3: Process each subscription
foreach ($subscriptionId in $subscriptions) {
# Generate cost details report
$generateReportUri = "https://management.azure.com/subscriptions/$subscriptionId/providers/Microsoft.CostManagement/generateCostDetailsReport?api-version=2022-10-01"
$reportRequest = @{
metric = "ActualCost"
timePeriod = @{
start = $startDate
end = $endDate
}
}
$reportResponse = Invoke-RestMethod -Uri $generateReportUri -Method Post -Body ($reportRequest | ConvertTo-Json) -Headers @{ "Authorization" = "Bearer $((Get-AzAccessToken).Token)" }
# Get usage report URI
$usageGet1Uri = $reportResponse.Headers.Location
# Download and rename the usage report file
$usageReport = Invoke-RestMethod -Uri $usageGet1Uri -Method Get -Headers @{ "Authorization" = "Bearer $((Get-AzAccessToken).Token)" }
$blobLink = $usageReport.Manifest.blobs.blobLink
$subscriptionName = (Get-AzSubscription -SubscriptionId $subscriptionId).Name
$fileName = "$subscriptionName.csv"
Invoke-WebRequest -Uri $blobLink -OutFile $fileName
Write-Host "Downloaded and renamed usage report for subscription '$subscriptionName' to '$fileName'."
}
I want to make sure that I am getting both Headers.Location from POST method and the BlobLink from the reponse body from GET method, and I don't know whether I called them right in the script or not. This is the error that I got when I tried to run it on my environment:
Invoke-RestMethod : Cannot validate argument on parameter 'Uri'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again. At C:\Users\XXXXXX\VScode\POST_method_try.ps1:29 char:43
$usageReport = Invoke-RestMethod -Uri $usageGet1Uri -Method Get - ...
~~~~~~~~~~~~~
- CategoryInfo : InvalidData: (:) [Invoke-RestMethod], ParameterBindingValidationException
- FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.InvokeRestMethodCommand Invoke-WebRequest : Cannot validate argument on parameter 'Uri'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again. At C:\Users\XXXXXX\VScode\POST_method_try.ps1:34 char:28
Invoke-WebRequest -Uri $blobLink -OutFile $fileName
~~~~~~~~~
- CategoryInfo : InvalidData: (:) [Invoke-WebRequest], ParameterBindingValidationException
- FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
Upvotes: 1
Views: 1098
Reputation: 1
Use Invoke-WebRequest
instead for your first call,
$reportResponse = Invoke-WebRequest -Uri $generateReportUri -Method Post -Body ($reportRequest | ConvertTo-Json) -Headers @{ "Authorization" = "Bearer $((Get-AzAccessToken).Token)" }
Upvotes: 0