Goで複数のAWSアカウントの全リージョンのEC2の情報をもってくるコマンドを書いた

こちらの記事 [AWS - bashだけで簡単ec2 ssh接続（踏み台対応） - Qiita](http://qiita.com/gujauja/items/a959e0b217f040eafe6f)に触発されて、前から自分がほしかったものを書いてみた。

今の職場ではプロジェクトごとにAWSのアカウントが分かれており、さらに海外向けもあるので複数のリージョンを使っていたりで、管理するのがめんどくさい。都度プロファイルとリージョンを指定してコマンドを叩くのも面倒なので、credentialファイルにある全アクセスキーの全リージョンにあるEC2インスタンスの情報をとにかくもってきたい。

その後は[peco](https://github.com/peco/peco)に任せて、SSH接続するなり、「m3.medium」とかで絞り込んでこのインスタンスタイプのEC2はこれだけあるのかとか見ながらニヤニヤするとかしたい。

ただ[EC2対応リージョン](https://docs.aws.amazon.com/ja_jp/general/latest/gr/rande.html#ec2_region)が現時点で8つあり、さらに複数のアカウントとなるとAPIを何度も投げる必要があり、シーケンシャルに実行するととても待ってられない。そこでGoと[aws-sdk-go](https://github.com/aws/aws-sdk-go)を使って、並列でインスタンス情報を持ってくるコマンドを書いてみた。アカウントが増えても大体2秒程度で結果が取れる。

[sudix/go-ec2list](https://github.com/sudix/go-ec2list)

（英語でREADMEも書いてみたけどむちゃくちゃなので誰か直してほしい・・・。）

# インストール

[リリースページ](https://github.com/sudix/go-ec2list/releases)にgoxでクロスコンパイルしたバイナリを置いてみたので、自分のプラットフォームに合ったバイナリをダウンロードしてきて、パスの通ったところに置けばいい。そのままだと名前が長すぎるのでリネームした方がいい。以下では`go-ec2list`にリネームしたとして説明していく。

なお、Goの開発環境があれば`go get github.com/sudix/go-ec2list`でもいい。

# credentialファイルの準備

`aws configure`コマンドとかでcredentialファイルを設定する。使いたいアカウント分だけ設定しておく。設定したら以下のようになっているはず。

__~/.aws/credentials__

```
[default]
aws_access_key_id = XXXXXXXXXXXX
aws_secret_access_key = XXXXXXXXXXXXXXXXXXXXXXX

[project1]
aws_access_key_id = XXXXXXXXXXXX
aws_secret_access_key = XXXXXXXXXXXXXXXXXXXXXXX

[project2]
aws_access_key_id = XXXXXXXXXXXX
aws_secret_access_key = XXXXXXXXXXXXXXXXXXXXXXX
```

なお環境変数での指定には対応していない。

# 実行

とりあえず実行してみる。コマンド叩くだけ。

```
$ go-ec2list
```

# 結果

結果は以下のような感じで出力されるはず。（値はダミー）

```
admin_server     i-xxxxxxxxx      52.xxx.xxx.xxx   172.xxx.xxx.xxx   default   ap-southeast-1a t2.small        running
api_server1 i-xxxxxxxxx      52.xxx.xxx.xxx    172.xxx.xxx.xxx   default   ap-southeast-1a t2.small        running
api_server2 i-xxxxxxxxx      52.xxx.xxx.xxx    172.xxx.xxx.xxx     default   ap-southeast-1a t2.micro        running
app_server1     i-xxxxxxxxx      52.xxx.xxx.xxx   172.xxx.xxx.xxx   project1 ap-southeast-1b m1.small        running
app_server2  i-xxxxxxxxx      52.xxx.xxx.xxx    172.xxx.xxx.xxx   project1 ap-southeast-1a m3.medium       running
app_server1     i-xxxxxxxxx      52.xxx.xxx.xxx   10.xxx.xxx.xxx   project2 ap-southeast-1b m1.small        running
hoge_server1  i-xxxxxxxxx              10.xxx.xxx.xxx      project2 ap-northeast-1c t2.micro        stopped
nat_server i-xxxxxxxxx      52.xxx.xxx.xxx   172.xxx.xxx.xxx    default   ap-southeast-1b t2.micro        stopped
```

Nameタグの昇順でソートしてから表示している。各行はタブ区切りとなっていて、出力される値は以下の順となっている。

- Instance Name
- Instance ID
- Public IP
- Private IP
- Profile Name
- Availability zone
- Instance type
- Instance state

# キャッシュ

APIアクセスを待っても2秒程度で表示されるので自分が使う分にはこれで問題なかったけど、毎回数十回とかAPIアクセスするのはさすがに悪いと思ったので、キャッシュ機能も追加した。デフォルトでは無効だけど、`-cachemin`オプションにキャッシュ有効期間（分単位）を指定すると、その間はキャッシュがあればそこから前回取得した情報を再表示する。

これだと10分間キャッシュ有効。

```
$ go-ec2list -cachemin 10
```

インスタンスを追加などして、キャッシュを更新したい場合は`-refresh`を追加すれば、cacheminの値に関係なく最新情報を取得してくる。

```
$ go-ec2list -cachemin 10 -refresh
```

キャッシュは単なるファイルなので、手動で消してもいい。ファイルは以下に作られる。

```
$HOME/.go-ec2list/cache
```


# pecoとの連携など

例えば全てのEC2インスタンスがパブリックにアクセス可能で、自分のマシンの公開鍵も登録しているとすると、

```
alias ec2="go-ec2list -cachemin 30 | peco | cut -f3 | xargs -I{} sh -c 'ssh "ec2-user@{}" </dev/tty' ssh"
```

こんな感じのaliasを登録すれば、pecoで絞り込んでSSHログインできる。

でも実際は踏み台経由でアクセスしたりするだろうし、インスタンス名やプロファイル名をみて接続方法を切り替えるようなスクリプトを後ろに置かないと使い物にならない。

# 苦労したところ

プロファイル一覧とか簡単に取れるだろうと思っていたら、aws-sdk-goにはそんな機能は無さそうだった。
仕方なく一旦プロファイル名を指定せずSharedCredentialsProviderを作り、そこからcredentialファイルのパスを取得、そのファイルをiniファイルとして読み込んでセクションとしてプロファイル一覧を取得、とかまわりくどいことをしている。

# 作ってみて
同じような悩みをもっている人はそんなにいないんじゃないかと思いながらも、個人的には便利に使っている。
Goとaws-sdk-goを使えばこの手のツールは量産できそうなので、みんなも作ればいいと思う。Let's 車輪の再発明。