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: [email protected] (Ansible Automates)
        to:
        - John Brown <[email protected]>
        attach:
        - "{{  command_output.stdout_lines }}"
        headers:
        - [email protected]
        - 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 <[email protected]> and if you have multiple to: John Brown <[email protected]>, John Doe <[email protected]>
  • For the headers, if you have only one headers: '[email protected]' and if you have multiple headers: '[email protected]|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: [email protected] (Ansible Automates)
    to: John Brown <[email protected]>
    attach: "{{ command_output.stdout_lines | join(' ') }}"
    headers: '[email protected]|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: [email protected] (Ansible Automates)
        to: John Brow <[email protected]>
        attach: "{{ command_output.stdout_lines | join(',') }}"
        headers:
        - [email protected]
        - X-Special="Write something special about this Email"
        charset: us-ascii

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