--- /dev/null
+# Crash resilience integration test
+
+**Goal:** Test that even in cases when the manager crashes and restarts, the operation on the resolver is not interrupted.
\ No newline at end of file
--- /dev/null
+{
+ "server": {
+ "instances": %s
+ },
+ "lua": {
+ "script_list": [
+ "-- SPDX-License-Identifier: CC0-1.0",
+ "-- vim:syntax=lua:set ts=4 sw=4:",
+ "-- Refer to manual: https://knot-resolver.readthedocs.org/en/stable/",
+ "-- Network interface configuration","net.listen('127.0.0.1', 53, { kind = 'dns' })",
+ "net.listen('127.0.0.1', 853, { kind = 'tls' })",
+ "--net.listen('127.0.0.1', 443, { kind = 'doh2' })",
+ "net.listen('::1', 53, { kind = 'dns', freebind = true })",
+ "net.listen('::1', 853, { kind = 'tls', freebind = true })",
+ "--net.listen('::1', 443, { kind = 'doh2' })",
+ "-- Load useful modules","modules = {",
+ "'hints > iterate', -- Load /etc/hosts and allow custom root hints",
+ "'stats', -- Track internal statistics",
+ "'predict', -- Prefetch expiring/frequent records",
+ "}",
+ "-- Cache size",
+ "cache.size = 100 * MB"
+ ]
+ }
+}
\ No newline at end of file
--- /dev/null
+#!/bin/bash
+
+# fail early
+set -e
+
+cd /test
+echo "Starting manager..."
+systemctl start knot-resolver-manager.service
+
+# give it time to start
+sleep 1
+
+# start kresd instances and verify, that it works
+python3 run_test.py
+
+# kill the manager and start it again
+systemctl kill --signal=SIGKILL knot-resolver-manager.service
+systemctl start knot-resolver-manager.service
+
+# wait for proper startup
+sleep 1
+
+# run the same test again testing, that instances can start and that the count is correct
+# because there should be kresd instances left after the first run, this tests that the initialization of the manager properly finds them
+python3 run_test.py
+
+
+
--- /dev/null
+
+
+
+import subprocess
+import time
+
+import requests
+import requests_unixsocket
+
+# patch requests library so that it supports unix socket
+requests_unixsocket.monkeypatch()
+
+PAYLOAD_PATH = "./payload.json"
+with open(PAYLOAD_PATH, "r") as file:
+ PAYLOAD = file.read()
+
+# f-string is not working with JSON because of {}
+PAYLOAD_F = lambda num: PAYLOAD % num
+
+def set_workers(num: int):
+ # send the config
+ r = requests.post('http+unix://%2Ftmp%2Fmanager.sock/config', data=PAYLOAD_F(num))
+ r.raise_for_status()
+
+def count_running() -> int:
+ cmd = subprocess.run("ps aux | grep kresd | grep -v grep", shell=True, stdout=subprocess.PIPE)
+ return len(str(cmd.stdout, 'utf8').strip().split("\n"))
+
+
+print("Initial 1 worker config...")
+set_workers(1)
+time.sleep(1)
+count = count_running()
+assert count == 1, f"Unexpected number of kresd instances is running - {count}"
+
+print("Increasing worker count to 2")
+set_workers(8)
+time.sleep(2)
+count = count_running()
+assert count == 8, f"Unexpected number of kresd instances is running - {count}"
--- /dev/null
+image = "knot-manager:debian"
+cmd = ["/test/run"]
+
+[mount]
+"/test" = "integration/tests/basic_crash"
+"/code" = "."
\ No newline at end of file