はじめに
when
とregister
を使用した際、想像していた動作と違っていたのでメモ。
やりたいこと
- タスクを実行後、結果を変数に格納
-
when
で条件分岐させ、複数の要素から、特定の要素にのみtaskを実行 - 結果を変数として取得
HTTPステータスコードの取得
特定の文字列が含まれたURLに対してGETを行い、HTTPのステータスコードを取得したい。
以下のようなplaybookを作成。
http-get-playbook.yml
---
- hosts: all
connection: local
vars:
- url_list:
- "http://www.yahoo.co.jp"
- "http://www.google.com"
tasks:
- name: http-get
uri:
url: "{{ item }}"
with_items: "{{ url_list }}"
register: result
when:
- '"google" in "{{ item }}"'
- name: debug
debug: msg='{{ result.results.status }}'
"http://www.google.com"
に対しての結果のみがresult
に入るものだと思っていた。
が、実際の結果は以下の通り。
result
PLAY [all] **************************************************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************************************
ok: [127.0.0.1]
TASK [http-get] *********************************************************************************************************************************************
[WARNING]: when statements should not include jinja2 templating delimiters such as {{ }} or {% %}. Found: "google" in "{{ item }}"
skipping: [127.0.0.1] => (item=http://www.yahoo.co.jp)
ok: [127.0.0.1] => (item=http://www.google.com)
TASK [debug] ************************************************************************************************************************************************
fatal: [127.0.0.1]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'list object' has no attribute 'status'\n\nThe error appears to have been in 'http-get-playbook.yml': line 17, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - name: debug\n ^ here\n"}
to retry, use: --limit xxx
PLAY RECAP **************************************************************************************************************************************************
127.0.0.1 : ok=2 changed=0 unreachable=0 failed=1
status
が存在しないという旨のエラーが発生した。
エラーの原因
when
で条件分岐させた後、resister
を使用して結果を格納した場合、**"スキップした"**という結果も同時にネストされる。
つまり上記のyaml
の場合、'result'は以下の要素がネストされた状態で存在している。
result = [
'"http://www.yahoo.co.jp"をスキップ',
'"http://www.google.com"を実行した結果'
]
エラーの回避
結果はネストされているため、"http://www.google.com"
の結果のみ出力したい場合は、{{ result.results.1.status }}
のように指定すればよい。
ただし、汎用性はない。
http-get-playbook.yml
---
- hosts: all
connection: local
vars:
- url_list:
- "http://www.yahoo.co.jp"
- "http://www.google.com"
tasks:
- name: http-get
uri:
url: "{{ item }}"
with_items: "{{ url_list }}"
register: result
when:
- '"google" in "{{ item }}"'
- name: debug
debug: msg='{{ result.results.1.status }}'