2
votes

I need to use Ansible to copy from the remote server the log files, rename them and send by emails as attachments.

I created this playbook:

---
 - hosts: WebAccessServers
   vars:
    date: "{{ lookup('pipe', 'date +%Y%m%d') }}"
   tasks:
     - name: copy web access log file from Web servers to Ansible Server and rename it
       fetch:
        src: /var/www/html/mywebapp/logs/access.log
        dest: /tmp/{{ date }}_{{ inventory_hostname }}_access.log
        flat: yes
        ignore_errors: true
        delegate_to: localhost

 - hosts: localhost
   vars:
    date: "{{ lookup('pipe', 'date +%Y%m%d') }}"
   tasks:
     - name: create variable for the attachments
       shell: "ls /tmp/{{ date }}_*.log"
       register: command_output
     - debug: msg="{{ command_output.stdout_lines }}"

     - name: Send Emails to a bunch of users, with Playbook Report as an attachment.
       mail:
        host: mysmtp.mydomain.com
        port: 25
        subject: Ansible Playbook Report
        body: This is an Email generated using Ansible after execution of task.
        from: ansibbe@gmydomain.com (Ansible Automates)
        to:
        - John Brown <j.ba@mydomain.com>
        attach:
        - "{{  command_output.stdout_lines }}"
        headers:
        - Reply-To=ansible@group-miki.com
        - X-Special="Write something special about this Email"
        charset: us-ascii

If I run it I receive this output:

PLAY [WebAccess]


TASK [Gathering Facts] ************************************************************************************************************************************ ok: [Server-1] ok: [Server-2] ok: [Server-3]

TASK [copy custom web access log file from Web servers] ********************************************************************************************* ok: [Server-1] ok: [Server-2] ok: [Server-3]

PLAY [localhost]


TASK [Gathering Facts] ************************************************************************************************************************************ ok: [localhost]

TASK [create variable for the attachments] **************************************************************************************************************** changed: [localhost]

TASK [debug] ********************************************************************************************************************************************** ok: [localhost] => { "msg": [ "/tmp/20200923_Server-1_access.log", "/tmp/20200923_Server-2_access.log", "/tmp/20200923_Server-3_access.log" ] } TASK [Send Emails to a bunch of users, with Playbook Report as an attachment.] **************************************************************************** An exception occurred during task execution. To see the full traceback, use -vvv. The error was: TypeError: expected str, bytes or os.PathLike object, not list fatal: [localhost]: FAILED! => {"changed": false, "msg": "Failed to send mail: can't attach file ['/tmp/20200923_Server-1_access.log', '/tmp/20200923_Server-2_access.log', '/tmp/20200923_Server-3_access.log']: expected str, bytes or os.PathLike object, not list", "rc": 1} PLAY RECAP ************************************************************************************************************************************************ Server-1 : ok= changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 Server-2 : ok=2 changed=0 unreachable=0
failed=0 skipped=0 rescued=0 ignored=0 Server-3 : ok=2
changed=0 unreachable=0 failed=0 skipped=0 rescued=0
ignored=0 localhost : ok=3 changed=1 unreachable=0 failed=1
skipped=0 rescued=0 ignored=0

Where is the best way to assign dynamically and recursively the attach in the email? Thanks for the support. Marco

2
I'm guessing the email is fine and your email client is doing something stupid, If you are on Windows, try not to be; or if you have to, try to find an editor which can display files with Unix line endings. - tripleee
Hi tripleee, I'm on Linux, and my problem is to assign dinalically more attachs to the email. - Marco Ferrara

2 Answers

1
votes

As prompted by the error message, to, attach and headers are not supposed to be lists.

  • to: The email-address(es) the mail is being sent to. This is a comma-separated list, which may contain address and phrase portions.
  • headers: A vertical-bar-separated list of headers which should be added to the message. Each individual header is specified as header=value (see example below).
  • attach: A space-separated list of pathnames of files to attach to the message. Attached files will have their content-type set to application/octet-stream.

Source: https://docs.ansible.com/ansible/2.3/mail_module.html, emphasis mine

  • For the to, if you have only one recipient to: John Brown <john.brown@example.org> and if you have multiple to: John Brown <john.brown@example.org>, John Doe <john.doe@example.org>
  • For the headers, if you have only one headers: 'Reply-To=ansible@example.org' and if you have multiple headers: 'Reply-To=ansible@example.org|X-Special="Write something special about this Email"'
  • For attach since you are taking it from another the output of another task, using Jinja join filter allows you to convert your list into a space-separated string representation of the said list.

So you mail task should actually be:

- name: Send Emails to a bunch of users, with Playbook Report as an attachment.
  mail:
    host: mysmtp.mydomain.com
    port: 25
    subject: Ansible Playbook Report
    body: This is an Email generated using Ansible after execution of task.
    from: ansibbe@gmydomain.com (Ansible Automates)
    to: John Brown <j.ba@mydomain.com>
    attach: "{{ command_output.stdout_lines | join(' ') }}"
    headers: 'Reply-To=ansible@group-miki.com|X-Special="Write something special about this Email"'
    charset: us-ascii
0
votes

This is my work solution:

---
 - hosts: myapp
   vars:
    date: "{{ lookup('pipe', 'date +%Y%m%d') }}"
   tasks:
     - name: copy access_allowed log file from MyApp servers
       fetch:
        src: /var/www/html/myapp/logs/access_allowed.log
        dest: /tmp/{{ date }}_{{ inventory_hostname }}_access_allowed.log
        flat: yes
        ignore_errors: true
        delegate_to: localhost
     - name: copy access_denied log file from MyApp servers
       fetch:
        src: /var/www/html/myapp/logs/access_denied.log
        dest: /tmp/{{ date }}_{{ inventory_hostname }}_access_denied.log
        flat: yes
        ignore_errors: true
        delegate_to: localhost

     - name: Ansible delete log file
       shell: sudo rm -rf /var/www/html/myapp/logs/access*.log

 - hosts: localhost
   vars:
    date: "{{ lookup('pipe', 'date +%Y%m%d') }}"
   tasks:
     - name: create variable for the attachments
       shell: "ls /tmp/{{ date }}_*.log"
       register: command_output

     - name: Send Emails to a bunch of users, with Playbook Report as an attachment.
       mail:
        host: my.smtp.local
        port: 25
        subject: Ansible Playbook Report
        body: This is an Email generated using Ansible after execution of task.
        from: ansible@mydomain.com (Ansible Automates)
        to: John Brow <JB@mydomain.com>
        attach: "{{ command_output.stdout_lines | join(',') }}"
        headers:
        - Reply-To=ansible@mydomain.com
        - X-Special="Write something special about this Email"
        charset: us-ascii

     - name: Ansible delete log file
       shell: sudo rm -rf /tmp/*access*.log