[小ネタ] Boto3 で取得した AWS情報を素直に Markdownテーブルに表示する Pythonスクリプト

2020.03.01

Boto3 で AWSのリソース情報を取得して、 Notebookや Markdownにまとめる記事を書いてきました。

各AWSのリソースの種類ごとにテーブルの構造を考えたりしていたので、 もうちょっと汎用的なもの作れないかな と感じたのが今回のモチベーションです。

そこで以下のような入力 → 出力 を行うスクリプトを作ってみました (要 Pandas ≧1.0.0 )。 辞書(or 辞書のリスト) を見出し付きで Markdownテーブルに表示します。

目次

  1. スクリプト
  2. 利用例
    1. VPC
    2. EC2インスタンス
    3. S3バケット
    4. CloudFront ディストリビューション
  3. 終わりに

スクリプト

dict_to_md.py

import pandas as pd


def dict_to_md(dc,
               title="TOP", depth=1, format="md"):
    """
    dict(もしくは list) を 見出し付き Markdownテーブルに変換する

    Args:
        dc ([type]): 変換対象の (dict, もしくは list)
        title (str, optional): トップ見出しのタイトル. Defaults to "TOP".
        depth (int, optional): トップ見出しの深さ. Defaults to 1.
        format (str, optional): 見出しのフォーマット ("md" もしくは "org") . Defaults to "md".
    """
    # format (md or org)
    head_str = "*" if format == "org" else "#"
    # データ変換
    items = []
    if type(dc) == dict:
        # ### dict は items() へ変換
        items = dc.items()
    elif type(dc) == list:
        # ### list は タプルリストへ変換
        items = [("#{}".format(i+1), v) for i, v in enumerate(dc)]
    # 表示可能アイテム、表示不可能アイテムに分類
    displayable = [(k, v) for k, v in items if type(v) not in [dict, list]]
    not_displayable = [(k, v) for k, v in items if type(v) in [dict, list]]
    # 見出しを print
    print("{} {}".format(head_str * depth, title))
    # 表示可能アイテムを print
    if displayable:
        print(pd.DataFrame(displayable,
                           columns=["key", "value"]).to_markdown(showindex=False))
    # 表示不可能アイテムを parse
    for k, v in not_displayable:
        dict_to_md(v, title=k, depth=depth+1, format=format)

利用例

以下実行した上で出力例を載せます。

from dict_to_md import dict_to_md
import boto3

VPC

ec2_client = boto3.client('ec2')
vpcs = ec2_client.describe_vpcs()['Vpcs']
dict_to_md(vpcs[0], title="VPC", format="md")

また、辞書のリストにも対応しています。 以下のように全てのVPC情報も取得できます。

dict_to_md(vpcs, title="All VPCs", format="org")

※表示は普段私が使っている org-mode シンタックス( *# と変換するとそのまま Markdown記法、 ... 部分は折りたたみ)

EC2インスタンス

instances = sum([group['Instances'] for group in ec2_client.describe_instances()['Reservations']], [])
dict_to_md(instances, title="All EC2 Instances", format="org")

S3バケット

s3_client = boto3.client('s3')
dict_to_md(s3_client.list_buckets()['Buckets'], title="S3 Buckets", format="org")

CloudFront ディストリビューション

cf_client = boto3.client('cloudfront')
dict_to_md(cf_client.list_distributions()['DistributionList']['Items'], title="CloudFront distributions", format="org")    

終わりに

boto3のAWS情報取得用に作成しましたが、 list, dict からなるオブジェクトであれば 表示ができるので、他にも利用はできそうです。

改善としては Tags のように同じキー構造の dict しか持たない list について 1つのテーブルに表現することで見出しの深さを抑えられそうです。

この記事が少しでもどなたかのお役に立てば幸いです。