Persist daemon resource runtime state
This commit is contained in:
Executable
+122
@@ -0,0 +1,122 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import json
|
||||
import os
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
|
||||
from registry import Registry
|
||||
|
||||
|
||||
PLUGIN_SOURCE = r"""
|
||||
def notify(config, runtime_state, request_parameters):
|
||||
runtime_state["postgresql"] = {
|
||||
"notification": dict(request_parameters),
|
||||
"reconnect_started_at": 123.4,
|
||||
"state_changed_at": 567.8,
|
||||
}
|
||||
|
||||
return {
|
||||
"ocf_rc": 0,
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
def require(condition, message):
|
||||
if not condition:
|
||||
raise SystemExit("FAIL: " + message)
|
||||
|
||||
|
||||
print("===== DAEMON STATE PERSISTENCE =====")
|
||||
|
||||
with tempfile.TemporaryDirectory() as temporary_root:
|
||||
root = Path(temporary_root)
|
||||
plugin_root = root / "plugins" / "fake"
|
||||
plugin_root.mkdir(parents=True)
|
||||
|
||||
(plugin_root / "manifest.json").write_text(
|
||||
json.dumps({
|
||||
"name": "fake",
|
||||
"version": 1,
|
||||
"module": "plugin.py",
|
||||
"actions": ["notify"],
|
||||
"required_config": [],
|
||||
})
|
||||
)
|
||||
(plugin_root / "plugin.py").write_text(PLUGIN_SOURCE)
|
||||
|
||||
state_dir = root / "state"
|
||||
|
||||
environment = {
|
||||
"MANAGED_CONTAINERD_PLUGIN_ROOT": str(
|
||||
root / "plugins"
|
||||
),
|
||||
"MANAGED_CONTAINERD_STATE_DIR": str(state_dir),
|
||||
"RESOURCE_ID": "fake-resource",
|
||||
"PLUGIN": "fake",
|
||||
}
|
||||
|
||||
parameters = {
|
||||
"type": "pre",
|
||||
"operation": "demote",
|
||||
"promote_uname": "david-eve",
|
||||
}
|
||||
|
||||
with patch.dict(os.environ, environment, clear=False):
|
||||
first = Registry()
|
||||
result = first.execute(
|
||||
"fake-resource",
|
||||
"notify",
|
||||
parameters,
|
||||
)
|
||||
|
||||
require(
|
||||
result["result"]["ocf_rc"] == 0,
|
||||
"initial notify failed",
|
||||
)
|
||||
|
||||
files = list(state_dir.glob("*.json"))
|
||||
require(
|
||||
len(files) == 1,
|
||||
"state file was not created",
|
||||
)
|
||||
|
||||
mode = files[0].stat().st_mode & 0o777
|
||||
require(
|
||||
mode == 0o600,
|
||||
"state file is not mode 0600",
|
||||
)
|
||||
|
||||
saved = json.loads(files[0].read_text())
|
||||
require(
|
||||
saved["postgresql"]["notification"]
|
||||
== parameters,
|
||||
"notification was not persisted",
|
||||
)
|
||||
require(
|
||||
"reconnect_started_at"
|
||||
not in saved["postgresql"],
|
||||
"volatile reconnect state was persisted",
|
||||
)
|
||||
require(
|
||||
"state_changed_at"
|
||||
not in saved["postgresql"],
|
||||
"volatile monotonic state was persisted",
|
||||
)
|
||||
print("atomic_state_write persisted")
|
||||
|
||||
second = Registry()
|
||||
restored = second.resources[
|
||||
"fake-resource"
|
||||
].runtime_state
|
||||
|
||||
require(
|
||||
restored["postgresql"]["notification"]
|
||||
== parameters,
|
||||
"notification was not restored",
|
||||
)
|
||||
print("restart_state_load restored")
|
||||
|
||||
print()
|
||||
print("STATE_PERSISTENCE_TEST_PASS=1")
|
||||
Reference in New Issue
Block a user