mirror of
https://github.com/bunkerity/bunkerweb
synced 2026-05-24 09:28:37 +00:00
feat: add configuration testing option for Nginx reload endpoint
This commit is contained in:
parent
53d6114fc1
commit
818270384c
5 changed files with 46 additions and 13 deletions
|
|
@ -92,19 +92,29 @@ api.global.GET["^/ping$"] = function(self)
|
|||
return self:response(HTTP_OK, "success", "pong")
|
||||
end
|
||||
|
||||
api.global.POST["^/reload$"] = function(self)
|
||||
-- Check config
|
||||
logger:log(NOTICE, "Checking Nginx configuration")
|
||||
local status = execute("nginx -t")
|
||||
if status ~= 0 then
|
||||
return self:response(HTTP_INTERNAL_SERVER_ERROR, "error", "config check failed")
|
||||
api.global.POST["^/reload"] = function(self)
|
||||
-- Get test argument
|
||||
local args = ngx.req.get_uri_args()
|
||||
local test_arg = args.test or "yes"
|
||||
|
||||
if test_arg ~= "no" then
|
||||
-- Check Nginx configuration
|
||||
logger:log(NOTICE, "Checking Nginx configuration")
|
||||
local status = execute("nginx -t")
|
||||
if status ~= 0 then
|
||||
return self:response(HTTP_INTERNAL_SERVER_ERROR, "error", "config check failed")
|
||||
end
|
||||
logger:log(NOTICE, "Nginx configuration is valid")
|
||||
end
|
||||
logger:log(NOTICE, "Nginx configuration is valid, reloading Nginx")
|
||||
|
||||
-- Reload Nginx
|
||||
logger:log(NOTICE, "Reloading Nginx")
|
||||
-- Send HUP signal to master process
|
||||
local ok, err = kill(get_master_pid(), "HUP")
|
||||
if not ok then
|
||||
return self:response(HTTP_INTERNAL_SERVER_ERROR, "error", "err = " .. err)
|
||||
end
|
||||
|
||||
return self:response(HTTP_OK, "success", "reload successful")
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,11 @@ try:
|
|||
LOGGER.info(
|
||||
f"Successfully sent API request to {api.endpoint}/lets-encrypt/certificates",
|
||||
)
|
||||
sent, err, status, resp = api.request("POST", "/reload", timeout=max(reload_min_timeout, 2 * len(services)))
|
||||
sent, err, status, resp = api.request(
|
||||
"POST",
|
||||
f"/reload?test={'no' if getenv('DISABLE_CONFIGURATION_TESTING', 'no').lower() == 'yes' else 'yes'}",
|
||||
timeout=max(reload_min_timeout, 2 * len(services)),
|
||||
)
|
||||
if not sent:
|
||||
status = 1
|
||||
LOGGER.error(f"Can't send API request to {api.endpoint}/reload : {err}")
|
||||
|
|
|
|||
|
|
@ -134,7 +134,11 @@ class JobScheduler(ApiCaller):
|
|||
self.__logger.error("RELOAD_MIN_TIMEOUT must be an integer, defaulting to 5")
|
||||
reload_min_timeout = 5
|
||||
|
||||
reload_success = self.send_to_apis("POST", "/reload", timeout=max(int(reload_min_timeout), 2 * len(self.__env["SERVER_NAME"].split(" "))))[0]
|
||||
reload_success = self.send_to_apis(
|
||||
"POST",
|
||||
f"/reload?test={'no' if self.__env.get('DISABLE_CONFIGURATION_TESTING', 'no').lower() == 'yes' else 'yes'}",
|
||||
timeout=max(int(reload_min_timeout), 2 * len(self.__env["SERVER_NAME"].split(" "))),
|
||||
)[0]
|
||||
if reload_success:
|
||||
self.__logger.info("Successfully reloaded nginx")
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -101,6 +101,11 @@ if not RELOAD_MIN_TIMEOUT.isdigit():
|
|||
|
||||
RELOAD_MIN_TIMEOUT = int(RELOAD_MIN_TIMEOUT)
|
||||
|
||||
DISABLE_CONFIGURATION_TESTING = getenv("DISABLE_CONFIGURATION_TESTING", "no").lower() == "yes"
|
||||
|
||||
if DISABLE_CONFIGURATION_TESTING:
|
||||
LOGGER.warning("Configuration testing is disabled, changes will be applied without testing (we hope you know what you're doing) ...")
|
||||
|
||||
|
||||
def handle_stop(signum, frame):
|
||||
current_time = datetime.now().astimezone()
|
||||
|
|
@ -383,6 +388,8 @@ def healthcheck_job():
|
|||
|
||||
HEALTHCHECK_EVENT.set()
|
||||
|
||||
# env = SCHEDULER.db.get_config() # TODO: uncomment when the healthcheck endpoint is ready @fl0ppy-d1sk
|
||||
|
||||
for db_instance in SCHEDULER.db.get_instances():
|
||||
bw_instance = API(f"http://{db_instance['hostname']}:{db_instance['port']}", db_instance["server_name"])
|
||||
try:
|
||||
|
|
@ -421,7 +428,7 @@ def healthcheck_job():
|
|||
# api_caller.send_files(PRO_PLUGINS_PATH, "/pro_plugins")
|
||||
# api_caller.send_files(join(sep, "etc", "nginx"), "/confs")
|
||||
# api_caller.send_files(CACHE_PATH, "/cache")
|
||||
# if not api_caller.send_to_apis("POST", "/reload")[0]:
|
||||
# if not api_caller.send_to_apis("POST", f"/reload?test={'no' if DISABLE_CONFIGURATION_TESTING else 'yes'}", timeout=max(RELOAD_MIN_TIMEOUT, 2 * len(env["SERVER_NAME"].split(" "))),)[0]:
|
||||
# HEALTHCHECK_LOGGER.error(f"Error while reloading instance {bw_instance.endpoint}")
|
||||
# ret = SCHEDULER.db.update_instance(db_instance["hostname"], "loading")
|
||||
# if ret:
|
||||
|
|
@ -806,7 +813,10 @@ if __name__ == "__main__":
|
|||
thread.join()
|
||||
|
||||
success, responses = SCHEDULER.send_to_apis(
|
||||
"POST", "/reload", timeout=max(RELOAD_MIN_TIMEOUT, 2 * len(env["SERVER_NAME"].split(" "))), response=True
|
||||
"POST",
|
||||
f"/reload?test={'no' if DISABLE_CONFIGURATION_TESTING else 'yes'}",
|
||||
timeout=max(RELOAD_MIN_TIMEOUT, 2 * len(env["SERVER_NAME"].split(" "))),
|
||||
response=True,
|
||||
)
|
||||
if not success:
|
||||
reachable = False
|
||||
|
|
@ -872,7 +882,11 @@ if __name__ == "__main__":
|
|||
for thread in tmp_threads:
|
||||
thread.join()
|
||||
|
||||
if not SCHEDULER.send_to_apis("POST", "/reload", timeout=max(RELOAD_MIN_TIMEOUT, 2 * len(env["SERVER_NAME"].split(" "))))[0]:
|
||||
if not SCHEDULER.send_to_apis(
|
||||
"POST",
|
||||
f"/reload?test={'no' if DISABLE_CONFIGURATION_TESTING else 'yes'}",
|
||||
timeout=max(RELOAD_MIN_TIMEOUT, 2 * len(env["SERVER_NAME"].split(" "))),
|
||||
)[0]:
|
||||
LOGGER.error("Error while reloading bunkerweb with failover configuration, skipping ...")
|
||||
elif not reachable:
|
||||
LOGGER.warning("No BunkerWeb instance is reachable, skipping failover ...")
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#!/usr/bin/env python3
|
||||
from datetime import datetime
|
||||
from operator import itemgetter
|
||||
from os import getenv
|
||||
from typing import Any, List, Literal, Optional, Tuple, Union
|
||||
|
||||
from API import API # type: ignore
|
||||
|
|
@ -67,7 +68,7 @@ class Instance:
|
|||
|
||||
def reload(self) -> str:
|
||||
try:
|
||||
result = self.apiCaller.send_to_apis("POST", "/reload")[0]
|
||||
result = self.apiCaller.send_to_apis("POST", f"/reload?test={'no' if getenv('DISABLE_CONFIGURATION_TESTING', 'no').lower() == 'yes' else 'yes'}")[0]
|
||||
except BaseException as e:
|
||||
return f"Can't reload instance {self.hostname}: {e}"
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue