|
38 | 38 | OperatorUser, |
39 | 39 | ) |
40 | 40 | from charms.prometheus_k8s.v0.prometheus_scrape import MetricsEndpointProvider |
| 41 | +from data_platform_helpers.version_check import ( |
| 42 | + CrossAppVersionChecker, |
| 43 | + get_charm_revision, |
| 44 | +) |
41 | 45 | from ops.charm import ( |
42 | 46 | ActionEvent, |
43 | 47 | CharmBase, |
44 | 48 | ConfigChangedEvent, |
45 | 49 | RelationDepartedEvent, |
| 50 | + RelationEvent, |
46 | 51 | StartEvent, |
47 | 52 | UpdateStatusEvent, |
48 | 53 | ) |
|
55 | 60 | ModelError, |
56 | 61 | Relation, |
57 | 62 | RelationDataContent, |
58 | | - StatusBase, |
59 | 63 | Unit, |
60 | 64 | WaitingStatus, |
61 | 65 | ) |
@@ -93,6 +97,7 @@ def __init__(self, *args): |
93 | 97 | super().__init__(*args) |
94 | 98 |
|
95 | 99 | self.framework.observe(self.on.mongod_pebble_ready, self._on_mongod_pebble_ready) |
| 100 | + self.framework.observe(self.on.config_changed, self._on_config_changed) |
96 | 101 | self.framework.observe(self.on.start, self._on_start) |
97 | 102 | self.framework.observe(self.on.update_status, self._on_update_status) |
98 | 103 | self.framework.observe( |
@@ -138,6 +143,15 @@ def __init__(self, *args): |
138 | 143 | self.config_server = ShardingProvider(self) |
139 | 144 | self.cluster = ClusterProvider(self) |
140 | 145 |
|
| 146 | + self.version_checker = CrossAppVersionChecker( |
| 147 | + self, |
| 148 | + version=get_charm_revision(self.unit, local_version=self.get_charm_internal_revision), |
| 149 | + relations_to_check=[ |
| 150 | + Config.Relations.SHARDING_RELATIONS_NAME, |
| 151 | + Config.Relations.CONFIG_SERVER_RELATIONS_NAME, |
| 152 | + ], |
| 153 | + ) |
| 154 | + |
141 | 155 | # BEGIN: properties |
142 | 156 |
|
143 | 157 | @property |
@@ -468,16 +482,15 @@ def primary(self) -> str | None: |
468 | 482 |
|
469 | 483 | return None |
470 | 484 |
|
| 485 | + @property |
| 486 | + def get_charm_internal_revision(self) -> str: |
| 487 | + """Returns the contents of the get_charm_internal_revision file.""" |
| 488 | + with open(Config.CHARM_INTERNAL_VERSION_FILE, "r") as f: |
| 489 | + return f.read().strip() |
| 490 | + |
471 | 491 | # END: properties |
472 | 492 |
|
473 | 493 | # BEGIN: generic helper methods |
474 | | - def get_cluster_mismatched_revision_status(self) -> Optional[StatusBase]: |
475 | | - """Returns a Status if the cluster has mismatched revisions. |
476 | | -
|
477 | | - TODO implement this method as a part of sharding upgrades. |
478 | | - """ |
479 | | - return None |
480 | | - |
481 | 494 | def remote_mongos_config(self, hosts) -> MongoConfiguration: |
482 | 495 | """Generates a MongoConfiguration object for mongos in the deployment of MongoDB.""" |
483 | 496 | # mongos that are part of the cluster have the same username and password, but different |
@@ -659,25 +672,40 @@ def _on_start(self, event) -> None: |
659 | 672 | event.defer() |
660 | 673 | return |
661 | 674 |
|
662 | | - def _relation_changes_handler(self, event) -> None: |
| 675 | + def _relation_changes_handler(self, event: RelationEvent) -> None: |
663 | 676 | """Handles different relation events and updates MongoDB replica set.""" |
664 | 677 | self._connect_mongodb_exporter() |
665 | 678 | self._connect_pbm_agent() |
666 | 679 |
|
667 | | - if type(event) is RelationDepartedEvent: |
| 680 | + if isinstance(event, RelationDepartedEvent): |
668 | 681 | if event.departing_unit.name == self.unit.name: |
669 | 682 | self.unit_peer_data.setdefault("unit_departed", "True") |
670 | 683 |
|
671 | 684 | if not self.unit.is_leader(): |
672 | 685 | return |
673 | 686 |
|
| 687 | + if self.upgrade_in_progress: |
| 688 | + logger.warning( |
| 689 | + "Adding replicas during an upgrade is not supported. The charm may be in a broken, unrecoverable state" |
| 690 | + ) |
| 691 | + event.defer() |
| 692 | + return |
| 693 | + |
674 | 694 | # Admin password and keyFile should be created before running MongoDB. |
675 | 695 | # This code runs on leader_elected event before mongod_pebble_ready |
676 | 696 | self._generate_secrets() |
677 | 697 |
|
678 | 698 | if not self.db_initialised: |
679 | 699 | return |
680 | 700 |
|
| 701 | + self._reconcile_mongo_hosts_and_users(event) |
| 702 | + |
| 703 | + def _reconcile_mongo_hosts_and_users(self, event: RelationEvent) -> None: |
| 704 | + """Auxiliary function to reconcile mongo data for relation events. |
| 705 | +
|
| 706 | + Args: |
| 707 | + event: The relation event |
| 708 | + """ |
681 | 709 | with MongoDBConnection(self.mongodb_config) as mongo: |
682 | 710 | try: |
683 | 711 | replset_members = mongo.get_replset_members() |
@@ -1551,7 +1579,7 @@ def is_relation_feasible(self, rel_interface: str) -> bool: |
1551 | 1579 | ) |
1552 | 1580 | return False |
1553 | 1581 |
|
1554 | | - if revision_mismatch_status := self.get_cluster_mismatched_revision_status(): |
| 1582 | + if revision_mismatch_status := self.status.get_cluster_mismatched_revision_status(): |
1555 | 1583 | self.status.set_and_share_status(revision_mismatch_status) |
1556 | 1584 | return False |
1557 | 1585 |
|
|
0 commit comments