commit 555df61ee112a712a11099699c348ac063360be9
parent 9f92f5436ed2ae11c21fc3a07323ecabe6b08568
Author: Asher Morgan <asher@ashermorgan.net>
Date: Tue, 8 Sep 2026 19:27:56 -0700
Extract common config parsing logic
Diffstat:
2 files changed, 39 insertions(+), 33 deletions(-)
diff --git a/aoh/runner.py b/aoh/runner.py
@@ -1,3 +1,4 @@
+import ast
import json
import os
import shlex
@@ -24,6 +25,33 @@ class RunnerError(Exception):
"""Raised for AoH runner errors."""
+def get_config_values(config, keys):
+ """Query Ansible config option values."""
+
+ with tempfile.TemporaryDirectory(prefix='aoh-') as dir:
+ raw_config = ansible_runner.get_ansible_config(
+ 'dump',
+ config,
+ private_data_dir=dir,
+ quiet=True,
+ )[0]
+
+ if not raw_config:
+ raise RunnerError(f'Failed to dump Ansible config from {config}')
+
+ result = {}
+ for key in keys:
+ line = next((
+ x for x in raw_config.split('\n')
+ if x.startswith(key + '(')
+ ), None)
+ if not line:
+ raise RunnerError(f'Ansible config key "{key}" not found')
+ result[key] = ast.literal_eval(line.split('=')[1])
+
+ return result
+
+
class Runner:
"""An Ansible-over-HTTP playbook runner."""
@@ -77,30 +105,21 @@ class Runner:
f.write(f'[aoh]\n{self.host} ansible_connection=aoh\n')
f.writelines(f'[{g}]\n{self.host}\n' for g in self.playbook.groups)
- raw_config = ansible_runner.get_ansible_config(
- 'dump',
+ config = get_config_values(
self.playbook.config,
- private_data_dir=self._DIR,
- quiet=True,
- )[0]
- connection_plugins = eval(next(
- x for x in raw_config.split('\n')
- if x.startswith('DEFAULT_CONNECTION_PLUGIN_PATH')
- ).split('= ')[1])
- inventory = eval(next(
- x for x in raw_config.split('\n')
- if x.startswith('DEFAULT_HOST_LIST')
- ).split('= ')[1])
+ ['DEFAULT_CONNECTION_PLUGIN_PATH', 'DEFAULT_HOST_LIST']
+ )
env = {
'ANSIBLE_AOH_DIR': self._DIR,
'ANSIBLE_CONNECTION_PLUGINS': ':'.join(
- [_CONNECTION_PLUGIN_DIR] + connection_plugins
+ [_CONNECTION_PLUGIN_DIR] +
+ config['DEFAULT_CONNECTION_PLUGIN_PATH']
),
'ANSIBLE_CONFIG': self.playbook.config,
'ANSIBLE_FORCE_COLOR': '1',
'ANSIBLE_INVENTORY': ','.join(
- [f'{self._DIR}/inventory.ini'] + inventory
+ [f'{self._DIR}/inventory.ini'] + config['DEFAULT_HOST_LIST']
),
}
pw_prompt_answers = {}
diff --git a/aoh/security.py b/aoh/security.py
@@ -1,10 +1,8 @@
-import tempfile
-
-import ansible_runner
import bcrypt
import yaml
from .config import AOH_PASSWORDS_FILE
+from .runner import get_config_values
_CLI_OPT_WHITELIST = [
# These options should be safe for clients to invoke
@@ -92,21 +90,10 @@ def get_required_passwords(playbook, args):
if opt in opts:
pw_types.add(pw_type)
- with tempfile.TemporaryDirectory(prefix='aoh-') as dir:
- raw_config = ansible_runner.get_ansible_config(
- 'dump',
- playbook.config,
- private_data_dir=dir,
- quiet=True,
- )[0]
-
- for opt, pw_type in _CONFIG_PASSWORD_OPTS.items():
- val = eval(next(
- x for x in raw_config.split('\n')
- if x.startswith(opt)
- ).split('= ')[1])
- if val:
- pw_types.add(pw_type)
+ opts = get_config_values(playbook.config, _CONFIG_PASSWORD_OPTS.keys())
+ for opt, pw_type in _CONFIG_PASSWORD_OPTS.items():
+ if opts[opt]:
+ pw_types.add(pw_type)
return list(pw_types)