Skip to content

Commit f26efa7

Browse files
authored
[MISC] Hold database created hook for pg_hba changes (#1002)
* Hold database requested hook for pg_hba changes * Remove dead code * Bump expected python version to 3.12 * Set stale patch version
1 parent ad149ea commit f26efa7

File tree

10 files changed

+51
-170
lines changed

10 files changed

+51
-170
lines changed

lib/charms/postgresql_k8s/v0/postgresql.py

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535

3636
# Increment this PATCH version before using `charmcraft publish-lib` or reset
3737
# to 0 if you are raising the major API version
38-
LIBPATCH = 55
38+
LIBPATCH = 52
3939

4040
# Groups to distinguish HBA access
4141
ACCESS_GROUP_IDENTITY = "identity_access"
@@ -751,7 +751,7 @@ def list_users_from_relation(self, current_host=False) -> Set[str]:
751751
"SELECT usename "
752752
"FROM pg_catalog.pg_user "
753753
"WHERE usename LIKE 'relation_id_%' OR usename LIKE 'relation-%' "
754-
"OR usename LIKE 'pgbouncer_auth_relation_id_%' OR usename LIKE '%_user_%_%';"
754+
"OR usename LIKE 'pgbouncer_auth_relation_%' OR usename LIKE '%_user_%_%';"
755755
)
756756
usernames = cursor.fetchall()
757757
return {username[0] for username in usernames}
@@ -831,7 +831,7 @@ def set_up_database(self, temp_location: Optional[str] = None) -> None:
831831
END IF;
832832
END LOOP;
833833
-- Remove users that don't exist anymore from the pg_hba file.
834-
FOR rec IN SELECT h.lines FROM pg_hba AS h LEFT JOIN relation_users AS r ON SPLIT_PART(h.lines, ' ', 3) = r.user WHERE r.user IS NULL AND (SPLIT_PART(h.lines, ' ', 3) LIKE 'relation_id_%' OR SPLIT_PART(h.lines, ' ', 3) LIKE 'pgbouncer_auth_relation_id_%' OR SPLIT_PART(h.lines, ' ', 3) LIKE '%_user_%_%')
834+
FOR rec IN SELECT h.lines FROM pg_hba AS h LEFT JOIN relation_users AS r ON SPLIT_PART(h.lines, ' ', 3) = r.user WHERE r.user IS NULL AND (SPLIT_PART(h.lines, ' ', 3) LIKE 'relation_id_%' OR SPLIT_PART(h.lines, ' ', 3) LIKE 'pgbouncer_auth_relation_%' OR SPLIT_PART(h.lines, ' ', 3) LIKE '%_user_%_%')
835835
LOOP
836836
DELETE FROM pg_hba WHERE lines = rec.lines;
837837
changes := changes + 1;
@@ -1081,3 +1081,21 @@ def validate_group_map(self, group_map: Optional[str]) -> bool:
10811081
return False
10821082

10831083
return True
1084+
1085+
def is_user_in_hba(self, username: str) -> bool:
1086+
"""Check if user was added in pg_hba."""
1087+
connection = None
1088+
try:
1089+
with self._connect_to_database() as connection, connection.cursor() as cursor:
1090+
cursor.execute(
1091+
SQL(
1092+
"SELECT COUNT(*) FROM pg_hba_file_rules WHERE {} = ANY(user_name);"
1093+
).format(Literal(username))
1094+
)
1095+
return cursor.fetchone()[0] > 0
1096+
except psycopg2.Error as e:
1097+
logger.debug(f"Failed to check pg_hba: {e}")
1098+
return False
1099+
finally:
1100+
if connection:
1101+
connection.close()

poetry.lock

Lines changed: 5 additions & 91 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ package-mode = false
66
requires-poetry = ">=2.0.0"
77

88
[tool.poetry.dependencies]
9-
python = "^3.10"
9+
python = "^3.12"
1010
ops = "^2.22.0"
1111
boto3 = "^1.38.27"
1212
pgconnstr = "^1.0.1"
@@ -94,7 +94,7 @@ markers = ["juju3", "juju_secrets"]
9494
[tool.ruff]
9595
# preview and explicit preview are enabled for CPY001
9696
preview = true
97-
target-version = "py310"
97+
target-version = "py312"
9898
src = ["src", "."]
9999
line-length = 99
100100

src/backups.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import re
1010
import tempfile
1111
import time
12-
from datetime import datetime, timezone
12+
from datetime import UTC, datetime
1313
from io import BytesIO
1414

1515
import boto3
@@ -371,9 +371,7 @@ def _generate_backup_list_output(self) -> str:
371371
backup_reference, _ = self._parse_backup_id(backup["reference"][-1])
372372
lsn_start_stop = f"{backup['lsn']['start']} / {backup['lsn']['stop']}"
373373
time_start, time_stop = (
374-
datetime.strftime(
375-
datetime.fromtimestamp(stamp, timezone.utc), "%Y-%m-%dT%H:%M:%SZ"
376-
)
374+
datetime.strftime(datetime.fromtimestamp(stamp, UTC), "%Y-%m-%dT%H:%M:%SZ")
377375
for stamp in backup["timestamp"].values()
378376
)
379377
backup_timeline = (
@@ -465,7 +463,7 @@ def _list_timelines(self) -> dict[str, tuple[str, str]]:
465463

466464
return dict[str, tuple[str, str]]({
467465
datetime.strftime(
468-
datetime.fromtimestamp(timeline_object["time"], timezone.utc),
466+
datetime.fromtimestamp(timeline_object["time"], UTC),
469467
"%Y-%m-%dT%H:%M:%SZ",
470468
): (
471469
timeline.split("/")[1],
@@ -513,8 +511,8 @@ def _parse_psql_timestamp(self, timestamp: str) -> datetime:
513511
t = re.sub(r"\.(\d+)", lambda x: f".{x[1]:06}", t)
514512
dt = datetime.fromisoformat(t)
515513
# Convert to the timezone-naive
516-
if dt.tzinfo is not None and dt.tzinfo is not timezone.utc:
517-
dt = dt.astimezone(tz=timezone.utc)
514+
if dt.tzinfo is not None and dt.tzinfo is not UTC:
515+
dt = dt.astimezone(tz=UTC)
518516
return dt.replace(tzinfo=None)
519517

520518
def _parse_backup_id(self, label) -> tuple[str, str]:

src/constants.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,4 @@
5454

5555
DATABASE = "database"
5656

57-
ENDPOINT_SIMULTANEOUSLY_BLOCKING_MESSAGE = (
58-
"Please choose one endpoint to use. No need to relate all of them simultaneously!"
59-
)
60-
6157
PGBACKREST_LOGROTATE_FILE = "/etc/logrotate.d/pgbackrest.logrotate"

0 commit comments

Comments
 (0)