How to break `with_lines` cycle in Ansible?

心已入冬 提交于 2019-12-08 03:30:31

问题


I would like to use the following handler with Ansible:

- name: force ntp update
  shell: ntpdate {{item}}
  with_lines: /etc/ntpd.serverlist

But I want it to end execution after the first successful execution (the list contains ntpd servers with which you can attempt to sync. One is enough). How would I do that?


回答1:


That's a very interesting situation you have. I haven't tried this personally, but I wonder if something like this would work:

- name: force ntp update
  shell: ntpdate {{item}}
  with_lines: /etc/ntpd.serverlist
  register: ntp_result
  when: ntp_result is not defined or ntp_result.rc != 0
  ignore_errors: yes

So in a nutshell, each call to ntpdate should populate the ntp_result variable with the return code of the call to ntpdate. The when clause then ensures the loop continues if the variable doesn't exist (as it wouldn't have been populated during the first iteration), or if the ntpdate call failed (rc != 0). Telling Ansible to ignore any errors ensures that it continues looping if any of the calls to ntpdate does return an error.

The only real downside to this is that it won't directly notify you if none of the calls to ntpdate succeed. However you can probably follow this task with something along the lines of:

- name: fail if ntpdate fails
  fail: msg="All calls to ntpdate failed"
  when: ntp_result.rc != 0

If the last call resulted in a non-zero result from ntpdate then it means none of them succeeded.




回答2:


At least on Ansible 2.2.1.0 a when statement can break the loop, and the following works skipping all evaluations after the first success:

---
# test.yml

# run this playbook with: ansible-playbook -i localhost, test.yml

- hosts: localhost
connection: local
gather_facts: no
tasks:
  - name: check
    shell: "[ {{item}} -ne 2 ]"
    register: checks
    ignore_errors: yes
    changed_when: false
    when: checks is not defined or checks.rc != 0
    with_items: [2,3,2,4]
  - name: set
    set_fact: first_working={{ item.item }}
    when: "'rc' in item and item.rc == 0"
    with_items: "{{ checks.results }}"
  - debug: var=first_working
  # Note that first_working will be undefined if no check succeeded

This is the output:

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

TASK [check] *******************************************************************
failed: [localhost] (item=2) => {"changed": false, "cmd": "[ 2 -ne 2 ]", "delta": "0:00:00.001735", "end": "2017-03-13 16:14:00.515372", "failed": true, "item": 2, "rc": 1, "start": "2017-03-13 16:14:00.513637", "stderr": "", "stdout": "", "stdout_lines": [], "warnings": []}
ok: [localhost] => (item=3)
skipping: [localhost] => (item=2)
skipping: [localhost] => (item=4)
...ignoring

TASK [set] *********************************************************************
skipping: [localhost] => (item={'_ansible_parsed': True, u'cmd': u'[ 2 -ne 2 ]', u'end': u'2017-03-13 16:14:00.515372', '_ansible_no_log': False, u'stdout': u'', '_ansible_item_result': True, u'changed': False, 'item': 2, u'delta': u'0:00:00.001735', u'stderr': u'', u'rc': 1, 'invocation': {'module_name': u'command', u'module_args': {u'creates': None, u'executable': None, u'_uses_shell': True, u'_raw_params': u'[ 2 -ne 2 ]', u'removes': None, u'warn': True, u'chdir': None}}, 'stdout_lines': [], u'start': u'2017-03-13 16:14:00.513637', u'warnings': [], 'failed': True})
ok: [localhost] => (item={'_ansible_parsed': True, u'changed': False, u'stdout': u'', '_ansible_no_log': False, u'warnings': [], '_ansible_item_result': True, u'rc': 0, u'end': u'2017-03-13 16:14:00.615658', u'start': u'2017-03-13 16:14:00.613978', u'cmd': u'[ 3 -ne 2 ]', 'item': 3, u'delta': u'0:00:00.001680', 'invocation': {'module_name': u'command', u'module_args': {u'creates': None, u'executable': None, u'_uses_shell': True, u'_raw_params': u'[ 3 -ne 2 ]', u'removes': None, u'warn': True, u'chdir': None}}, 'stdout_lines': [], u'stderr': u''})
skipping: [localhost] => (item={'skipped': True, '_ansible_no_log': False, 'skip_reason': u'Conditional check failed', '_ansible_item_result': True, 'item': 2, 'changed': False})
skipping: [localhost] => (item={'skipped': True, '_ansible_no_log': False, 'skip_reason': u'Conditional check failed', '_ansible_item_result': True, 'item': 4, 'changed': False})

TASK [debug] *******************************************************************
ok: [localhost] => {
    "first_working": "3"
}


来源:https://stackoverflow.com/questions/29993341/how-to-break-with-lines-cycle-in-ansible

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!