出力を入力へ

プログラミングに関する自分が考えた事を中心にまとめます

EC2インスタンスIDを取得するec2idをリリースした

AWS EC2インスタンスのインスタンスIDをNameタグから逆引きするCLIツールec2idを作ってリリースした。

github.com

インスタンスIDを取得したい

AWS EC2インスタンスを一意に識別する情報はインスタンスIDであり、AWS SSMセッションズマネージャーでログインするときなどでインスタンスIDを指定する必要がある。 例えば、aws cliを用いてSSMセッションズマネージャーで接続するには以下の通り。

$ aws ssm start-session --target <instance-id>

docs.aws.amazon.com

このようにインスタンスIDを指定する上で、インスタンスIDを取得する必要がある。 インスタンスIDはユーザがEC2に割り当てることはできず、EC2インスタンスを構築する度にランダムに決定する。このため、EC2インスタンスを頻繁に再構築している場合、事前に値を記録する運用も難しい。 インスタンスIDを利用する直前に動的に取得する仕組みが必要である。

インスタンスIDの取得方法

マネージメントコンソールから取得する

一番直感的なのはWebのマネージメントコンソールから取得する方法である。

マネージメントコンソール画面からインスタンスIDを参照する

一方で、EC2インスタンスIDを取得するために、わざわざマネージメントコンソール画面を開きたくない。 また、大量のEC2インスタンスIDが稼動している場合に目当てのインスタンスを探すのは手間だし間違いが生じやすい。 より簡単にインスタンスIDを取得する方法が必要である。

aws cliを利用する

aws cliでSSM接続するためにインスタンスIDが必要なのであれば、同じくaws cliでインスタンスIDを取得できれば話は早い。 当然aws cliにはそのためのサブコマンドが提供されており、describe-instancesを利用することでインスタンス情報一覧を取得できる。

awscli.amazonaws.com

一方で、この方法ではquery/filterオプションを覚えるのが面倒という問題がある。 EC2インスタンスが1台しか存在していないのであれば問題ないが、複数インスタンスが稼動している中で目的のインスタンスを取得するには、queryおよびfilterオプションを指定する必要がある。 query/filterで、インスタンス名sampleのインスタンスIDおよびその起動時刻を取得するコマンドが以下の通り(以下の例では該当するインスタンスが2台ある場合)。

$ aws ec2 describe-instances --filters Name=instance-state-name,Values=running Name=tag:Name,Values=sample --query 'Reservations[*].Instances[*].[LaunchTime, InstanceId]'
[
    [
        [
            "2022-12-31T10:02:33+00:00",
            "i-0691a69ff0914bae1"
        ]
    ],
    [
        [
            "2022-12-31T11:24:57+00:00",
            "i-0acd9f178c934caea"
        ]
    ]
]

このように、これだけでもquery/filterはそれなりに複雑で覚えておける気がしない。 特に同名インスタンスがある場合には出力結果を人の目でパースする(いわゆる目grepする)か、追加のsortフィルタ等を加えて適切なインスタンスを選ぶ必要がある。

ec2id

こういった課題を解決するためのcliツールとしてec2idを開発・リリースした。

github.com

専用CLIの実装

やりたい事はインスタンス名からインスタンスIDを取得すること。なのでその用途に特化したCLIがあればよい。 無駄なオプションを実装せず単目的に利用することを想定することで、シンプルなツールを実現した。

これを利用することで簡単にインスタンスIDを取得できる。

# 引数を指定しなければ全インスタンスから最後に起動したインスタンスのIDを取得する
$ ec2id
i-0691a69ff0914bae1

# 引数を指定すればそのインスタンス名の中から最後に起動したインスタンスのIDを取得する
$ ec2id sample
i-0acd9f178c934caea

go言語による実装

利用時に依存パッケージの問題を発生させたくないのでシングルバイナリで利用できることが望ましい。 Linux(Ubuntu) / Intel mac / m1 macで利用することは見えているので、マルチOSサポートが容易が言語にしたい。 そういった事を考えるとgo言語が適切だと判断した。

わざわざgo言語で実装しなくてもシェルスクリプトなどでも実装可能かもしれないが、フィルタやクエリが複雑になりメンテが大変になりそうだった。 また、別のツール用にgo言語のCLIを作りたいとも考えていたので、go言語のナレッジ蓄積をしたかった。 go言語の技術検証用にシンプルな仕様のツールがあると都合が良く、ec2idはこの条件に合っていた。

作ってみて

検証時に思った通り、テストまわりが難しく感じた。 AWS APIをモックにする必要があり、インタフェースやモックコードの生成などもからむので、多少複雑にはなった。 これはgo言語に慣れれば解決するのか、今のところ感触はあまりよろしくない。

シングルバイナリやマルチOSサポートが容易なのは大きなメリットと感じる。 このあたりリリースまわりが楽なのは嬉しい。