We're currently migrating from our on premise HipChat instance to Google Chat (basically a nicer UI for Hangouts). Since our deployments are orchestrated by ansible playbooks we'd like to write out to changelog chat rooms whenever a deployment starts and finishes (either with a success or a failure message), I had to figure out how to write to those Google Chat rooms/conversations via the simple Webhook API.

First of all I learned a few more things about ansible.

  1. The "role_path" variable is no longer available, but "playbook_dir" works.
  2. The lookup() template module has strange lookup path to try by default:

    looking for "card.json.j2" at "/home/sven/deploy/roles/googlechat-notify/handlers/templates/card.json.j2"
    looking for "card.json.j2" at "/home/sven/deploy/roles/googlechat-notify/handlers/card.json.j2"
    looking for "card.json.j2" at "/home/sven/deploy/templates/card.json.j2"
    looking for "card.json.j2" at "/home/sven/deploy/card.json.j2"
    looking for "card.json.j2" at "/home/sven/deploy/templates/card.json.j2"
    looking for "card.json.j2" at "/home/sven/deploy/card.json.j2"

I'm still wondering why they try everything except the templates directory within the calling role "/home/sven/deploy/roles/googlechat-notify/templates/card.json.j2".

I ended up with the following handler:

- name: notify google chat changelog channel
  uri:
    url: "{{ googlechat_room }}"
    body: "{{ lookup('template', playbook_dir + '/roles/googlechat-notify/templates/card.json.j2') }}"
    body_format: "json"
    method: "POST"
  ignore_errors: yes
  register: googlechat_result
  when: not (disable_googlechat_notification | default(false))

- set_fact:
    googlechat_conversation: "{{googlechat_result.json.thread.name}}"
  ignore_errors: yes

Sending the following json template:

{
{% if googlechat_conversation is defined %}
  "thread": {
      "name": "{{ googlechat_conversation }}"
  },
{% endif %}
  "cards": [
    {
      "sections": [
        {
          "widgets": [
            {
              "textParagraph": {
              {% if googlechat_msg is defined and googlechat_status is defined and googlechat_status == "SUCCESS" %}
                "text": "<b><font color=\"#0BCA14\">{{ googlechat_status }}</font></b> - {{ googlechat_msg }}"
              {% elif googlechat_msg is defined and googlechat_status is defined and googlechat_status == "FAILED" %}
                "text": "<b><font color=\"#E41B2B\">{{ googlechat_status }}</font></b> - {{ googlechat_msg }}"
              {% elif googlechat_msg is defined and googlechat_status is defined and googlechat_status == "START" %}
                "text": "<b><font color=\"#3A3CC4\">{{ googlechat_status }}</font></b> - {{ googlechat_msg }}"
              {% else %}
                "text": "<b><font color=\"#F66905\">UNKOWN status</font></b> - {{ googlechat_msg }}"
              {% endif %}
              }
            }
          ]
        }
      ]
    }
  ]
}

The message card documentation is here, in case you would like to lookup the details. The advantage of cards compared to the simple text messages is that you can colorize the output. So it's visually distinguishable if you're dealing with a success or a failure.

The calling code in the playbook looks like this:

- hosts: deploy-hosts
  tasks:
  -name: deploy
    block:
      - include: roles/googlechat-notify/handlers/main.yml
        vars:
          googlechat_status: "START"
          googlechat_msg: "foo"
        run_once: true
        [... do the actual deployment ...]
      - meta: flush_handlers
      - include: roles/googlechat-notify/handlers/main.yml
        vars:
          googlechat_status: "SUCCESS"
          googlechat_msg: "bar"
        run_once: true
      - meta: flush_handlers
    rescue:
       - include: roles/googlechat-notify/handlers/main.yml
         vars:
          googlechat_status: "FAILED"
          googlechat_msg: "baz"
         run_once: true