Ansible with_items列表根据条件

时间:2016-05-20 22:55:47

标签: ansible ansible-playbook ansible-2.x

背景:我想写一个适用于不同操作系统的ansible playbook。它的基本功能之一是使用DbSet命令安装软件包(在ansible 2.0中新引入)。

问题是每个操作系统上的软件包列表都不同。我想在某处指定常用的,然后分别放置Ubuntu特定的和CentOS特定的。那么对于CentOS,CentOS6和CentOS7也有一些常见的和不同的,所以我想在某处为CentOS放置常用的,在其他地方放置CentOS6和CentOS7。

我想到的最直接的方法就是拥有group_vars,但是,我知道的方式不会起作用。假设在group_vars下我有文件all,ubuntu,centos,centos6和centos7来定义变量,其优先顺序是不确定的。对于CentOS6主机,它分为all,centos和centos6。无法指定package应优先于centos6centos超过centos

我找到的另一种方法是在ansible.cfg中设置all,然而,这会修改全局行为,这会过度杀伤。可能存在需要默认行为的情况,因此全局修改它并不是一个好方法。

我应该如何以干净的方式组织所有事情,尽可能地分享和重复使用普通事物?

1 个答案:

答案 0 :(得分:3)

角色内的操作系统条件

我使用的一种常见方法是在角色的vars目录中定义OS专用默认变量文件,然后将它们包含在main.yml任务的开头。 Ansible帮助我使用{{ ansible_distribution }}{{ ansible_distribution_version }}自动识别当前使用的分配,因此我只需相应地命名OS专用的yml文件。

角色目录树

my_role/
├── handlers
│   ├── main.yml
│   └── Ubuntu14.04.yml
├── tasks
│   ├── main.yml
│   └── Ubuntu14.04.yml
├── templates
│   └── Ubuntu14_04.config.j2
└── vars
    └── Ubuntu14.04.yml

main.yml中,您首先包含默认的操作系统特定变量,然后运行特定于操作系统的任务:

<强>任务/ main.yml:

---

- name: include distribution specific vars
  include_vars: "{{ ansible_distribution }}{{ ansible_distribution_version }}.yml"

- name: include distribution specific install
  include: "{{ ansible_distribution }}{{ ansible_distribution_version }}.yml"

- name: Do general stuff
  ...

现在,您可以在每个发行版的vars文件中轻松定义包,例如,Ubuntu14.04:

<强>乏/ Ubuntu14.04.yml:

---

my_role_packages: 
  - a
  - b

最后将它们安装在您的分发特定设置任务中。

<强>任务/ Ubuntu14.04.yml:

---

- name: Install packages for Ubuntu14.04
  apt:
    name={{ item }}
    state=present
    update_cache=yes
  with_items: "{{ my_role_packages }}"

您现在还可以轻松定义特定于操作系统的处理程序和模板,例如:

<强>处理程序/ main.yml:

---

- name: distribution specific handler
  include: "{{ ansible_distribution }}{{ ansible_distribution_version }}.yml"

哈希合并

关于全局设置hash_behaviour=merge,此处引用official Ansible documentation

  

有些用户更喜欢哈希变量(又名'词典')   在Python术语中)合并。此设置称为“合并”。   除非您认为,否则我们通常建议您不要使用此设置   绝对需要它,以及官方例子中的剧本   repos不使用此设置。

最初我来自SaltStack世界并且习惯于将默认值map.jinja中的哈希值与专用支柱合并,但在Ansible中我开始更多地依赖变量前缀,因此不是

nginx:
  pkg: "nginx"
  repo: "deb http://nginx.org/packages/ubuntu/ trusty nginx"

我会写

nginx_pkg: "nginx"
nginx_repo: "deb http://nginx.org/packages/ubuntu/ trusty nginx"

为了避免在上升变量层次结构时意外覆盖哈希值。如果在某些情况下您仍然喜欢合并,则可以在变量文件中使用jinja2 combine过滤器:dict_a: {{ dict_b|combine(dict_c) }}

变量分组

Ansible文档强调大量使用group_vars,我发现这是一个很好的建议。这里的一般方法是在我的库存文件中定义我的组,例如:

<强>主机/测试

[app] 
app-test-a 
app-test-b

[app_test:children] 
app

<强>主机/活

[app] 
app-live-a 
app-live-b

[app_live:children] 
app

现在我可以轻松地使用group_vars根据定义的组包含变量:

group_vars/
├── all.yml
├── app_test.yml
├── app_live.yml
└── app.yml

Ansible Galaxy和DebObs

我还建议您查看Ansible Galaxy个角色。他们总是一个很好的起点来获得一些想法(包括这个想法)。另一个很好的灵感来源是DebObs repository