ansible:将 with_items 与通知处理程序一起使用

问题描述 投票:0回答:5

我想将一个变量传递给通知处理程序,但在 SO、文档或 github 存储库中的问题、如何做到这一点上找不到任何地方。我正在做的是部署多个 Web 应用程序,当其中一个 Web 应用程序的代码发生更改时,它应该重新启动该 Web 应用程序的服务。

这个问题,我得到了这个工作,有点:

- hosts: localhost
  tasks:
  - name: "task 1"
    shell: "echo {{ item }}"
    register: "task_1_output"
    with_items: [a,b]
  - name: "task 2"
    debug:
      msg: "{{ item.item }}"
    when: item.changed
    with_items: task_1_output.results

(放入 test.yml 并使用

ansible-playbook test.yml -c local
运行它。)

但这会注册第一个任务的结果,并有条件地循环第二个任务的结果。我的问题是,当您有两个或多个任务需要通知第二个任务时,它会变得混乱!例如,如果更新了代码或更改了配置,则重新启动 Web 服务。

AFAICT,无法将变量传递给处理程序。这将为我彻底解决它。我在 github 上发现了一些问题,其他人也遇到了同样的问题,并提出了一些语法,但它们实际上都不起作用。

包含子剧本也不起作用,因为

with_items
include
一起使用已被弃用。

在我的剧本中,我有一个

site.yml
列出了某个组的角色,然后在该组的
group_vars
中,我定义了应安装的 Web 应用程序(包括版本)列表。这对我来说似乎是正确的,因为这样我就可以使用相同的剧本进行登台和制作。但也许唯一的解决方案是多次定义角色,并复制用于登台和生产的角色列表。

那么这里的智慧是什么?

ansible
5个回答
20
投票

Ansible 中的变量是全局的,因此没有理由将变量传递给处理程序。如果您尝试以处理程序名称中的变量的方式对处理程序进行参数化,您将无法在 Ansible 中执行此操作。

您可以做的是创建一个足够轻松地循环服务列表的处理程序,这是一个可以在本地测试的工作示例:

- hosts: localhost
  tasks:
  - file:  >
      path=/tmp/{{ item }}
      state=directory
    register: files_created
    with_items:
      - one
      - two
    notify: some_handler

  handlers:
    - name: "some_handler"
      shell: "echo {{ item }} has changed!"
      when: item.changed
      with_items: files_created.results

6
投票

我最终通过将应用程序拆分为同一角色的多个实例来解决这个问题。这样,角色中的处理程序就可以引用定义为角色变量的变量。

在 site.yml 中:

- hosts: localhost
  roles:
  - role: something
    name: a
  - role: something
    name: b

在角色/某事/任务/main.yml中:

- name: do something
  shell: "echo {{ name }}"
  notify: something happened

- name: do something else
  shell: "echo {{ name }}"
  notify: something happened

在roles/something/handlers/main.yml中:

- name: something happened
  debug:
    msg: "{{ name }}"

看起来比第一个解决方案要简单得多!


6
投票

为了更新上面 jarv 的答案,Ansible 2.5 将

with_items
替换为
loop
。当得到结果时,
item
本身是行不通的。您需要明确获取名称,例如
item.name

- hosts: localhost
  tasks:
  - file:  >
      path=/tmp/{{ item }}
      state=directory
    register: files_created
    loop:
      - one
      - two
    notify: some_handler

  handlers:
    - name: "some_handler"
      shell: "echo {{ item.name }} has changed!"
      when: item.changed
      loop: files_created.results

1
投票

我让我的像这样工作 - 我必须添加一些大括号

tasks:
    - name: Aktivieren von Security-, Backport- und Non-Security-Upgrades
      lineinfile:
        path: /etc/apt/apt.conf.d/50unattended-upgrades
        regexp: '^[^"//"]*"\${distro_id}:\${distro_codename}-{{ item }}";'
        line: '        "${distro_id}:${distro_codename}-{{ item }}";'
        insertafter: "Unattended-Upgrade::Allowed-Origins {"
        state: present
      register: aenderung
      loop:
        - updates
        - security
        - backports
      notify: Auskommentierte Zeilen entfernen

    handlers:
        - name: Auskommentierte Zeilen entfernen
          lineinfile:
            path: /etc/apt/apt.conf.d/50unattended-upgrades
            regexp: '^\/\/.*{{ item.item }}";.*'
            state: absent
          when: item.changed
          loop: "{{ aenderung.results }}"

0
投票

您也可以在处理程序中使用循环。例如:

tasks:
  - name: create ipip tunnel
    ansible.builtin.template:
      src: ifcfg-tunl.j2
      dest: "/etc/sysconfig/network-scripts/ifcfg-{{ item.ifname }}"
    notify: ifup tunl
    register: tunnels_changed
    with_items: "{{ cluster_tunl }}"

handlers:
  - name: ifup tunl
    listen: ifup tunl
    ansible.builtin.shell: "ifup {{ item.item.ifname }}"
    when: item.changed
    loop: "{{ tunnels_changed.results }}"
© www.soinside.com 2019 - 2024. All rights reserved.