Azureの各サービス価格をapiで取得する

# はじめに
Azureの価格は[料金計算ツール](https://azure.microsoft.com/ja-jp/pricing/calculator/)等での確認となり、必要なサービスを選択してポチポチ操作する必要がありました。
少ないサービスであれば良いですが多くなると大変です。
apiで取得出来るようになったようなので取得してみたいと思います。

https://learn.microsoft.com/ja-jp/rest/api/cost-management/retail-prices/azure-retail-prices

# api実行してみる
今回はPowerShellで試します。
試したPowreShellのバージョンは7.2.6です。

```powershell
Invoke-RestMethod -uri "https://prices.azure.com:443/api/retail/prices?api-version=2021-10-01-preview&meterRegion='primary'" 

BillingCurrency    : USD
CustomerEntityId   : Default
CustomerEntityType : Retail
Items              : {@{currencyCode=USD; tierMinimumUnits=0; retailPrice=0.40365; unitPrice=0.40365; armRegionName=southindia; location=IN South; effectiveStartDate=2022/05/01 0:00:00; effectiveEndDate
                     =2022/10/31 23:59:00; meterId=000009d0-057f-5f2b-b7e9-9e26add324a8; meterName=D14/DS14 Spot; productId=DZH318Z0BPVW; skuId=DZH318Z0BPVW/00QZ; availabilityId=; productName=Virtual Ma
                     chines D Series Windows; skuName=D14 Spot; serviceName=Virtual Machines; serviceId=DZH313Z7MMC8; serviceFamily=Compute; unitOfMeasure=1 Hour; type=Consumption; isPrimaryMeterRegion=
                     True; armSkuName=Standard_D14}, @{currencyCode=USD; tierMinimumUnits=0; retailPrice=0.1955; unitPrice=0.1955; armRegionName=southindia; location=IN South; effectiveStartDate=2022/05
                     /01 0:00:00; meterId=000009d0-057f-5f2b-b7e9-9e26add324a8; meterName=D14/DS14 Spot; productId=DZH318Z0BPVW; skuId=DZH318Z0BPVW/00QZ; availabilityId=; productName=Virtual Machines D 
                     Series Windows; skuName=D14 Spot; serviceName=Virtual Machines; serviceId=DZH313Z7MMC8; serviceFamily=Compute; unitOfMeasure=1 Hour; type=DevTestConsumption; isPrimaryMeterRegion=Tr
                     ue; armSkuName=Standard_D14}, @{currencyCode=USD; tierMinimumUnits=0; retailPrice=1.088102; unitPrice=1.088102; armRegionName=eastasia; location=AP East; effectiveStartDate=2022/08/
                     01 0:00:00; effectiveEndDate=2022/10/31 23:59:00; meterId=00014e7d-fff9-54dd-962e-4e992887ad3c; meterName=D64s v5 Spot; productId=DZH318Z08M9T; skuId=DZH318Z08M9T/00CC; availability 
                     Id=; productName=Virtual Machines Dsv5 Series Windows; skuName=Standard_D64s_v5 Spot; serviceName=Virtual Machines; serviceId=DZH313Z7MMC8; serviceFamily=Compute; unitOfMeasure=1 Ho 
                     ur; type=Consumption; isPrimaryMeterRegion=True; armSkuName=Standard_D64s_v5}, @{currencyCode=USD; tierMinimumUnits=0; retailPrice=0.430003; unitPrice=0.430003; armRegionName=eastas 
                     ia; location=AP East; effectiveStartDate=2022/09/01 0:00:00; effectiveEndDate=2022/10/31 23:59:00; meterId=00014e7d-fff9-54dd-962e-4e992887ad3c; meterName=D64s v5 Spot; productId=DZ 
                     H318Z08M9T; skuId=DZH318Z08M9T/00CC; availabilityId=; productName=Virtual Machines Dsv5 Series Windows; skuName=Standard_D64s_v5 Spot; serviceName=Virtual Machines; serviceId=DZH313 
                     Z7MMC8; serviceFamily=Compute; unitOfMeasure=1 Hour; type=DevTestConsumption; isPrimaryMeterRegion=True; armSkuName=Standard_D64s_v5}…}
NextPageLink       : https://prices.azure.com:443/api/retail/prices?api-version=2021-10-01-preview&meterRegion=%27primary%27&$skip=100
Count              : 100
```

どうやら100件ずつの取得みたいです。
通貨の指定やフィルター掛ける事も出来るようですので通貨を日本円、日本のリージョンのみを取得してみます。

```powershell
Invoke-RestMethod -uri "https://prices.azure.com:443/api/retail/prices?api-version=2021-10-01-preview&meterRegion='primary'&currencycode='JPY'&`$filter=armRegionName eq 'japaneast' or armRegionName eq 'japanwest'"

BillingCurrency    : JPY
CustomerEntityId   : Default
CustomerEntityType : Retail
Items              : {@{currencyCode=JPY; tierMinimumUnits=1024000; retailPrice=5.7834; unitPrice=5.7834; armRegionName=japaneast; location=JA East; effectiveStartDate=2018/05/01 0:00:00; meterId=000a27 
                     55-e888-4145-9cdc-629fcd956d28; meterName=Pay-as-you-go Data at Rest; productId=DZH318Z0BQPX; skuId=DZH318Z0BQPX/0018; availabilityId=; productName=Data Lake Store; skuName=Pay-as-y 
                     ou-go; serviceName=Data Lake Store; serviceId=DZH314H0T4NQ; serviceFamily=Analytics; unitOfMeasure=1 GB/Month; type=Consumption; isPrimaryMeterRegion=True; armSkuName=}, @{currencyC 
                     ode=JPY; tierMinimumUnits=0; retailPrice=6.0726; unitPrice=6.0726; armRegionName=japaneast; location=JA East; effectiveStartDate=2018/05/01 0:00:00; meterId=000a2755-e888-4145-9cdc- 
                     629fcd956d28; meterName=Pay-as-you-go Data at Rest; productId=DZH318Z0BQPX; skuId=DZH318Z0BQPX/0018; availabilityId=; productName=Data Lake Store; skuName=Pay-as-you-go; serviceName 
                     =Data Lake Store; serviceId=DZH314H0T4NQ; serviceFamily=Analytics; unitOfMeasure=1 GB/Month; type=Consumption; isPrimaryMeterRegion=True; armSkuName=}, @{currencyCode=JPY; tierMinim 
                     umUnits=5120000; retailPrice=5.6388; unitPrice=5.6388; armRegionName=japaneast; location=JA East; effectiveStartDate=2018/05/01 0:00:00; meterId=000a2755-e888-4145-9cdc-629fcd956d28 
                     ; meterName=Pay-as-you-go Data at Rest; productId=DZH318Z0BQPX; skuId=DZH318Z0BQPX/0018; availabilityId=; productName=Data Lake Store; skuName=Pay-as-you-go; serviceName=Data Lake S 
                     tore; serviceId=DZH314H0T4NQ; serviceFamily=Analytics; unitOfMeasure=1 GB/Month; type=Consumption; isPrimaryMeterRegion=True; armSkuName=}, @{currencyCode=JPY; tierMinimumUnits=1024 
                     00; retailPrice=5.928; unitPrice=5.928; armRegionName=japaneast; location=JA East; effectiveStartDate=2018/05/01 0:00:00; meterId=000a2755-e888-4145-9cdc-629fcd956d28; meterName=Pay 
                     -as-you-go Data at Rest; productId=DZH318Z0BQPX; skuId=DZH318Z0BQPX/0018; availabilityId=; productName=Data Lake Store; skuName=Pay-as-you-go; serviceName=Data Lake Store; serviceId 
                     =DZH314H0T4NQ; serviceFamily=Analytics; unitOfMeasure=1 GB/Month; type=Consumption; isPrimaryMeterRegion=True; armSkuName=}…}
NextPageLink       : https://prices.azure.com:443/api/retail/prices?api-version=2021-10-01-preview&meterRegion=%27primary%27&currencycode=%27JPY%27&$filter=armRegionName%20eq%20%27japaneast%27%20or%20ar 
                     mRegionName%20eq%20%27japanwest%27&$skip=100
Count              : 100
```

各アイテムの情報はこのような感じ。

```powershell
currencyCode         : JPY
tierMinimumUnits     : 1024000
retailPrice          : 5.7834
unitPrice            : 5.7834
armRegionName        : japaneast
location             : JA East
effectiveStartDate   : 2018/05/01 0:00:00
meterId              : 000a2755-e888-4145-9cdc-629fcd956d28
meterName            : Pay-as-you-go Data at Rest
productId            : DZH318Z0BQPX
skuId                : DZH318Z0BQPX/0018
availabilityId       : 
productName          : Data Lake Store
skuName              : Pay-as-you-go
serviceName          : Data Lake Store
serviceId            : DZH314H0T4NQ
serviceFamily        : Analytics
unitOfMeasure        : 1 GB/Month
type                 : Consumption
isPrimaryMeterRegion : True
armSkuName           : 
```

# 一括取得
100件ずつコマンド実行していたらきりがないため、テキストファイル形式で一括ダウンロード出来るようにします。
apiプロパティやフィルターは別ファイルで定義出来るようにしておきます。

```json:config.json
{
    "Export": {
        "Directory": "C:\\out",
        "csv": {
            "Delimiter": "\t"
        },
        "Property": [
            {
                "key": "currencycode",
                "value": "JPY"
            }
        ],
        "Filter": {
            "armRegionName": [
                "japaneast",
                "japanwest"
            ]
        }
    }
}

```

取得した情報の中に次ページのリンクが入っているため、リンクを都度取得してapi実行します。

```powershell:GetPriceList.ps1
param (
    [parameter(mandatory = $true)][string]$ConfigFileName
)

$SettingFileDir = Split-Path $MyInvocation.MyCommand.Path -Parent | Split-Path -Parent | Join-Path -ChildPath etc -Resolve
$SettingFilePath = Join-Path -Path $SettingFileDir -ChildPath $ConfigFileName

# 設定ファイルの読込
$Settingjson = Get-Content $SettingFilePath | ConvertFrom-Json
$FileFullPath = Join-Path $Settingjson.Export.Directory -ChildPath "AzurePriceList_$(Get-Date -UFormat '%Y%m%d%H%M%S')_${PID}.txt"

$BasicURL = "https://prices.azure.com:443/api/retail/prices?api-version=2021-10-01-preview&meterRegion='primary'"
$apiProperty = $null
foreach ($eachProperty in $Settingjson.Export.Property) {
    $apiProperty += "&$($eachProperty.key)='$($eachProperty.value)'"
}

$filterarmRegionName = "&`$filter="
$addOperator = $null
foreach ($eacharmRegionName in $Settingjson.Export.Filter.armRegionName) {
    $filterarmRegionName += "${addOperator}armRegionName eq '${eacharmRegionName}'"
    $addOperator = " or " 
}

$NextPageLink = "${BasicURL}${apiProperty}${filterarmRegionName}"
$responseCount = 0
do {
    $apiResponse = Invoke-RestMethod -Uri $NextPageLink
    $responseCount += $apiResponse.Count
    Write-Progress -Activity "Read Price List" -Status "${responseCount} Complete" -PercentComplete 100

    $apiResponse.Items | Export-Csv -Path $FileFullPath -Encoding utf8 -Delimiter "`t" -Append

    $NextPageLink = $apiResponse.NextPageLink


} while ($NextPageLink)

Write-Host "${responseCount}件のレコードを出力しました。"

exit 

```

プログレスバーは今の件数が表示されるだけで進捗率は無意味です。
最大件数が取得できなかったので諦めました…。
![Progressbar.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604991/4ced0cb1-39aa-eef2-90ac-6735a0c86a35.png)

# 出力結果
行形式で出力出来てます。

```plaintext
"currencyCode"	"tierMinimumUnits"	"retailPrice"	"unitPrice"	"armRegionName"	"location"	"effectiveStartDate"	"meterId"	"meterName"	"productId"	"skuId"	"availabilityId"	"productName"	"skuName"	"serviceName"	"serviceId"	"serviceFamily"	"unitOfMeasure"	"type"	"isPrimaryMeterRegion"	"armSkuName"
"JPY"	"1024000"	"5.7834"	"5.7834"	"japaneast"	"JA East"	"2018/05/01 0:00:00"	"000a2755-e888-4145-9cdc-629fcd956d28"	"Pay-as-you-go Data at Rest"	"DZH318Z0BQPX"	"DZH318Z0BQPX/0018"		"Data Lake Store"	"Pay-as-you-go"	"Data Lake Store"	"DZH314H0T4NQ"	"Analytics"	"1 GB/Month"	"Consumption"	"True"	""
"JPY"	"0"	"6.0726"	"6.0726"	"japaneast"	"JA East"	"2018/05/01 0:00:00"	"000a2755-e888-4145-9cdc-629fcd956d28"	"Pay-as-you-go Data at Rest"	"DZH318Z0BQPX"	"DZH318Z0BQPX/0018"		"Data Lake Store"	"Pay-as-you-go"	"Data Lake Store"	"DZH314H0T4NQ"	"Analytics"	"1 GB/Month"	"Consumption"	"True"	""
"JPY"	"5120000"	"5.6388"	"5.6388"	"japaneast"	"JA East"	"2018/05/01 0:00:00"	"000a2755-e888-4145-9cdc-629fcd956d28"	"Pay-as-you-go Data at Rest"	"DZH318Z0BQPX"	"DZH318Z0BQPX/0018"		"Data Lake Store"	"Pay-as-you-go"	"Data Lake Store"	"DZH314H0T4NQ"	"Analytics"	"1 GB/Month"	"Consumption"	"True"	""
"JPY"	"102400"	"5.928"	"5.928"	"japaneast"	"JA East"	"2018/05/01 0:00:00"	"000a2755-e888-4145-9cdc-629fcd956d28"	"Pay-as-you-go Data at Rest"	"DZH318Z0BQPX"	"DZH318Z0BQPX/0018"		"Data Lake Store"	"Pay-as-you-go"	"Data Lake Store"	"DZH314H0T4NQ"	"Analytics"	"1 GB/Month"	"Consumption"	"True"	""
"JPY"	"0"	"129.8146"	"129.8146"	"japanwest"	"JA West"	"2022/09/01 0:00:00"	"000b2fef-5bfc-5640-83a7-40de273d4214"	"E64-16as v5 Spot"	"DZH318Z093WZ"	"DZH318Z093WZ/05CD"		"Virtual Machines Easv5 Series"	"E64-16as v5 Spot"	"Virtual Machines"	"DZH313Z7MMC8"	"Compute"	"1 Hour"	"Consumption"	"True"	"Standard_E64-16as_v5"

```

# おわりに
取得した価格の一覧をうまく使えば簡単に必要なAzureサービスの料金が割り出せる…はず？