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

Ansibleのplaybookで`with_items`等でループ処理したすべての実行結果を`register`してdebugで取り出す方法

More than 3 years have passed since last update.

はじめに

本記事は、Ansibleのplaybookでwith_items等でループ処理した時の実行結果をregisterした後に、debugモジュールを利用して、標準出力結果をループ数分取り出す方法を試行錯誤した結果です。ループしなければ簡単なのですが、地味にはまりました。
なお、デバッグオプション(-v)をつけてplaybookを実行すれば、registerdebugモジュールでこんなことをしなくても画面に出力されますが、改行されず見づらい等もあるので、自分用の備忘メモもかねて。

アジェンダ

ENV. 実行環境
Sample Playbook サンプルプレイブック
Results サンプルプレイブック実行結果
解説

Env.

# cat /etc/redhat-release
CentOS release 6.7 (Final)
#ansible --version
ansible 2.1.0 (devel d358a22542) last updated 2016/04/04 23:43:05 (GMT +900)
  lib/ansible/modules/core: (detached HEAD a38bdfc720) last updated 2016/04/04 23:43:15 (GMT +900)
  lib/ansible/modules/extras: (detached HEAD 7c3999a92a) last updated 2016/04/04 23:43:22 (GMT +900)
  config file = /etc/ansible/ansible.cfg
  configured module search path = Default w/o overrides

Sample playbook

reg_ret_with_items.yml
- hosts: localhost
  gather_facts: no
  vars:
    TEST_CMD:
      - cmd: echo "# LOOP01 *** THIS IS LOOP01 STDOUT ***"
      - cmd: echo "# LOOP02 *** THIS IS LOOP02 STDOUT ***"
      - cmd: echo "# LOOP03 *** THIS IS LOOP03 STDOUT ***"

  tasks:
   - raw: echo "# NOLOOP *** THIS IS NOLOOP STDOUT ***"
     register: RESULT
   - name: "DEBUG0: Output RESULT.stdout_lines"
     debug: var=RESULT.stdout_lines

   - raw:  "{{ item.cmd }}"
     register: CMD_RESULT
     with_items: '{{ TEST_CMD }}'

   - name: "DEBUG1: Output CMD_RESULT.stdout_lines"
     debug: var=CMD_RESULT.stdout_lines

   - name: "DEBUG2: Output CMD_RESULT.results"
     debug: var=CMD_RESULT.results

   - name: "DEBUG3: Output CMD_RESULT.results.stdout_lines by using with_items loop"
     debug: var=item.stdout_lines
     with_items: '{{ CMD_RESULT.results }}'

   - name: "DEBUG4: Output CMD_RESULT.results.stdout_lines by using jinjya2 fileter"
     debug:
      msg: |
        {% for r in CMD_RESULT.results %}
          {{ r.stdout_lines | to_nice_json }}
        {% endfor %}

Results

# ansible-playbook reg_ret_with_items.yml

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

TASK [raw] *********************************************************************
ok: [localhost]

TASK [DEBUG0: Output RESULT.stdout_lines] **************************************
ok: [localhost] => {
    "RESULT.stdout_lines": [
        "# NOLOOP *** THIS IS NOLOOP STDOUT ***"
    ]
}

TASK [raw] *********************************************************************
ok: [localhost] => (item={u'cmd': u'echo "# LOOP01 *** THIS IS LOOP01 STDOUT ***"'})
ok: [localhost] => (item={u'cmd': u'echo "# LOOP02 *** THIS IS LOOP02 STDOUT ***"'})
ok: [localhost] => (item={u'cmd': u'echo "# LOOP03 *** THIS IS LOOP03 STDOUT ***"'})

TASK [DEBUG1: Output CMD_RESULT.stdout_lines] **********************************
ok: [localhost] => {
    "CMD_RESULT.stdout_lines": "VARIABLE IS NOT DEFINED!"
}

TASK [DEBUG2: Output CMD_RESULT.results] ***************************************
ok: [localhost] => {
    "CMD_RESULT.results": [
        {
            "_ansible_item_result": true,
            "_ansible_no_log": false,
            "invocation": {
                "module_args": {
                    "_raw_params": "echo \"# LOOP01 *** THIS IS LOOP01 STDOUT ***\""
                },
                "module_name": "raw"
            },
            "item": {
                "cmd": "echo \"# LOOP01 *** THIS IS LOOP01 STDOUT ***\""
            },
            "rc": 0,
            "stderr": "",
            "stdout": "# LOOP01 *** THIS IS LOOP01 STDOUT ***\n",
            "stdout_lines": [
                "# LOOP01 *** THIS IS LOOP01 STDOUT ***"
            ]
        },
        {
            "_ansible_item_result": true,
            "_ansible_no_log": false,
            "invocation": {
                "module_args": {
                    "_raw_params": "echo \"# LOOP02 *** THIS IS LOOP02 STDOUT ***\""
                },
                "module_name": "raw"
            },
            "item": {
                "cmd": "echo \"# LOOP02 *** THIS IS LOOP02 STDOUT ***\""
            },
            "rc": 0,
            "stderr": "",
            "stdout": "# LOOP02 *** THIS IS LOOP02 STDOUT ***\n",
            "stdout_lines": [
                "# LOOP02 *** THIS IS LOOP02 STDOUT ***"
            ]
        },
        {
            "_ansible_item_result": true,
            "_ansible_no_log": false,
            "invocation": {
                "module_args": {
                    "_raw_params": "echo \"# LOOP03 *** THIS IS LOOP03 STDOUT ***\""
                },
                "module_name": "raw"
            },
            "item": {
                "cmd": "echo \"# LOOP03 *** THIS IS LOOP03 STDOUT ***\""
            },
            "rc": 0,
            "stderr": "",
            "stdout": "# LOOP03 *** THIS IS LOOP03 STDOUT ***\n",
            "stdout_lines": [
                "# LOOP03 *** THIS IS LOOP03 STDOUT ***"
            ]
        }
    ]
}

TASK [DEBUG3: Output CMD_RESULT.results.stdout_lines by using with_items loop] *
ok: [localhost] => (item={'_ansible_no_log': False, 'stdout': u'# LOOP01 *** THIS IS LOOP01 STDOUT ***\n', '_ansible_item_result': True, 'item': {u'cmd': u'echo "# LOOP01 *** THIS IS LOOP01 STDOUT ***"'}, 'stderr': u'', 'rc': 0, 'invocation': {'module_name': u'raw', 'module_args': {u'_raw_params': u'echo "# LOOP01 *** THIS IS LOOP01 STDOUT ***"'}}, 'stdout_lines': [u'# LOOP01 *** THIS IS LOOP01 STDOUT ***']}) => {
    "item": {
        "invocation": {
            "module_args": {
                "_raw_params": "echo \"# LOOP01 *** THIS IS LOOP01 STDOUT ***\""
            },
            "module_name": "raw"
        },
        "item": {
            "cmd": "echo \"# LOOP01 *** THIS IS LOOP01 STDOUT ***\""
        },
        "rc": 0,
        "stderr": "",
        "stdout": "# LOOP01 *** THIS IS LOOP01 STDOUT ***\n",
        "stdout_lines": [
            "# LOOP01 *** THIS IS LOOP01 STDOUT ***"
        ]
    },
    "item.stdout_lines": [
        "# LOOP01 *** THIS IS LOOP01 STDOUT ***"
    ]
}
ok: [localhost] => (item={'_ansible_no_log': False, 'stdout': u'# LOOP02 *** THIS IS LOOP02 STDOUT ***\n', '_ansible_item_result': True, 'item': {u'cmd': u'echo "# LOOP02 *** THIS IS LOOP02 STDOUT ***"'}, 'stderr': u'', 'rc': 0, 'invocation': {'module_name': u'raw', 'module_args': {u'_raw_params': u'echo "# LOOP02 *** THIS IS LOOP02 STDOUT ***"'}}, 'stdout_lines': [u'# LOOP02 *** THIS IS LOOP02 STDOUT ***']}) => {
    "item": {
        "invocation": {
            "module_args": {
                "_raw_params": "echo \"# LOOP02 *** THIS IS LOOP02 STDOUT ***\""
            },
            "module_name": "raw"
        },
        "item": {
            "cmd": "echo \"# LOOP02 *** THIS IS LOOP02 STDOUT ***\""
        },
        "rc": 0,
        "stderr": "",
        "stdout": "# LOOP02 *** THIS IS LOOP02 STDOUT ***\n",
        "stdout_lines": [
            "# LOOP02 *** THIS IS LOOP02 STDOUT ***"
        ]
    },
    "item.stdout_lines": [
        "# LOOP02 *** THIS IS LOOP02 STDOUT ***"
    ]
}
ok: [localhost] => (item={'_ansible_no_log': False, 'stdout': u'# LOOP03 *** THIS IS LOOP03 STDOUT ***\n', '_ansible_item_result': True, 'item': {u'cmd': u'echo "# LOOP03 *** THIS IS LOOP03 STDOUT ***"'}, 'stderr': u'', 'rc': 0, 'invocation': {'module_name': u'raw', 'module_args': {u'_raw_params': u'echo "# LOOP03 *** THIS IS LOOP03 STDOUT ***"'}}, 'stdout_lines': [u'# LOOP03 *** THIS IS LOOP03 STDOUT ***']}) => {
    "item": {
        "invocation": {
            "module_args": {
                "_raw_params": "echo \"# LOOP03 *** THIS IS LOOP03 STDOUT ***\""
            },
            "module_name": "raw"
        },
        "item": {
            "cmd": "echo \"# LOOP03 *** THIS IS LOOP03 STDOUT ***\""
        },
        "rc": 0,
        "stderr": "",
        "stdout": "# LOOP03 *** THIS IS LOOP03 STDOUT ***\n",
        "stdout_lines": [
            "# LOOP03 *** THIS IS LOOP03 STDOUT ***"
        ]
    },
    "item.stdout_lines": [
        "# LOOP03 *** THIS IS LOOP03 STDOUT ***"
    ]
}

TASK [DEBUG4: Output CMD_RESULT.results.stdout_lines by using jinjya2 fileter] *
ok: [localhost] => {
    "msg": "  [\n    \"# LOOP01 *** THIS IS LOOP01 STDOUT ***\"\n]\n  [\n    \"# LOOP02 *** THIS IS LOOP02 STDOUT ***\"\n]\n  [\n    \"# LOOP03 *** THIS IS LOOP03 STDOUT ***\"\n]\n"
}

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

#

解説

ループ処理がない場合

ループ処理がない場合、DEBUG0のように標準出力の結果を画面表示できますが、
with_items等でループ処理をした場合は、少し工夫が必要です。

ループ処理がある場合

ループ処理がある場合、registerした結果は、変数名.resultsの下に配列として格納されているようなので、ループ処理がない時と同じようにしてもうまくいきません。

  • DEBUG1では、ループ処理が無いときと同じように書いているため、"VARIABLE IS NOT DEFINED!"として出力に失敗した例です。
  • DEBUG2では、変数名.resultsの配列をまるごと出力した例です。
  • DEBUG3では、変数名.results.stdout_lineswith_itmesとして変数名.resultsを指定した例です。itemの中身も出力されるので少し見ずらいです。
  • DEBUG4では、変数名.results.stdout_linesをjinjya2 filterを使ってstdout_linesのみを出力した例ですが、jinjya2 filterの理解不足のためか改行処理がうまくいっていません。。。

おわりに

もっと上手い書き方があると思いますので、こんな風にすれば良い等、ありましたら是非コメント頂ければと思います。

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
No 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
ユーザーは見つかりませんでした