Help us understand the problem. What is going on with this article?

ansibleで変数に入れたyes/noの扱いに苦しんだ

タイトルをどうつければ伝わるか悩んだ結果こうなった・・・

背景

Ansibleを使っていると、ある1つの環境だけ特別に実行したいとかあると思います。
(雲行きが怪しいぞ・・・という反応がうかがえます。)
例えば3台立っているアプリケーションサーバに、cronを仕込みたいけど、3台で動かしたくないなーといった場合を考えてみます。
(ちゃんとグループを分けなさい、ケチらずバッチサーバを用意して分けなさいという意見が聞こえてきます。)

こんな感じにインベントリ内に変数is_mainを持たせました。

hosts
[app]
foo-app-01 is_main=yes
foo-app-02 is_main=no
foo-app-03 is_main=no

このyes/noはansibleを書いているとよく出てくる値です。
serviceなら自動実行を開始させるためにenabled: yesみたいに使います。今回はcronのdisabledの値として使うイメージです。

次にタスクの内容です。is_main=yesなところだけが有効になってほしかったのでタスクはこんな感じにした。

tasks/main.yml
cron:
  # ...
  disabled: "{{ is_main == False }}" # NG!! 

今回の条件では disabledに入る値は常にFalse になるため、全部の環境でcronが有効になります。ちなみに、{{ not is_main }} でも同じです。

やりたい事と違う!

原因の推測

何度かdebugタスクで表示して確認した上での推測です。全然裏が取れてないです。

  • まずinventoryで定義した変数is_mainは文字列として扱っている
  • ファイル自体はYAMLなので、まず最初にYAMLとして処理される。YAMLではYes,No等の値はBool値として解釈される。なのでdisabled: no等の記載なら、期待通り動く。
  • 今回の場合、disabled: "{{ is_main == False }}"はYAML的にはただの文字列。
  • しかし、テンプレート構文なのでJinja2で解釈した結果になる
  • Jinja2的には変数is_mainの値は文字列と解釈して「1文字以上の文字列だからTrue」と判断している
  • なのでこの式は、disabled: "{{ is_main == False }}"disabled: "{{ True == False }}"disabled: False となる

あっているでしょうか・・・?

対応

自然な感じで書きたいのだけど、どうしたら良いか調べたところ bool フィルターを使うと良さそうとのことだった。boolフィルターは良くあるポジティブな値はTrueにしてくれます。今回求めてたやつですね!

tasks/main.yml
cron:
  # ...
  disabled: "{{ is_main | bool == False }}"

しかしこの見た目は不吉な匂いを感じます。
これなら文字列が入ってくる前提で考えて {{ is_main == 'no' }} とかの方がまだ良い気がしないでもない・・・。

やはりグループを分けるべきだったか・・・。

Ansibleはこういうミスは忘れたころに何度も踏んでる気がする・・・頭の悪さを感じてとても辛い。

追記: インベントリファイル(INI形式)の変数の扱い

コメントにて、インベントリファイルの変数で対処する方法等を教えていただきました。
また、インベントリファイルのbooleanの扱いについてBlogでまとめておられます。ありがたし。

https://tekunabe.hatenablog.jp/entry/2019/02/09/ansible_ini_bool_vars

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away