如何使用Ansible Playbook迭代主机的N级子级?

时间:2016-05-27 15:14:34

标签: loops ansible ansible-playbook

我知道如何使用host_vars实现这一点,但问题是主机文件可能会变得复杂,所以我倾向于ini文件,我可以将所有数据放在一个文件中。这篇SO帖子帮助我了解了如何将集合放入特定主机的变量中。

我有这个样本库存:

;hosts.yml
[web1]
example1.com databases=["example1_com","mysql"]
example2.com databases=["example1_com","mysql"]

[web1:vars]
ansible_host=10.0.16.21

[web2]
example3.com databases=["example3_com"]
example4.com databases=["example4_com","mysql"]

[web2:vars]
ansible_host=10.0.16.22

[web:children]
web1
web2

现在我想使用web组遍历每个主机,并遍历databases主机变量。

我做了类似的事情:

---
- debug:
    msg: "{{ item }} - {{ hostvars[item]['databases'] }} "
  with_items:
    - "{{ groups['web'] }}"

,输出为:

ok: [localhost] => (item=example1.com) => {
    "item": "example1.com", 
    "msg": "example1.com - [example1_com,mysql] "
}
ok: [localhost] => (item=example2.com) => {
    "item": "example2.com", 
    "msg": "example2.com - [example1_com,mysql] "
}
ok: [localhost] => (item=example3.com) => {
    "item": "example3.com", 
    "msg": "example3.com - [example3_com] "
}
ok: [localhost] => (item=example4.com) => {
    "item": "example4.com", 
    "msg": "example4.com - [example4_com,mysql] "
}

我尝试使用with_sublements循环实现此目的但问题是第二个元素需要是动态的,这是不可能的with_subelements

with_subelements:
    - "{{ groups['web'] }}"
    - {{ hostvars[item]['databases'] }} #item is dynamic, this will cause an undefined host error.

1 个答案:

答案 0 :(得分:1)

我不能100%清楚你原来的方法是什么,以及你问题中的代码是否代表你的新方法(因为你仍然在那里引用hostvars)。我认为您需要在运行playbook时指定要在playbook(hosts: web)或命令行(-l web)中受影响的组,以便仅为所需的主机运行任务而不是试图在任务本身内动态获取组。

关于链接的问题/答案,其中讨论了在变量中定义列表的方法:您需要确保将列表数据括在单引号内,例如: '["example1_com","mysql"]'

鉴于此,如果您只想从库存文件中定义的主机变量迭代列表,则可以执行以下操作:

广告资源“inv”

[web1]
example1.com databases='["example1_com","mysql"]'
example2.com databases='["example1_com","mysql"]'

[web1:vars]
ansible_host=10.0.16.21

[web2]
example3.com databases='["example3_com"]'
example4.com databases='["example4_com","mysql"]'

[web2:vars]
ansible_host=10.0.16.22

[web:children]
web1
web2

Playbook文件“test.yml”

---
- hosts: web
  gather_facts: no
  tasks:
    - debug: msg="Host is {{ inventory_hostname }}. Database is {{ item }}"
      with_items:
        - "{{ databases }}"

然后你可以运行剧本:

ansible-playbook test.yml -i inv

生成以下输出:

PLAY ***************************************************************************

TASK [debug] *******************************************************************
ok: [example3.com] => (item=example3_com) => {
    "item": "example3_com", 
    "msg": "Host is example3.com. Database is example3_com"
}
ok: [example1.com] => (item=example1_com) => {
    "item": "example1_com", 
    "msg": "Host is example1.com. Database is example1_com"
}
ok: [example1.com] => (item=mysql) => {
    "item": "mysql", 
    "msg": "Host is example1.com. Database is mysql"
}
ok: [example2.com] => (item=example1_com) => {
    "item": "example1_com", 
    "msg": "Host is example2.com. Database is example1_com"
}
ok: [example2.com] => (item=mysql) => {
    "item": "mysql", 
    "msg": "Host is example2.com. Database is mysql"
}
ok: [example4.com] => (item=example4_com) => {
    "item": "example4_com", 
    "msg": "Host is example4.com. Database is example4_com"
}
ok: [example4.com] => (item=mysql) => {
    "item": "mysql", 
    "msg": "Host is example4.com. Database is mysql"
}

PLAY RECAP *********************************************************************
example1.com               : ok=1    changed=0    unreachable=0    failed=0   
example2.com               : ok=1    changed=0    unreachable=0    failed=0   
example3.com               : ok=1    changed=0    unreachable=0    failed=0   
example4.com               : ok=1    changed=0    unreachable=0    failed=0   

如果您正确构建了Playbook,您还可以将其设置为针对不同的主机组运行不同的任务集(可能包括来自外部文件的任务,以便您进行干燥)。或者您只需在剧本中指定hosts: all,并使用命令行限制仅针对特定主机集运行任务。