Prompt

Ansible:如何驗證 ansible_become_user,以及是否缺少使用者輸入提示(多個主機)

  • April 24, 2022

我使用多個主機,如果清單或劇本中未設置 ansible_become_user 和 ansible_become_password,我想提示使用者提供 sudo 使用者名和密碼

我使用以下內容:

庫存文件:

os:
 children:
   centos:
     hosts:
       clean_centos_1:
         vars:
         ansible_become_user: root
         ansible_become_password: root
   rocky:
     hosts:
       clean_rocky_1:
   ubuntu:
     hosts:
       clean_ubuntu_1:
   debian:
     hosts:
       clean_debian_1:
   alpine:
     hosts:
       clean_alpine_1:
         vars:
         ansible_become_user: root
         ansible_become_password: root
 vars:
   ansible_user: test 
   ansible_password: test

劇本

- name: "PLAY1"
 hosts: all
 gather_facts: no

 tasks:
## Identify ansible_become_user if present
#------------------------------------------------------
 - name: "Test if ansible_become_user is empty" 
   debug:
     var: ansible_become_user
   register: result
   when: ansible_become_user | length > 0
   ignore_errors: yes

 - name: "Set status_ansible_become_user"
   set_fact:
     status_ansible_become_user: "{{ status_ansible_become_user|default({}) | combine( { ansible_host: 'absent' if result.failed is true else 'present' }) }}"


## Get user input
#------------------------------------------------------
 - name: "User-input: <ansible_become_user>"
   pause:
     prompt: "\nEnter root username or sudo username for host: {{ansible_host}}"
   when: item == 'absent'
   loop: "{{status_ansible_become_user.values()}}"

 - set_fact:
     ansible_become_user: "{{ result.user_input }}"
   when: result.failed is false


 - debug:
     var: item == 'absent'
   loop: "{{status_ansible_become_user.values()}}"

上例中因為 clean_centos_1 排在第一位,並且設置了 ansible_become_user 和 ansible_become_passwor,其他主機如下跳過,沒有提示

TASK [User-input: <ansible_become_user>] **********************************************************************************************************************************************************************************************************************************
skipping: [clean_centos_1] => (item=present)

TASK [set_fact] ***********************************************************************************************************************************************************************************************************************************************************
fatal: [clean_centos_1]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'user_input'\n\nThe error appears to be in '/git/ansible/role/rar.pkg.python/playbook/test.yml': line 28, column 5, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n  - set_fact:\n    ^ here\n"}
skipping: [clean_rocky_1]
skipping: [clean_debian_1]
skipping: [clean_ubuntu_1]
fatal: [clean_alpine_1]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'user_input'\n\nThe error appears to be in '/git/ansible/role/rar.pkg.python/playbook/test.yml': line 28, column 5, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n  - set_fact:\n    ^ here\n"}

問題:

如何正確驗證是否設置了 ansible_become_user 和 ansible_become_password,如果未設置,如何提示使用以提供每個主機可能不同的 ansible_become_user 和 ansible_become_password?

例如,在下面的劇本中

- hosts: all
 gather_facts: false
 vars:
   ab: "{{ hostvars|dict2items|json_query(_query) }}"
   _query: "[].{host: key,
                ansible_become_user: value.ansible_become_user,
                ansible_become_password: value.ansible_become_password}"
   ab_hosts: "{{ ab|map(attribute='host')|list }}"
   ab_dict: "{{ dict(ab_hosts|zip(ab)) }}"
 tasks:
   - block:
       - include_tasks: enter_ansible_become.yml
         loop: "{{ ab }}"
       - set_fact:
           ab_dict: "{{ ab_dict|combine(ab_update, recursive=True) }}"
     run_once: true
   - add_host:
       groups: test
       hostname: "{{ item.key }}"
       ansible_become_user: "{{ item.value.ansible_become_user }}"
       ansible_become_password: "{{ item.value.ansible_become_password }}"
     loop: "{{ ab_dict|dict2items }}"

- hosts: test
 gather_facts: false
 tasks:
   - debug:
       msg: |-
         ansible_become_user: {{ ansible_become_user }}
         ansible_become_password: {{ ansible_become_password }}

創建主機和變數的列表和字典

 ab:
 - ansible_become_password: root
   ansible_become_user: root
   host: clean_centos_1
 - ansible_become_password: null
   ansible_become_user: null
   host: clean_rocky_1
 - ansible_become_password: null
   ansible_become_user: null
   host: clean_ubuntu_1
 - ansible_become_password: null
   ansible_become_user: null
   host: clean_debian_1
 - ansible_become_password: root
   ansible_become_user: root
   host: clean_alpine_1
 ab_dict:
   clean_alpine_1:
     ansible_become_password: root
     ansible_become_user: root
     host: clean_alpine_1
   clean_centos_1:
     ansible_become_password: root
     ansible_become_user: root
     host: clean_centos_1
   clean_debian_1:
     ansible_become_password: null
     ansible_become_user: null
     host: clean_debian_1
   clean_rocky_1:
     ansible_become_password: null
     ansible_become_user: null
     host: clean_rocky_1
   clean_ubuntu_1:
     ansible_become_password: null
     ansible_become_user: null
     host: clean_ubuntu_1

執行一次,迭代塊中的列表,並包含文件enter_ansible_become.yml中的任務

shell> cat enter_ansible_become.yml
- block:
   - pause:
       prompt: "[{{ item.host }}] Enter ansible_become_user"
     register: result
   - set_fact:
       ab_update: "{{ ab_update|d({})|combine(update, recursive=True) }}"
     vars:
       update: "{{ {item.host: {'ansible_become_user': result.user_input}} }}"
 when: not item.ansible_become_user

- block:
   - pause:
       prompt: "[{{ item.host }}] Enter ansible_become_password"
     register: result
   - set_fact:
       ab_update: "{{ ab_update|d({})|combine(update, recursive=True) }}"
     vars:
       update: "{{ {item.host: {'ansible_become_password': result.user_input}} }}"
 when: not item.ansible_become_password

(可選)設置參數echo: false以隱藏密碼。預設值為true。見迴聲


例如,輸入缺失變數的值

TASK [pause] *********************************************************************************
[pause]
[clean_rocky_1] Enter ansible_become_user:
admin1^Mok: [clean_centos_1]

TASK [set_fact] ******************************************************************************
ok: [clean_centos_1]

TASK [pause] *********************************************************************************
[pause]
[clean_rocky_1] Enter ansible_become_password:
123^Mok: [clean_centos_1]

TASK [set_fact] ******************************************************************************
ok: [clean_centos_1]

TASK [pause] *********************************************************************************
[pause]
[clean_ubuntu_1] Enter ansible_become_user:
admin2^Mok: [clean_centos_1]

TASK [set_fact] ******************************************************************************
ok: [clean_centos_1]

TASK [pause] *********************************************************************************
[pause]
[clean_ubuntu_1] Enter ansible_become_password:
456^Mok: [clean_centos_1]

TASK [set_fact] ******************************************************************************
ok: [clean_centos_1]

TASK [pause] *********************************************************************************
[pause]
[clean_debian_1] Enter ansible_become_user:
admin3^Mok: [clean_centos_1]

TASK [set_fact] ******************************************************************************
ok: [clean_centos_1]

TASK [pause] *********************************************************************************
[pause]
[clean_debian_1] Enter ansible_become_password:
789^Mok: [clean_centos_1]

TASK [set_fact] ******************************************************************************
ok: [clean_centos_1]

這將創建字典ab_update

 ab_update:
   clean_debian_1:
     ansible_become_password: '789'
     ansible_become_user: admin3
   clean_rocky_1:
     ansible_become_password: '123'
     ansible_become_user: admin1
   clean_ubuntu_1:
     ansible_become_password: '456'
     ansible_become_user: admin2

仍然在塊中,組合字典

 ab_dict:
   clean_alpine_1:
     ansible_become_password: root
     ansible_become_user: root
     host: clean_alpine_1
   clean_centos_1:
     ansible_become_password: root
     ansible_become_user: root
     host: clean_centos_1
   clean_debian_1:
     ansible_become_password: '789'
     ansible_become_user: admin3
     host: clean_debian_1
   clean_rocky_1:
     ansible_become_password: '123'
     ansible_become_user: admin1
     host: clean_rocky_1
   clean_ubuntu_1:
     ansible_become_password: '456'
     ansible_become_user: admin2
     host: clean_ubuntu_1

在下一個任務中使用模組add_host並創建動態組test。在下一場比賽中使用這個小組。變數應正確聲明

PLAY [test] **********************************************************************************

TASK [debug] *********************************************************************************
ok: [clean_centos_1] => 
 msg: |-
   ansible_become_user: root
   ansible_become_password: root
ok: [clean_rocky_1] => 
 msg: |-
   ansible_become_user: admin1
   ansible_become_password: 123
ok: [clean_ubuntu_1] => 
 msg: |-
   ansible_become_user: admin2
   ansible_become_password: 456
ok: [clean_debian_1] => 
 msg: |-
   ansible_become_user: admin3
   ansible_become_password: 789
ok: [clean_alpine_1] => 
 msg: |-
   ansible_become_user: root
   ansible_become_password: root

引用自:https://unix.stackexchange.com/questions/700192