3

Consider the following Ansible task:

- name: stop tomcat
  gather_facts: false
  hosts: pod1
  pre_tasks:
  - include_vars:
      dir: "vars/{{ environment }}"
  vars:
    hipchat_message: "stop tomcat pod1 done."
    hipchat_notify: "yes"
  tasks:
    - include: tasks/stopTomcat8AndClearCache.yml
    - include: tasks/stopHttpd.yml
    - include: tasks/hipchatNotification.yml

This stops tomcat on n number of servers. What I want it to do is send a hipchat notification when it's done doing this. However, this code sends a separate hipchat message for each server the task happens on. This floods the hipchat window with redundant messages. Is there a way to make the hipchat task happen once after the stop tomcat/stop httpd tasks have been done on all the targets? I want the task to shut down tomcat on all the servers, then send one hip chat message saying "tomcat stopped on pod 1".

Sly_Boots
  • 185
  • 2
  • 14
  • [`run_once: true`](https://docs.ansible.com/ansible/latest/user_guide/playbooks_delegation.html#run-once) might be your friend here but it is not (from what I recall) usable on an include. I don't think your hipchat yml has so many tasks. You can probably use it there. – Zeitounator Apr 02 '19 at 21:04

2 Answers2

1

You can conditionally run the hipchat notification task on only one of the pod1 hosts.

- include: tasks/hipChatNotification.yml
  when: inventory_hostname == groups.pod1[0]

Alternately you could only run it on localhost if you don't need any of the variables from the previous play.

- name: Run notification
  gather_facts: false
  hosts: localhost
  tasks:
  - include: tasks/hipchatNotification.yml

You also could use the run_once flag on the task itself.

- name: Do a thing on the first host in a group.
  debug: 
    msg: "Yay only prints once"
  run_once: true

- name: Run this block only once per host group
  block:
  - name: Do a thing on the first host in a group.
    debug: 
      msg: "Yay only prints once"
  run_once: true
Nick
  • 1,834
  • 20
  • 32
  • I'm trying to avoid doing it that way as to not bloat up the playbook. I have a very long playbook automating a lengthy deploy process. I suppose I could put a play after a play to notify that the previous play succeeded but that seems too verbose. I don't want to do it the first way - conditionally on one host- because the step isn't considered done until all hosts in the section are complete. – Sly_Boots Apr 02 '19 at 18:57
  • You probably want to look into the run_once flag inside the included task then. You also might try doing that on a block of tasks. – Nick Apr 02 '19 at 22:34
0

Ansible handlers are made for this type of problem where you want to run a task once at the end of an operation even though it may have been triggered multiple times in the play.

You can define a handler section in your playbook and notify it in the tasks, the handlers will not run unless notified by a task, and will only run once regardless of how many times they are notified.

handlers:
    - name: hipchat notify
      hipchat:
        room: someroom
        msg: tomcat stopped on pod 1

In your play tasks just include a "notify" on the tasks that should trigger the handler and if they change it will run the handler after all tasks have executed.

- name: Stop service httpd, if started
  service:
    name: httpd
    state: stopped
  notify: 
    - hipchat notify
Tj Kellie
  • 6,336
  • 2
  • 31
  • 40