diff mbox series

[layerindex-web,1/6] rrs/tools/common.py: don't write a log file without TOOLS_LOG_DIR

Message ID 20261115003506.53654-2-tim.orling@konsulko.com
State Under Review
Delegated to: Tim Orling
Headers show
Series Get the RRS update scripts working again | expand

Commit Message

Tim Orling Nov. 15, 2026, 12:35 a.m. UTC
get_logger() always added a log file at TOOLS_LOG_DIR/<name>, but
TOOLS_LOG_DIR is empty by default, so the file was created in the
current directory. In the Docker image that is /opt/layerindex, which
the layers user can't write to, so every RRS update script failed as
soon as it started. Only log to the console when TOOLS_LOG_DIR is not
set.

[YOCTO #16499]

AI-Generated: Claude Opus 5.5
Signed-off-by: Tim Orling <tim.orling@konsulko.com>
---
 docker/settings.py       |  2 +-
 rrs/tools/common.py      | 16 ++++++++++------
 settings.py              |  2 +-
 tests/test_rrs_logger.py | 38 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 50 insertions(+), 8 deletions(-)
 create mode 100644 tests/test_rrs_logger.py
diff mbox series

Patch

diff --git a/docker/settings.py b/docker/settings.py
index a610052..9f18a55 100644
--- a/docker/settings.py
+++ b/docker/settings.py
@@ -309,7 +309,7 @@  AXES_COOLOFF_TIME = 1
 # Full path to directory to store logs for dynamically executed tasks
 TASK_LOG_DIR = "/opt/layerindex-task-logs"
 
-# Full path to directory where rrs tools stores logs
+# Full path to a directory where the rrs tools also write their logs, if any
 TOOLS_LOG_DIR = ""
 
 USE_X_FORWARDED_HOST = True
diff --git a/rrs/tools/common.py b/rrs/tools/common.py
index 0cac1f7..0caf1c9 100644
--- a/rrs/tools/common.py
+++ b/rrs/tools/common.py
@@ -34,12 +34,16 @@  def get_logger(name, settings):
     handler.setFormatter(formatter)
     logger.addHandler(handler)
 
-    filename = os.path.join(settings.TOOLS_LOG_DIR, name)
-    maxBytes = 8388608 # 8MB
-    handler = RotatingFileHandler(filename, maxBytes=maxBytes)
-
-    handler.setFormatter(formatter)
-    logger.addHandler(handler)
+    # Also log to a file if a directory is set for it; otherwise the console
+    # output is all there is (as collected by cron, systemd or docker)
+    log_dir = getattr(settings, 'TOOLS_LOG_DIR', '')
+    if log_dir:
+        filename = os.path.join(log_dir, name)
+        maxBytes = 8388608 # 8MB
+        handler = RotatingFileHandler(filename, maxBytes=maxBytes)
+
+        handler.setFormatter(formatter)
+        logger.addHandler(handler)
 
     logger.setLevel(logging.INFO)
 
diff --git a/settings.py b/settings.py
index 324ad50..495af1e 100644
--- a/settings.py
+++ b/settings.py
@@ -298,5 +298,5 @@  AXES_COOLOFF_TIME = 1
 # Full path to directory to store logs for dynamically executed tasks
 TASK_LOG_DIR = "/tmp/layerindex-task-logs"
 
-# Full path to directory where rrs tools stores logs
+# Full path to a directory where the rrs tools also write their logs, if any
 TOOLS_LOG_DIR = ""
diff --git a/tests/test_rrs_logger.py b/tests/test_rrs_logger.py
new file mode 100644
index 0000000..b03c928
--- /dev/null
+++ b/tests/test_rrs_logger.py
@@ -0,0 +1,38 @@ 
+# layerindex-web - tests for the RRS tools' logger
+#
+# Licensed under the MIT license, see COPYING.MIT for details
+#
+# SPDX-License-Identifier: MIT
+
+import logging
+import os
+import sys
+import types
+
+import pytest
+
+sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'rrs', 'tools'))
+from common import get_logger
+
+
+@pytest.fixture
+def readonly_cwd(tmp_path, monkeypatch):
+    os.chmod(tmp_path, 0o555)
+    monkeypatch.chdir(tmp_path)
+    yield tmp_path
+    os.chmod(tmp_path, 0o755)
+
+
+def test_no_log_file_without_tools_log_dir(readonly_cwd):
+    # [YOCTO #16499] the scripts run in a directory they can't write to
+    logger = get_logger('RRSTestNoDir', types.SimpleNamespace(TOOLS_LOG_DIR=''))
+    assert not [h for h in logger.handlers if isinstance(h, logging.FileHandler)]
+    assert os.listdir(readonly_cwd) == []
+
+
+def test_log_file_in_tools_log_dir(tmp_path):
+    logger = get_logger('RRSTestDir', types.SimpleNamespace(TOOLS_LOG_DIR=str(tmp_path)))
+    logger.info('hello')
+    for h in logger.handlers:
+        h.flush()
+    assert 'hello' in (tmp_path / 'RRSTestDir').read_text()