Yogafireがバージョンアップしてさらに捗る!

機能追加したら捗りすぎてまじつらい。
以下ChangeLog

ChangeLog(主要なもののみ)

  • 大幅なリファクタリング
  • ターゲットインスタンスを決定するロジックを統一化
  • ssh vpc サポート
  • ssh proxy サポート
  • インクリメンタルにフィルタを行えるように
  • 'yogafire'を指定することにより、表示オブジェクトすべてに対してコマンド実行
  • renderコマンドに'template-file'オプション追加
  • 'change-instance-type'コマンド追加
  • 'update-ec2-tags'コマンド追加
  • selfオプション対応
  • 'loop' オプション対応
  • instance-typeを最新にUpdateしたのとカラーリング対応
  • start / stop / reboot/ terminateなど複数同時実行出来ていなかったのを対応
  • 'copy-and-launch' コマンドが外に出ていなかったので出した

ターゲットインスタンスを決定するロジックを統一化

今までコマンドによってまちまちだったりしたので統一しました。
ターゲット元の正規表現によって以下の判定を行います。

  • private_dns
  • public_dns
  • instance_id
  • (上記以外)タグ名
# private dnsとして接続
yoga ssh ip-10-199-60-10.us-west-1.compute.internal
# public dnsとして接続
yoga ssh ec2-50-1-30-251.us-west-1.compute.amazonaws.com
# インスタンスIDとして接続
yoga ssh --proxy=i-9bed5ac3
# タグ名(単独)
yoga get www01 ./getfile ./
# タグ名(複数)
yoga put 'www*' ./putfile /tmp

ipアドレスも対応する予定でしたが、諸事情によりTodo。

ssh vpc / proxy サポート

最近VPC使うことも多くなってきました。
しかしyogafireがバグっててそもそもssh繋がらなかったのでまずはそれを修正しました。
また、踏み台対応もyogafireだけで出来るようにしてみました。
以下のようにすると踏み台指定出来ます。

yoga ssh --proxy=<target_id>

# get / put / cmdも対象。以下は「fumidai」というタグ名のインスタンスを踏み台に指定
yoga cmd www1 ls --proxy=fumidai
yoga put www1 ./putfile.txt ./ --proxy=fumidai
yoga get www1 ./getfile.txt ./ --proxy=fumidai

または、.yogaファイルに「proxy」を設定してもOKです。
共通でプロキシ通したい場合はこちらが良いでしょう。

application1:
  access_key_id: xxxxxxxxxxxxxxxxx
...
  proxy: fumidai
...

インスタンスの一覧表示時、インクリメンタルにフィルタ出来るようにした

※(詳しくは別記事にします)
対象はコマンドは
ssh / start / stop / reboot / terminate / copy-and-launch / change-instance-type / ls -i / ls-ami -i
です。
前バージョンまでは、重複したTagNameを指定すると「一つになるように再度指定してね」と弾いていたのですが
面倒なのでインクリメンタルっぽく絞り込めるようにしてみました。
これはマジで便利すぎて鼻がもげる!


'yogafire'指定で表示しているインスタンスを全対象にして実行

現状は start / stop / reboot / terminate のみ使用可能です。
インタラクティブ実行中に「yogafire」を実行すると
今表示しているオブジェクト全てに対してコマンドを実行します。*1
change-instance-typeも対応する予定ですがこちらはTodo。

renderコマンドに'template-file'オプション追加

yoga render --template-file=<file_name>

# example
yoga render --template-file=./example/render/simple.tt --state=running

前バージョンまでは文字列を直接指定するしかできなかったのですが
それに加えてテンプレートファイルを指定できるようにしました。
この機能により「インスタンスの"ロール"/"状態"などによりコンフィグファイルを生成する」
といったことが可能になりました。

テンプレートエンジン

Text::Xslate(TT2like)を利用しているので、基本Xslateの構文がそのまま使えます。
詳しく知りたい方は以下のドキュメントをご覧ください。
http://search.cpan.org/~gfuji/Text-Xslate-2.0000/lib/Text/Xslate/Syntax/TTerse.pm
http://search.cpan.org/~dmaki/Text-Xslate-Bridge-TT2Like-0.00010/lib/Text/Xslate/Bridge/TT2Like.pod

シンプルな例

テンプレートには条件に一致したインスタンスの配列が
「instances」という名前で渡ってきます。
以下のテンプレートはインスタンス毎にパブリックDNS名を出力します。
インスタンスアトリビュートについてはVM::EC2のメソッドと同等になります。

[% FOREACH i IN instances %]
  [% i.dnsName %]
[% END %]
シンプルな例:条件分岐

従来通り yoga render コマンド時にfilter指定して使うことももちろん可能ですが、
テンプレート内で条件分岐させることも可能です。
以下のテンプレートはタグ名が「www」で始まるインスタンスであれば
プライベートIPをインスタンス毎に出力します。

[% FOREACH i IN instances %]
  [% IF i.tags.Name.match('^www') %]
    [% i.privateIpAddress %]
  [% END %]
[% END %]
シンプルな例:JSONの扱い

カスタムタグにJSON文字列を入れてゴニョゴニョしている方もいると思います。
そういったニーズにお応えしてJSONをデコードする関数も定義しました。
以下の例では「Role」というカスタムタグに
「{"Nagios":"1","Group":"www"}」
という文字列が入力されているのをデコードして利用するパターンです。

[% FOREACH i IN instances %]
  [% SET ROLE = decode_json(i.tags.Role) %]
  [% ROLE.Nagios %] # 「1」が表示される
  [% ROLE.Group  %] # 「www」が表示される
[% END %]
応用例:NagiosやMuninのコンフィグを自動生成してみる

もう少し具体的な例を上げてみましょう。
AWSでインフラ構築している方は
インスタンス名」もしくは「独自タグ」を見て
Nagios/Munin/Capistoranoなどのコンフィグを生成する、といったスクリプト
自前で実装したりしていないでしょうか?(自分はしています)
そのような要件があった時、yogafireがあればスクリプトを書くまでもなく
テンプレートファイルを作るだけで済むようになります!
例としていくつかテンプレートを作ってみました。

muninの場合

基本的な設定だけであれば
このような一つのファイルを作るだけで良いです。

さらに、自動でグルーピングを設定したいときにはIF文を使えば簡単ですね*2
これも一つのファイルだけでOKです。

nagiosの場合

全てに基本監視するだけならこのような一つのファイルを作るだけで良いです。
また、ロールによって監視項目を追加したいこともありますよね。
IF文で条件分岐しても良いですが、今回は例として外部のインクルードファイルを使うパターンを作ってみました。
参考にしてみてください*3
https://github.com/toritori0318/p5-Yogafire/blob/master/example/render/nagios/nagios_include.tt
https://github.com/toritori0318/p5-Yogafire/tree/master/example/render/nagios


他にもnginx のサンプルも置いてありますのでご参照ください。


上記の例題テンプレートをダウンロードして
自分の環境で動かしてみるだけでも感触がつかめると思います。
renderコマンドは標準出力に出すだけなので何も考えずに色々と試してみてください!

'change-instance-type'コマンド追加

yoga change-instance-type <target_id>

その名の通り、instance-typeを変更します。
このコマンドの何が嬉しいかというと、
暗黙的に以下のような手順を行なってくれることです。

  1. インスタンスが起動していたら停止する。(a) EIPがついてたら保持しておく
  2. ステータスがstoppedになるまで待つ
  3. インスタンスタイプ変更
  • 1.を通っている場合
    • インスタンスを起動し直す
    • ステータスがrunninngになるまで待つ
    • (a) のEIPがあれば、EIPを付け直す

EC2classicで運用しているのであれば、より便利なコマンドとなりますね。


また以下のように一度に複数のインスタンスに対しても実行可能です。
複数インスタンスを一気に「t1.micro」から「c1.xlarge」にスケールアップ、といった操作も簡単!

yoga change-instance-type  'www*'  --type=c1.xlarge --force


さらに完全に蛇足ですが、
以前から使える expand-volumeコマンドも似たようなことをしています。

  1. インスタンスが起動していたら停止する。(a) EIPがついてたら保持しておく
  2. ステータスがstoppedになるまで待つ
  3. スナップショット作成
  4. スナップショットステータスが「completed」になるまで待つ
  5. 新しいサイズでボリュームを作る
  6. ボリュームステータスが「available」になるまで待つ
  7. 現在のボリュームをdetachする
  8. ボリュームステータスが「detached」になるまで待つ
  9. 新しいボリュームをattachする
  10. ボリュームステータスが「attached」になるまで待つ
  • 1.を通っている場合
    • インスタンスを起動し直す
    • ステータスがrunninngになるまで待つ
    • (a) のEIPがあれば、EIPを付け直す
  • ※上記のどこかでエラーが発生したら元のボリュームにロールバックする

'update-ec2-tags'コマンド追加

※このAPIは将来コマンドインタフェースを変える可能性があります

yoga update-ec2-tags  <target_id> --key='<tag_name>=<tag_value>'

基本的にはtagを更新するだけのコマンドですが、
自動で連番を付けてくれる機能もあります。
以下のコマンドは「image-id=ami-xxxxx」のインスタンス全てに対し
「Nameタグ=www<連番>」と「Roleタグ=webapp」のタグ更新を実行します。

yoga update-ec2-tags --filter='image-id=ami-xxxxx' --key='Name=www[% seqno %]' --key='Role=webapp'

selfオプション対応

自分自身のサーバを対象とする「self」オプションを追加しました。
もちろん、ec2インスタンス上で実行する場合限定となります。
以下簡単な例ですが、自殺コマンドです。ほげぇ

yoga terminate --self
応用編1

高額インスタンスを起動してテスト中、
インスタンス落とし忘れたらどうしよう…ガクブル」
とビクビクしている人も多いことでしょう。
そんなとき、atコマンドを指定しておくと落とし忘れが無くなって良いですね。*4

# 2013/03/26 23:00 に自動的にインスタンスをstopする
echo "yoga stop --self --force" | at "23:00 26.03.13"
応用編2

時間のかかるようなビルドを実行する時、
インスタンスを一時的に「t1.micorからc1.mediumにアップグレードする」
といったことは日常茶飯事ですね。
しかしインスタンスを戻し忘れて「あ”あ”ー!」となることも度々あります。
そんなときはコマンド終了と同時に
インスタンスをstopする」または「インスタンスをt1.microに戻す」
などとしておくと安眠できますね。

# perlbrewの後は何が何でもstopする
perlbrew install v5.16.3 ; yoga stop --self --force

# コマンドが成功した時だけt1.microに戻す
cpanm Task::Plack && yoga change-instance-type --type t1.micro --force

'loop' オプション対応

インタラクティブに入力できるコマンド全部が対象です。
前バージョンまではコマンド実行後に終了してしまいましたが
loopオプションを付けておくとコマンド終了後にインスタンス一覧選択画面に戻るため、
繰り返しインスタンスに対してコマンド実行することが出来ます。

yoga ls -i -l

instance-typeのUpdateとカラーリング対応

最新情報にUpdateしたのと、グループごとにカラーリング表示するようにしました。


現在実装中(次バージョンで公開予定)のコマンド達

  • 別リージョンにAMIを作るまでを自動化してくれるコマンド
  • 特定のグループ毎にインスタンス数を調整するコマンド。手動AutoScaleみたいな感じ*5

Todo

  • ログ出力整理
  • VPCユーティリティを充実させたい
  • cmd / put/ getのパラレル対応
  • テストの充実(そもそもどうしよう)


まだ少しバギーな部分もあるかもですが、
よろしければアップデートしてみてください〜

*1:本当は「yogaInferno」にしたかったけど打ちづらいので却下

*2:"Role"という独自タグに"www"や"db"などの文字列がそのまま入っていると仮定しています

*3:インクルードパターンでは、ロール名と一致するテンプレートが存在しないとエラーになりますのでご注意を

*4:ただしatコマンドの仕様で、atコマンドを実行しないまま手動でサーバを落としたりすると、次回サーバ起動時に登録したコマンドが実行されてしまうらしいので注意。terminateは危険かも

*5:どっちやねん