[Oracle Cloud] コンパートメントごとの利用料金をcsv形式で出力する

# やったこと

- 2020/5/2追記：コスト分析のUIが一新されて、日別のコンパートメント単位の積み上げグラフを見ることができるようになっていました。

たくさんの人がサンドボックス的に利用しているOracle Cloud環境があり、いつ誰が何をどのくらいつかっていたのか調べようとした。
OCIのWEBコンソールから、アカウント管理 → コスト分析 を利用して、指定期間のトータルの利用料金を見ることができる。コンパートメント単位でフィルターすることができる。日付指定もできる。

ただ、指定期間の使用料金の(日単位)推移グラフをみることができなかった。これをコンパートメント単位の積み上げグラフで見たかった。

こういうのが見たかったのだ。
![cost01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456818/239e9eb8-7c7f-1b58-0a61-f15258108da9.png)


いろいろ調べた結果、今のところ、[Oracle Cloud Account Metering REST API](https://docs.oracle.com/en/cloud/get-started/subscriptions-cloud/meter/api-resource-usage-cost.html) を使用して、直接API参照する方法しかなさそうだった。

でも、これでできそうなので、csvファイルに落とす方法までを書いてみる。

# 参考にしたもの
[Oracle Cloud Account Metering REST API](https://docs.oracle.com/en/cloud/get-started/subscriptions-cloud/meter/api-resource-usage-cost.html)
[Aquire and Analyse your OCI Consumption Data](https://www.oc-blog.com/2019/10/11/aquire-and-analyse-your-oci-consumption-data/)
[Oracle Cloud Infrastructure REST APIをリクエストしてみた vol.3: Account Metering REST API編](https://cloudii.atomitech.jp/entry/oracle_metering_api) → 一番参考になりました！

# 前提
・JSONファイルを扱うためにjqをインストールしてます
・oci cliはインストール済みの前提です

各インストール方法は省略します。

# 方法
curlコマンドを使って、Oracle cloud Account Metring REST APIから直接取得する。DAILYを指定すると、指定期間の、日単位・サービス単位の課金情報が取得できる。

エンドポイント：https://itra.oraclecloud.com
メソッド：GET
PATH：/metering/api/v1/usagecost/{accountId}

出力内容は、コンパートメントIDでフィルターができる。が、コンパートメントIDは自分で指定する必要があるので、oci cliを使ってコンパートメントの一覧を取得→ループさせて、コンパートメント単位でリクエストを送って取得した。

# 必要な権限
1. 課金情報を見る権限を持ってるIDCSユーザ (OCI_Administratorsグループ所属) で検証してます。curlコマンド実行時に認証情報(ID/パスワード)を渡します。
2. OCI CLIコマンドでコンパートメント一覧を取得するため、OCI CLIコマンドは、"inspect all-resources in tenancy"権限を付与したユーザのAPIキーを使ってます。

# 必要な情報
課金情報は、以下のコマンドで取得できます。指定するパラメータの値をどこから取得すればいいのかかなり迷ったので、説明していきます

```
IDCS_AUTH=<ユーザ名>:<パスワード>
IDCS_GUID=idcs-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
ACCOUNT_ID=cacct-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
compartment_ocid="ocid1.compartment.oc1..aaaaaaaaxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
start_time="$(date -d '1 month ago' '+%Y-%m-%d')T00:00:00.000" # 一か月前
end_time="$(date '+%Y-%m-%d')T00:00:00.000" # 本日 0:00

curl -s -X GET -u ${IDCS_AUTH} -H "X-ID-TENANT-NAME:${IDCS_GUID}" 'https://itra.oraclecloud.com/metering/api/v1/usagecost/'${ACCOUNT_ID}'/tagged?tags=ORCL:OCICompartment='${compartment_ocid}'&startTime='${start_time}'&endTime='${end_time}'&usageType=DAILY&timeZone=Asia/Tokyo'
```
## IDCS_AUTH変数に指定する値
IDCSユーザのユーザ名とパスワードをコロンでつなげます。ユーザ名がfoo@bar.comで、パスワードがHoge_Hoge_11の場合、以下のように指定します

IDCS_AUTH=foo@bar.com:Hoge_Hoge_11

## IDCS GUID変数に指定する値
[サービス検出ユース・ケース](https://docs.oracle.com/cd/E97706_01/Content/MyServices/Tasks/servicediscovery.htm)のノート部分に記載されている、「IDCS GUIDを取得するには」を参考に取得します。なんと、URLから値を取得します

>My Servicesダッシュボードのユーザー・ページに移動し、「アイデンティティ・コンソール」をクリックします。 ブラウザ・アドレス・フィールドのURLには、アイデンティティ・ドメインのIDCS GUIDが表示されます。

My Servicesダッシュボードは、IDCSユーザでOCIコンソールにログイン後、画面右上の人マークから、「サービス・ユーザー・コンソール」を選択します。
(OCIユーザでログインするとリンクが表示されません。また、ホームリージョン以外のリージョンが選択されている場合も表示されないみたいです。)

![oci-idcs.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456818/775bcd41-775b-3e88-1d5c-90a3481cbcd3.png)

IDCSの管理コンソールのリンクを押下します
![oci-idcs2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456818/239a2da6-a18e-0cd7-1e1b-eb74c0d27fe4.png)

そして、なんとリンク先のURLから値を確認するそうです。。
![oci-idcs3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456818/2f95ec96-a2fe-cfd0-e0d3-ea7d3f0daa43.png)


## ACCOUNT_ID変数に指定する値
これがまた面倒。ACCOUNT_IDは、APIから取得する。取得コマンドは以下。

```
IDCS_AUTH=<ユーザ名>:<パスワード> # IDCSアカウントのユーザ名とパスワード
IDCS_GUID=idcs-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # 上記記載の方法で値を取得

 curl -s -X GET -u ${IDCS_AUTH} -H "X-ID-TENANT-NAME:${IDCS_GUID}" 'https://itra.oraclecloud.com/itas/'${IDCS_GUID}'/myservices/api/v1/serviceEntitlements' |jq -r '.items[]."cloudAccount"."id"' |sort -u
----------　出力 ----------
cacct-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
→ cacct-から始まるIDが出力されれば成功

```
-- 追記 --
いちいちAPIをたたかなくてもMy ServicesダッシュボードのURLから値を持ってこれそう。
URLが、myservices-[Account ID (cacct-から始まる文字列)].console.oraclecloud.comになってるので、[Account ID]部分をコピペ。
![oci-idcs4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456818/e293943a-5526-99fd-965c-b69d9fa52b9c.png)


## compartment_ocid
コンパートメントのOCIDはoci cliコマンドを使用して一覧を取得します。

```
以下のコマンドで取得しました。

oci search resource structured-search --raw-output --query-text 'query all resources' --query 'data.[items[?"resource-type"==`Compartment`]] |[] |[]'  |jq -r '["display-name","identifier"],(. [] |[."display-name",."identifier"]) |@csv'

↓のように出力されれば成功
"display-name","identifier"
"compartment_1","ocid1.compartment.oc1..xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
"compartment_2","ocid1.compartment.oc1..xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
…
```

## start_timeとend_time
期間を指定します。ここでは、1か月前の情報を取得すために、start_timeを1か月前に指定してます。

# サンプル

まとめると、こんな感じで出力してます。課金情報だけ見れればいいので出力を以下に絞りました
・startTimeUtc
・serviceName
・computedAmount

```
# vi test.sh
-----------------------------------------------------------------
#!/bin/bash

IDCS_AUTH=<ユーザ名>:<パスワード>
IDCS_GUID=idcs-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
ACCOUNT_ID=cacct-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
start_time="$(date -d '1 month ago' '+%Y-%m-%d')T00:00:00.000"
end_time="$(date '+%Y-%m-%d')T00:00:00.000" # 本日 0:00

oci search resource structured-search --raw-output --query-text 'query all resources' --query 'data.[items[?"resource-type"==`Compartment`]] |[] |[]'  |jq -r '["display-name","identifier"],(. [] |[."display-name",."identifier"]) |@csv' |sort |while read line
do
  compartment_name=$(echo ${line} |tr -d '"' |awk -F, '{print $1}')
  compartment_ocid=$(echo ${line} |tr -d '"' |awk -F, '{print $2}')
  connect_uri='https://itra.oraclecloud.com/metering/api/v1/usagecost/'${ACCOUNT_ID}'/tagged?tags=ORCL:OCICompartment='${compartment_ocid}'&startTime='${start_time}'&endTime='${end_time}'&usageType=DAILY&timeZone=Asia/Tokyo'

   curl -s -X GET -u ${IDCS_AUTH} -H "X-ID-TENANT-NAME:${IDCS_GUID}" ${connect_uri} |jq -r '."items"[]' |jq -r '[."startTimeUtc",."serviceName",(."costs"[] |."computedAmount")] | @csv' |sort |awk '{print "\"'${compartment_name}'\"," $0}'
done
-----------------------------------------------------------------
# ./test.sh
↓みたいに出力できたら成功です。
"compartment_1","2019-09-08T00:00:00.000","ADWC",1065.1022845413
"compartment_1","2019-09-08T00:00:00.000","ADWC",124.59366342617
"compartment_1","2019-09-08T00:00:00.000","COMPUTEBAREMETAL",0
"compartment_1","2019-09-08T00:00:00.000","COMPUTEBAREMETAL",0

でも実は、これだけだとrootコンパートメント直下に作成したリソースがでてこないので、
rootコンパートメント直下にリソースを作成している場合は、compartment_ocidにテナント
のOCIDを指定して同じように実行してあげる必要があります

```

# 余談
このcsvを定期的に出力 & オブジェクトストレージにつっこんで、Always FreeのADWから外部表で参照して、APEXで見ればいい感じに管理できるかも！とAPEX構成しようとしたら↓のエラーがでて撃沈。

![adw-error.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456818/92f04147-ed7f-271f-5712-8b273e1f8af2.png)

少し前まで構成できてたのになぁ。。