mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2025-11-08 06:08:05 +00:00
feat(filters): enforce safe Node.js heap sizing via reusable filter
- Add node_autosize filter (node_max_old_space_size) using get_app_conf - Raise error when mem_limit < min_mb to prevent OOM-kill misconfigurations - Wire Whiteboard NODE_OPTIONS and increase mem_limit to 1g; set cpus=1 - Refactor PeerTube to use the same filter; simplify vars - Add unit tests; keep integration filters usage green Context: https://chatgpt.com/share/690e0499-6a94-800f-b8ed-2c5124690103
This commit is contained in:
80
tests/unit/filter_plugins/test_node_autosize.py
Normal file
80
tests/unit/filter_plugins/test_node_autosize.py
Normal file
@@ -0,0 +1,80 @@
|
||||
# tests/unit/filter_plugins/test_node_autosize.py
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
# Module under test
|
||||
import filter_plugins.node_autosize as na
|
||||
|
||||
try:
|
||||
from ansible.errors import AnsibleFilterError # type: ignore
|
||||
except Exception:
|
||||
AnsibleFilterError = Exception
|
||||
|
||||
|
||||
class TestNodeAutosizeFilter(unittest.TestCase):
|
||||
"""Unit tests for the node_autosize filter plugin."""
|
||||
|
||||
def setUp(self):
|
||||
# Default parameters used by all tests
|
||||
self.applications = {"web-app-nextcloud": {"docker": {"services": {"whiteboard": {}}}}}
|
||||
self.application_id = "web-app-nextcloud"
|
||||
self.service_name = "whiteboard"
|
||||
|
||||
# Patch get_app_conf (imported from module_utils.config_utils) inside the filter plugin
|
||||
self.patcher = patch("filter_plugins.node_autosize.get_app_conf")
|
||||
self.mock_get_app_conf = self.patcher.start()
|
||||
|
||||
def tearDown(self):
|
||||
self.patcher.stop()
|
||||
|
||||
def _set_mem_limit(self, value):
|
||||
"""Helper: mock get_app_conf to return a specific mem_limit value."""
|
||||
def _fake_get_app_conf(applications, application_id, config_path, strict=True, default=None, **_kwargs):
|
||||
assert application_id == self.application_id
|
||||
assert config_path == f"docker.services.{self.service_name}.mem_limit"
|
||||
return value
|
||||
self.mock_get_app_conf.side_effect = _fake_get_app_conf
|
||||
|
||||
# --- Tests for node_max_old_space_size (MB) ---
|
||||
|
||||
def test_512m_below_minimum_raises(self):
|
||||
# mem_limit=512 MB < min_mb=768 -> must raise
|
||||
self._set_mem_limit("512m")
|
||||
with self.assertRaises(AnsibleFilterError):
|
||||
na.node_max_old_space_size(self.applications, self.application_id, self.service_name)
|
||||
|
||||
def test_2g_caps_to_minimum_768(self):
|
||||
self._set_mem_limit("2g")
|
||||
mb = na.node_max_old_space_size(self.applications, self.application_id, self.service_name)
|
||||
self.assertEqual(mb, 768) # 35% of 2g = 700 < 768 -> min wins
|
||||
|
||||
def test_8g_uses_35_percent_without_hitting_hardcap(self):
|
||||
self._set_mem_limit("8g")
|
||||
mb = na.node_max_old_space_size(self.applications, self.application_id, self.service_name)
|
||||
self.assertEqual(mb, 2800) # 8g -> 8000 MB * 0.35 = 2800
|
||||
|
||||
def test_16g_hits_hardcap_3072(self):
|
||||
self._set_mem_limit("16g")
|
||||
mb = na.node_max_old_space_size(self.applications, self.application_id, self.service_name)
|
||||
self.assertEqual(mb, 3072) # 35% of 16g = 5600, hardcap=3072
|
||||
|
||||
def test_numeric_bytes_input(self):
|
||||
# 2 GiB in bytes (IEC): 2 * 1024 ** 3 = 2147483648
|
||||
self._set_mem_limit(2147483648)
|
||||
mb = na.node_max_old_space_size(self.applications, self.application_id, self.service_name)
|
||||
# 2 GiB ≈ 2147 MB; 35% => ~751, min 768 => 768
|
||||
self.assertEqual(mb, 768)
|
||||
|
||||
def test_invalid_unit_raises_error(self):
|
||||
self._set_mem_limit("12x") # invalid unit
|
||||
with self.assertRaises(AnsibleFilterError):
|
||||
na.node_max_old_space_size(self.applications, self.application_id, self.service_name)
|
||||
|
||||
def test_missing_mem_limit_raises_error(self):
|
||||
self._set_mem_limit(None)
|
||||
with self.assertRaises(AnsibleFilterError):
|
||||
na.node_max_old_space_size(self.applications, self.application_id, self.service_name)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user