Skip to content

Commit 0e93ef5

Browse files
WIP: Expose read-write and read-only endpoints when related to data-integrator
1 parent fd35e6c commit 0e93ef5

File tree

10 files changed

+2302
-31
lines changed

10 files changed

+2302
-31
lines changed

charmcraft.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ parts:
2727
echo 'ERROR: Use "tox run -e build" instead of calling "charmcraft pack" directly' >&2
2828
exit 1
2929
fi
30+
build-packages:
31+
- libffi-dev
32+
- libssl-dev
33+
- pkg-config
34+
- rustc
35+
- cargo
3036
charm-entrypoint: src/machine_charm.py
3137
prime:
3238
- charm_version

lib/charms/tls_certificates_interface/v2/tls_certificates.py

Lines changed: 1959 additions & 0 deletions
Large diffs are not rendered by default.

metadata.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ requires:
3838
juju-info:
3939
interface: juju-info
4040
scope: container
41+
certificates:
42+
interface: tls-certificates
43+
optional: true
44+
limit: 1
4145
peers:
4246
cos:
4347
interface: cos

poetry.lock

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

pyproject.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ jinja2 = "^3.1.2"
1818
[tool.poetry.group.charm-libs.dependencies]
1919
# data_platform_libs/v0/data_interfaces.py
2020
ops = ">=2.0.0"
21+
# tls_certificates_interface/v1/tls_certificates.py
22+
cryptography = "*"
23+
jsonschema = "*"
2124
# grafana_agent/v0/cos_agent.py
2225
pydantic = "<2"
2326
cosl = "*"

src/abstract_charm.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,9 @@ def _tls_certificate(self) -> str:
116116
# TODO VM TLS: Update property after implementing TLS on machine_charm
117117
return None
118118

119+
def is_exposed(self, relation=None) -> bool:
120+
return self._database_provides.is_exposed(relation)
121+
119122
def _cos_exporter_config(self, event) -> typing.Optional[relations.cos.ExporterConfig]:
120123
"""Returns the exporter config for MySQLRouter exporter if cos relation exists"""
121124
cos_relation_exists = self._cos.relation_exists and not self._cos.is_relation_breaking(

src/machine_charm.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@
2727
class MachineSubordinateRouterCharm(abstract_charm.MySQLRouterCharm):
2828
"""MySQL Router machine subordinate charm"""
2929

30+
READ_WRITE_PORT = 6446
31+
READ_ONLY_PORT = 6447
32+
3033
def __init__(self, *args) -> None:
3134
super().__init__(*args)
3235
# DEPRECATED shared-db: Enable legacy "mysql-shared" interface
@@ -67,12 +70,21 @@ def _logrotate(self) -> machine_logrotate.LogRotate:
6770
def _cos(self) -> relations.cos.COSRelation:
6871
return self._cos_relation
6972

73+
@property
74+
def _host_address(self) -> str:
75+
"""The host address for the machine."""
76+
return self.model.get_binding(upgrade.PEER_RELATION_ENDPOINT_NAME).network.bind_address
77+
7078
@property
7179
def _read_write_endpoint(self) -> str:
80+
if self._database_provides.is_exposed():
81+
return f"{self._host_address}:{self.READ_WRITE_PORT}"
7282
return f'file://{self._container.path("/run/mysqlrouter/mysql.sock")}'
7383

7484
@property
7585
def _read_only_endpoint(self) -> str:
86+
if self._database_provides.is_exposed():
87+
return f"{self._host_address}:{self.READ_ONLY_PORT}"
7688
return f'file://{self._container.path("/run/mysqlrouter/mysqlro.sock")}'
7789

7890
# =======================
@@ -119,6 +131,10 @@ def _on_force_upgrade_action(self, event: ops.ActionEvent) -> None:
119131
event.set_results({"result": f"Forcefully upgraded {self.unit.name}"})
120132
logger.debug("Forced upgrade")
121133

134+
def reconcile(self, event=None) -> None:
135+
self.database_provides.reconcile_ports()
136+
super().reconcile(event=event)
137+
122138

123139
if __name__ == "__main__":
124140
ops.main.main(MachineSubordinateRouterCharm)

src/relations/database_providers_wrapper.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ def __init__(
3838
charm_
3939
)
4040

41+
def is_exposed(self, _) -> bool:
42+
"""Whether the relation is exposed"""
43+
return self._database_provides.is_exposed()
44+
45+
def reconcile_ports(self) -> None:
46+
"""Reconcile ports for this unit"""
47+
self._database_provides.reconcile_ports()
48+
4149
def reconcile_users(
4250
self,
4351
*,

src/relations/database_provides.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,8 @@ class RelationEndpoint:
162162

163163
def __init__(self, charm_: "abstract_charm.MySQLRouterCharm") -> None:
164164
self._interface = data_interfaces.DatabaseProvides(charm_, relation_name=self._NAME)
165+
self._charm = charm_
166+
165167
charm_.framework.observe(charm_.on[self._NAME].relation_created, charm_.reconcile)
166168
charm_.framework.observe(self._interface.on.database_requested, charm_.reconcile)
167169
charm_.framework.observe(charm_.on[self._NAME].relation_broken, charm_.reconcile)
@@ -179,6 +181,21 @@ def _shared_users(self) -> typing.List[_RelationWithSharedUser]:
179181
pass
180182
return shared_users
181183

184+
def is_exposed(self) -> bool:
185+
"""Whether the relation is exposed."""
186+
relation_data = self._interface.fetch_relation_data(fields=["external-node-connectivity"])
187+
return any(
188+
[data.get("external-node-connectivity") == "true" for data in relation_data.values()]
189+
)
190+
191+
def reconcile_ports(self) -> None:
192+
"""Reconcile ports for this unit"""
193+
if self.is_exposed():
194+
ports = [self._charm.READ_WRITE_PORT, self._charm.READ_ONLY_PORT]
195+
else:
196+
ports = []
197+
self._charm.unit.set_ports(ports)
198+
182199
def reconcile_users(
183200
self,
184201
*,

src/socket_workload.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,11 @@ class AuthenticatedSocketWorkload(workload.AuthenticatedWorkload):
2020
# TODO python3.10 min version: Use `list` instead of `typing.List`
2121
def _get_bootstrap_command(self, password: str) -> typing.List[str]:
2222
command = super()._get_bootstrap_command(password)
23+
bind_address = "0.0.0.0" if self._charm._database_provides.is_exposed() else "127.0.0.1"
2324
command.extend(
2425
[
2526
"--conf-bind-address",
26-
"127.0.0.1",
27+
bind_address,
2728
"--conf-use-sockets",
2829
# For unix sockets, authentication fails on first connection if this option is not
2930
# set. Workaround for https://bugs.mysql.com/bug.php?id=107291

0 commit comments

Comments
 (0)