てくなべ (tekunabe)

ansible / network automation / 学習メモ

[Ansible] Playbook Debugger でタスク変数の値を変更してもタスクに反映されない現象について

■ はじめに

Ansible には Playbook Debugger という、Playbook 実行時に変数の値を確認、変更などできる機能があります。

参考

タスク変数も変更できますが、変更後、タスクを再実行しても変更前の値のまま再実行してしまう現象があります。 2.5 系 から 2.7 系までが対象です。2.4 系では発生しない現象でした。次期バージョンの Ansible 2.8 で、追加される Debugger のコマンド update_task によって改修される予定です。

この記事ではこの現象についてご紹介します。


■ 公式ドキュメントに記載の手順は正しくタスク変数の値が変更できない

本記事執筆時点で、最新安定版(2.7対応)のドキュメントの Playbook Debugger の説明ページには、以下のようなタスス変数の変更手順が記載されています。

  • Playbook
- hosts: test
  strategy: debug
  gather_facts: yes
  vars:
    pkg_name: not_exist
  tasks:
    - name: install package
      apt: name={{ pkg_name }}
  • デバッガ操作手順
[192.0.2.10] TASK: install package (debug)> p task_vars['pkg_name']
u'not_exist'
[192.0.2.10] TASK: install package (debug)> task_vars['pkg_name'] = 'bash'
[192.0.2.10] TASK: install package (debug)> p task_vars['pkg_name']
'bash'
[192.0.2.10] TASK: install package (debug)> redo

手順はここで終わっていて、redo の結果が記載されていません。これを実際試すと redo 後にエラーにってしまいます。 (環境の都合上、apt ではなく yum モジュールを利用しますが、現象に影響はありません)

$ ansible-playbook -i localhost, debuger_ad.yml

PLAY [localhost] *************************************************

TASK [Gathering Facts] *******************************************
ok: [localhost]

TASK [install package] *******************************************
fatal: [localhost]: FAILED! => {"changed": false, "msg": "No package matching 'not_exist' found available, installed or updated", "rc": 126, "results": ["No package matching 'not_exist' found available, installed or updated"]}
[localhost] TASK: install package (debug)> redo
fatal: [localhost]: FAILED! => {"changed": false, "msg": "No package matching 'not_exist' found available, installed or updated", "rc": 126, "results": ["No package matching 'not_exist' found available, installed or updated"]}
[localhost] TASK: install package (debug)> task_vars['pkg_name'] = 'bash'
[localhost] TASK: install package (debug)> p task_vars['pkg_name']
'bash'
[localhost] TASK: install package (debug)> redo
fatal: [localhost]: FAILED! => {"changed": false, "msg": "No package matching 'not_exist' found available, installed or updated", "rc": 126, "results": ["No package matching 'not_exist' found available, installed or updated"]}
[localhost] TASK: install package (debug)>

redo 後も、not_exist というパッケージ名を探していて、見つからないためエラーになっています。つまり、task_vars['pkg_name'] = 'bash' のようにタスク変数を書き換えても、実際のタスク実行上に利用する値は変更前(この場合 not_exits)ということになります。


■ 2.7 までのワークアラウンド

変更した(見かけ上の)タスク変数の値をタスクのオプション(task.args['name'])に代入すれば、変更後の値で redoできます。

(...略...)
[localhost] TASK: install package (debug)> task_vars['pkg_name'] = 'bash'
[localhost] TASK: install package (debug)> p task_vars['pkg_name']
'bash'
[localhost] TASK: install package (debug)> task.args['name'] = '{{ pkg_name }}'
[localhost] TASK: install package (debug)> redo
ok: [localhost]

PLAY RECAP *****************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0

もちろん、タスク変数を経由せずに、最初から task.args['name'] = 'bash' のようにタスクのオプションの値を直接変更しても、正常に redo できます。

(...略...)
[localhost] TASK: install package (debug)> task.args['name'] = 'bash'
[localhost] TASK: install package (debug)> redo
ok: [localhost]

PLAY RECAP *****************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0


■ 2.8 からの新しい手順で正しく変更

次期バージョンの Ansible 2.8 の Playbook Debugger では update_task というコマンドが利用できます。 このコマンドにより、Debuger 上で変更したタスク変数の値を、正しく redo 時にタスクが利用できます。

次期バージョン(2.8/devel)のドキュメントにも以下の手順が記載されています。

[192.0.2.10] TASK: install package (debug)> p task_vars['pkg_name']
u'not_exist'
[192.0.2.10] TASK: install package (debug)> task_vars['pkg_name'] = 'bash'
[192.0.2.10] TASK: install package (debug)> p task_vars['pkg_name']
'bash'
[192.0.2.10] TASK: install package (debug)> update_task
[192.0.2.10] TASK: install package (debug)> redo


■ [補足] Ansible 2.4 では本現象は発生しない

Ansible 2.4 にも Playbook Debugger 機能はあります(debugger ディレクティブではなく、strategy: debug としての機能)。2.4 では本件の現象は発生せず、通常の手順で変更後のタスク変数の値でタスクを再実行できます。

$ ansible --version
ansible 2.4.0.0
(...略...)

$ ansible-playbook -i localhost, debuger_ad.yml

PLAY [localhost] ************************************************************

TASK [Gathering Facts] ******************************************************
ok: [localhost]

TASK [install package] ******************************************************
fatal: [localhost]: FAILED! => {"changed": false, "failed": true, "msg": "No package matching 'not_exist' found available, installed or updated", "rc": 126, "results": ["No package matching 'not_exist' found available, installed or updated"]}
Debugger invoked
(debug) p vars['pkg_name']
u'not_exist'
(debug) vars['pkg_name'] = 'bash'
(debug) p vars['pkg_name']
'bash'
(debug) redo
ok: [localhost]

PLAY RECAP *****************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0

※ Ansible 2.4 までは、タスク変数は vars 内に格納されていましたが、Python のオブジェクト名と重複するため、2.5 で task_vars に変更されました。


■ まとめ

  • Ansible 2.5 系 から 2.7 系までの Playbook Debugger で、タスク変数の値を変更後に redo しても、変更前の値のまま再実行してしまう
  • ワークアラウンドはタスクのオプション task.args への代入
  • Ansible 2.8 で改修予定(update_task コマンドの追加)

参考

  • 対応issue

github.com

  • 対応PR

github.com