3

Writing a playbook to perform yum updates and then get an email from each server. I'd like the email to contain the changed contents of yum.log.

IOW, I want the results of:

grep [today's date] /var/log/yum.log

to be emailed from each server.

I tried using shell: to perform the grep then send the mail :

    shell: grep '^`date +"%b %d"`' /var/log/yum.log | mail -s "updates applied to `hostname -s` today" updatereports@mydomain.com

It just sends a blank email.

Also tried using the mail function but am struggling to dump a multi-line variable into the body of the message:

- name: test result
  ignore_errors: yes
  shell: grep "`date '+%b %d'`" /var/log/messages
  register: updated

- name: mail result
  mail:
    to: updatereports@mydomain.com
    subject: "updates applied to {{ ansible_hostname }} today"
    body: "{{ item }}"
    with_items: "{{ updated.results|map(attribute='stdout_lines')|list }}"
  when: updated.stdout

It also sends, but prints the timestamp then generates a line of errors for each matched line in yum.log:

['Sep 12 16:15:28 host-ng ansible-command: Invoked with warn=True executable=None _uses_shell=True _raw_params=grep "`date \'+%b %d\'`" /var/log/messages | tail removes=None creates=None chdir=None'

I found that fancy results|map code here but don't understand it enough to work without errors.

Mike
  • 53
  • 1
  • 6

2 Answers2

5

I am not certain if it is your only problem, but one problem is that your with_items is indented incorrectly. The with_items belongs to a task, not the mail.

- name: mail result
  mail:
    to: updatereports@mydomain.com
    subject: "updates applied to {{ ansible_hostname }} today"
    body: "{{ item }}"
  with_items: "{{ updated.results|map(attribute='stdout_lines')|list }}"
  when: updated.stdout

I am not really sure if you need the with_items at all in this case though. You need to use with_items when you are looping over a collection of something.

Since I don't know the answer, if I where in your shoes I would simply start with some simple debug tasks instead of the mail. Once you see the results of the debug it should be a lot easier to see what you need to do.

- name: mail result
  debug:
    msg: "{{ updated }}"
- name: mail result
  debug:
    msg: ""{{ updated.results|map(attribute='stdout_lines')|list }}""
Zoredache
  • 130,897
  • 41
  • 276
  • 420
  • good catch with the formatting and thanks for explaining! – Mike Sep 14 '17 at 14:59
  • The debug tips helped. It's working in the debug msg when I remove the fancy code above and just dump `updated.stdout_lines`, but when it mails the result the lines are all mashed together. Is there a way to print stdout_lines with carriage returns? – Mike Sep 14 '17 at 15:09
  • Maybe try using the `updated.stdout` instead of `stdout.stdout_lines`. The stdout_lines is a list of the lines split on the line feeds. I think the stdout is the entire output. See the 'Return values' section of the shell module. http://docs.ansible.com/ansible/latest/shell_module.html I bet there some way to add line breaks with jinja, but I am also relatively new to ansible so I don't know how yet. – Zoredache Sep 14 '17 at 16:54
2

Thank you for sharing your ideas @Zoredache! This works just fine:

- name: test result
  ignore_errors: yes
  shell: grep "`date '+%b.%d'`" /var/log/yum.log
  register: updated

- name: mail result
  mail:
    to: updatereports@mydomain.com
    subject: "updates applied to {{ ansible_hostname }} today"
    body: "{{ updated.stdout }}"
  when: updated.stdout

Update: I spoke too soon! I was testing it by grepping /var/log/messages but when I perform the grep on /var/log/yum.log the output is mashed together again without any linebreaks.**

Mike
  • 53
  • 1
  • 6