Freeze lab-tested PostgreSQL plugin engine
Extract PostgreSQL, Podman runtime and systemd lifecycle adapters while preserving existing lifecycle and scoring behavior. Update RPM layout and add guarded operator-run lab harnesses. Record successful manual stop/start, promotion, demotion and rewind-only rejoin with pinned installed hashes. The unfenced lab does not validate automatic failover, Pacemaker-managed transitions or divergent-data rewind. Validation: 103 offline tests, original-function differential checks, checksum manifest and whitespace checks passed.
This commit is contained in:
+11
-13
@@ -6,11 +6,12 @@ import re
|
||||
import subprocess
|
||||
import tempfile
|
||||
import xml.etree.ElementTree as ET
|
||||
from plugin_test_support import LOAD, restore_boundaries
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
REFERENCE = ROOT / 'reference/managed-container'
|
||||
AGENT = ROOT / 'refactored/managed-container'
|
||||
MODULES = sorted((AGENT.parent / 'managed-container.d').glob('*.sh'))
|
||||
MODULES = sorted((AGENT.parent / 'managed-container.d').rglob('*.sh'))
|
||||
SOURCE = REFERENCE.read_text()
|
||||
PATTERN = r'^([a-z_]+)\(\)\n\{\n.*?^\}'
|
||||
|
||||
@@ -43,21 +44,16 @@ print('PASS both reference hashes')
|
||||
|
||||
current_functions = functions('\n'.join(p.read_text() for p in MODULES))
|
||||
for name, definition in functions(SOURCE).items():
|
||||
assert current_functions[name] == definition, name
|
||||
assert set(current_functions) - set(functions(SOURCE)) == {
|
||||
'mc_promotion_score_set', 'mc_promotion_score_from_monitor',
|
||||
'mc_promotion_monitor', 'mc_promotion_action', 'mc_promotion_validate', 'mc_pg_promotion_eligible',
|
||||
'mc_promotion_metadata', 'mc_pg_standby_observation', 'mc_pg_standby_score',
|
||||
}
|
||||
assert restore_boundaries(current_functions[name]) == definition, name
|
||||
assert len(functions(SOURCE)) == 29
|
||||
common = (AGENT.parent / 'managed-container.d/common.sh').read_text()
|
||||
common = (AGENT.parent / 'managed-container.d/applications/postgresql/plugin.sh').read_text()
|
||||
defaults = SOURCE[SOURCE.index('OCF_RESKEY_service_user_default='):SOURCE.index('\n###############################################################################\n# Metadata')].strip()
|
||||
assert defaults in common
|
||||
print('PASS all 29 original function bodies and defaults/globals identical; nine scoring helpers added')
|
||||
print('PASS all 29 original function bodies identical after exact adapter-call reversal; defaults unchanged')
|
||||
|
||||
for path in [AGENT, *MODULES]:
|
||||
subprocess.run(['bash', '-n', str(path)], check=True)
|
||||
print('PASS syntax for entrypoint and all nine modules')
|
||||
print('PASS syntax for entrypoint and all modules')
|
||||
|
||||
metadata = []
|
||||
for path in (REFERENCE, AGENT):
|
||||
@@ -69,6 +65,10 @@ parameters = extended.find('parameters')
|
||||
added = parameters.find("parameter[@name='disconnected_max_age']")
|
||||
assert added is not None and added.find('content').get('default') == '300'
|
||||
parameters.remove(added)
|
||||
for name, default in [('application', 'postgresql'), ('container_runtime', 'podman'), ('lifecycle_manager', 'systemd')]:
|
||||
added = parameters.find("parameter[@name='" + name + "']")
|
||||
assert added is not None and added.find('content').get('default') == default
|
||||
parameters.remove(added)
|
||||
def normalize(element):
|
||||
return (element.tag, element.attrib, (element.text or '').strip(),
|
||||
[normalize(child) for child in element])
|
||||
@@ -80,9 +80,7 @@ print('PASS original metadata preserved plus freshness parameter and XML parsing
|
||||
|
||||
# Sourcing production modules in a fresh shell tests their real loading order.
|
||||
# No dispatcher executes. All operational boundaries are overridden below.
|
||||
modular_definitions = SOURCE[:SOURCE.index('\n###############################################################################')]
|
||||
for name in ('common', 'container', 'postgres', 'auth', 'replication', 'notify', 'promote', 'demote', 'rejoin'):
|
||||
modular_definitions += '\n. ' + "'" + str(AGENT.parent / 'managed-container.d' / (name + '.sh')).replace("'", "'\\''") + "'"
|
||||
modular_definitions = LOAD
|
||||
base = '''
|
||||
ocf_log() { printf 'log %s\\n' "$*"; }
|
||||
ocf_exit_reason() { printf 'reason %s\\n' "$*" >&2; }
|
||||
|
||||
Reference in New Issue
Block a user