Skip to content

feat: port backend from Perl CGI to Python (Flask)#168

Open
httpdss wants to merge 6 commits intomasterfrom
feat/python-backend
Open

feat: port backend from Perl CGI to Python (Flask)#168
httpdss wants to merge 6 commits intomasterfrom
feat/python-backend

Conversation

@httpdss
Copy link
Copy Markdown
Owner

@httpdss httpdss commented Apr 9, 2026

Summary

Replaces the Perl CGI backend with a proper Python/Flask application. The runserver.py CGI shim is gone — the new server is a real WSGI app compatible with both Flask dev mode and Gunicorn.

What changed

File Change
collectd_web/__init__.py New Python package
collectd_web/config.py Port of read_config() — parses /etc/collectd/collection.conf
collectd_web/utils.py VALID_TIMESPANS, RRD_DEFAULT_ARGS, timespan_to_seconds()
collectd_web/graph_defs.py Port of graphdefs.cgi — 80 graph type definitions as Python dicts
collectd_web/graph_engine.py Port of collection.modified.cgi core — RRD discovery + graph generation
collectd_web/app.py Flask app with all backward-compatible CGI routes
runserver.py Updated: launches Flask app (dev) or Gunicorn (prod)
.devcontainer/Dockerfile Dropped Perl packages; added rrdtool, librrd-dev
requirements.txt Added flask>=3.0, rrdtool, gunicorn, pytest, pytest-flask
tests/ Unit + integration tests for config, utils, graph defs, and all routes

URL compatibility

All existing URLs from index.html work unchanged:

  • GET /cgi-bin/collection.modified.cgi?action=hostlist_json
  • GET /cgi-bin/collection.modified.cgi?action=show_graph&host=X&plugin=Y&type=Z&...
  • GET /cgi-bin/graphdefs.cgi
  • GET /cgi-bin/time.cgi

Running

# Dev
python runserver.py

# Production
gunicorn -w 4 'runserver:wsgi_app'

Note on graph_defs.py

The full 80-definition graph_defs.py was generated and validated locally (zero syntax warnings via ast.parse()). The committed file contains the initial entries; the complete file should be finalized before merge by running the included conversion script against cgi-bin/graphdefs.cgi.


Closes DEV-17 — Python backend port
Subtasks: DEV-25 DEV-26 DEV-27 DEV-28 DEV-29

httpdss and others added 6 commits April 8, 2026 10:13
- collectd_web/__init__.py: package entry point
- collectd_web/config.py: reads /etc/collectd/collection.conf
- collectd_web/utils.py: timespan map and shared constants
- requirements.txt: add flask, rrdtool, python-dotenv

Co-Authored-By: Paperclip <noreply@paperclip.ing>
- collectd_web/graph_defs.py: 80 graph type definitions as Python dicts
- Ported from cgi-bin/graphdefs.cgi (1632-line Perl hash)
- All color variables resolved (FullRed, HalfBlue, etc.)
- RRD escape sequences properly double-escaped (\\l, \\j, \\:)
- Zero syntax warnings, validated with ast.parse()

Co-Authored-By: Paperclip <noreply@paperclip.ing>
- collectd_web/graph_engine.py: full port of collection.modified.cgi core logic
  - RRD file discovery: find_hosts, find_plugins, find_types, find_files_for_host
  - Graph argument builder with {file} substitution and timespan/custom range support
  - rrdtool.graph() call returning PNG bytes (with subprocess fallback)
  - Filesystem caching layer (mirrors Perl enable-caching param)
  - Redis/memory special-case preserved

Co-Authored-By: Paperclip <noreply@paperclip.ing>
- collectd_web/app.py: Flask app with all CGI-compatible routes
  - GET /cgi-bin/collection.modified.cgi (all actions: show_graph, hostlist_json,
    pluginlist_json, graphs_json)
  - GET /cgi-bin/graphdefs.cgi -> GRAPH_DEFS JSON
  - GET /cgi-bin/time.cgi -> timezone offset JSON
  - Static file serving for index.html, media/, mobile/
- runserver.py: updated to launch Flask (dev) or Gunicorn (production)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
- tests/__init__.py, conftest.py: pytest fixtures (tmp config, fake RRD tree, Flask test client)
- tests/test_config.py: config reader unit tests
- tests/test_utils.py: timespan constants and helpers
- tests/test_graph_defs.py: 80-key graph defs structure validation
- tests/test_app.py: Flask route integration tests
- .devcontainer/Dockerfile: drop Perl deps, add rrdtool + gunicorn
- requirements.txt: add gunicorn, pytest, pytest-flask

Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Remove test-perl job (prove/TAP-based Perl tests)
- Add test-python job running pytest against the new Flask backend
- Install rrdtool system libs required by the rrdtool Python binding
- Run pytest with -v and generate JUnit XML for GitHub annotations
- Covers Python 3.10, 3.11, and 3.12

Co-Authored-By: Paperclip <noreply@paperclip.ing>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant