Environment variable

Hello,

I’m trying to reset the ANSIBLE_LOG_PATH environment variable. To do this, I’ve written the following code:

play.yml

- name: test la genration de fichier de log
  hosts: all
  #gather_facts: no
  connection: local
  tasks:
    - import_role:
        name: role1

role1/main.yml

---

- set_fact:
    datetime: "{{ ansible_date_time.iso8601_basic_short }}"

- name: "Emplacement du log"
  block:
    - file:
        path: "{{ inventory_dir }}/logs"
        state: directory
    - file:
        path: "{{ inventory_dir }}/logs/{{ datetime }}_{{ ansible_role_name }}.log"
        state: touch
  delegate_to: localhost

- name: 
  command: export $ANSIBLE_LOG_PATH
  environment:
    ANSIBLE_LOG_PATH: "{{ inventory_dir }}/logs/{{ datetime }}_{{ ansible_role_name }}.log"

- block:
  - shell: echo $ANSIBLE_LOG_PATH
    register: test
  - name: Affichage de la variable test
    debug:
      msg: "{{ test }}"

- name: Affichage de la variable role1
  debug:
    msg: "{{ role1 }}"

I get the following error without understanding why

TASK [role1 : command] *****************************************************************************************************************************************************************************************
fatal: [ma_machine1]: FAILED! => {"changed": false, "cmd": "export /home/alexandre/inventory/logs/20241208T100856_role1.log", "msg": "[Errno 2] No such file or directory: b'export'", "rc": 2, "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}

However, the file is present in the logs directory.

I’d like to reload this variable in order to change the log file when a role is started.

Thank You

export is a shell builtin and you’re using the command module (which doesn’t use a shell). This will never work.

Even if you used the shell module it wouldn’t work as the export would happen within that shell invocation and not carried forward.

At best (though I don’t know whether log output can be reset) you use the environment: task attribute on the task you want the log to be changed.

1 Like

Thanks for your feedback, I must admit that when I tried to use copilot, I got the following library:

from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

import os
from ansible.plugins.callback import CallbackBase

class CallbackModule(CallbackBase):
    CALLBACK_VERSION = 2.0
    CALLBACK_TYPE = 'notification'
    CALLBACK_NAME = 'role_logger'
    CALLBACK_NEEDS_WHITELIST = True

    def __init__(self, display=None):
        super(CallbackModule, self).__init__(display)
        self.logs = {}
        self.current_role = None
        self.log_dir = os.getenv('ANSIBLE_LOG_DIR', '/path/to/logs')

    def v2_playbook_on_task_start(self, task, is_conditional):
        role = task._role
        if role:
            self.current_role = role.get_name()
            if self.current_role not in self.logs:
                self.logs[self.current_role] = []

    def v2_runner_on_ok(self, result):
        self._log(result)

    def v2_runner_on_failed(self, result, ignore_errors=False):
        self._log(result)

    def v2_runner_on_skipped(self, result):
        self._log(result)

    def v2_runner_on_unreachable(self, result):
        self._log(result)

    def _log(self, result):
        if self.current_role:
            msg = self._dump_results(result._result)
            self.logs[self.current_role].append(msg)
            self._write_log(self.current_role)

    def v2_playbook_on_stats(self, stats):
        pass  # No need to handle logs here, already handled per task.

    def _write_log(self, role_name):
        log_file = os.path.join(self.log_dir, f"log_{role_name}_{self._timestamp()}.log")
        with open(log_file, 'w') as f:
            for entry in self.logs[role_name]:
                f.write(entry + '\n')

    def _timestamp(self):
        import datetime
        return datetime.datetime.now().strftime('%Y%m%d%H%M%S')

I placed it in a directory at the root of my play. But I didn’t know how to use it, even though I had set the variables in ansible.cfg:

[defaults]
callback_whitelist = role_logger
callback_plugins = ./callback_plugins

I had no log files being created. Could you help me to get this library working?
Where to place it?
How to call it?

Thanking you

That is a custom callback plugin, but you can just use existing ones that create log files, here are a few:

syslog_json
tree
log plays

1 Like