Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
2
Help us understand the problem. What is going on with this article?
@yaegashi

azbill: Azure 利用明細・課金情報出力 CLI の紹介

はじめに

azbill という Azure クラウドサービスの利用明細・課金情報を出力してくれる CLI ツールを Go 言語で作ったので紹介します。主に Enterprise Agreement (EA) で Azure を導入している組織向けで、例えば部署ごと・リソースの種類ごと・タグごとの使用量を算出するといったようなコスト分析のためのデータを出力するツールです。

azbill を使うと EA の課金アカウントや Azure サブスクリプションに含まれるすべてのリソースの使用量・課金額を日次で取得し、CSV や JSONL の形式でファイルに保存できます。

このような利用明細の取得は Azure CLI でもできると思われるかもしれませんが、現行の Azure CLI は新しいバージョンの Consumption API に対応しておらず、予約 VM の利用状況といったような情報がとれません。 azbill を使えばそのような最新のメトリクスが取得できますし、CSV やフラットな JSON といったような、気の利いた出力が可能です。

azbill は現時点で次の種類の課金アカウントに対応しています。

  • Microsoft Online Services Program (個人のクレジットカードによる従量課金契約はこれに含まれます)
  • Enterprise Agreement (企業向けの年間契約)

インストール

azbill には Windows・macOS・Linux 向けにビルドされたバイナリがありますのでそれをダウンロードしご利用してください。ひとつの実行ファイルのみで動作します。

Go がインストールされているシステムであれば、次のコマンドでインストールすることもできます。

$ go get -u github.com/yaegashi/azbill

使用法

多くのコマンドラインオプションや環境変数による設定があります。 azbill -h で表示されるヘルプを参照してください。

$ azbill -h
Azure billing data exporter

Usage:
  azbill [command]

Available Commands:
  accounts      List billing accounts you have access to
  help          Help about any command
  invoices      List invoices
  login         Force auth-dev login
  subscriptions List subscriptions
  tenants       List tenants
  usage-details List usage details

Flags:
      --auth string         auth source [dev,env,file,cli] (env:AZBILL_AUTH, default:dev)
      --auth-dev string     auth dev store (env:AZBILL_AUTH_DEV, default:auth_dev.json)
      --auth-file string    auth file store (env:AZBILL_AUTH_FILE, default:auth_file.json)
      --client string       Azure client (env:AZURE_CLIENT_ID, default:4a034c56-da44-48ce-90db-039a408974bd)
      --config-dir string   config dir (env:AZBILL_CONFIG_DIR, default:~/.azbill)
      --format string       output format [csv,json,flatten,pretty] (env:AZBILL_FORMAT, default:csv)
  -h, --help                help for azbill
  -o, --output string       output file
  -q, --quiet               quiet
      --tenant string       Azure tenant (env:AZURE_TENANT_ID, default:common)
  -v, --version             version for azbill

Use "azbill [command] --help" for more information about a command.

認証

azbill loginAzure AD のデバイス承認フローによるサインインができます。 ブラウザで https://microsoft.com/devicelogin を開き、表示されたコードを入力した後にサインインしてください。

$ azbill login
2020/07/06 23:05:05 To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code HL94ZL7Y8 to authenticate.
2020/07/06 23:05:21 Saving auth-dev token in /Users/yaegashi/.azbill/auth_dev.json

ホームとは異なるテナントにゲストとしてサインインするには --tenant で指定してください。

$ azbill login --tenant l0wdev.onmicrosoft.com

認証トークンは ~/.azbill/auth_dev.json ファイルに保存されます。 --auth-dev オプションにより保存するファイルを指定できます。相対パスを指定した場合は --config-dir で指定したディレクトリ (デフォルト ~/.azbill) 内に保存されます。

また Azure Blob Storage の SAS つき URL を指定することもできます。これは CI/CD サービスの環境で azbill を実行する場合に便利です。 SAS つき URL は秘匿すべき情報ですので、 --auth-dev ではなく環境変数 AZBILL_AUTH_DEV で設定するようにしてください。

Azure SDK for Go がサポートする他の認証方式を使うこともできます。 Azure CLI で認証済みの場合は --auth cli を使うのが簡単です。 Azure CLI で生成したサービスプリンシパルの JSON ファイルを使う場合は --auth file を使い、ファイルの場所を --auth-file で指定してください。

出力フォーマット

出力フォーマットは --format で指定します。基本は csv または json の 2 種類です。カンマ区切りで flatten または pretty を追加指定できます。

--format 説明
csv 1レコードが 1 行のCSV 形式で出力します (デフォルト)
json 1 レコードが 1 JSON オブジェクトで、それらを改行で区切った JSONL 形式で出力します
json,flatten 入れ子でない JSON オブジェクトを出力します。
flatten でも同じ意味です。
json,pretty インデントつきの JSON オブジェクトを出力します。
pretty でも同じ意味です。
json,flatten,pretty 入れ子でないインデントつきの JSON オブジェクトを出力します。
flatten,pretty でも同じ意味です。

JSON 形式

次は --format json,pretty を指定した時の 1 レコードの出力です。 JSON 形式の場合、丸め誤差を避けるために数字は文字列で表現されていることに注意してください。

{
  "properties": {
    "billingPeriodStartDate": "2020-05-03T00:00:00Z",
    "billingPeriodEndDate": "2020-06-02T00:00:00Z",
    "billingProfileId": "/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
    "billingProfileName": "Pay-As-You-Go",
    "subscriptionId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
    "subscriptionName": "Pay-As-You-Go",
    "date": "2020-06-01T00:00:00Z",
    "meterId": "d54686f0-77ff-43f3-9e7c-2099030d32a7",
    "meterDetails": {
      "meterName": "Public Queries",
      "meterCategory": "Azure DNS",
      "meterSubCategory": "",
      "unitOfMeasure": "10000000"
    },
    "quantity": "0.000997",
    "effectivePrice": "55.3250345781466",
    "cost": "0.055159059474412",
    "unitPrice": "0",
    "billingCurrency": "JPY",
    "resourceLocation": "Unknown",
    "consumedService": "Microsoft.Network",
    "resourceId": "/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/dns/providers/Microsoft.Network/dnszones/l0w.dev",
    "resourceName": "l0w.dev",
    "resourceGroup": "dns",
    "offerId": "MS-AZR-0003P",
    "isAzureCreditEligible": false,
    "publisherType": "Azure",
    "chargeType": "Usage",
    "frequency": "UsageBased"
  },
  "id": "/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/providers/Microsoft.Billing/billingPeriods/202006/providers/Microsoft.Consumption/usageDetails/de545724-82e8-f099-bc3b-53c5f0ae1711",
  "name": "de545724-82e8-f099-bc3b-53c5f0ae1711",
  "type": "Microsoft.Consumption/usageDetails",
  "tags": null,
  "kind": "legacy"
}

フラット形式

次は --format json,flatten,pretty を指定した時の出力です。フラットな JSON オブジェクトとなります。

{
  "id": "/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/providers/Microsoft.Billing/billingPeriods/202006/providers/Microsoft.Consumption/usageDetails/de545724-82e8-f099-bc3b-53c5f0ae1711",
  "kind": "legacy",
  "name": "de545724-82e8-f099-bc3b-53c5f0ae1711",
  "properties.billingCurrency": "JPY",
  "properties.billingPeriodEndDate": "2020-06-02T00:00:00Z",
  "properties.billingPeriodStartDate": "2020-05-03T00:00:00Z",
  "properties.billingProfileId": "/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "properties.billingProfileName": "Pay-As-You-Go",
  "properties.chargeType": "Usage",
  "properties.consumedService": "Microsoft.Network",
  "properties.cost": "0.055159059474412",
  "properties.date": "2020-06-01T00:00:00Z",
  "properties.effectivePrice": "55.3250345781466",
  "properties.frequency": "UsageBased",
  "properties.isAzureCreditEligible": false,
  "properties.meterDetails.meterCategory": "Azure DNS",
  "properties.meterDetails.meterName": "Public Queries",
  "properties.meterDetails.meterSubCategory": "",
  "properties.meterDetails.unitOfMeasure": "10000000",
  "properties.meterId": "d54686f0-77ff-43f3-9e7c-2099030d32a7",
  "properties.offerId": "MS-AZR-0003P",
  "properties.publisherType": "Azure",
  "properties.quantity": "0.000997",
  "properties.resourceGroup": "dns",
  "properties.resourceId": "/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/dns/providers/Microsoft.Network/dnszones/l0w.dev",
  "properties.resourceLocation": "Unknown",
  "properties.resourceName": "l0w.dev",
  "properties.subscriptionId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "properties.subscriptionName": "Pay-As-You-Go",
  "properties.unitPrice": "0",
  "tags": null,
  "type": "Microsoft.Consumption/usageDetails"
}

CSV 形式

次は --format csv を指定した時の出力です。

id,kind,name,properties.accountName,properties.accountOwnerId,properties.additionalInfo,properties.billingAccountId,properties.billingAccountName,properties.billingCurrency,properties.billingPeriodEndDate,properties.billingPeriodStartDate,properties.billingProfileId,properties.billingProfileName,properties.chargeType,properties.consumedService,properties.cost,properties.costCenter,properties.date,properties.effectivePrice,properties.frequency,properties.invoiceSection,properties.isAzureCreditEligible,properties.meterDetails.meterCategory,properties.meterDetails.meterName,properties.meterDetails.meterSubCategory,properties.meterDetails.serviceFamily,properties.meterDetails.unitOfMeasure,properties.meterId,properties.offerId,properties.partNumber,properties.planName,properties.product,properties.productOrderId,properties.productOrderName,properties.publisherName,properties.publisherType,properties.quantity,properties.reservationId,properties.reservationName,properties.resourceGroup,properties.resourceId,properties.resourceLocation,properties.resourceName,properties.serviceInfo1,properties.serviceInfo2,properties.subscriptionId,properties.subscriptionName,properties.term,properties.unitPrice,tags,type
/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/providers/Microsoft.Billing/billingPeriods/202006/providers/Microsoft.Consumption/usageDetails/de545724-82e8-f099-bc3b-53c5f0ae1711,legacy,de545724-82e8-f099-bc3b-53c5f0ae1711,,,,,,JPY,2020-06-02T00:00:00Z,2020-05-03T00:00:00Z,/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX,Pay-As-You-Go,Usage,Microsoft.Network,0.055159059474412,,2020-06-01T00:00:00Z,55.3250345781466,UsageBased,,false,Azure DNS,Public Queries,,,10000000,d54686f0-77ff-43f3-9e7c-2099030d32a7,MS-AZR-0003P,,,,,,,Azure,0.000997,,,dns,/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/dns/providers/Microsoft.Network/dnszones/l0w.dev,Unknown,l0w.dev,,,XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX,Pay-As-You-Go,,0,{},Microsoft.Consumption/usageDetails

1 行目の CSV ヘッダは json,flatten 指定時のキーと同じものです。 JSON 形式では省かれたキーもすべて含まれています。エンコーディングは BOM つきの UTF-8 で、改行コードは CRLF であるため Microsoft Excel で直接開くことができます。

アクセス可能な課金アカウントを CSV 形式で出力します。

$ azbill accounts

アクセス可能な Azure AD テナントを JSONL 形式で出力します。

$ azbill tenants --format json

アクセス可能なサブスクリプションをフラットな JSONL 形式で出力します。

$ azbill subscriptions --format flatten

Microsoft Online Service Program アカウント: サブスクリプション XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX の 2020 年 6 月の利用明細をフラットなインデントした JSONL 形式で出力します。

$ azbill usage-details --format flatten,pretty -S XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX --start 2020-06-01 --end 2020-06-30 -o usage.jsonl
2020/07/06 23:43:59 Loading auth-dev token in /Users/yaegashi/.azbill/auth_dev.json
2020/07/06 23:43:59 Requesting with consumption.UsageDetailsClient
2020/07/06 23:43:59    scope: "subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
2020/07/06 23:43:59   filter: "properties/usageStart eq '2020-06-01' and properties/usageEnd eq '2020-06-30'"
2020/07/06 23:44:11 Writing to "usage.jsonl" in json,flatten,pretty
.                                                       138 records
2020/07/06 23:44:11 Done 138 records in 16.893702ms, 8168.724653 records/sec

Enterprise Agreement アカウント: 課金アカウント XXXXXXXX のビリング期間 202006 の利用明細を CSV 形式で出力します。

$ azbill usage-details --format csv -A XXXXXXXX -P 202006 -o usage.csv
2020/07/06 23:45:15 Loading auth-dev token in /Users/yaegashi/.azbill/auth_dev.json
2020/07/06 23:45:15 Requesting with consumption.UsageDetailsClient
2020/07/06 23:45:15    scope: "providers/Microsoft.Billing/billingAccounts/XXXXXXXX/providers/Microsoft.Billing/billingPeriods/202006"
2020/07/06 23:45:15   filter: ""
2020/07/06 23:45:34 Writing to "usage.csv" in csv
..................................................     5000 records
..................................................    10000 records
..................................................    15000 records
....................                                  17001 records
2020/07/06 23:46:38 Done 17001 records in 1m4.325743007s, 264.295431 records/sec

azbill の開発

azbill の CLI コマンド階層およびフラグ処理には cobra-comder を使用しています (cobra-cmder で Go の CLI を簡単に作る を参照)。

azbill では Azure SDK for Go を使用していますが、現行の SDK ではまだ対応していない新しいバージョンの Azure REST API を使用しています。 バージョン 2019-11-01 の Consumption 利用明細 API などです。

このため AutoRest ツールにより、新しいバージョンの OpenAPI 仕様書から SDK をコード生成しています。生成されたコードは azure-sdk-for-go ディレクトリにあります。
生成を自動的に行うシェルスクリプトが gen.sh です。

このような AutoRest による Azure SDK コードの生成については、別の記事で詳しく説明したいと思います。

2
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
yaegashi
Linux や Unix が得意で低レベルなことが好きなエンジニアです
bandainamcostudios
バンダイナムコスタジオは、家庭用ゲームソフト、モバイルコンテンツ、の企画・開発・運営、ゲームに関する技術研究・開発を行っている会社です。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
2
Help us understand the problem. What is going on with this article?