mongo-charms-single-kernel 1.8.9__tar.gz → 1.8.11__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.

Potentially problematic release.


This version of mongo-charms-single-kernel might be problematic. Click here for more details.

Files changed (91) hide show
  1. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/PKG-INFO +1 -1
  2. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/pyproject.toml +5 -2
  3. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/config/literals.py +5 -5
  4. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/core/abstract_upgrades_v3.py +11 -3
  5. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/core/operator.py +7 -0
  6. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/core/version_checker.py +0 -12
  7. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/managers/config.py +10 -6
  8. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/managers/mongo.py +11 -11
  9. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/managers/mongodb_operator.py +26 -31
  10. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/managers/mongos_operator.py +25 -18
  11. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/managers/sharding.py +27 -29
  12. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/managers/upgrade_v3.py +32 -10
  13. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/managers/upgrade_v3_status.py +8 -5
  14. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/state/charm_state.py +15 -15
  15. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/state/config_server_state.py +6 -6
  16. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/state/models.py +2 -2
  17. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/utils/mongodb_users.py +20 -20
  18. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/LICENSE +0 -0
  19. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/README.md +0 -0
  20. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/__init__.py +0 -0
  21. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/abstract_charm.py +0 -0
  22. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/config/__init__.py +0 -0
  23. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/config/models.py +0 -0
  24. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/config/relations.py +0 -0
  25. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/config/statuses.py +0 -0
  26. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/core/__init__.py +0 -0
  27. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/core/k8s_workload.py +0 -0
  28. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/core/kubernetes_upgrades_v3.py +0 -0
  29. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/core/machine_upgrades_v3.py +0 -0
  30. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/core/secrets.py +0 -0
  31. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/core/structured_config.py +0 -0
  32. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/core/vm_workload.py +0 -0
  33. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/core/workload.py +0 -0
  34. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/events/__init__.py +0 -0
  35. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/events/backups.py +0 -0
  36. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/events/cluster.py +0 -0
  37. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/events/database.py +0 -0
  38. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/events/ldap.py +0 -0
  39. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/events/lifecycle.py +0 -0
  40. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/events/primary_action.py +0 -0
  41. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/events/sharding.py +0 -0
  42. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/events/tls.py +0 -0
  43. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/exceptions.py +0 -0
  44. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/lib/charms/certificate_transfer_interface/v0/certificate_transfer.py +0 -0
  45. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/lib/charms/data_platform_libs/v0/data_interfaces.py +0 -0
  46. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/lib/charms/data_platform_libs/v0/s3.py +0 -0
  47. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/lib/charms/glauth_k8s/v0/ldap.py +0 -0
  48. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/lib/charms/grafana_agent/v0/cos_agent.py +0 -0
  49. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/lib/charms/grafana_k8s/v0/grafana_dashboard.py +0 -0
  50. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/lib/charms/loki_k8s/v0/loki_push_api.py +0 -0
  51. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/lib/charms/operator_libs_linux/v0/sysctl.py +0 -0
  52. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/lib/charms/operator_libs_linux/v1/systemd.py +0 -0
  53. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/lib/charms/operator_libs_linux/v2/snap.py +0 -0
  54. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/lib/charms/prometheus_k8s/v0/prometheus_scrape.py +0 -0
  55. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/lib/charms/tls_certificates_interface/v4/tls_certificates.py +0 -0
  56. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/managers/__init__.py +0 -0
  57. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/managers/backups.py +0 -0
  58. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/managers/cluster.py +0 -0
  59. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/managers/k8s.py +0 -0
  60. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/managers/ldap.py +0 -0
  61. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/managers/observability.py +0 -0
  62. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/managers/tls.py +0 -0
  63. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/observability_rules/__init__.py +0 -0
  64. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/observability_rules/grafana_dashboards/MongoDB_Cluster_Summary.json +0 -0
  65. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/observability_rules/grafana_dashboards/MongoDB_ReplSet_Summary.json +0 -0
  66. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/observability_rules/k8s_prometheus_alert_rules/percona-mongodb-exporter.rule +0 -0
  67. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/observability_rules/loki/.gitkeep +0 -0
  68. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/observability_rules/vm_prometheus_alert_rules/percona-mongodb-exporter.yml +0 -0
  69. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/state/__init__.py +0 -0
  70. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/state/abstract_state.py +0 -0
  71. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/state/app_peer_state.py +0 -0
  72. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/state/cluster_state.py +0 -0
  73. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/state/ldap_state.py +0 -0
  74. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/state/tls_state.py +0 -0
  75. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/state/unit_peer_state.py +0 -0
  76. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/templates/__init__.py +0 -0
  77. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/templates/enable-transparent-huge-pages.service.j2 +0 -0
  78. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/templates/ldap.conf.j2 +0 -0
  79. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/templates/logrotate.j2 +0 -0
  80. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/utils/__init__.py +0 -0
  81. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/utils/event_helpers.py +0 -0
  82. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/utils/helpers.py +0 -0
  83. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/utils/mongo_config.py +0 -0
  84. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/utils/mongo_connection.py +0 -0
  85. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/utils/mongo_error_codes.py +0 -0
  86. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/workload/__init__.py +0 -0
  87. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/workload/backup_workload.py +0 -0
  88. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/workload/log_rotate_workload.py +0 -0
  89. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/workload/mongodb_workload.py +0 -0
  90. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/workload/mongos_workload.py +0 -0
  91. {mongo_charms_single_kernel-1.8.9 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/workload/monitor_workload.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mongo-charms-single-kernel
3
- Version: 1.8.9
3
+ Version: 1.8.11
4
4
  Summary: Shared and reusable code for Mongo-related charms
5
5
  License-Expression: Apache-2.0
6
6
  License-File: LICENSE
@@ -40,7 +40,7 @@ dependencies = [
40
40
  "python-ldap",
41
41
  "charm-refresh (>=3.1.0.2,<4.0.0.0)"
42
42
  ]
43
- version = "1.8.9"
43
+ version = "1.8.11"
44
44
 
45
45
  [project.urls]
46
46
  homepage = "https://github.com/canonical/mongo-single-kernel-library"
@@ -136,6 +136,8 @@ more_itertools = "*"
136
136
  httpx = "*"
137
137
  boto3 = "^1.37.12"
138
138
  mypy-boto3-s3 = "^1.37.0"
139
+ tomli = '*'
140
+ tomli-w = '*'
139
141
 
140
142
  [tool.ruff]
141
143
  target-version = "py310"
@@ -206,7 +208,8 @@ exclude = [
206
208
  "^single_kernel_mongo/lib/*",
207
209
  "tests/charms/*",
208
210
  "tests/integration/*",
209
- "tests/unit/*"
211
+ "tests/unit/*",
212
+ "typings[\\/].*"
210
213
  ]
211
214
  # https://mypy.readthedocs.io/en/stable/command_line.html#cmdoption-mypy-ignore-missing-imports
212
215
  ignore_missing_imports = true
@@ -51,13 +51,13 @@ class MongoPorts(IntEnum):
51
51
  class InternalUsernames(str, Enum):
52
52
  """The allowed internal usernames."""
53
53
 
54
- OPERATOR = "operator"
55
- BACKUP = "backup"
56
- MONITOR = "monitor"
57
- LOGROTATE = "logrotate"
54
+ CHARMED_OPERATOR = "charmed-operator"
55
+ CHARMED_BACKUP = "charmed-backup"
56
+ CHARMED_STATS = "charmed-stats"
57
+ CHARMED_LOGROTATE = "charmed-logrotate"
58
58
 
59
59
 
60
- SECRETS_APP = [f"{user}-password" for user in InternalUsernames] + ["keyfile"]
60
+ SECRETS_APP = [f"{username}-password" for username in InternalUsernames] + ["keyfile"]
61
61
 
62
62
  VERSIONS_FILE = Path("refresh_versions.toml")
63
63
 
@@ -4,6 +4,7 @@ import abc
4
4
  import dataclasses
5
5
  import logging
6
6
 
7
+ import charm_ as charm_api
7
8
  import charm_refresh
8
9
  import poetry.core.constraints.version as poetry_version
9
10
  from tenacity import RetryError
@@ -12,9 +13,7 @@ from typing_extensions import override
12
13
  from single_kernel_mongo.config.literals import CharmKind
13
14
  from single_kernel_mongo.config.models import BackupState
14
15
  from single_kernel_mongo.core.operator import OperatorProtocol
15
- from single_kernel_mongo.exceptions import (
16
- FailedToMovePrimaryError,
17
- )
16
+ from single_kernel_mongo.exceptions import FailedToMovePrimaryError
18
17
  from single_kernel_mongo.managers.upgrade_v3 import MongoDBUpgradesManager
19
18
  from single_kernel_mongo.state.charm_state import CharmState
20
19
 
@@ -108,6 +107,15 @@ class MongoDBRefresh(charm_refresh.CharmSpecificCommon, abc.ABC):
108
107
  logger.error("Cluster cannot read/write to replicas")
109
108
  raise charm_refresh.PrecheckFailed("Cluster is not able to read/write to replicas")
110
109
 
110
+ if not (
111
+ isinstance(charm_api.event, charm_api.ActionEvent)
112
+ and charm_api.event.action == "pre-refresh-check"
113
+ ):
114
+ logger.info(
115
+ "Not checking the compatibility version, this can only run in manual pre-refresh-check."
116
+ )
117
+ return
118
+
111
119
  fcv = self.state.app_peer_data.feature_compatibility_version
112
120
  if not self.upgrades_manager.is_feature_compatibility_version(fcv):
113
121
  logger.info(
@@ -393,3 +393,10 @@ class OperatorProtocol(ABC, Object, ManagerStatusProtocol):
393
393
  return
394
394
 
395
395
  Path(self.state.paths.conf_path).mkdir(exist_ok=True)
396
+
397
+ def instantiate_keyfile(self):
398
+ """Instantiate the keyfile."""
399
+ if not (keyfile := self.state.get_keyfile()):
400
+ raise Exception("Waiting for leader unit to generate keyfile contents")
401
+
402
+ self.workload.write(self.workload.paths.keyfile, keyfile)
@@ -42,14 +42,6 @@ class VersionChecker:
42
42
  "-locally built" if self.version_checker.is_local_charm(self.charm.app.name) else ""
43
43
  )
44
44
  try:
45
- # This part needs some explanation: On VM, if we are running this
46
- # during the pre-refresh hook that happens after the upgrade, all
47
- # charm codes have been refreshed.
48
- # We want to check our version against the already upgraded config server, so
49
- # we use the current revision that stores the revision of the
50
- # former charm until that unit is fully upgraded.
51
- old_version = self.version_checker.version
52
- self.version_checker.version = self.state.unit_peer_data.current_revision
53
45
  if self.version_checker.are_related_apps_valid():
54
46
  return None
55
47
  except NoVersionError as e:
@@ -61,10 +53,6 @@ class VersionChecker:
61
53
  current_charms_version, local_identifier
62
54
  )
63
55
 
64
- finally:
65
- # Always restore the former version.
66
- self.version_checker.version = old_version
67
-
68
56
  if self.state.is_role(MongoDBRoles.SHARD):
69
57
  config_server_revision = self.version_checker.get_version_of_related_app(
70
58
  self.state.config_server_name
@@ -28,7 +28,11 @@ from single_kernel_mongo.core.structured_config import MongoConfigModel, MongoDB
28
28
  from single_kernel_mongo.core.workload import WorkloadBase
29
29
  from single_kernel_mongo.exceptions import WorkloadServiceError
30
30
  from single_kernel_mongo.state.charm_state import CharmState
31
- from single_kernel_mongo.utils.mongodb_users import BackupUser, LogRotateUser, MonitorUser
31
+ from single_kernel_mongo.utils.mongodb_users import (
32
+ CharmedBackupUser,
33
+ CharmedLogRotateUser,
34
+ CharmedStatsUser,
35
+ )
32
36
  from single_kernel_mongo.workload import (
33
37
  get_logrotate_workload_for_substrate,
34
38
  get_mongodb_exporter_workload_for_substrate,
@@ -135,7 +139,7 @@ class BackupConfigManager(CommonConfigManager):
135
139
  logger.info("Not starting PBM yet. Shard not added to config-server")
136
140
  return
137
141
 
138
- if not self.state.get_user_password(BackupUser):
142
+ if not self.state.get_user_password(CharmedBackupUser):
139
143
  logger.info("No password found.")
140
144
  return
141
145
 
@@ -184,7 +188,7 @@ class LogRotateConfigManager(CommonConfigManager):
184
188
  logger.info("DB is not initialised.")
185
189
  return
186
190
 
187
- if not self.state.get_user_password(LogRotateUser):
191
+ if not self.state.get_user_password(CharmedLogRotateUser):
188
192
  logger.info("No password found.")
189
193
  return
190
194
 
@@ -224,17 +228,17 @@ class MongoDBExporterConfigManager(CommonConfigManager):
224
228
 
225
229
  @override
226
230
  def build_parameters(self) -> list[list[str]]:
227
- return [[self.state.monitor_config.uri]]
231
+ return [[self.state.stats_config.uri]]
228
232
 
229
233
  def configure_and_restart(self):
230
234
  """Exposes the endpoint to mongodb_exporter."""
231
235
  if not self.state.db_initialised:
232
236
  return
233
237
 
234
- if not self.state.get_user_password(MonitorUser):
238
+ if not self.state.get_user_password(CharmedStatsUser):
235
239
  return
236
240
 
237
- if not self.workload.active() or self.get_environment() != self.state.monitor_config.uri:
241
+ if not self.workload.active() or self.get_environment() != self.state.stats_config.uri:
238
242
  try:
239
243
  # Always enable the service
240
244
  self.workload.stop()
@@ -52,11 +52,11 @@ from single_kernel_mongo.utils.mongo_config import (
52
52
  from single_kernel_mongo.utils.mongo_connection import MongoConnection, NotReadyError
53
53
  from single_kernel_mongo.utils.mongodb_users import (
54
54
  OPERATOR_ROLE,
55
- BackupUser,
56
- LogRotateUser,
55
+ CharmedBackupUser,
56
+ CharmedLogRotateUser,
57
+ CharmedOperatorUser,
58
+ CharmedStatsUser,
57
59
  MongoDBUser,
58
- MonitorUser,
59
- OperatorUser,
60
60
  )
61
61
 
62
62
  if TYPE_CHECKING:
@@ -138,12 +138,12 @@ class MongoManager(Object, ManagerStatusProtocol):
138
138
 
139
139
  def initialise_charm_admin_users(self) -> None:
140
140
  """First initialisation of each user."""
141
- self.initialise_operator_user()
142
- self.initialise_user(MonitorUser)
143
- self.initialise_user(BackupUser)
144
- self.initialise_user(LogRotateUser)
141
+ self.initialise_charmed_operator_user()
142
+ self.initialise_user(CharmedStatsUser)
143
+ self.initialise_user(CharmedBackupUser)
144
+ self.initialise_user(CharmedLogRotateUser)
145
145
 
146
- def initialise_operator_user(self):
146
+ def initialise_charmed_operator_user(self):
147
147
  """Creates initial admin user for MongoDB.
148
148
 
149
149
  Initial admin user can be created only through localhost connection.
@@ -154,7 +154,7 @@ class MongoManager(Object, ManagerStatusProtocol):
154
154
  It is needed to install mongodb-clients inside charm container to make
155
155
  this function work correctly.
156
156
  """
157
- if self.state.app_peer_data.is_user_created(OperatorUser.username):
157
+ if self.state.app_peer_data.is_user_created(CharmedOperatorUser.username):
158
158
  return
159
159
  config = self.state.mongo_config
160
160
  cmd = [
@@ -169,7 +169,7 @@ class MongoManager(Object, ManagerStatusProtocol):
169
169
  '})"',
170
170
  ]
171
171
  self.workload.run_bin_command("mongodb://localhost/admin", cmd, input=config.password)
172
- self.state.app_peer_data.set_user_created(OperatorUser.username)
172
+ self.state.app_peer_data.set_user_created(CharmedOperatorUser.username)
173
173
 
174
174
  def initialise_user(self, user: MongoDBUser):
175
175
  """Creates a user and sets its role on the MongoDB database."""
@@ -33,10 +33,7 @@ from single_kernel_mongo.config.models import (
33
33
  PasswordManagementContext,
34
34
  PasswordManagementState,
35
35
  )
36
- from single_kernel_mongo.config.relations import (
37
- ExternalRequirerRelations,
38
- RelationNames,
39
- )
36
+ from single_kernel_mongo.config.relations import ExternalRequirerRelations, RelationNames
40
37
  from single_kernel_mongo.config.statuses import (
41
38
  BackupStatuses,
42
39
  CharmStatuses,
@@ -100,12 +97,12 @@ from single_kernel_mongo.state.charm_state import CharmState
100
97
  from single_kernel_mongo.utils.helpers import is_valid_ldap_options, is_valid_ldapusertodnmapping
101
98
  from single_kernel_mongo.utils.mongo_connection import MongoConnection, NotReadyError
102
99
  from single_kernel_mongo.utils.mongodb_users import (
103
- BackupUser,
100
+ CharmedBackupUser,
101
+ CharmedLogRotateUser,
102
+ CharmedOperatorUser,
103
+ CharmedStatsUser,
104
104
  InternalUsers,
105
- LogRotateUser,
106
105
  MongoDBUser,
107
- MonitorUser,
108
- OperatorUser,
109
106
  get_user_from_username,
110
107
  validate_charm_user_password_config,
111
108
  )
@@ -236,7 +233,7 @@ class MongoDBOperator(OperatorProtocol, Object):
236
233
  raise
237
234
 
238
235
  self.upgrades_status_manager = MongoDBUpgradesStatusManager(
239
- state=self.state, workload=self.workload, refresh=self.refresh
236
+ self, state=self.state, workload=self.workload, refresh=self.refresh
240
237
  )
241
238
 
242
239
  self.sysctl_config = sysctl.Config(name=self.charm.app.name)
@@ -274,13 +271,13 @@ class MongoDBOperator(OperatorProtocol, Object):
274
271
  if not self.refresh:
275
272
  return
276
273
 
274
+ # Update the version across all relations so that we can notify other units
275
+ self.cross_app_version_checker.set_version_across_all_relations()
276
+
277
277
  if self.state.app_peer_data.feature_compatibility_version == FEATURE_VERSION:
278
278
  # We have already run all this logic before, no need to run it again.
279
279
  return
280
280
 
281
- # Update the version across all relations so that we can notify other units
282
- self.cross_app_version_checker.set_version_across_all_relations()
283
-
284
281
  if (
285
282
  self.state.is_role(MongoDBRoles.CONFIG_SERVER)
286
283
  and not self.cross_app_version_checker.are_related_apps_valid()
@@ -324,12 +321,15 @@ class MongoDBOperator(OperatorProtocol, Object):
324
321
 
325
322
  if not refresh.workload_allowed_to_start:
326
323
  return
324
+
327
325
  logger.info("Restarting workloads")
328
326
  # always apply the current charm revision's config
329
327
  self._configure_workloads()
330
328
  self.start_charm_services()
331
329
 
332
- self.state.unit_peer_data.current_revision = self.cross_app_version_checker.version
330
+ if self.charm.unit.is_leader():
331
+ # Update the version across all relations so that we can notify other units
332
+ self.cross_app_version_checker.set_version_across_all_relations()
333
333
 
334
334
  if self.name == CharmKind.MONGOD:
335
335
  self._restart_related_services()
@@ -391,13 +391,13 @@ class MongoDBOperator(OperatorProtocol, Object):
391
391
  """The ordered list of components for this operator."""
392
392
  return (
393
393
  self,
394
+ self.upgrades_status_manager,
394
395
  self.mongo_manager,
395
396
  self.tls_manager,
396
397
  self.shard_manager,
397
398
  self.config_server_manager,
398
399
  self.backup_manager,
399
400
  self.ldap_manager,
400
- self.upgrades_status_manager,
401
401
  )
402
402
 
403
403
  # BEGIN: Handlers.
@@ -480,7 +480,7 @@ class MongoDBOperator(OperatorProtocol, Object):
480
480
  if not self.mongo_manager.mongod_ready():
481
481
  raise WorkloadNotReadyError
482
482
 
483
- self.state.statuses.set(CharmStatuses.ACTIVE_IDLE.value, scope="unit", component=self.name)
483
+ self.state.statuses.clear(scope="unit", component=self.name)
484
484
 
485
485
  try:
486
486
  self._initialise_replica_set()
@@ -503,7 +503,7 @@ class MongoDBOperator(OperatorProtocol, Object):
503
503
  logger.error("Could not restart the related services.")
504
504
  return
505
505
 
506
- self.state.statuses.set(CharmStatuses.ACTIVE_IDLE.value, scope="unit", component=self.name)
506
+ self.state.statuses.clear(scope="unit", component=self.name)
507
507
 
508
508
  @override
509
509
  def prepare_for_shutdown(self) -> None: # pragma: nocover
@@ -719,10 +719,10 @@ class MongoDBOperator(OperatorProtocol, Object):
719
719
 
720
720
  Adds the unit as a replica to the MongoDB replica set.
721
721
  """
722
- # Changing the monitor or the backup password will lead to non-leader
723
- # units receiving a relation changed event. We must update the monitor
724
- # and pbm URI if the password changes so that COS/pbm can continue to
725
- # work.
722
+ # Changing the charmed-stats or the charmed-backup password will lead
723
+ # to non-leader units receiving a relation changed event. We must update
724
+ # the monitor and pbm URI if the password changes so that COS/pbm can
725
+ # continue to work.
726
726
  if self.state.db_initialised and self.workload.active():
727
727
  self.mongodb_exporter_config_manager.configure_and_restart()
728
728
  self.backup_manager.configure_and_restart()
@@ -912,16 +912,18 @@ class MongoDBOperator(OperatorProtocol, Object):
912
912
  def update_single_user_password(self, user: MongoDBUser, new_password: str) -> None:
913
913
  """Set password in Mongod and restart the appropriate services."""
914
914
  self.mongo_manager.set_user_password(user, new_password)
915
- if user == BackupUser:
915
+ if user == CharmedBackupUser:
916
916
  # Update and restart PBM Agent.
917
917
  self.backup_manager.configure_and_restart()
918
- if user == MonitorUser:
918
+ if user == CharmedStatsUser:
919
919
  # Update and restart mongodb exporter.
920
920
  self.mongodb_exporter_config_manager.configure_and_restart()
921
- if user == LogRotateUser:
921
+ if user == CharmedLogRotateUser:
922
922
  # Update and restart logrotate.
923
923
  self.logrotate_config_manager.configure_and_restart()
924
- if user in (OperatorUser, BackupUser) and self.state.is_role(MongoDBRoles.CONFIG_SERVER):
924
+ if user in (CharmedOperatorUser, CharmedBackupUser) and self.state.is_role(
925
+ MongoDBRoles.CONFIG_SERVER
926
+ ):
925
927
  self.config_server_manager.update_credentials(
926
928
  user.password_key_name,
927
929
  new_password,
@@ -1151,13 +1153,6 @@ class MongoDBOperator(OperatorProtocol, Object):
1151
1153
  # Sets directory permissions
1152
1154
  self.set_permissions()
1153
1155
 
1154
- def instantiate_keyfile(self):
1155
- """Instantiate the keyfile."""
1156
- if not (keyfile := self.state.get_keyfile()):
1157
- raise Exception("Waiting for leader unit to generate keyfile contents")
1158
-
1159
- self.workload.write(self.workload.paths.keyfile, keyfile)
1160
-
1161
1156
  def _initialise_replica_set(self):
1162
1157
  """Helpful method to initialise the replica set and the users.
1163
1158
 
@@ -20,12 +20,7 @@ from ops.model import Relation, Unit
20
20
  from pymongo.errors import PyMongoError
21
21
  from typing_extensions import override
22
22
 
23
- from single_kernel_mongo.config.literals import (
24
- CharmKind,
25
- MongoPorts,
26
- Scope,
27
- Substrates,
28
- )
23
+ from single_kernel_mongo.config.literals import CharmKind, MongoPorts, Scope, Substrates
29
24
  from single_kernel_mongo.config.models import ROLES
30
25
  from single_kernel_mongo.config.relations import ExternalRequirerRelations, RelationNames
31
26
  from single_kernel_mongo.config.statuses import CharmStatuses, MongosStatuses
@@ -57,9 +52,7 @@ from single_kernel_mongo.managers.upgrade_v3 import MongoDBUpgradesManager
57
52
  from single_kernel_mongo.managers.upgrade_v3_status import MongoDBUpgradesStatusManager
58
53
  from single_kernel_mongo.state.app_peer_state import AppPeerDataKeys
59
54
  from single_kernel_mongo.state.charm_state import CharmState
60
- from single_kernel_mongo.workload import (
61
- get_mongos_workload_for_substrate,
62
- )
55
+ from single_kernel_mongo.workload import get_mongos_workload_for_substrate
63
56
  from single_kernel_mongo.workload.mongos_workload import MongosWorkload
64
57
 
65
58
  if TYPE_CHECKING:
@@ -137,7 +130,7 @@ class MongosOperator(OperatorProtocol, Object):
137
130
  sys.exit()
138
131
 
139
132
  self.upgrades_status_manager = MongoDBUpgradesStatusManager(
140
- self.state, self.workload, self.refresh
133
+ self, self.state, self.workload, self.refresh
141
134
  )
142
135
 
143
136
  # LDAP Manager, which covers both send-ca-cert interface and ldap interface.
@@ -169,6 +162,9 @@ class MongosOperator(OperatorProtocol, Object):
169
162
 
170
163
  Checks if unit is healthy and allow the next unit to update.
171
164
  """
165
+ if not self.state.db_initialised:
166
+ return
167
+
172
168
  if not refresh.workload_allowed_to_start:
173
169
  return
174
170
 
@@ -178,7 +174,7 @@ class MongosOperator(OperatorProtocol, Object):
178
174
  self._configure_workloads()
179
175
  self.start_charm_services()
180
176
 
181
- logger.debug("Running post refresh checks to verify monogs is not broken after refresh")
177
+ logger.debug("Running post refresh checks to verify mongos is not broken after refresh")
182
178
  if not self.state.db_initialised:
183
179
  refresh.next_unit_allowed_to_refresh = True
184
180
  return
@@ -232,6 +228,12 @@ class MongosOperator(OperatorProtocol, Object):
232
228
 
233
229
  self.mongos_config_manager.set_environment()
234
230
 
231
+ # Instantiate the keyfile
232
+ try:
233
+ self.instantiate_keyfile()
234
+ except Exception:
235
+ logger.info("Not instantiating as we don't have a keyfile yet.")
236
+
235
237
  @override
236
238
  def prepare_for_startup(self) -> None:
237
239
  """For this case, we don't start any service.
@@ -248,19 +250,24 @@ class MongosOperator(OperatorProtocol, Object):
248
250
 
249
251
  if self.refresh.in_progress:
250
252
  # Bypass the regular start if refresh is in progress
253
+ logger.info("Refresh in progress, skipping regular start")
251
254
  return
252
255
 
253
256
  self._configure_workloads()
254
257
 
255
- # start hooks are fired before relation hooks and `mongos` requires a config-server in
258
+ if self.state.mongos_cluster_relation:
259
+ self.instantiate_keyfile()
260
+ self.start_charm_services()
261
+ return
262
+
263
+ # start hooks that are fired before relation hooks and `mongos` requires a config-server in
256
264
  # order to start. Wait to receive config-server info from the relation event before
257
265
  # starting `mongos` daemon
258
- if not self.state.mongos_cluster_relation:
259
- self.state.statuses.add(
260
- MongosStatuses.MISSING_CONF_SERVER_REL.value,
261
- scope="unit",
262
- component=self.name,
263
- )
266
+ self.state.statuses.add(
267
+ MongosStatuses.MISSING_CONF_SERVER_REL.value,
268
+ scope="unit",
269
+ component=self.name,
270
+ )
264
271
 
265
272
  @override
266
273
  def update_secrets_and_restart(self, secret_label: str, secret_id: str) -> None:
@@ -18,9 +18,7 @@ from data_platform_helpers.advanced_statuses.models import StatusObject
18
18
  from data_platform_helpers.advanced_statuses.protocol import ManagerStatusProtocol
19
19
  from data_platform_helpers.advanced_statuses.types import Scope
20
20
  from ops.framework import Object
21
- from ops.model import (
22
- Relation,
23
- )
21
+ from ops.model import Relation
24
22
  from pymongo.errors import (
25
23
  NotPrimaryError,
26
24
  OperationFailure,
@@ -37,10 +35,7 @@ from single_kernel_mongo.config.literals import (
37
35
  )
38
36
  from single_kernel_mongo.config.models import BackupState
39
37
  from single_kernel_mongo.config.relations import RelationNames
40
- from single_kernel_mongo.config.statuses import (
41
- ConfigServerStatuses,
42
- ShardStatuses,
43
- )
38
+ from single_kernel_mongo.config.statuses import ConfigServerStatuses, ShardStatuses
44
39
  from single_kernel_mongo.core.structured_config import MongoDBRoles
45
40
  from single_kernel_mongo.exceptions import (
46
41
  BalancerNotEnabledError,
@@ -62,9 +57,9 @@ from single_kernel_mongo.state.tls_state import SECRET_CA_LABEL
62
57
  from single_kernel_mongo.utils.mongo_connection import MongoConnection, NotReadyError
63
58
  from single_kernel_mongo.utils.mongo_error_codes import MongoErrorCodes
64
59
  from single_kernel_mongo.utils.mongodb_users import (
65
- BackupUser,
60
+ CharmedBackupUser,
61
+ CharmedOperatorUser,
66
62
  MongoDBUser,
67
- OperatorUser,
68
63
  )
69
64
  from single_kernel_mongo.workload.mongodb_workload import MongoDBWorkload
70
65
 
@@ -108,10 +103,10 @@ class ConfigServerManager(Object, ManagerStatusProtocol):
108
103
  )
109
104
  relation_data = {
110
105
  AppShardingComponentKeys.OPERATOR_PASSWORD.value: self.state.get_user_password(
111
- OperatorUser
106
+ CharmedOperatorUser
112
107
  ),
113
108
  AppShardingComponentKeys.BACKUP_PASSWORD.value: self.state.get_user_password(
114
- BackupUser
109
+ CharmedBackupUser
115
110
  ),
116
111
  AppShardingComponentKeys.KEY_FILE.value: self.state.get_keyfile(),
117
112
  AppShardingComponentKeys.HOST.value: json.dumps(sorted(self.state.internal_hosts)),
@@ -195,11 +190,8 @@ class ConfigServerManager(Object, ManagerStatusProtocol):
195
190
  # Note: we permit this logic based on status since we aren't checking
196
191
  # self.charm.unit.status`, instead `get_cluster_mismatched_revision_status` directly
197
192
  # computes the revision check.
198
- if (
199
- rev_status
200
- := self.dependent.cluster_version_checker.get_cluster_mismatched_revision_status()
201
- ):
202
- self.state.statuses.add(rev_status, scope="app", component=self.dependent.name)
193
+ if self.dependent.cluster_version_checker.get_cluster_mismatched_revision_status():
194
+ # The status will be added during the get status
203
195
  raise DeferrableFailedHookChecksError("Mismatched versions in the cluster")
204
196
 
205
197
  def assert_pass_hook_checks(self, relation: Relation, leaving: bool = False) -> None:
@@ -476,8 +468,8 @@ class ConfigServerManager(Object, ManagerStatusProtocol):
476
468
  if not hosts:
477
469
  return unreachable_hosts
478
470
 
479
- # use a URI that is not dependent on the operator password, as we are not guaranteed
480
- # that the shard has received the password yet.
471
+ # use a URI that is not dependent on the charmed-operator password, as we are
472
+ # not guaranteed that the shard has received the password yet.
481
473
  # To check if the shard is ready, we check the entire replica set for readiness
482
474
  uri = f"mongodb://{','.join(hosts)}"
483
475
  if not self.dependent.mongo_manager.mongod_ready(uri, direct=False):
@@ -526,11 +518,8 @@ class ShardManager(Object, ManagerStatusProtocol):
526
518
  # Note: we permit this logic based on status since we aren't checking
527
519
  # self.charm.unit.status`, instead `get_cluster_mismatched_revision_status` directly
528
520
  # computes the revision check.
529
- if (
530
- rev_status
531
- := self.dependent.cluster_version_checker.get_cluster_mismatched_revision_status()
532
- ):
533
- self.state.statuses.add(rev_status, scope="app", component=self.dependent.name)
521
+ if self.dependent.cluster_version_checker.get_cluster_mismatched_revision_status():
522
+ # The status will be added during the get status
534
523
  raise DeferrableFailedHookChecksError("Mismatched versions in the cluster")
535
524
 
536
525
  def assert_pass_hook_checks(self, relation: Relation, is_leaving: bool = False) -> None:
@@ -637,7 +626,7 @@ class ShardManager(Object, ManagerStatusProtocol):
637
626
  self.state.app_peer_data.mongos_hosts = self.state.shard_state.mongos_hosts
638
627
 
639
628
  def handle_secret_changed(self, secret_label: str | None) -> None:
640
- """Update operator and backup user passwords when rotation occurs.
629
+ """Update charmed-operator and charmed-backup user passwords when rotation occurs.
641
630
 
642
631
  Changes in secrets do not re-trigger a relation changed event, so it is necessary to listen
643
632
  to secret changes events.
@@ -665,7 +654,9 @@ class ShardManager(Object, ManagerStatusProtocol):
665
654
  backup_password = self.state.shard_state.backup_password
666
655
 
667
656
  if not operator_password or not backup_password:
668
- raise WaitingForSecretsError("Missing operator password or backup password")
657
+ raise WaitingForSecretsError(
658
+ "Missing charmed-operator password or charmed-backup password"
659
+ )
669
660
  self.sync_cluster_passwords(operator_password, backup_password)
670
661
 
671
662
  # Add the certificate if it is present
@@ -764,7 +755,10 @@ class ShardManager(Object, ManagerStatusProtocol):
764
755
  )
765
756
  raise NotReadyError
766
757
 
767
- for user, password in ((OperatorUser, operator_password), (BackupUser, backup_password)):
758
+ for user, password in (
759
+ (CharmedOperatorUser, operator_password),
760
+ (CharmedBackupUser, backup_password),
761
+ ):
768
762
  try:
769
763
  self.update_password(user=user, new_password=password)
770
764
  except SetPasswordError:
@@ -888,7 +882,7 @@ class ShardManager(Object, ManagerStatusProtocol):
888
882
  )
889
883
  return False
890
884
 
891
- config = self.state.mongos_config_for_user(OperatorUser, set(mongos_hosts))
885
+ config = self.state.mongos_config_for_user(CharmedOperatorUser, set(mongos_hosts))
892
886
 
893
887
  drained = shard_name not in self.dependent.mongo_manager.get_draining_shards(
894
888
  config=config, shard_name=shard_name
@@ -927,9 +921,13 @@ class ShardManager(Object, ManagerStatusProtocol):
927
921
 
928
922
  def should_synchronise_cluster_passwords(self) -> bool:
929
923
  """Decides if we should synchronise cluster passwords or not."""
930
- if self.state.shard_state.operator_password != self.state.get_user_password(OperatorUser):
924
+ if self.state.shard_state.operator_password != self.state.get_user_password(
925
+ CharmedOperatorUser
926
+ ):
931
927
  return True
932
- if self.state.shard_state.backup_password != self.state.get_user_password(BackupUser):
928
+ if self.state.shard_state.backup_password != self.state.get_user_password(
929
+ CharmedBackupUser
930
+ ):
933
931
  return True
934
932
  return False
935
933