postgresql-charms-single-kernel 16.2.2__tar.gz → 16.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. {postgresql_charms_single_kernel-16.2.2 → postgresql_charms_single_kernel-16.3.0}/PKG-INFO +12 -2
  2. {postgresql_charms_single_kernel-16.2.2 → postgresql_charms_single_kernel-16.3.0}/pyproject.toml +20 -8
  3. postgresql_charms_single_kernel-16.3.0/single_kernel_postgresql/charms/__init__.py +5 -0
  4. postgresql_charms_single_kernel-16.3.0/single_kernel_postgresql/charms/abstract_charm.py +84 -0
  5. postgresql_charms_single_kernel-16.3.0/single_kernel_postgresql/charms/k8s_charm.py +65 -0
  6. postgresql_charms_single_kernel-16.3.0/single_kernel_postgresql/charms/vm_charm.py +58 -0
  7. postgresql_charms_single_kernel-16.3.0/single_kernel_postgresql/config/enums.py +13 -0
  8. postgresql_charms_single_kernel-16.3.0/single_kernel_postgresql/config/exceptions.py +27 -0
  9. postgresql_charms_single_kernel-16.3.0/single_kernel_postgresql/config/literals.py +163 -0
  10. postgresql_charms_single_kernel-16.3.0/single_kernel_postgresql/config/locales.py +527 -0
  11. postgresql_charms_single_kernel-16.3.0/single_kernel_postgresql/config/statuses.py +47 -0
  12. {postgresql_charms_single_kernel-16.2.2/single_kernel_postgresql/events → postgresql_charms_single_kernel-16.3.0/single_kernel_postgresql/core}/__init__.py +1 -1
  13. postgresql_charms_single_kernel-16.3.0/single_kernel_postgresql/core/config.py +266 -0
  14. postgresql_charms_single_kernel-16.3.0/single_kernel_postgresql/core/peer_relation.py +328 -0
  15. postgresql_charms_single_kernel-16.3.0/single_kernel_postgresql/core/relation_state.py +110 -0
  16. postgresql_charms_single_kernel-16.3.0/single_kernel_postgresql/core/state.py +405 -0
  17. postgresql_charms_single_kernel-16.3.0/single_kernel_postgresql/events/__init__.py +3 -0
  18. postgresql_charms_single_kernel-16.3.0/single_kernel_postgresql/events/postgresql.py +230 -0
  19. postgresql_charms_single_kernel-16.3.0/single_kernel_postgresql/lib/charms/data_platform_libs/v0/data_interfaces.py +5774 -0
  20. postgresql_charms_single_kernel-16.3.0/single_kernel_postgresql/lib/charms/data_platform_libs/v1/data_models.py +361 -0
  21. postgresql_charms_single_kernel-16.3.0/single_kernel_postgresql/managers/__init__.py +8 -0
  22. postgresql_charms_single_kernel-16.3.0/single_kernel_postgresql/managers/base.py +48 -0
  23. postgresql_charms_single_kernel-16.3.0/single_kernel_postgresql/managers/cluster.py +150 -0
  24. postgresql_charms_single_kernel-16.3.0/single_kernel_postgresql/managers/config.py +194 -0
  25. postgresql_charms_single_kernel-16.3.0/single_kernel_postgresql/managers/k8s.py +162 -0
  26. postgresql_charms_single_kernel-16.3.0/single_kernel_postgresql/managers/patroni.py +109 -0
  27. postgresql_charms_single_kernel-16.3.0/single_kernel_postgresql/managers/tls.py +101 -0
  28. {postgresql_charms_single_kernel-16.2.2 → postgresql_charms_single_kernel-16.3.0}/single_kernel_postgresql/utils/__init__.py +14 -1
  29. postgresql_charms_single_kernel-16.3.0/single_kernel_postgresql/utils/arch.py +46 -0
  30. {postgresql_charms_single_kernel-16.2.2 → postgresql_charms_single_kernel-16.3.0}/single_kernel_postgresql/utils/postgresql.py +1 -1
  31. postgresql_charms_single_kernel-16.3.0/single_kernel_postgresql/utils/secret.py +14 -0
  32. postgresql_charms_single_kernel-16.3.0/single_kernel_postgresql/utils/status.py +32 -0
  33. postgresql_charms_single_kernel-16.3.0/single_kernel_postgresql/workload/__init__.py +12 -0
  34. postgresql_charms_single_kernel-16.3.0/single_kernel_postgresql/workload/base.py +240 -0
  35. postgresql_charms_single_kernel-16.3.0/single_kernel_postgresql/workload/k8s.py +203 -0
  36. postgresql_charms_single_kernel-16.3.0/single_kernel_postgresql/workload/paths/__init__.py +7 -0
  37. postgresql_charms_single_kernel-16.3.0/single_kernel_postgresql/workload/paths/base.py +70 -0
  38. postgresql_charms_single_kernel-16.3.0/single_kernel_postgresql/workload/paths/k8s.py +63 -0
  39. postgresql_charms_single_kernel-16.3.0/single_kernel_postgresql/workload/paths/vm.py +93 -0
  40. postgresql_charms_single_kernel-16.3.0/single_kernel_postgresql/workload/vm.py +225 -0
  41. postgresql_charms_single_kernel-16.2.2/single_kernel_postgresql/abstract_charm.py +0 -27
  42. postgresql_charms_single_kernel-16.2.2/single_kernel_postgresql/config/literals.py +0 -32
  43. {postgresql_charms_single_kernel-16.2.2 → postgresql_charms_single_kernel-16.3.0}/LICENSE +0 -0
  44. {postgresql_charms_single_kernel-16.2.2 → postgresql_charms_single_kernel-16.3.0}/README.md +0 -0
  45. {postgresql_charms_single_kernel-16.2.2 → postgresql_charms_single_kernel-16.3.0}/single_kernel_postgresql/__init__.py +0 -0
  46. {postgresql_charms_single_kernel-16.2.2 → postgresql_charms_single_kernel-16.3.0}/single_kernel_postgresql/charmcraft.yaml +0 -0
  47. {postgresql_charms_single_kernel-16.2.2 → postgresql_charms_single_kernel-16.3.0}/single_kernel_postgresql/compat/__init__.py +0 -0
  48. {postgresql_charms_single_kernel-16.2.2 → postgresql_charms_single_kernel-16.3.0}/single_kernel_postgresql/compat/postgresql.py +0 -0
  49. {postgresql_charms_single_kernel-16.2.2 → postgresql_charms_single_kernel-16.3.0}/single_kernel_postgresql/compat/pyproject.toml +0 -0
  50. {postgresql_charms_single_kernel-16.2.2 → postgresql_charms_single_kernel-16.3.0}/single_kernel_postgresql/config/__init__.py +0 -0
  51. {postgresql_charms_single_kernel-16.2.2 → postgresql_charms_single_kernel-16.3.0}/single_kernel_postgresql/config/pyproject.toml +0 -0
  52. {postgresql_charms_single_kernel-16.2.2 → postgresql_charms_single_kernel-16.3.0}/single_kernel_postgresql/events/tls_transfer.py +0 -0
  53. {postgresql_charms_single_kernel-16.2.2 → postgresql_charms_single_kernel-16.3.0}/single_kernel_postgresql/utils/filesystem.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: postgresql-charms-single-kernel
3
- Version: 16.2.2
3
+ Version: 16.3.0
4
4
  Summary: Shared and reusable code for PostgreSQL-related charms
5
5
  Author: Canonical Data Platform
6
6
  Author-email: Canonical Data Platform <data-platform@lists.launchpad.net>
@@ -210,9 +210,19 @@ Classifier: Development Status :: 3 - Alpha
210
210
  Classifier: Intended Audience :: Developers
211
211
  Classifier: Operating System :: POSIX :: Linux
212
212
  Requires-Dist: ops>=2.0.0
213
- Requires-Dist: psycopg2>=2.9.10
214
213
  Requires-Dist: tenacity>=9.0.0
214
+ Requires-Dist: psycopg2>=2.9.10 ; extra == 'postgresql'
215
215
  Requires-Dist: httpx ; python_full_version >= '3.12' and extra == 'postgresql'
216
+ Requires-Dist: data-platform-helpers>=0.1.7 ; python_full_version >= '3.12' and extra == 'postgresql'
217
+ Requires-Dist: charmlibs-pathops>=1.0.1 ; python_full_version >= '3.12' and extra == 'postgresql'
218
+ Requires-Dist: charmlibs-snap>=1.0.1 ; python_full_version >= '3.12' and extra == 'postgresql'
219
+ Requires-Dist: charmlibs-interfaces-tls-certificates>=1.8.3 ; python_full_version >= '3.12' and extra == 'postgresql'
220
+ Requires-Dist: charm-refresh ; python_full_version >= '3.12' and extra == 'postgresql'
221
+ Requires-Dist: requests ; python_full_version >= '3.12' and extra == 'postgresql'
222
+ Requires-Dist: tomli ; python_full_version >= '3.12' and extra == 'postgresql'
223
+ Requires-Dist: pydantic>=2.0 ; python_full_version >= '3.12' and extra == 'postgresql'
224
+ Requires-Dist: jinja2>=3.1.6 ; python_full_version >= '3.12' and extra == 'postgresql'
225
+ Requires-Dist: charmlibs-rollingops>=1.1.1 ; python_full_version >= '3.12' and extra == 'postgresql'
216
226
  Requires-Python: >=3.8, <4.0
217
227
  Provides-Extra: postgresql
218
228
  Description-Content-Type: text/markdown
@@ -4,7 +4,7 @@
4
4
  [project]
5
5
  name = "postgresql-charms-single-kernel"
6
6
  description = "Shared and reusable code for PostgreSQL-related charms"
7
- version = "16.2.2"
7
+ version = "16.3.0"
8
8
  readme = "README.md"
9
9
  license = {file = "LICENSE"}
10
10
  authors = [
@@ -18,12 +18,24 @@ classifiers = [
18
18
  requires-python = ">=3.8,<4.0"
19
19
  dependencies = [
20
20
  "ops>=2.0.0",
21
- "psycopg2>=2.9.10",
22
21
  "tenacity>=9.0.0",
23
22
  ]
24
23
 
25
24
  [project.optional-dependencies]
26
- postgresql = ["httpx; python_version >= '3.12'"]
25
+ postgresql = [
26
+ "psycopg2>=2.9.10",
27
+ "httpx; python_version >= '3.12'",
28
+ "data-platform-helpers>=0.1.7; python_version >= '3.12'",
29
+ "charmlibs-pathops>=1.0.1; python_version >= '3.12'",
30
+ "charmlibs-snap>=1.0.1; python_version >= '3.12'",
31
+ "charmlibs-interfaces-tls-certificates>=1.8.3; python_version >= '3.12'",
32
+ "charm-refresh; python_version >= '3.12'",
33
+ "requests; python_version >= '3.12'",
34
+ "tomli; python_version >= '3.12'",
35
+ "pydantic>=2.0; python_version >= '3.12'",
36
+ "jinja2 >=3.1.6; python_version >= '3.12'",
37
+ "charmlibs-rollingops>=1.1.1; python_version >= '3.12'",
38
+ ]
27
39
 
28
40
  [build-system]
29
41
  requires = ["uv_build>=0.11.0,<0.12.0"]
@@ -35,15 +47,15 @@ module-root = ""
35
47
 
36
48
  [dependency-groups]
37
49
  format = [
38
- "ruff==0.15.14"
50
+ "ruff==0.15.17"
39
51
  ]
40
52
  lint = [
41
53
  "codespell==2.4.2",
42
- "ty==0.0.39"
54
+ "ty==0.0.49"
43
55
  ]
44
56
  unit = [
45
- "coverage[toml]==7.14.0",
46
- "pytest==9.0.3"
57
+ "coverage[toml]==7.14.1",
58
+ "pytest==9.1.0"
47
59
  ]
48
60
 
49
61
 
@@ -117,4 +129,4 @@ python = ".tox/lint/"
117
129
  python-version = "3.12"
118
130
 
119
131
  [tool.ty.src]
120
- exclude = ["tests"]
132
+ exclude = ["tests", "single_kernel_postgresql/lib"]
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env python3
2
+ # Copyright 2026 Canonical Ltd.
3
+ # See LICENSE file for licensing details.
4
+
5
+ """Charms Definitions."""
@@ -0,0 +1,84 @@
1
+ # Copyright 2025 Canonical Ltd.
2
+ # See LICENSE file for licensing details.
3
+ """Skeleton for the abstract charm."""
4
+
5
+ from abc import ABC, abstractmethod
6
+
7
+ from data_platform_helpers.advanced_statuses import StatusHandler
8
+ from ops.charm import CharmBase
9
+
10
+ from single_kernel_postgresql.core.state import CharmState
11
+ from single_kernel_postgresql.events.postgresql import PostgreSQLEventsHandler
12
+ from single_kernel_postgresql.managers.cluster import ClusterManager
13
+ from single_kernel_postgresql.managers.config import ConfigManager
14
+ from single_kernel_postgresql.managers.patroni import PatroniManager
15
+ from single_kernel_postgresql.managers.tls import TLSManager
16
+ from single_kernel_postgresql.workload.base import BaseWorkload
17
+
18
+ from ..config.enums import Substrates
19
+ from ..utils.postgresql import PostgreSQL
20
+
21
+
22
+ class AbstractPostgreSQLCharm(CharmBase, ABC):
23
+ """An abstract PostgreSQL charm."""
24
+
25
+ def __init__(self, *args):
26
+ super().__init__(*args)
27
+
28
+ # State
29
+ self.state = CharmState(charm=self, substrate=self.substrate)
30
+
31
+ # Managers
32
+ self.cluster_manager = ClusterManager(
33
+ state=self.state, workload=self.workload, client=self.postgresql
34
+ )
35
+ self.tls_manager = TLSManager(
36
+ state=self.state, workload=self.workload, client=self.postgresql
37
+ )
38
+ self.config_manager = ConfigManager(
39
+ state=self.state, workload=self.workload, client=self.postgresql
40
+ )
41
+ self.patroni_manager = PatroniManager(
42
+ state=self.state, workload=self.workload, client=self.postgresql
43
+ )
44
+
45
+ # Events Handler
46
+ self.postgresql_events_handler = PostgreSQLEventsHandler(
47
+ self,
48
+ self.workload,
49
+ self.state,
50
+ self.cluster_manager,
51
+ self.tls_manager,
52
+ self.config_manager,
53
+ self.patroni_manager,
54
+ )
55
+
56
+ # Status Handler
57
+ self.status_handler = StatusHandler(
58
+ self,
59
+ self.cluster_manager,
60
+ self.tls_manager,
61
+ self.config_manager,
62
+ self.patroni_manager,
63
+ )
64
+
65
+ # Postgresql Client
66
+ @property
67
+ @abstractmethod
68
+ def postgresql(self) -> PostgreSQL:
69
+ """Return a PostgreSQL client."""
70
+ pass
71
+
72
+ # Postgresql Workload
73
+ @property
74
+ @abstractmethod
75
+ def workload(self) -> BaseWorkload:
76
+ """Access current workload."""
77
+ pass
78
+
79
+ # Postgresql Substrate
80
+ @property
81
+ @abstractmethod
82
+ def substrate(self) -> Substrates:
83
+ """Access current substrate."""
84
+ pass
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env python3
2
+ # Copyright 2025 Canonical Ltd.
3
+ # See LICENSE file for licensing details.
4
+
5
+ """PostgreSQL Kubernetes Charm."""
6
+
7
+ import logging
8
+
9
+ from single_kernel_postgresql.charms.abstract_charm import AbstractPostgreSQLCharm, PostgreSQL
10
+ from single_kernel_postgresql.config.enums import Substrates
11
+ from single_kernel_postgresql.config.literals import CONTAINER_NAME, SYSTEM_USERS, USER
12
+ from single_kernel_postgresql.managers.k8s import K8sManager
13
+ from single_kernel_postgresql.workload.base import BaseWorkload
14
+ from single_kernel_postgresql.workload.k8s import K8sWorkload
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+
19
+ class PostgreSQLK8sCharm(AbstractPostgreSQLCharm):
20
+ """PostgreSQL K8s Charm."""
21
+
22
+ def __init__(self, *args):
23
+ """Initialize the PostgreSQL Kubernetes Charm."""
24
+ super().__init__(*args)
25
+ assert isinstance(self.workload, K8sWorkload), ( # noqa: S101
26
+ "Workload must be an instance of K8sWorkload"
27
+ )
28
+ self.k8s_manager = K8sManager(self.state, self.workload, self.postgresql)
29
+
30
+ @property
31
+ def postgresql(self) -> PostgreSQL:
32
+ """Return a PostgreSQL client."""
33
+ return PostgreSQL(
34
+ substrate=Substrates.K8S,
35
+ primary_host="localhost",
36
+ current_host="localhost",
37
+ user=USER,
38
+ # The password is hardcoded because this is an abstract charm and
39
+ # it meant to be used only in unit tests.
40
+ password="test-password", # noqa S106
41
+ database="test-database",
42
+ system_users=SYSTEM_USERS,
43
+ )
44
+
45
+ @property
46
+ def workload(self) -> BaseWorkload:
47
+ """Access current workload instance.
48
+
49
+ Returns the workload object.
50
+
51
+ Returns:
52
+ BaseWorkload: The K8sWorkload instance for this charm
53
+ """
54
+ return K8sWorkload(
55
+ charm_dir=self.charm_dir, container=self.unit.get_container(CONTAINER_NAME)
56
+ )
57
+
58
+ @property
59
+ def substrate(self) -> Substrates:
60
+ """Access current substrate type.
61
+
62
+ Returns:
63
+ Substrates: always Substrates.K8S for this charm
64
+ """
65
+ return Substrates.K8S
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env python3
2
+ # Copyright 2025 Canonical Ltd.
3
+ # See LICENSE file for licensing details.
4
+
5
+ """PostgreSQL VM Charm."""
6
+
7
+ import logging
8
+
9
+ from single_kernel_postgresql.charms.abstract_charm import AbstractPostgreSQLCharm, PostgreSQL
10
+ from single_kernel_postgresql.config.enums import Substrates
11
+ from single_kernel_postgresql.config.literals import SYSTEM_USERS, USER
12
+ from single_kernel_postgresql.workload.base import BaseWorkload
13
+ from single_kernel_postgresql.workload.vm import VMWorkload
14
+
15
+ logger = logging.getLogger(__name__)
16
+
17
+
18
+ class PostgreSQLVMCharm(AbstractPostgreSQLCharm):
19
+ """PostgreSQL VM Charm."""
20
+
21
+ def __init__(self, *args):
22
+ """Initialize the PostgreSQL VM Charm."""
23
+ super().__init__(*args)
24
+
25
+ @property
26
+ def postgresql(self) -> PostgreSQL:
27
+ """Return a PostgreSQL client."""
28
+ return PostgreSQL(
29
+ substrate=Substrates.VM,
30
+ primary_host="localhost",
31
+ current_host="localhost",
32
+ user=USER,
33
+ # The password is hardcoded because this is an abstract charm and
34
+ # it meant to be used only in unit tests.
35
+ password="test-password", # noqa S106
36
+ database="test-database",
37
+ system_users=SYSTEM_USERS,
38
+ )
39
+
40
+ @property
41
+ def workload(self) -> BaseWorkload:
42
+ """Access current workload instance.
43
+
44
+ Returns the workload object.
45
+
46
+ Returns:
47
+ BaseWorkload: The VMWorkload instance for this charm
48
+ """
49
+ return VMWorkload(charm_dir=self.charm_dir)
50
+
51
+ @property
52
+ def substrate(self) -> Substrates:
53
+ """Access current substrate type.
54
+
55
+ Returns:
56
+ Substrates: always Substrates.VM for this charm
57
+ """
58
+ return Substrates.VM
@@ -0,0 +1,13 @@
1
+ # Copyright 2025 Canonical Ltd.
2
+ # See LICENSE file for licensing details.
3
+
4
+ """PostgreSQL enums."""
5
+
6
+ from enum import Enum
7
+
8
+
9
+ class Substrates(str, Enum):
10
+ """Possible substrates."""
11
+
12
+ K8S = "k8s"
13
+ VM = "vm"
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env python3
2
+ # Copyright 2025 Canonical Ltd.
3
+ # See LICENSE file for licensing details.
4
+
5
+ """Charm-specific exceptions."""
6
+
7
+ from single_kernel_postgresql.compat.postgresql import PostgreSQLBaseError
8
+
9
+
10
+ class PostgreSQLFileOperationError(PostgreSQLBaseError):
11
+ """Exception thrown when file operations related to PostgreSQL fail."""
12
+
13
+
14
+ class StorageUnavailableError(Exception):
15
+ """Cannot find storage mountpoint."""
16
+
17
+
18
+ class SettingSystemPasswordError(PostgreSQLBaseError):
19
+ """Exception thrown when setting the system password fails."""
20
+
21
+
22
+ class PostgreSQLCannotConnectError(Exception):
23
+ """Cannot run smoke check on connected Database."""
24
+
25
+
26
+ class TlsError(Exception):
27
+ """TLS implementation internal exception."""
@@ -0,0 +1,163 @@
1
+ # Copyright 2025 Canonical Ltd.
2
+ # See LICENSE file for licensing details.
3
+ """Literal string for the different charms.
4
+
5
+ This module should contain the literals used in the charms (paths, relation names, etc).
6
+ """
7
+
8
+ from typing import Literal
9
+
10
+ # Permissions.
11
+ POSTGRESQL_STORAGE_PERMISSIONS = 0o700
12
+
13
+ # Relations
14
+ PEER_RELATION = "database-peers"
15
+ STATUS_PEERS_RELATION = "status-peers"
16
+
17
+ # Users.
18
+ BACKUP_USER = "backup"
19
+ MONITORING_USER = "monitoring"
20
+ REPLICATION_USER = "replication"
21
+ REWIND_USER = "rewind"
22
+ SNAP_USER = "_daemon_"
23
+ USER = "operator"
24
+ SYSTEM_USERS = [BACKUP_USER, MONITORING_USER, REPLICATION_USER, REWIND_USER, USER]
25
+
26
+ # Paths
27
+ ## VM Paths
28
+ BASE_SNAP_DIR = "/var/snap/charmed-postgresql"
29
+ SNAP_DATA = "current"
30
+ SNAP_COMMON = "common"
31
+ SNAP = "/snap/charmed-postgresql/current"
32
+ VM_LOGS_PATH = "var/log/postgresql"
33
+ VM_DATA_PATH = "var/lib/postgresql"
34
+
35
+ ## K8s Paths
36
+ K8S_DATA_PATH = "var/lib/pg/data"
37
+
38
+ ## Shared Paths
39
+ # NOTE: The paths don't have leading slahes since pathops
40
+ # will handle path concatenation otherwise it will use "/var/lib/postgresql"
41
+ # instead of using the root path or any other part defined by the / operator.
42
+ # e.g. snap_current / "/etc/postgresql" will result in "/etc/postgresql" instead of "/var/snap/postgresql/current/etc/postgresql"
43
+ POSTGRESQL_CONF_PATH = "etc/postgresql"
44
+ POSTGRESQL_CONF_FILE = "postgresql.conf"
45
+
46
+
47
+ ## TLS Paths
48
+ TLS_CA_BUNDLE_FILE = "peer_ca_bundle.pem"
49
+
50
+ # Scopes
51
+ SCOPES = Literal["app", "unit"]
52
+ APP_SCOPE = "app"
53
+ UNIT_SCOPE = "unit"
54
+
55
+ # Patroni
56
+ ## Patroni Paths
57
+ PATRONI_CONF_PATH = "etc/patroni"
58
+ PATRONI_LOGS_PATH = "var/log/patroni"
59
+ ## Patroni states
60
+ STARTED_STATES = ["running", "streaming"]
61
+ RUNNING_STATES = [*STARTED_STATES, "starting"]
62
+ ## Patroni config
63
+ ORIGINAL_PATRONI_ON_FAILURE_CONDITION = "restart"
64
+
65
+
66
+ # Secrets
67
+ SECRET_KEY_OVERRIDES = {"ca": "cauth"}
68
+
69
+
70
+ # Password keys
71
+ REPLICATION_PASSWORD_KEY = "replication-password" # noqa: S105
72
+ REWIND_PASSWORD_KEY = "rewind-password" # noqa: S105
73
+ USER_PASSWORD_KEY = "operator-password" # noqa: S105
74
+ MONITORING_PASSWORD_KEY = "monitoring-password" # noqa: S105
75
+ RAFT_PASSWORD_KEY = "raft-password" # noqa: S105
76
+ PATRONI_PASSWORD_KEY = "patroni-password" # noqa: S105
77
+ SECRET_INTERNAL_LABEL = "internal-secret" # noqa: S105
78
+ SECRET_DELETED_LABEL = "None" # noqa: S105
79
+ SYSTEM_USERS_PASSWORD_CONFIG = "system-users" # noqa: S105
80
+
81
+ # K8s
82
+ ## K8s Services
83
+ K8S_POSTGRESQL_SERVICE_NAME = "postgresql"
84
+ K8S_PGBACK_REST_SERVER_SERVICE_NAME = "pgbackrest server"
85
+ K8S_LDAP_SYNC_SERVICE_NAME = "ldap-sync"
86
+ K8S_METRICS_SERVER_SERVICE_NAME = "metrics_server"
87
+ K8S_PGBACKREST_METRICS_SERVER_SERVICE_NAME = "pgbackrest_metrics_server"
88
+ K8S_ROTATE_LOGS_SERVICE_NAME = "rotate-logs"
89
+ ## K8s User and group
90
+ K8S_WORKLOAD_OS_GROUP = "postgres"
91
+ K8S_WORKLOAD_OS_USER = "postgres"
92
+
93
+
94
+ # File permissions as octal
95
+ # standard directory permissions
96
+ DIR_PERMISSIONS_READONLY = 0o750
97
+
98
+
99
+ # Container name for K8s deployments
100
+ CONTAINER_NAME = "postgresql"
101
+
102
+ API_REQUEST_TIMEOUT = 5
103
+
104
+
105
+ # --- Shared constants migrated from the charms ---
106
+
107
+ # Database
108
+ DATABASE = "database"
109
+ DATABASE_DEFAULT_NAME = "postgres"
110
+ DATABASE_PORT = "5432"
111
+
112
+ # Client relations
113
+ ALL_CLIENT_RELATIONS = [DATABASE]
114
+
115
+ # Async replication relations
116
+ REPLICATION_CONSUMER_RELATION = "replication"
117
+ REPLICATION_OFFER_RELATION = "replication-offer"
118
+
119
+ # TLS files
120
+ TLS_KEY_FILE = "key.pem"
121
+ TLS_CA_FILE = "ca.pem"
122
+ TLS_CERT_FILE = "cert.pem"
123
+
124
+ # Metrics ports (kept as str to match the K8s charm; VM adapts on flip)
125
+ METRICS_PORT = "9187"
126
+ PGBACKREST_METRICS_PORT = "9854"
127
+
128
+ # Secret/database mapping labels
129
+ USERNAME_MAPPING_LABEL = "custom-usernames"
130
+ DATABASE_MAPPING_LABEL = "prefix-databases"
131
+
132
+ # Overrides
133
+ BACKUP_TYPE_OVERRIDES = {"full": "full", "differential": "diff", "incremental": "incr"}
134
+ PLUGIN_OVERRIDES = {"audit": "pgaudit", "uuid_ossp": '"uuid-ossp"'}
135
+
136
+ # SPI extension modules
137
+ SPI_MODULE = ["refint", "autoinc", "insert_username", "moddatetime"]
138
+
139
+ # Tracing
140
+ TRACING_RELATION_NAME = "tracing"
141
+ TRACING_PROTOCOL = "otlp_http"
142
+
143
+ # Patroni
144
+ PATRONI_CLUSTER_STATUS_ENDPOINT = "cluster"
145
+
146
+ # pgBackRest
147
+ PGBACKREST_LOGROTATE_FILE = "/etc/logrotate.d/pgbackrest.logrotate"
148
+ # pgBackRest emits all error/warning output on stderr (the default is stdout) so error
149
+ # extraction stays consistent. Reference: https://pgbackrest.org/configuration.html#section-log
150
+ PGBACKREST_LOG_LEVEL_STDERR = "--log-level-stderr=warn"
151
+ # Archive timeout: unable to archive WAL files within the configured timeout period.
152
+ PGBACKREST_ARCHIVE_TIMEOUT_ERROR_CODE = 82
153
+
154
+ # Backup ID formats
155
+ BACKUP_ID_FORMAT = "%Y-%m-%dT%H:%M:%SZ"
156
+ PGBACKREST_BACKUP_ID_FORMAT = "%Y%m%d-%H%M%S"
157
+
158
+ # Watcher relation (VM)
159
+ WATCHER_OFFER_RELATION = "watcher-offer"
160
+ WATCHER_RELATION = "watcher"
161
+ WATCHER_USER = "watcher"
162
+ WATCHER_PASSWORD_KEY = "watcher-password" # noqa: S105
163
+ WATCHER_SECRET_LABEL = "watcher-secret" # noqa: S105