commit e94ed3eb739f36265e7126b3469a12dbc8920a76
parent a1a4b9ccebaa9c9635edaa8449975f0e064cc222
Author: Asher Morgan <asher@ashermorgan.net>
Date: Tue, 20 Oct 2026 07:16:44 -0700
Add public AOH_GC_{INTERVAL,THRESHOLD} config vars
The ability to control this timing will be useful for future e2e tests.
Diffstat:
3 files changed, 33 insertions(+), 7 deletions(-)
diff --git a/README.md b/README.md
@@ -118,6 +118,13 @@ variables.
- `AOH_DEBUG`: If set to `1`, the AoH server will copy `ansible-playbook` output
to the server's stdout. Defaults to `0`.
+- `AOH_GC_INTERVAL`: The interval on which to clean up exited runners, in
+ seconds. Defaults to `60`.
+
+- `AOH_GC_THRESHOLD`: The delay after a runner exits before is may be cleaned
+ up, in seconds. This delay exists so that clients have time to fetch the final
+ lines of Ansible output. Defaults to `60`.
+
- `AOH_LOG_LEVEL`: The threshold for AoH logs, which are written to the server's
stdout. Must be one of `CRITICAL`, `ERROR`, `WARNING`, `INFO`, or `DEBUG`.
Defaults to `ERROR`.
diff --git a/aoh/config.py b/aoh/config.py
@@ -11,6 +11,24 @@ load_dotenv()
AOH_DEBUG = (os.getenv('AOH_DEBUG', '0') == '1')
+try:
+ AOH_GC_INTERVAL = int(os.getenv('AOH_GC_INTERVAL', '60'))
+except ValueError:
+ logger.critical('$AOH_GC_INTERVAL must be a non-negative integer')
+ sys.exit(1)
+if AOH_GC_INTERVAL < 0:
+ logger.critical('$AOH_GC_INTERVAL must be a non-negative integer')
+ sys.exit(1)
+
+try:
+ AOH_GC_THRESHOLD = int(os.getenv('AOH_GC_THRESHOLD', '60'))
+except ValueError:
+ logger.critical('$AOH_GC_THRESHOLD must be a positive integer')
+ sys.exit(1)
+if AOH_GC_THRESHOLD <= 0:
+ logger.critical('$AOH_GC_THRESHOLD must be a positive integer')
+ sys.exit(1)
+
AOH_LOG_LEVEL = os.getenv('AOH_LOG_LEVEL', 'ERROR')
try:
diff --git a/aoh/server.py b/aoh/server.py
@@ -4,7 +4,12 @@ import os
from flask import Flask, abort, render_template, request, session
from flask_apscheduler import APScheduler
-from aoh.config import AOH_MAX_RUNNERS, AOH_ORIGIN
+from aoh.config import (
+ AOH_GC_INTERVAL,
+ AOH_GC_THRESHOLD,
+ AOH_MAX_RUNNERS,
+ AOH_ORIGIN,
+)
from aoh.playbook import PlaybookFileError, get_playbook
from aoh.runner import Runner, RunnerError
from aoh.security import (
@@ -16,10 +21,6 @@ from aoh.security import (
_RUNNERS = {}
-# Every 60s, tear down runners that finished more than 60s ago
-_GC_INTERVAL = 60
-_GC_THRESHOLD = 60
-
app = Flask(__name__)
app.secret_key = os.urandom(16)
@@ -29,13 +30,13 @@ scheduler.init_app(app)
logger = logging.getLogger(__name__)
-@scheduler.task('interval', seconds=_GC_INTERVAL)
+@scheduler.task('interval', seconds=AOH_GC_INTERVAL)
def gc():
"""Tear down and delete timed-out runners."""
runners = list(_RUNNERS.items())
for id, runner in runners:
- if runner and runner.has_timed_out(_GC_THRESHOLD):
+ if runner and runner.has_timed_out(AOH_GC_THRESHOLD):
logger.info(f'{runner.playbook.name} (#{id[:8]}): Runner torn down '
'due to inactivity')
runner.teardown()