最近は、仕事でも趣味でも、サーバ構築を自動化したいときは Ansible を使ってます。
アプリケーションのデプロイには Capistrano も使うんですが、つい最近 Ansistrano という便利な Ansible role の使い方を覚えてしまったので、そこも Ansible で済むようになりました。
ansible-playbook の --extra-vars 引数
ところで、Ansible の playbook を書いていると、「普段の動作は決まっているけど、ごくまれに違う動作をさせたい」ことがたまにありませんか? そういうとき、僕は ansible-playbook の --extra-vars 引数(-e 引数)を良く使います。
例えば、自作のアプリケーションをデプロイするための playbook で、「普段は master ブランチをデプロイするけど、たまに違うブランチをデプロイしたい」ことがあったとします。そういう場合、playbook のなかで version 変数を、
- hosts: apservers vars: version: master
のように定義しておいて、master ブランチをデプロイしたい場合は --extra-vars 引数なしで実行します。
$ ansible-playbook -i inventory deploy-app.yml
そして master 以外のブランチをデプロイしたい場合だけ、以下のように --extra-vars 引数を使ってブランチ名を指定します。
$ ansible-playbook -i inventory deploy-app.yml --extra-vars="version=develop"
Ansible 公式の Variables にある通り、あらゆる変数指定のなかで --extra-vars の指定は最優先されます。そのため、このような上書きが可能なわけです。
--extra-vars のデメリット
この方法はだいたいうまくいくのですが、「変数名を間違えても何のアラートも出ない」というデメリットがあります。
例えばつい最近、僕が書いた playbook を使ってアプリをデプロイした同僚から、「develop ブランチを指定したのに master ブランチがデプロイされてる。playbook がバグってないか?」と言われたことがありました。何か実装間違えたかな、と思って彼が実行したコマンドを見たら、こうなっていました。
$ ansible-playbook -i inventory deploy-app.yml --extra-vars="develop"
調べてみたところ、これは無効な変数指定として ansible-playbook に無視されるようです。その結果、version 変数はデフォルトの master のままで、master ブランチがデプロイされました。その同僚はどうも「引数でブランチ名を変えられる」程度の理解だったようです。
そのときは同僚に --extra-vars 引数の使い方を解説して終わったのですが、あとから考えてみると、--extra-vars で動作を変更させること自体が危険なんじゃないか? という気がしてきました。今回は引数の使い間違えでしたが、引数の使い方を理解していても version を versoin と書き間違えてしまうくらいは、普通にありそうです。
--extra-vars の代替案としての vars_prompt
--extra-vars の代替案としては、Prompts に説明のある vars_prompt
を使うという方法があります。
vars_prompt は、playbook の実行後に、変数入力のプロンプトを表示するためのオプションです。例えば、playbook に、
- hosts: apservers vars_prompt: - name: "version" prompt: "Branch name?" default: master
と書いておくと、playbook の実行時に以下のプロンプトが表示されます。そのまま Enter キーを押せば version 変数に "master" が代入され、ブランチ名を入れればそちらに変わります。
Branch name? [master]:
これでまあ確かに安全になるので、多くの場合は vars_prompt を使うのがよいと思います。
ただ、master ブランチをデプロイするのが大半、というケースでは Enter キーを無駄にぺちぺち押さないといけないのが面倒です。また、カスタマイズ可能な変数がもっと多い場合は、その変数の数だけ Enter キーをぺちぺち押さないといけなくなります。何も考えずに Enter キーをぺちぺち押す習慣ができるのは、またなにか別の障害の原因になりそうで嫌な感じです。
--extra-vars を安全に使うためのラッパー ansible-playbook-se
さっきの同僚の例について考え直してみると、要するにあれは "develop" という僕の想定しない変数名を、ansible-playbook コマンドが受け入れてしまったのがいけなかったわけです。
それなら、--extra-vars 引数に指定できる変数名を限定できれば、それで十分安全になるのでは? そう考えて、ansible-playbook コマンドのラッパー "ansible-playbook-se" を試作してみました。最近覚えた Python 3 で実装し、GitHub にソースコードを置いておきました。
使い方はまず、このリンク先にある ansible-playbook-se と extra-vars-cheker を、どこかパスが通ったところに置きます。
次に、playbook が置いてあるのと同じディレクトリに、以下のような内容で extra-vars.yml という名前のファイルを作ります。このファイルには、playbook のファイル名と、各ファイルが --extra-vars で指定するのを許す変数名を書きます。
--- deploy-app.yml: - version
そして、いつも使っている ansible-playbook の代わりに、ansible-playbook-se を使うようにします。そうすると、想定外の変数が指定された場合、ansible-playbook-se は以下のようなエラーを出して、処理を中断します。
$ ansible-playbook-se -i inventory deploy-app.yml --extra-vars="develop" ERROR: Invalid extra-var format: develop ERROR: extra-vars-checker Failed.
安全になりましたね? なりましたよね? でも、これはこれで何だか面倒な気がしますね……。
試しに作ってはみたのですが、まだ実際の環境には導入していません。こういうニーズって、他の人にもあるもんでしょうか? もしニーズがあればもう少しちゃんと作ろうと思うので、ご意見お待ちしています。