diff --git a/tests/test_volume_mount_audit.py b/tests/test_volume_mount_audit.py new file mode 100644 index 0000000..4558931 --- /dev/null +++ b/tests/test_volume_mount_audit.py @@ -0,0 +1,33 @@ +import sys +import tempfile +import unittest +from pathlib import Path + +sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "tools")) + +from volume_mount_audit import build + + +class VolumeMountAuditTest(unittest.TestCase): + def test_detects_missing_mounts(self): + with tempfile.TemporaryDirectory() as tmpdir: + root = Path(tmpdir) + static = root / "deployment" / "mx-exporter" + helm = static / "helm" / "mx-exporter" / "templates" + helm.mkdir(parents=True) + static.joinpath("mx-exporter-daemonset.yaml").write_text( + '- name: "config-vol"\n mountPath: "/etc/config"\n- name: "var-log"\n mountPath: "/host/var/log"\n', + encoding="utf-8", + ) + helm.joinpath("daemonset.yaml").write_text( + '- name: "config-vol"\n mountPath: "/etc/config"\n', + encoding="utf-8", + ) + + report = build(root) + + self.assertEqual(report["only_in_static"], ["var-log"]) + + +if __name__ == "__main__": + unittest.main() diff --git a/tools/volume_mount_audit.py b/tools/volume_mount_audit.py new file mode 100644 index 0000000..1ed1510 --- /dev/null +++ b/tools/volume_mount_audit.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 +"""Compare static and Helm volume mounts for mx-exporter.""" + +from __future__ import annotations + +import argparse +import json +from pathlib import Path + + +def extract_mounts(text: str) -> list[dict[str, str]]: + mounts = [] + current_name = None + for raw_line in text.splitlines(): + line = raw_line.strip() + if line.startswith('- name: "') and line.endswith('"'): + current_name = line.split('"')[1] + continue + if current_name and line.startswith('mountPath: "') and line.endswith('"'): + mounts.append({"name": current_name, "path": line.split('"')[1]}) + current_name = None + return mounts + + +def build(repo_root: Path) -> dict[str, object]: + static_text = (repo_root / "deployment" / "mx-exporter" / "mx-exporter-daemonset.yaml").read_text(encoding="utf-8") + helm_text = (repo_root / "deployment" / "mx-exporter" / "helm" / "mx-exporter" / "templates" / "daemonset.yaml").read_text(encoding="utf-8") + static_mounts = extract_mounts(static_text) + helm_mounts = extract_mounts(helm_text) + static_names = {mount["name"] for mount in static_mounts} + helm_names = {mount["name"] for mount in helm_mounts} + return { + "static_mount_count": len(static_mounts), + "helm_mount_count": len(helm_mounts), + "only_in_static": sorted(static_names - helm_names), + "only_in_helm": sorted(helm_names - static_names), + } + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--repo-root", type=Path, default=Path(".")) + parser.add_argument("--output", type=Path) + args = parser.parse_args() + + text = json.dumps(build(args.repo_root), indent=2, ensure_ascii=False) + if args.output: + args.output.write_text(text + "\n", encoding="utf-8") + else: + print(text) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main())