プログラマ行進曲第二章

主にソフトウェア関連の技術をネタにした記事を執筆するためのブログ

ansibleのextra varsをコマンドラインから渡す際、複雑な形式の変数を渡す方法

それまで使う必要が無かったのですが、仕事で必要になって調べた際、時間を使ってしまったので、ブログ記事にして記録を残しておきます。基本、公式ドキュメントを読めばいい話なのですが、一応詰まった話なので供養。

ansibleを使用する際、普通なら必要になる変数はgroup varsやhost varsを記載しているファイルに値を書いておけばいいのですが、ansible実行時に値を書き換えたいときが発生すると ansible-playbookコマンドの -e オプションを使って渡す必要が出てきます。

ansibleの公式ドキュメントのUsing VariablesのPassing variables on the command lineを読めば分かるとおり、以下のようにJSON形式の文字列を渡すことができます。

$ ansible-playbook release.yml --extra-vars '{"version":"1.23.45","other_variable":"foo"}'
$ ansible-playbook arcade.yml --extra-vars '{"pacman":"mrs","ghosts":["inky","pinky","clyde","sue"]}'

これにより複雑な形式の変数を渡すことができます。

私が仕事で困って調べるのに時間を使ってしまったのは、ネストしたJSONのkeyにあたる箇所の値を実行先ホストによって変えたい場合の渡し方でした。

うまく説明できているかは分かりませんが、以下のようなYAML形式のパラメータの parameter にあたる部分を実行先ホストによって変更した値をコマンドラインからansible-playbookコマンドに渡したい場合の話です。

redash_db_upgrade_enabled:
  parameter: true

結果から書くと以下のようにbash変数を利用して、JSON形式の文字列を渡してやれば上手くいきました。同じことをYAML形式の文字列で渡すやり方で試してみても上手くいかなかったので、JSON形式の方がいいのかもしれません。*1

$ proj_name=default
$ ansible-playbook playbook.yml -i hosts.ini -e "{'redash_db_upgrade_enabled': {'${proj_name}': true}}"

上記の例ではプロジェクト名が default の時には redash_db_upgrade_enabled で表現したい状態をオンにする(=それ以外のプロジェクトではオフのままにする)ということをしたくてやっているものです。

事前にbash変数で proj_name=default とproj_nameの値を設定しておけば {'redash_db_upgrade_enabled': {'${proj_name}': true}}" という書き方で {'redash_db_upgrade_enabled': {'default': true}}" と渡したときと同じように働きました*2

あまり複雑な形式の変数をコマンドライン経由でansibleに渡すのはアンチパターンだとは思いますが、もしgroup varsなどを使えない状況だったときには利用できるやり方かもしれません。

*1:ansibleのバージョンは2.7.4だったはずです

*2:shellの昨日や働きを熟知している人にとっては当然なのでしょうが