Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge branch "dev' into branch "staging" #1276

Merged
merged 53 commits into from
Jun 14, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
37826bf
feat: Fix error with default value for setting_checkbox.html
TheophileDiot Jun 7, 2024
8e3dd31
chore: Update database restoration instructions for different databas…
TheophileDiot Jun 8, 2024
49494af
Update image format for BunkerWeb Cloud overview in integrations.md
TheophileDiot Jun 8, 2024
561e158
feat: Move update-check.py script into "jobs" plugin and enhance the …
TheophileDiot Jun 8, 2024
b17d45c
Update image format for BunkerWeb Cloud overview in integrations.md
TheophileDiot Jun 8, 2024
eda2997
Update SSL certificate configuration for stream server to avoid tryin…
TheophileDiot Jun 8, 2024
0dc7035
chore: Update Database.py to fix query filter for checking if a setti…
TheophileDiot Jun 8, 2024
f8b86a9
deps/gha: bump ruby/setup-ruby from 1.179.0 to 1.179.1
dependabot[bot] Jun 10, 2024
e46db21
Merge pull request #1264 from bunkerity/dependabot/github_actions/dev…
TheophileDiot Jun 10, 2024
dc9774f
chore: Update Dockerfile to use Python 3.12.4-alpine3.19
TheophileDiot Jun 10, 2024
c3a903d
chore: Improve error handling in mmdb-asn and mmdb-country scripts
TheophileDiot Jun 10, 2024
4075c95
add plugin svg for types
syrk4web Jun 10, 2024
4e3cc4c
chore: Update session and cookie configurations in web UI
TheophileDiot Jun 10, 2024
5b95542
chore: Update session and cookie configurations in web UI
TheophileDiot Jun 10, 2024
e22b901
account get current key value and disabled scheduler
syrk4web Jun 10, 2024
d08eec1
chore: Enable self-signed SSL certificate generation for UI services …
TheophileDiot Jun 10, 2024
7ab6c86
chore: Update plugin SVGs for external plugins by adding an external …
TheophileDiot Jun 10, 2024
8cf616c
deps/tests/linux: bump redhat/ubi8-init in /tests/linux
dependabot[bot] Jun 11, 2024
9ef12df
deps/gha: bump docker/build-push-action from 5.3.0 to 5.4.0
dependabot[bot] Jun 11, 2024
b56606b
chore: Refactor check_cert function to handle exceptions and improve …
TheophileDiot Jun 12, 2024
d24831f
chore: Update libmaxminddb dependency to v1.10.0
TheophileDiot Jun 12, 2024
1b0ee3e
chore: Update lua-cjson dependency to v2.1.0.14
TheophileDiot Jun 12, 2024
e66e2bb
Squashed 'src/deps/src/libmaxminddb/' changes from e26013e1d2..7acfe4…
TheophileDiot Jun 12, 2024
1974c40
Merge commit 'e66e2bb891b06aaec6f18b1676ff208f034f071d' into dev
TheophileDiot Jun 12, 2024
cdc12b2
Squashed 'src/deps/src/lua-cjson/' changes from 881accc8fa..f95cd9ea1e
TheophileDiot Jun 12, 2024
3c5d76e
Merge commit 'cdc12b239d4332a896d933cfa998fdc40b6a7aa8' into dev
TheophileDiot Jun 12, 2024
d10c0c2
Merge pull request #1266 from bunkerity/dependabot/github_actions/dev…
TheophileDiot Jun 12, 2024
f67f5f6
Merge pull request #1265 from bunkerity/dependabot/docker/tests/linux…
TheophileDiot Jun 12, 2024
95c7896
feat: Fix cookie handling for session in logs_page.py tests
TheophileDiot Jun 12, 2024
ffd0e6a
chore: Update maxminddb dependency to version 2.6.2
TheophileDiot Jun 12, 2024
0d3ae93
Add failover logic to scheduler and web UI
TheophileDiot Jun 12, 2024
5a6720e
Update CHANGELOG.md
TheophileDiot Jun 12, 2024
4bee7d1
feat: Add Event object for applying changes before stopping
TheophileDiot Jun 12, 2024
3f91758
chore: Update plugin.json files and docs with improved help text for …
TheophileDiot Jun 12, 2024
b98d2e5
deps/gha: bump ruby/setup-ruby from 1.179.1 to 1.180.0
dependabot[bot] Jun 13, 2024
b54be96
deps/gha: bump actions/checkout from 4.1.6 to 4.1.7
dependabot[bot] Jun 13, 2024
781a861
Optimize web UI DB requests and avoid skip of pro-plugins download wh…
TheophileDiot Jun 13, 2024
0aabffb
Fix shenanigans in web UI automatic tests
TheophileDiot Jun 13, 2024
8d8cc8b
chore: Fix config checks in web UI (post optimization)
TheophileDiot Jun 13, 2024
43b9f2b
deps/tests/linux: bump redhat/ubi9-init in /tests/linux
dependabot[bot] Jun 14, 2024
ccd9ab6
deps/gha: bump github/codeql-action from 3.25.8 to 3.25.10
dependabot[bot] Jun 14, 2024
2250655
deps/linux: bump redhat/ubi9 from `d31d3e5` to `d98fdae` in /src/linux
dependabot[bot] Jun 14, 2024
4803c49
Optimize and fix database config handling in general
TheophileDiot Jun 14, 2024
eb17ba2
Fix small mistake in config gathering with global_only argument being…
TheophileDiot Jun 14, 2024
15dc826
Merge pull request #1272 from bunkerity/dependabot/github_actions/dev…
TheophileDiot Jun 14, 2024
41cb958
Merge pull request #1269 from bunkerity/dependabot/github_actions/dev…
TheophileDiot Jun 14, 2024
c5c0946
Merge pull request #1268 from bunkerity/dependabot/github_actions/dev…
TheophileDiot Jun 14, 2024
819875c
Merge pull request #1273 from bunkerity/dependabot/docker/src/linux/d…
TheophileDiot Jun 14, 2024
195c880
Merge pull request #1271 from bunkerity/dependabot/docker/tests/linux…
TheophileDiot Jun 14, 2024
1c22ec3
chore: Update selenium and fix automatic web UI tests
TheophileDiot Jun 14, 2024
4850731
chore: Update redis dependency to version 5.0.6
TheophileDiot Jun 14, 2024
727244e
chore: Update requests dependency to version 2.32.3
TheophileDiot Jun 14, 2024
89abb65
chore: Refresh page after navigating to configs page so that we don't…
TheophileDiot Jun 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Optimize and fix database config handling in general
  • Loading branch information
TheophileDiot committed Jun 14, 2024
commit 4803c4997e1b94c25c7ae90d8ef13bff5668d913
4 changes: 2 additions & 2 deletions src/common/core/misc/jobs/anonymous-report.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
if key not in ("version", "integration", "database_version", "is_pro"):
data.pop(key, None)

db_config = JOB.db.get_config(methods=True, with_drafts=True)
db_config = JOB.db.get_non_default_settings(methods=True, with_drafts=True)
services = db_config.get("SERVER_NAME", {"value": ""})["value"].split(" ")
multisite = db_config.get("MULTISITE", {"value": "no"})["value"] == "yes"

Expand Down Expand Up @@ -85,7 +85,7 @@

data["non_default_settings"] = {}
for setting, setting_data in db_config.items():
if isinstance(setting_data, dict) and setting_data["method"] != "default":
if isinstance(setting_data, dict):
for server in services:
if setting.startswith(server + "_"):
setting = setting[len(server) + 1 :] # noqa: E203
Expand Down
245 changes: 96 additions & 149 deletions src/common/db/Database.py
Original file line number Diff line number Diff line change
Expand Up @@ -1533,102 +1533,15 @@ def save_custom_configs(

return message

def get_config(self, global_only: bool = False, methods: bool = False, with_drafts: bool = False) -> Dict[str, Any]:
"""Get the config from the database"""
with self.__db_session() as session:
config = {}
multisite = []
for setting in (
session.query(Settings)
.with_entities(
Settings.id,
Settings.context,
Settings.default,
Settings.multiple,
)
.order_by(Settings.order)
):
default = setting.default or ""
config[setting.id] = default if not methods else {"value": default, "global": True, "method": "default"}

for global_value in (
session.query(Global_values).with_entities(Global_values.value, Global_values.suffix, Global_values.method).filter_by(setting_id=setting.id)
):
config[setting.id + (f"_{global_value.suffix}" if setting.multiple and global_value.suffix > 0 else "")] = (
global_value.value
if not methods
else {
"value": global_value.value,
"global": True,
"method": global_value.method,
}
)

if setting.context == "multisite":
multisite.append(setting.id)

is_multisite = config.get("MULTISITE", {"value": "no"})["value"] == "yes" if methods else config.get("MULTISITE", "no") == "yes"

services = session.query(Services).with_entities(Services.id, Services.is_draft)
if not with_drafts:
services = services.filter_by(is_draft=False)

if not global_only and is_multisite:
for service in services:
config[f"{service.id}_IS_DRAFT"] = "yes" if service.is_draft else "no"
if methods:
config[f"{service.id}_IS_DRAFT"] = {"value": config[f"{service.id}_IS_DRAFT"], "global": False, "method": "default"}

checked_settings = []
for key, value in config.copy().items():
original_key = key
if self.suffix_rx.search(key):
key = key[: -len(str(key.split("_")[-1])) - 1]

if key not in multisite:
continue
elif f"{service.id}_{original_key}" not in config:
config[f"{service.id}_{original_key}"] = value

if original_key not in checked_settings:
checked_settings.append(original_key)
else:
continue

for service_setting in (
session.query(Services_settings)
.with_entities(
Services_settings.value,
Services_settings.suffix,
Services_settings.method,
)
.filter_by(service_id=service.id, setting_id=key)
):
value = service_setting.value
if key == "SERVER_NAME" and service.id not in value.split(" "):
value = f"{service.id} {value}".strip()

config[f"{service.id}_{key}" + (f"_{service_setting.suffix}" if service_setting.suffix > 0 else "")] = (
value
if not methods
else {
"value": value,
"global": False,
"method": service_setting.method,
}
)

servers = " ".join(service.id for service in services)
config["SERVER_NAME"] = servers if not methods else {"value": servers, "global": True, "method": "default"}

return config

def get_filtered_config(
def get_non_default_settings(
self,
global_only: bool = False,
methods: bool = False,
with_drafts: bool = False,
filtered_settings: Optional[Union[List[str], Set[str], Tuple[str]]] = None,
*,
original_config: Optional[Dict[str, Any]] = None,
original_multisite: Optional[Set[str]] = None,
) -> Dict[str, Any]:
"""Get the config from the database"""
filtered_settings = set(filtered_settings or [])
Expand All @@ -1637,14 +1550,15 @@ def get_filtered_config(
filtered_settings.update(("SERVER_NAME", "MULTISITE"))

with self.__db_session() as session:
config = {}
config = original_config or {}
multisite = original_multisite or set()

# Define the join operation
j = join(Settings, Global_values, Settings.id == Global_values.setting_id)

# Define the select statement
stmt = (
db_select(Settings.id, Settings.multiple, Global_values.value, Global_values.suffix, Global_values.method)
db_select(Settings.id.label("setting_id"), Settings.context, Settings.multiple, Global_values.value, Global_values.suffix, Global_values.method)
.select_from(j)
.order_by(Settings.order)
)
Expand All @@ -1655,78 +1569,111 @@ def get_filtered_config(
# Execute the query and fetch all results
results = session.execute(stmt).fetchall()

for setting in results:
key = setting.id + (f"_{setting.suffix}" if setting.multiple and setting.suffix else "")
config[key] = setting.value if not methods else {"value": setting.value, "global": True, "method": setting.method}
for global_value in results:
setting_id = global_value.setting_id + (f"_{global_value.suffix}" if global_value.multiple and global_value.suffix > 0 else "")
config[setting_id] = global_value.value if not methods else {"value": global_value.value, "global": True, "method": global_value.method}
if global_value.context == "multisite":
multisite.add(setting_id)

is_multisite = config.get("MULTISITE", {"value": "no"})["value"] == "yes" if methods else config.get("MULTISITE", "no") == "yes"
services = session.query(Services).with_entities(Services.id, Services.is_draft)

# Define the join operation
j = join(Services, Services_settings, Services.id == Services_settings.service_id)
j = j.join(Settings, Settings.id == Services_settings.setting_id)
if not with_drafts:
services = services.filter_by(is_draft=False)

# Define the select statement
stmt = db_select(
Services.id.label("service_id"),
Services.is_draft,
Settings.id.label("setting_id"),
Settings.context,
Settings.default,
Settings.multiple,
Services_settings.value,
Services_settings.suffix,
Services_settings.method,
).select_from(j)
servers = ""
for service in services:
config[f"{service.id}_IS_DRAFT"] = "yes" if service.is_draft else "no"
if methods:
config[f"{service.id}_IS_DRAFT"] = {"value": config[f"{service.id}_IS_DRAFT"], "global": False, "method": "default"}
for key in multisite:
config[f"{service.id}_{key}"] = config[key]
servers += f"{service.id} "
servers = servers.strip()

if not with_drafts:
stmt = stmt.where(Services.is_draft == False) # noqa: E712
config["SERVER_NAME"] = servers if not methods else {"value": servers, "global": True, "method": "default"}

if filtered_settings:
stmt = stmt.where(Services_settings.setting_id.in_(filtered_settings))
if not global_only and (config.get("MULTISITE", {"value": "no"})["value"] == "yes" if methods else config.get("MULTISITE", "no") == "yes"):
# Define the join operation
j = join(Services, Services_settings, Services.id == Services_settings.service_id)
j = j.join(Settings, Settings.id == Services_settings.setting_id)

# Execute the query and fetch all results
results = session.execute(stmt).fetchall()
# Define the select statement
stmt = (
db_select(
Services.id.label("service_id"),
Settings.id.label("setting_id"),
Settings.multiple,
Services_settings.value,
Services_settings.suffix,
Services_settings.method,
)
.select_from(j)
.order_by(Services.id, Settings.order)
)

if not global_only and is_multisite:
for result in results:
if f"{result.service_id}_IS_DRAFT" not in config:
config[f"{result.service_id}_IS_DRAFT"] = "yes" if result.is_draft else "no"
if methods:
config[f"{result.service_id}_IS_DRAFT"] = {"value": config[f"{result.service_id}_IS_DRAFT"], "global": False, "method": "default"}
if not with_drafts:
stmt = stmt.where(Services.is_draft == False) # noqa: E712

key = result.setting_id
original_key = key
if self.suffix_rx.search(key):
key = key[: -len(str(key.split("_")[-1])) - 1]
if filtered_settings:
stmt = stmt.where(Settings.id.in_(filtered_settings))

if result.context != "multisite":
continue
elif f"{result.service_id}_{original_key}" not in config:
config[f"{result.service_id}_{original_key}"] = result.default
# Execute the query and fetch all results
results = session.execute(stmt).fetchall()

for result in results:
value = result.value
if key == "SERVER_NAME" and not search(r"(^| )" + escape(result.service_id) + r"($| )", value):
value = f"{result.service_id} {value}".strip()

config[f"{result.service_id}_{key}" + (f"_{result.suffix}" if result.multiple and result.suffix else "")] = (
value
if not methods
else {
"value": value,
"global": False,
"method": result.method,
}

if result.setting_id == "SERVER_NAME" and not search(r"^" + escape(result.service_id) + r"( |$)", value):
split = set(value.split(" "))
split.discard(result.service_id)
value = result.service_id + " " + " ".join(split)

config[f"{result.service_id}_{result.setting_id}" + (f"_{result.suffix}" if result.multiple and result.suffix else "")] = (
value if not methods else {"value": value, "global": False, "method": result.method}
)

services = session.query(Services).with_entities(Services.id)
return config

if not with_drafts:
services = services.filter_by(is_draft=False)
def get_config(
self,
global_only: bool = False,
methods: bool = False,
with_drafts: bool = False,
filtered_settings: Optional[Union[List[str], Set[str], Tuple[str]]] = None,
) -> Dict[str, Any]:
"""Get the config from the database"""
with self.__db_session() as session:
config = {}
multisite = set()

servers = " ".join(service.id for service in services)
config["SERVER_NAME"] = servers if not methods else {"value": servers, "global": True, "method": "default"}
query = (
session.query(Settings)
.with_entities(
Settings.id,
Settings.context,
Settings.default,
Settings.multiple,
)
.order_by(Settings.order)
)

return config
if filtered_settings:
query = query.filter(Settings.id.in_(filtered_settings))

for setting in query:
default = setting.default or ""
config[setting.id] = default if not methods else {"value": default, "global": True, "method": "default"}
if setting.context == "multisite":
multisite.add(setting.id)

return self.get_non_default_settings(
global_only=global_only,
methods=methods,
with_drafts=with_drafts,
filtered_settings=filtered_settings,
original_config=config,
original_multisite=multisite,
)

def get_custom_configs(self) -> List[Dict[str, Any]]:
"""Get the custom configs from the database"""
Expand Down
15 changes: 8 additions & 7 deletions src/ui/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -753,9 +753,9 @@ def account():
variable = {}
variable["PRO_LICENSE_KEY"] = request.form["license"]

error = app.config["CONFIG"].check_variables(variable)
variable = app.config["CONFIG"].check_variables(variable, {"PRO_LICENSE_KEY": request.form["license"]})

if error:
if not variable:
return redirect_flash_error("The license key variable checks returned error", "account", True)

# Force job to contact PRO API
Expand Down Expand Up @@ -963,7 +963,7 @@ def services():
if "SERVER_NAME" not in variables:
variables["SERVER_NAME"] = variables["OLD_SERVER_NAME"]

config = app.config["CONFIG"].get_config(with_drafts=True, filtered_settings=variables.keys())
config = app.config["DB"].get_config(methods=True, with_drafts=True)
server_name = variables["SERVER_NAME"].split(" ")[0]
was_draft = config.get(f"{server_name}_IS_DRAFT", {"value": "no"})["value"] == "yes"
operation = request.form["operation"]
Expand Down Expand Up @@ -997,15 +997,15 @@ def services():
del variables["OLD_SERVER_NAME"]

# Edit check fields and remove already existing ones
for variable, value in deepcopy(variables).items():
for variable, value in variables.copy().items():
if (
variable in variables
and variable != "SERVER_NAME"
and value == config.get(f"{server_name}_{variable}" if request.form["operation"] == "edit" else variable, {"value": None})["value"]
):
del variables[variable]

variables = app.config["CONFIG"].check_variables(variables)
variables = app.config["CONFIG"].check_variables(variables, config)

if (
was_draft == is_draft
Expand All @@ -1024,7 +1024,7 @@ def services():

is_request_params(["SERVER_NAME"], "services", True)

variables = app.config["CONFIG"].check_variables({"SERVER_NAME": request.form["SERVER_NAME"]})
variables = app.config["CONFIG"].check_variables({"SERVER_NAME": request.form["SERVER_NAME"]}, config)

if not variables:
error_message(f"Error while deleting the service {request.form['SERVER_NAME']}")
Expand Down Expand Up @@ -1138,12 +1138,13 @@ def global_config():
del variables["csrf_token"]

# Edit check fields and remove already existing ones
config = app.config["CONFIG"].get_config(with_drafts=True, filtered_settings=variables.keys())
config = app.config["DB"].get_config(methods=True, with_drafts=True)
services = config["SERVER_NAME"]["value"].split(" ")
for variable, value in variables.copy().items():
setting = config.get(variable, {"value": None, "global": True})
if setting["global"] and value == setting["value"]:
del variables[variable]
continue

variables = app.config["CONFIG"].check_variables(variables, config)

Expand Down
2 changes: 1 addition & 1 deletion src/ui/src/Config.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def get_config(
dict
The nginx variables env file as a dict
"""
return self.__db.get_filtered_config(global_only=global_only, methods=methods, with_drafts=with_drafts, filtered_settings=filtered_settings)
return self.__db.get_non_default_settings(global_only=global_only, methods=methods, with_drafts=with_drafts, filtered_settings=filtered_settings)

def get_services(self, methods: bool = True, with_drafts: bool = False) -> list[dict]:
"""Get nginx's services
Expand Down
2 changes: 1 addition & 1 deletion src/ui/src/Instances.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ def get_instances(self, override_instances=None) -> list[Instance]:
instances = []
# Override case : only return instances from DB
if override_instances is None:
config = self.__db.get_filtered_config(global_only=True, filtered_settings=("OVERRIDE_INSTANCES",))
config = self.__db.get_non_default_settings(global_only=True, filtered_settings=("OVERRIDE_INSTANCES",))
override_instances = config.get("OVERRIDE_INSTANCES", "") != ""
if override_instances:
for instance in self.__db.get_instances():
Expand Down
Loading