基于多个循环中的更改结果运行Ansible处理程序

9

我有一个包含一组Web服务器列表的Ansible变量(所有服务器都在同一主机上):

servers:
  - foo
  - bar
  - baz

一个任务会更改它们的配置文件,并在变量中注册结果:

- name: create server configs
  template: ...
  with_items: "{{ servers }}"
  notify: restart changed servers
  register: servers_changed

当任务运行时,重新启动只有更改过的服务器的处理程序:

- name: restart changed servers
  command: restart-my-server {{ item.item.name }}
  when: item.changed
  with_items: "{{ servers_changed.results }}"

我的问题是,我现在需要多个像上面那样的任务,去改变不同的配置文件。但如果我这样做,它们会覆盖servers_changed变量,因此只有最后一个会被使用。

我可以在每个任务中注册不同的变量,但这样我需要为每个变量编写不同的处理程序。这会变得混乱。有更好的方法吗?

2个回答

6
我发现了一种我更喜欢的方法。这个方法创建了一个名为 restart_servers 的变量,其中包含需要重新启动的服务器名称数组。在更新配置文件后,将更改的项目添加到该变量中。
变量:
```html

vars:

```
servers:
- name: server1
  port: 1000
- name: server2
  port: 1001

任务:

- name: create server configs
  template: ...
  with_items: "{{ servers }}"
  notify: restart changed servers
  register: servers_changed

- name: remember which servers need to restart
  set_fact:
    restart_servers: "{{ restart_servers | default([]) + [item.item.name] }}"
  when: item.changed
  with_items: "{{ servers_changed.results }}"

处理程序:
- name: restart changed servers
  command: restart-my-server {{ item.name }}
  when: item.name in restart_servers | default([])
  with_items: "{{ servers }}"

缺点是,在可能触发重新启动的每个任务后,您需要第二个任务基于更改的服务器来调用set_fact。
优点是易于理解,并且避免了重复处理程序或重复重新启动。

很酷。但是为什么不直接在处理程序中使用 with_items: "{{restart_servers}}",从而消除这个 when ...? - Wojciech Kaczmarek
1
@WojciechKaczmarek 我想我在我的示例中过于简化了一些事情。在我的实际设置中,servers 是一个包含有关每个服务器详细信息的字典列表,但 restart_servers 只是标识每个服务器的名称列表。您可以让处理程序循环 restart_servers,但循环 servers 可以让它访问有关正在重新启动的每个服务器的详细信息。例如,我让处理程序查看每个服务器的端口号,并等待其变为打开状态后再继续。 - JW.
是的,我怀疑你从某个更大的、现实的上下文中拖拽了这段代码。感谢更新示例。 - Wojciech Kaczmarek

5
使用servers_changed作为组合列表,并连接每个任务的结果:
- name: create server configs
  template: ...
  with_items: "{{ servers }}"
  notify: restart changed servers
  register: servers_changed_now

- set_fact:
    servers_changed: "{{ servers_changed | default([]) | union(servers_changed_now.results|default([]) }}"

并且

- name: restart changed servers
  command: restart-my-server {{ item.item.name }}
  when: item.changed
  with_items: "{{ servers_changed }}"

1
最终我编写了一个自定义过滤器来在set_fact中使用,它合并了已注册的变量,但忽略了重复的服务器(以避免重启服务器超过一次)。 - JW.
1
实际上这里不需要自定义过滤器,我更新了答案以处理空列表和重复条目。 - techraf
我不认为这会消除重复的服务器,因为你必须查找 item.item 才能找到服务器名称。 - JW.
这将消除重复项。根据您准备模板的方式,可能会或可能不会。您更清楚内部情况。 - techraf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接