如何在ansible中创建一次性用户提示输入?
How to create a one-time user prompt input in ansible?
我有以下过于简化的 ansible 剧本:
- name: Prepare worker nodes
hosts: "{{ hosts }}"
serial:
- 1
- 3
remote_user: root
any_errors_fatal: true
vars:
hosts: nodes
reboot: false
tasks:
- pause:
prompt: "Reboot server(s) to make sure things are working during setup? (Y/n)"
echo: true
register: confirm_reboot
tags: [ untagged, hostname, netplan, firewalld ]
- set_fact:
reboot: "{{ (confirm_reboot.user_input == '' or confirm_reboot.user_input == 'Y' or confirm_reboot.user_input == 'y' ) | ternary('True', 'False') }}"
tags: [ untagged, hostname, netplan, firewalld, firewalld-install, firewalld-config ]
- debug:
msg: "{{ reboot }}"
它要求用户输入,以便它可以决定一些重启策略。
当你只有一个节点时,这工作得很好,但当你有多个节点时,它会提示 each 一个。假设你有 42 个节点——它会问你 42 次。
我想弄清楚是否有一种简单的方法可以让提示只出现一次并在节点之间共享结果。也许我遗漏了文档中的某些内容?
看起来唯一可行的方法是使用 delegate_to
和 delegate_facts
。我想到了这样的事情:
- name: Prepare worker nodes
hosts: "{{ hosts }}"
serial:
- 1
- 3
remote_user: root
any_errors_fatal: true
vars:
hosts: nodes
reboot: true
pre_tasks:
- pause:
prompt: "Reboot server(s) to make sure things are working during setup? (Y/n)"
echo: true
register: confirm_reboot
run_once: true
delegate_to: localhost
delegate_facts: true
tags: [ untagged, hostname, netplan, firewalld, firewalld-install, firewalld-config ]
when: "'reboot' not in hostvars['localhost']"
- set_fact:
reboot: "{{ (confirm_reboot.user_input == '' or confirm_reboot.user_input == 'Y' or confirm_reboot.user_input == 'y' ) | ternary('True', 'False') }}"
run_once: true
delegate_to: localhost
delegate_facts: true
tags: [ untagged, hostname, netplan, firewalld, firewalld-install, firewalld-config ]
when: "'reboot' not in hostvars['localhost']"
- set_fact:
reboot: "{{ hostvars['localhost']['reboot'] }}"
run_once: true
tasks:
- debug:
msg: "{{ hostvars['localhost'] }}"
tags: [ untagged, hostname, netplan, firewalld, firewalld-install, firewalld-config ]
- debug:
msg: "{{ reboot }}"
tags: [ untagged, hostname, netplan, firewalld, firewalld-install, firewalld-config ]
这是通过将事实委托给 localhost
(控制节点)来实现的,然后它通过似乎保存在不同节点之间的引用来使用它。这对我来说是一个 hackish 的解决方法,但由于我没有那么多时间来深入研究“为什么”,所以现在必须这样做。
如果有人想出更好的方法 - 请随时 post 您的回答。
鉴于库存
shell> cat hosts
[test]
host1
host2
host3
host4
host5
剧本
shell> cat playbook.yml
---
- hosts: test
serial:
- 1
- 3
gather_facts: false
tasks:
- pause:
prompt: "Reboot? (Y/n)"
echo: true
register: confirm_reboot
run_once: true
- debug:
msg: "Reboot {{ inventory_hostname }}"
when: confirm_reboot.user_input|lower == 'y'
按预期工作
shell> ansible-playbook -i hosts playbook.yml
PLAY [test] *********************************
TASK [pause] ********************************
[pause]
Reboot? (Y/n):
ok: [host1]
TASK [debug] ********************************
ok: [host1] =>
msg: Reboot host1
PLAY [test] *********************************
TASK [pause] ********************************
[pause]
Reboot? (Y/n):
ok: [host2]
TASK [debug] ********************************
ok: [host2] =>
msg: Reboot host2
ok: [host3] =>
msg: Reboot host3
ok: [host4] =>
msg: Reboot host4
PLAY [test] *********************************
TASK [pause] ********************************
[pause]
Reboot? (Y/n):
ok: [host5]
TASK [debug] ********************************
ok: [host5] =>
msg: Reboot host5
问:"整个剧本只需要输入一次并传播到所有主机。"
A:拆分剧本,例如
shell> cat playbook.yml
---
- hosts: test
gather_facts: false
tasks:
- pause:
prompt: "Reboot? (Y/n)"
echo: true
register: confirm_reboot
run_once: true
- hosts: test
serial:
- 1
- 3
gather_facts: false
tasks:
- debug:
msg: "Reboot {{ inventory_hostname }}"
when: confirm_reboot.user_input|lower == 'y'
第一次播放的变量将在第二次播放中共享给所有主机
shell> ansible-playbook -i hosts playbook.yml
PLAY [test] *********************************
TASK [pause] ********************************
[pause]
Reboot? (Y/n):
ok: [host1]
PLAY [test] *********************************
TASK [debug] ********************************
ok: [host1] =>
msg: Reboot host1
PLAY [test] *********************************
TASK [debug] ********************************
ok: [host3] =>
msg: Reboot host3
ok: [host2] =>
msg: Reboot host2
ok: [host4] =>
msg: Reboot host4
PLAY [test] *********************************
TASK [debug] ********************************
ok: [host5] =>
msg: Reboot host5
我有以下过于简化的 ansible 剧本:
- name: Prepare worker nodes
hosts: "{{ hosts }}"
serial:
- 1
- 3
remote_user: root
any_errors_fatal: true
vars:
hosts: nodes
reboot: false
tasks:
- pause:
prompt: "Reboot server(s) to make sure things are working during setup? (Y/n)"
echo: true
register: confirm_reboot
tags: [ untagged, hostname, netplan, firewalld ]
- set_fact:
reboot: "{{ (confirm_reboot.user_input == '' or confirm_reboot.user_input == 'Y' or confirm_reboot.user_input == 'y' ) | ternary('True', 'False') }}"
tags: [ untagged, hostname, netplan, firewalld, firewalld-install, firewalld-config ]
- debug:
msg: "{{ reboot }}"
它要求用户输入,以便它可以决定一些重启策略。 当你只有一个节点时,这工作得很好,但当你有多个节点时,它会提示 each 一个。假设你有 42 个节点——它会问你 42 次。
我想弄清楚是否有一种简单的方法可以让提示只出现一次并在节点之间共享结果。也许我遗漏了文档中的某些内容?
看起来唯一可行的方法是使用 delegate_to
和 delegate_facts
。我想到了这样的事情:
- name: Prepare worker nodes
hosts: "{{ hosts }}"
serial:
- 1
- 3
remote_user: root
any_errors_fatal: true
vars:
hosts: nodes
reboot: true
pre_tasks:
- pause:
prompt: "Reboot server(s) to make sure things are working during setup? (Y/n)"
echo: true
register: confirm_reboot
run_once: true
delegate_to: localhost
delegate_facts: true
tags: [ untagged, hostname, netplan, firewalld, firewalld-install, firewalld-config ]
when: "'reboot' not in hostvars['localhost']"
- set_fact:
reboot: "{{ (confirm_reboot.user_input == '' or confirm_reboot.user_input == 'Y' or confirm_reboot.user_input == 'y' ) | ternary('True', 'False') }}"
run_once: true
delegate_to: localhost
delegate_facts: true
tags: [ untagged, hostname, netplan, firewalld, firewalld-install, firewalld-config ]
when: "'reboot' not in hostvars['localhost']"
- set_fact:
reboot: "{{ hostvars['localhost']['reboot'] }}"
run_once: true
tasks:
- debug:
msg: "{{ hostvars['localhost'] }}"
tags: [ untagged, hostname, netplan, firewalld, firewalld-install, firewalld-config ]
- debug:
msg: "{{ reboot }}"
tags: [ untagged, hostname, netplan, firewalld, firewalld-install, firewalld-config ]
这是通过将事实委托给 localhost
(控制节点)来实现的,然后它通过似乎保存在不同节点之间的引用来使用它。这对我来说是一个 hackish 的解决方法,但由于我没有那么多时间来深入研究“为什么”,所以现在必须这样做。
如果有人想出更好的方法 - 请随时 post 您的回答。
鉴于库存
shell> cat hosts
[test]
host1
host2
host3
host4
host5
剧本
shell> cat playbook.yml
---
- hosts: test
serial:
- 1
- 3
gather_facts: false
tasks:
- pause:
prompt: "Reboot? (Y/n)"
echo: true
register: confirm_reboot
run_once: true
- debug:
msg: "Reboot {{ inventory_hostname }}"
when: confirm_reboot.user_input|lower == 'y'
按预期工作
shell> ansible-playbook -i hosts playbook.yml
PLAY [test] *********************************
TASK [pause] ********************************
[pause]
Reboot? (Y/n):
ok: [host1]
TASK [debug] ********************************
ok: [host1] =>
msg: Reboot host1
PLAY [test] *********************************
TASK [pause] ********************************
[pause]
Reboot? (Y/n):
ok: [host2]
TASK [debug] ********************************
ok: [host2] =>
msg: Reboot host2
ok: [host3] =>
msg: Reboot host3
ok: [host4] =>
msg: Reboot host4
PLAY [test] *********************************
TASK [pause] ********************************
[pause]
Reboot? (Y/n):
ok: [host5]
TASK [debug] ********************************
ok: [host5] =>
msg: Reboot host5
问:"整个剧本只需要输入一次并传播到所有主机。"
A:拆分剧本,例如
shell> cat playbook.yml
---
- hosts: test
gather_facts: false
tasks:
- pause:
prompt: "Reboot? (Y/n)"
echo: true
register: confirm_reboot
run_once: true
- hosts: test
serial:
- 1
- 3
gather_facts: false
tasks:
- debug:
msg: "Reboot {{ inventory_hostname }}"
when: confirm_reboot.user_input|lower == 'y'
第一次播放的变量将在第二次播放中共享给所有主机
shell> ansible-playbook -i hosts playbook.yml
PLAY [test] *********************************
TASK [pause] ********************************
[pause]
Reboot? (Y/n):
ok: [host1]
PLAY [test] *********************************
TASK [debug] ********************************
ok: [host1] =>
msg: Reboot host1
PLAY [test] *********************************
TASK [debug] ********************************
ok: [host3] =>
msg: Reboot host3
ok: [host2] =>
msg: Reboot host2
ok: [host4] =>
msg: Reboot host4
PLAY [test] *********************************
TASK [debug] ********************************
ok: [host5] =>
msg: Reboot host5