mongo-charms-single-kernel 1.8.10__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.10 → mongo_charms_single_kernel-1.8.11}/PKG-INFO +1 -1
  2. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/pyproject.toml +5 -2
  3. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/core/abstract_upgrades_v3.py +11 -3
  4. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/core/operator.py +7 -0
  5. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/core/version_checker.py +0 -12
  6. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/managers/mongodb_operator.py +12 -19
  7. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/managers/mongos_operator.py +25 -18
  8. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/managers/sharding.py +6 -17
  9. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/managers/upgrade_v3.py +26 -4
  10. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/managers/upgrade_v3_status.py +8 -5
  11. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/LICENSE +0 -0
  12. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/README.md +0 -0
  13. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/__init__.py +0 -0
  14. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/abstract_charm.py +0 -0
  15. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/config/__init__.py +0 -0
  16. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/config/literals.py +0 -0
  17. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/config/models.py +0 -0
  18. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/config/relations.py +0 -0
  19. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/config/statuses.py +0 -0
  20. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/core/__init__.py +0 -0
  21. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/core/k8s_workload.py +0 -0
  22. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/core/kubernetes_upgrades_v3.py +0 -0
  23. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/core/machine_upgrades_v3.py +0 -0
  24. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/core/secrets.py +0 -0
  25. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/core/structured_config.py +0 -0
  26. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/core/vm_workload.py +0 -0
  27. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/core/workload.py +0 -0
  28. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/events/__init__.py +0 -0
  29. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/events/backups.py +0 -0
  30. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/events/cluster.py +0 -0
  31. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/events/database.py +0 -0
  32. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/events/ldap.py +0 -0
  33. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/events/lifecycle.py +0 -0
  34. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/events/primary_action.py +0 -0
  35. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/events/sharding.py +0 -0
  36. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/events/tls.py +0 -0
  37. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/exceptions.py +0 -0
  38. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/lib/charms/certificate_transfer_interface/v0/certificate_transfer.py +0 -0
  39. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/lib/charms/data_platform_libs/v0/data_interfaces.py +0 -0
  40. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/lib/charms/data_platform_libs/v0/s3.py +0 -0
  41. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/lib/charms/glauth_k8s/v0/ldap.py +0 -0
  42. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/lib/charms/grafana_agent/v0/cos_agent.py +0 -0
  43. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/lib/charms/grafana_k8s/v0/grafana_dashboard.py +0 -0
  44. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/lib/charms/loki_k8s/v0/loki_push_api.py +0 -0
  45. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/lib/charms/operator_libs_linux/v0/sysctl.py +0 -0
  46. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/lib/charms/operator_libs_linux/v1/systemd.py +0 -0
  47. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/lib/charms/operator_libs_linux/v2/snap.py +0 -0
  48. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/lib/charms/prometheus_k8s/v0/prometheus_scrape.py +0 -0
  49. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/lib/charms/tls_certificates_interface/v4/tls_certificates.py +0 -0
  50. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/managers/__init__.py +0 -0
  51. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/managers/backups.py +0 -0
  52. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/managers/cluster.py +0 -0
  53. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/managers/config.py +0 -0
  54. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/managers/k8s.py +0 -0
  55. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/managers/ldap.py +0 -0
  56. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/managers/mongo.py +0 -0
  57. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/managers/observability.py +0 -0
  58. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/managers/tls.py +0 -0
  59. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/observability_rules/__init__.py +0 -0
  60. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/observability_rules/grafana_dashboards/MongoDB_Cluster_Summary.json +0 -0
  61. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/observability_rules/grafana_dashboards/MongoDB_ReplSet_Summary.json +0 -0
  62. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/observability_rules/k8s_prometheus_alert_rules/percona-mongodb-exporter.rule +0 -0
  63. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/observability_rules/loki/.gitkeep +0 -0
  64. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/observability_rules/vm_prometheus_alert_rules/percona-mongodb-exporter.yml +0 -0
  65. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/state/__init__.py +0 -0
  66. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/state/abstract_state.py +0 -0
  67. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/state/app_peer_state.py +0 -0
  68. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/state/charm_state.py +0 -0
  69. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/state/cluster_state.py +0 -0
  70. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/state/config_server_state.py +0 -0
  71. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/state/ldap_state.py +0 -0
  72. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/state/models.py +0 -0
  73. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/state/tls_state.py +0 -0
  74. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/state/unit_peer_state.py +0 -0
  75. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/templates/__init__.py +0 -0
  76. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/templates/enable-transparent-huge-pages.service.j2 +0 -0
  77. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/templates/ldap.conf.j2 +0 -0
  78. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/templates/logrotate.j2 +0 -0
  79. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/utils/__init__.py +0 -0
  80. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/utils/event_helpers.py +0 -0
  81. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/utils/helpers.py +0 -0
  82. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/utils/mongo_config.py +0 -0
  83. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/utils/mongo_connection.py +0 -0
  84. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/utils/mongo_error_codes.py +0 -0
  85. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/utils/mongodb_users.py +0 -0
  86. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/workload/__init__.py +0 -0
  87. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/workload/backup_workload.py +0 -0
  88. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/workload/log_rotate_workload.py +0 -0
  89. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/workload/mongodb_workload.py +0 -0
  90. {mongo_charms_single_kernel-1.8.10 → mongo_charms_single_kernel-1.8.11}/single_kernel_mongo/workload/mongos_workload.py +0 -0
  91. {mongo_charms_single_kernel-1.8.10 → 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.10
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.10"
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
@@ -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
@@ -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,
@@ -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
@@ -1153,13 +1153,6 @@ class MongoDBOperator(OperatorProtocol, Object):
1153
1153
  # Sets directory permissions
1154
1154
  self.set_permissions()
1155
1155
 
1156
- def instantiate_keyfile(self):
1157
- """Instantiate the keyfile."""
1158
- if not (keyfile := self.state.get_keyfile()):
1159
- raise Exception("Waiting for leader unit to generate keyfile contents")
1160
-
1161
- self.workload.write(self.workload.paths.keyfile, keyfile)
1162
-
1163
1156
  def _initialise_replica_set(self):
1164
1157
  """Helpful method to initialise the replica set and the users.
1165
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,
@@ -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:
@@ -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:
@@ -11,10 +11,7 @@ from tenacity import Retrying, retry, stop_after_attempt, wait_fixed
11
11
  from single_kernel_mongo.core.operator import OperatorProtocol
12
12
  from single_kernel_mongo.core.structured_config import MongoDBRoles
13
13
  from single_kernel_mongo.core.workload import WorkloadBase
14
- from single_kernel_mongo.exceptions import (
15
- BalancerStillRunningError,
16
- ClusterNotHealthyError,
17
- )
14
+ from single_kernel_mongo.exceptions import BalancerStillRunningError, ClusterNotHealthyError
18
15
  from single_kernel_mongo.state.charm_state import CharmState
19
16
  from single_kernel_mongo.utils.mongo_config import MongoConfiguration
20
17
  from single_kernel_mongo.utils.mongo_connection import MongoConnection
@@ -60,6 +57,26 @@ class MongoDBUpgradesManager:
60
57
  )
61
58
  return False
62
59
 
60
+ def are_shards_accessible(self) -> bool:
61
+ """Checks if all nodes are responsive to a simple ping, fails otherwise."""
62
+ mongos_config = self.get_cluster_mongos()
63
+ for replica_set_config in self.get_all_replica_set_configs_in_cluster(mongos_config):
64
+ for single_host in replica_set_config.hosts:
65
+ if single_host != self.state.unit_peer_data.internal_address:
66
+ logger.info(f"Checking if shard {single_host} is responding to ping")
67
+ single_replica_config = self.state.mongodb_config_for_user(
68
+ CharmedOperatorUser,
69
+ hosts={single_host},
70
+ replset=replica_set_config.replset,
71
+ )
72
+ try:
73
+ with MongoConnection(single_replica_config, direct=True) as mongod:
74
+ mongod.client.admin.command("ping")
75
+ except PyMongoError as e:
76
+ logger.info(f"{single_host} does not respond to ping: {e}")
77
+ return False
78
+ return True
79
+
63
80
  def are_nodes_healthy(self) -> bool:
64
81
  """Returns true if all nodes in the MongoDB deployment are healthy."""
65
82
  if self.state.is_sharding_component and not self.state.has_sharding_integration:
@@ -68,6 +85,9 @@ class MongoDBUpgradesManager:
68
85
  return self.are_replica_set_nodes_healthy(self.state.mongo_config)
69
86
 
70
87
  mongos_config = self.get_cluster_mongos()
88
+ if not self.are_shards_accessible():
89
+ return False
90
+
71
91
  if not self.are_shards_healthy(mongos_config):
72
92
  logger.info(
73
93
  "One or more individual shards are not healthy - do not proceed with refresh."
@@ -242,6 +262,8 @@ class MongoDBUpgradesManager:
242
262
  secondary_config = copy.deepcopy(mongodb_config)
243
263
 
244
264
  for replica_ip in mongodb_config.hosts:
265
+ if replica_ip == self.state.unit_peer_data.internal_address:
266
+ continue
245
267
  secondary_config.hosts = {replica_ip}
246
268
  with MongoConnection(secondary_config, direct=True) as direct_secondary:
247
269
  db = direct_secondary.client[db_name]
@@ -10,6 +10,7 @@ from ops.model import ActiveStatus, BlockedStatus, MaintenanceStatus, StatusBase
10
10
 
11
11
  from single_kernel_mongo.config.literals import Substrates
12
12
  from single_kernel_mongo.config.statuses import CharmStatuses, UpgradeStatuses
13
+ from single_kernel_mongo.core.operator import OperatorProtocol
13
14
  from single_kernel_mongo.core.workload import WorkloadBase
14
15
  from single_kernel_mongo.exceptions import DeployedWithoutTrustError
15
16
  from single_kernel_mongo.state.charm_state import CharmState
@@ -23,8 +24,13 @@ class MongoDBUpgradesStatusManager(ManagerStatusProtocol):
23
24
  name: str = "upgrades"
24
25
 
25
26
  def __init__(
26
- self, state: CharmState, workload: WorkloadBase, refresh: charm_refresh.Common | None
27
+ self,
28
+ dependent: OperatorProtocol,
29
+ state: CharmState,
30
+ workload: WorkloadBase,
31
+ refresh: charm_refresh.Common | None,
27
32
  ) -> None:
33
+ self.dependent = dependent
28
34
  self.state = state
29
35
  self.workload = workload
30
36
  self.refresh = refresh
@@ -73,10 +79,7 @@ class MongoDBUpgradesStatusManager(ManagerStatusProtocol):
73
79
  return status_list
74
80
 
75
81
  if self.refresh.in_progress and not self.refresh.next_unit_allowed_to_refresh:
76
- if not self.dependent.mongo_manager.mongod_ready():
77
- status_list.append(UpgradeStatuses.HEALTH_CHECK_FAILED.value)
78
- else:
79
- status_list.append(UpgradeStatuses.CLUSTER_CHECK_FAILED.value)
82
+ status_list.append(UpgradeStatuses.HEALTH_CHECK_FAILED.value)
80
83
 
81
84
  if refresh_unit_status := self.refresh.unit_status_higher_priority:
82
85
  unit_status = self._convert_ops_status_to_advanced_status(refresh_unit_status)