ansible:使用带有通知处理程序的with_items

j00*_*057 10 ansible

我想将一个变量传递给通知处理程序,但无法在SO,文档或github repo中的问题中找到它,如何做到这一点.我正在做的是部署多个webapps,当其中一个webapps的代码发生变化时,它应该重新启动该webapp的服务.

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

- 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
Run Code Online (Sandbox Code Playgroud)

(将它放在test.yml中并运行它ansible-playbook test.yml -c local.)

但是这会记录第一个任务的结果,并在第二个任务中有条件地循环.我的问题是当你有两个或更多需要通知第二个任务的任务时它会变得混乱!例如,如果代码已更新或配置已更改,请重新启动Web服务.

AFAICT,没有办法将变量传递给处理程序.那会干净利落地为我解决.我在github上发现了一些问题,其他人遇到了同样的问题,并提出了一些语法,但它们都没有实际工作.

包括子剧本也不会起作用,因为with_items与之一起使用include已被弃用.

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

那么这里的智慧是什么?

jar*_*arv 16

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
Run Code Online (Sandbox Code Playgroud)

  • 我曾尝试过这种方法,但是当两个或多个任务可能会或可能不会通知处理程序时,它无法正常工作. (3认同)

j00*_*057 6

我终于通过将应用程序拆分到同一角色的多个实例上来解决它.这样,角色中的处理程序可以引用定义为角色变量的变量.

在site.yml中:

- hosts: localhost
  roles:
  - role: something
    name: a
  - role: something
    name: b
Run Code Online (Sandbox Code Playgroud)

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

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

- name: do something else
  shell: "echo {{ name }}"
  notify: something happened
Run Code Online (Sandbox Code Playgroud)

在角色/ something/handlers/main.yml中:

- name: something happened
  debug:
    msg: "{{ name }}"
Run Code Online (Sandbox Code Playgroud)

似乎比第一个解决方案更少的hackish!

  • 我认为这不起作用,只是用Ansible 1.8.4和1.9.0进行了相同的测试.处理程序总是根据第一个角色调用"a"来解析`name`,即使在后续角色调用触发时也是如此.由于处理程序及其通知在角色调用中是全局的,因此您无法像这样对其进行参数化. (2认同)
  • 奇怪!我想我测试了这个,当时是1.7.1.但是我通过将notify更改为在"tasks/main.yml中发生{`name}}"的事情并将处理程序的名称更改为"{{name}}上发生的事情",再次使用它. `. (2认同)

Den*_*oer 6

为了更新上面 jarv 的答案,Ansible 2.5 替换with_itemsloop. 当得到结果时,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
Run Code Online (Sandbox Code Playgroud)