如何在没有冗余代码的情况下在一个地方为所有后续主机设置变量?

How to set variables for all subsequent hosts in one place without redundant code?

TL/DR:我有 "src_host" 和 "dest_host" 变量,我想用它们来设置游戏中的“- hosts:”对象。但是,我必须在每个“- hosts:”部分的 "vars:" 下为每个游戏重新设置它们,例如src_host="{{ hostvars[[=​​49=]]['src_host'] }}" 如何在开始时设置这两个变量而不必重新设置它们?

我的主机文件如下所示

[wordpress]
localhost ansible_user=user ansible_port=22 ansible_ssh_private_key_file=/home/user/.ssh/id_rsa
root_localhost ansible_user=root ansible_port=22 ansible_ssh_private_key_file=/home/user/.ssh/id_rsa

---snip---

server2.net ansible_host="server2.net" ansible_user=user ansible_port=22 ansible_ssh_private_key_file=/home/user/.ssh/id_rsa
root_server2.net ansible_host="server2.net" ansible_user=root ansible_port=22  ansible_ssh_private_key_file=/home/user/.ssh/id_rsa

我的剧本的开头是这样的:

- hosts: localhost, server2.net, root_server2.net #always include "localhost" in this list because it is needed to store the variables for the src_host and dest_host
  vars:
    src_host: localhost #modify these and the host will be changed for all subsequent plays/tasks
    dest_host: server2.net #modify these and the host will be changed for all subsequent plays/tasks
    src_dump_path: /home/user/cvrt9_dump.sql #set vars for copying file
  roles:  
    - set_facts_for_db_copy

- hosts: "{{ src_host }}" 
  vars: 
    src_host: "{{ hostvars['localhost']['src_host'] }}"
    dest_host: "{{ hostvars['localhost']['dest_host'] }}"
    ---snip---
  roles:
    - dump_db
    - copy_file

等。 . .

for "- set_facts_for_db_copy" 我设置了 "main.yml" 和 "src_host" 和 "dest_host" 变量:

---
# tasks file for set_facts_for_db_copy
- name: create variables that equal src_dump_path and set src_host/dest_host
  set_fact:
    ---snip---
    src_host: "{{ src_host }}"
    dest_host: "{{ dest_host }}"

所以我需要为所有后续的“-主机:”设置"src_host"和"dest_host",通过从"set_fact_for_db_copy"设置的主机变量之一获取值来使用它们.正如您可能已经注意到的那样,我随机选择了 "localhost":

src_host: "{{ hostvars['localhost']['src_host'] }}"
dest_host: "{{ hostvars['localhost']['dest_host'] }}"

如果我没有那条线,我会得到:

user@localhost:/home/maintainer/ansible-play$ ansible-playbook -i hosts_tat-kay playbook.yml 

PLAY [localhost, server2.net, root_server2.net] **************

TASK [setup] *******************************************************************
ok: [server2.net]
ok: [root_server2.net]
ok: [localhost]

TASK [set_facts_for_db_copy : create variables that equal src_dump_path] *******
ok: [localhost]
ok: [server2.net]
ok: [root_server2.net]
ERROR! the field 'hosts' has an invalid value, which appears to include a variable that is undefined. The error was: 'src_host' is undefined

The error appears to have been in '/home/maintainer/ansible-play/playbook.yml': line 14, column 3, but may
be elsewhere in the file depending on the exact syntax problem.

The offending line appears to be:


- hosts: "{{ src_host }}" 
  ^ here

。 . .

现在我可以在我的主机文件中设置这些变量:

[wordpress:vars]
src_host=localhost
dest_host=server2.net

但是我仍然需要从我的剧本中随后的“-hosts:”对象中引用它们,使用“{{ hostvars[[=​​49=]]['src_host'] }}”等。 . .所以我的问题是如何摆脱所有后续“-hosts:”对象(如下所示)中的冗余代码,同时仍然让我在开始时更改 "src_host" 和 "dest_host" 变量一次,这些变化会影响其余的戏剧吗?谢谢。

    src_host: "{{ hostvars['localhost']['src_host'] }}"
    dest_host: "{{ hostvars['localhost']['dest_host'] }}"

为此,请使用您的清单文件,为您需要的主机创建一个父组,如下所示。

[desireenv:children]
wordpress
otherhost
etc

然后将变量值分配给创建的新父组

[desireenv:vars]
src_host: "{{ hostvars['localhost']['src_host'] }}"
dest_host: "{{ hostvars['localhost']['dest_host'] }}"

我在 https://whosebug.com/users/4716639/bryan-calvo-benoit 的帮助下找到的一个解决方案是将其放入我的主机文件(库存文件)

[wordpress] 
localhost 
server2.net 

[testenv:children] 
wordpress 

[testenv:vars] 
src_host=localhost 
dest_host=server2.net 

然后在 ansible 剧本及其调用的角色中,我必须替换

"{{ src_host }}" 

"{{ hostvars['localhost']['src_host'] }}"

同样适用于“{{ dest_host }}”

但是,我可以在我的 ansible 剧本中删除这段冗余代码:

src_host: "{{ hostvars['localhost']['src_host'] }}"
dest_host: "{{ hostvars['localhost']['dest_host'] }}"

如果我不必将 src_host 和 dest_host 更改为 hostvars[[=​​27=]] 就好了...因为使用 localhost 似乎很随意,而且如果我想 运行 一个接一个地 src_host 和 dest_host 几个 ansible 脚本怎么办?使用清单文件会将其锁定,因此这并不理想。如果没有其他人回答,我会接受这个答案,因为它是唯一有效的答案,并且从技术上讲它可以满足我的问题。