zaki work log

作業ログやら生活ログやらなんやら

[Ansible] loopとモジュール実行の結果を保持するregisterを併用する

registerを使うことでモジュールの実行結果(Return Values)を保持し、後続のタスクでその値を参照することができるので、処理の実行結果を次のタスクのパラメタにすることができます。
ただし、その結果のデータ構造がループでの実行時は通常とは異なるのでそれについての覚え書き。

通常時のサンプル

指定コマンドを実行するplaybookです。

---
- hosts: localhost
  gather_facts: false

  tasks:
    # コマンド実行
    - name: exec command
      ansible.builtin.command: hostname
      register: result_command

    - name: print result
      debug:
        msg: '{{ result_command }}'

1つ目のtaskでコマンド実行しつつ、その結果を2つ目のtaskで出力。内容は以下の通り。
commandのReturn Valueについてはドキュメントのこちら

ok: [localhost] => 
  msg:
    changed: true
    cmd:
    - hostname
    delta: '0:00:00.001591'
    end: '2021-04-06 18:53:48.144296'
    failed: false
    rc: 0
    start: '2021-04-06 18:53:48.142705'
    stderr: ''
    stderr_lines: []
    stdout: cloud-dev
    stdout_lines:
    - cloud-dev

この通り、モジュールの実行結果をregisterで指定した名称の変数にセットでます。
commandの場合は、コマンドの戻り値がrc・標準出力がstdoutに保持されます、ディクショナリ型データになっているのでキーを指定して参照できます。

ループ併用時

loopを使って以下の3つのコマンドを実行するように変更。

  • hostname
  • pwd
  • ls /opt
    - name: exec command
      ansible.builtin.command: "{{ item }}"
      loop:
        - hostname
        - pwd
        - ls /opt
      register: result_command

    - name: print result
      debug:
        msg: '{{ result_command }}'

この時の実行結果は以下の通り。
(長いので一部省略)

ok: [localhost] => 
  msg:
    changed: true
    msg: All items completed
    results:
    - ansible_loop_var: item
      changed: true
      cmd:
      - hostname
      delta: '0:00:00.001672'
      end: '2021-04-06 18:54:28.461799'
      failed: false
      invocation:
        module_args:
          ...
      item: hostname
      rc: 0
      start: '2021-04-06 18:54:28.460127'
      stderr: ''
      stderr_lines: []
      stdout: cloud-dev
      stdout_lines:
      - cloud-dev
    - ansible_loop_var: item
      changed: true
      cmd:
      - pwd
      delta: '0:00:00.001590'
      end: '2021-04-06 18:54:28.630725'
      failed: false
      invocation:
        module_args:
          ...
      item: pwd
      rc: 0
      start: '2021-04-06 18:54:28.629135'
      stderr: ''
      stderr_lines: []
      stdout: /home/zaki/src/ansible-sample/file
      stdout_lines:
      - /home/zaki/src/ansible-sample/file
    - ansible_loop_var: item
      changed: true
      cmd:
      - ls
      - /opt
      delta: '0:00:00.001935'
      end: '2021-04-06 18:54:28.798976'
      failed: false
      invocation:
        module_args:
          ...
      item: ls /opt
      rc: 0
      start: '2021-04-06 18:54:28.797041'
      stderr: ''
      stderr_lines: []
      stdout: |-
        cni
        containerd
      stdout_lines:
      - cni
      - containerd

loopwith_itemsなどのループとの併用時は、各ループ毎の実行結果はresultsというキー以下にリスト型でセットされるようにデータ構造が変化します。

該当ドキュメント

ループのドキュメントに載っています。

docs.ansible.com

When you use register with a loop, the data structure placed in the variable will contain a results attribute that is a list of all responses from the module. This differs from the data structure returned when using register without a loop:

環境

ansible 2.10.5
  config file = /home/zaki/src/ansible-sample/file/ansible.cfg
  configured module search path = ['/home/zaki/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/zaki/src/ansible-sample/venv/a2.10/lib64/python3.6/site-packages/ansible
  executable location = /home/zaki/src/ansible-sample/venv/a2.10/bin/ansible
  python version = 3.6.8 (default, Nov 16 2020, 16:55:22) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)]

ちょっと古いな…

Return Valueをカジュアルに確認したい場合

個人的には普段はansible-playbook実行時に-vを付けて実行してます。
verboseレベル1でモジュールの実行結果は標準出力へprintされるので、開発中は基本的にこのレベルで作業してます。

    - name: exec command
      ansible.builtin.command: hostname

このtaskを-v無しで実行してもchangedしか出力されないですが、-vを付けると以下のようにcommandの結果が出力されます。

changed: [localhost] => changed=true 
  cmd:
  - hostname
  delta: '0:00:00.001589'
  end: '2021-04-06 18:58:07.337019'
  rc: 0
  start: '2021-04-06 18:58:07.335430'
  stderr: ''
  stderr_lines: <omitted>
  stdout: cloud-dev
  stdout_lines: <omitted>