LoginSignup
5
3

More than 3 years have passed since last update.

シェルに入るだけでEC2インスタンスが見れるようにPythonとxonshでよしなにした

Last updated at Posted at 2020-06-10

はじめに

みなさんはTerraformの勉強は進んでますか?(威圧)

僕は始めたばかりで今必死にこの本を読んでいます
結構楽しいし、AWS環境が自由に触れるとインフラの勉強が捗るのでいいなぁと思っている今日この頃ですが、勉強環境に一つだけ不満がありました

いちいちAWSのコンソール見るのめんどくさすぎ!!!

書籍でも書かれていますが(詳細は著作権が怖いので明言は避けます)基本的にAWSのインスタンスを確認するにはWeb UIによるコンソールから確認していくと思います

普段はそれで全然いいんですが、なにせ
「Terraformでインスタンス作って。。。んで?次は削除?はいはい。。。んで?またコンソールかぁ。。。」
というのをKindle見ながらやるのは結構苦痛でした

しかも知らないインスタンスに興味もないし、触りたくもないのでただ表示する機能だけほしい
awc cliは使ってもいいけど、フィルタを噛まさずにWeb UIっぽいくなってほしい

とりあえず現状はEC2インスタンスしか立てていないので、それくらいなら一覧表示するのは楽勝だから作っちゃお!という感じです

準備

リポジトリ作成

まずは準備として、Terraform用リポジトリを作成します
リポジトリ作成はTerraformの性質上、ソースコード管理が基本になるので当たり前かもしれません
それならばそのリポジトリにPythonインスタンス表示スクリプトを埋め込めば楽かと思います

僕の場合は、練習用として作ったリポジトリなので、スクリプトをリポジトリに埋め込んじゃいました
ただし、書籍の著作権に関わるのでリポジトリは公開できません
ご了承お願いいたします

direnv、dotenvを使ってAWSのトークンを管理しよう!

direnv

direnvは「ディレクトリに入るだけでaliasや環境が勝手に読み込まれる!」いいやつです

dotenv

僕はいつもdirenvと一緒にdotenvも使います
npmから入れた気がするので、ちょっと面倒ですがbrewでnpmを入れる方法が揃っているのでMacユーザは楽に入るかと思います

dotenvでAWSのIAM情報を保持する

ここまで読まれた方は恐らくAWSのIAM情報に触れたことがある方かと思います
またはTerraform本を読んでる方かもしれません
ですからIAM情報の

  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY
  • AWS_DEFAULT_REGION

が何を意味するかは説明を割愛します
これらのトークンの意味はを詳しく知りたい方は公式ページをご確認ください

トークン情報が取得できた、または冒頭に書いた実践Terraformの本で言えば、2章に入った方から次に進んでもらえるとスムーズかと思います

実際にdotenvを使ってトークン情報を記述します
リポジトリrepoの直下に.envファイルを作成します

注意点として、このままではgit上に.envファイルが上がってしまうので、.gitignoreにちゃんと反映してください

repo/.gitignore
.env
repo/.env
AWS_ACCESS_KEY_ID=AAAAAAAAAAAAAAAAAAAA
AWS_SECRET_ACCESS_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
AWS_DEFAULT_REGION=ap-northeast-1

ちゃんと動くかの確認方法

direnvでdotenvを使う

次はdirenvでdotenvを読み込ませ、作業ディレクトリ下で自動に設定を反映させる方法です
direnvでは.envrcで情報を読み取ります

repo/.envrc
dotenv
xonsh --rc xonshrc.xsh

一行目のdotenvはdirenvで.envを自動に読み込む設定になります

説明は後述するので省きますが、xonshというshellを利用します
こちらはPythonスクリプトがターミナル上で簡単に動かせるため、PythonでAWSのスクリプトを書いたら結構便利にshellで走らせられるといった具合です

まとめ

以上でディレクトリに入るだけでAWSへ簡単に繋げられるような設定です
普段遣いしても不便はないし、Terraformの開発も大分楽になります

PythonでEC2インスタンス一覧表示スクリプトを使おう!

direnv、dotenvの設定が完了したら、早速Pythonでインスタンスを表示するスクリプトを動かしてみましょう

repo/describe_instances.py
import os
import boto3
import pandas as pd


def create_session():
    client = boto3.session.Session(
        aws_access_key_id=os.environ["AWS_ACCESS_KEY_ID"],
        aws_secret_access_key=os.environ["AWS_SECRET_ACCESS_KEY"],
        region_name=os.environ["AWS_DEFAULT_REGION"]
    ).client("ec2")

    return client


def to_pandas():
    response = create_session().describe_instances()
    df = pd.io.json.json_normalize(
        pd.DataFrame(
            pd.DataFrame(
                response["Reservations"]
            ) \
                .apply(lambda r: r.str[0])
                .Instances \
                .values
        )[0]
    )
    df.loc[df["Tags"].isnull(), "Tags"] = df.loc[df["Tags"].isnull(), "Tags"].apply(lambda x: [])
    df.Tags = df.Tags.apply(lambda r: {t["Key"]: t["Value"] for t in r} if len(r) > 0 else {})
    df = pd.concat([df.drop(["Tags"], axis=1), df["Tags"].apply(pd.Series)], axis=1)
    df["SecurityGroups"] = df["SecurityGroups"].apply(lambda r: ", ".join([i["GroupName"] for i in r]))

    return df[["Name",
               "ImageId",
               "InstanceType",
               "Placement.AvailabilityZone",
               "State.Name",
               "PublicDnsName",
               "PublicIpAddress",
               "KeyName",
               "Monitoring.State",
               "LaunchTime",
               "SecurityGroups",
               "Owner",
               ]].sort_values(["LaunchTime",
                               "State.Name"],
                              ascending=[False,
                                         True])


if __name__ == "__main__":
    print(to_pandas())

Pythonスクリプトを保存し

python describe_instances.py

を実行してみてください
インスタンスがDataframe表示されて一覧表示が可能になります

Name ImageId InstanceType Placement.AvailabilityZone State.Name PublicDnsName PublicIpAddress KeyName Monitoring.State LaunchTime SecurityGroups Owner
linux-adfdsf ami-2dfdfs t2.medium ap-northeast-1a running ec2-25-25-25-25.ap-northeast-1.compute.amazonaws.com 111.111.111.1 dfdfdest disabled 2020-01-10T01:01:32+0000 mdfsfsest NaN

xonshをdirenvで一時的に使おう!

xonshはPythonで設定をカスタマイズできるshellです
Pythonユーザが使っていることが多く、標準設定でもかなり便利なのでおすすめできます
(ちなみに僕は普段遣いはしていません。なんとなくです。)

導入方法は簡単で、Pythonで利用されるパッケージマネージャpipを使うだけです

pip install xonsh

先程の.envrcにxonshの記述がありましたが、あれは一時的にxonshにshellを乗り換えて、xonsh上でインスタンス一覧表示スクリプトを動かしちゃおう!という試みです

なぜxonshを一時利用するのか

xonshを一時利用する理由ですが、単刀直入に言うとshell上でのPython呼び出しのオーバーヘッドが大きすぎることが主な理由です
AWSへの接続、一覧の加工、表示をいちいちshell呼び出しからするのは非常に非効率なので、変数すらshellに保存しておけるxonshを選びました

xonshの設定

xonshはxonshrcファイルを作ることで便利にカスタマイズできます
ここでは公式のxonshrcに変更を加えて、自作のインスタンス一覧表示スクリプトが簡単に動かせるようにします

repo/xonshrc.xsh
# adjust some paths
$PATH.append('/home/scopatz/sandbox/bin')
$LD_LIBRARY_PATH = ['/home/scopatz/.local/lib', '/home/scopatz/miniconda3/lib', '']

# alias to quit AwesomeWM from the terminal
def _quit_awesome(args, stdin=None):
    lines = $(ps ux | grep "gnome-session --session=awesome").splitlines()
    pids = [l.split()[1] for l in lines]
    for pid in pids:
        kill @(pid)

aliases['qa'] = _quit_awesome

# some customization options, see https://xon.sh/envvars.html for details
$MULTILINE_PROMPT = '`·.,¸,.·*¯`·.,¸,.·*¯'
$XONSH_SHOW_TRACEBACK = True
$XONSH_STORE_STDOUT = True
$XONSH_HISTORY_MATCH_ANYWHERE = True
$COMPLETIONS_CONFIRM = True
$XONSH_AUTOPAIR = True


# ここからオジリナルのxonshrc

import os
import sys
sys.path.append(os.path.dirname(os.path.abspath(__file__)))

# 自作関数をインポート
import describe_instances
_df = describe_instances.to_pandas()
# 0から5列目までを表示
print(_df[_df.columns[0:5]])

Tips

これで、ディレクトリに移動するだけでインスタンス一覧表示が自動に行われ、さらには

describe_instances.to_pandas()

をxonshに流し込むだけでDataframeになった一覧が取得できます

便利なので是非使ってみてください〜〜〜

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3