mongo-charms-single-kernel 1.8.7__tar.gz → 1.8.9__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 (94) hide show
  1. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/PKG-INFO +1 -1
  2. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/pyproject.toml +2 -8
  3. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/config/literals.py +8 -3
  4. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/config/models.py +12 -0
  5. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/config/relations.py +2 -1
  6. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/config/statuses.py +127 -20
  7. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/core/operator.py +68 -1
  8. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/core/structured_config.py +2 -0
  9. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/core/workload.py +10 -4
  10. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/events/cluster.py +5 -0
  11. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/events/sharding.py +3 -1
  12. mongo_charms_single_kernel-1.8.9/single_kernel_mongo/events/tls.py +242 -0
  13. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/exceptions.py +0 -8
  14. mongo_charms_single_kernel-1.8.9/single_kernel_mongo/lib/charms/operator_libs_linux/v1/systemd.py +288 -0
  15. mongo_charms_single_kernel-1.8.9/single_kernel_mongo/lib/charms/tls_certificates_interface/v4/tls_certificates.py +1995 -0
  16. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/managers/cluster.py +70 -28
  17. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/managers/config.py +14 -8
  18. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/managers/mongo.py +1 -1
  19. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/managers/mongodb_operator.py +53 -56
  20. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/managers/mongos_operator.py +18 -20
  21. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/managers/sharding.py +154 -127
  22. mongo_charms_single_kernel-1.8.9/single_kernel_mongo/managers/tls.py +413 -0
  23. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/state/charm_state.py +39 -16
  24. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/state/cluster_state.py +8 -0
  25. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/state/config_server_state.py +9 -0
  26. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/state/tls_state.py +39 -12
  27. mongo_charms_single_kernel-1.8.9/single_kernel_mongo/templates/enable-transparent-huge-pages.service.j2 +14 -0
  28. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/utils/helpers.py +4 -19
  29. mongo_charms_single_kernel-1.8.7/single_kernel_mongo/events/tls.py +0 -216
  30. mongo_charms_single_kernel-1.8.7/single_kernel_mongo/lib/charms/tls_certificates_interface/v3/tls_certificates.py +0 -2123
  31. mongo_charms_single_kernel-1.8.7/single_kernel_mongo/managers/tls.py +0 -396
  32. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/LICENSE +0 -0
  33. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/README.md +0 -0
  34. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/__init__.py +0 -0
  35. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/abstract_charm.py +0 -0
  36. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/config/__init__.py +0 -0
  37. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/core/__init__.py +0 -0
  38. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/core/abstract_upgrades_v3.py +0 -0
  39. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/core/k8s_workload.py +0 -0
  40. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/core/kubernetes_upgrades_v3.py +0 -0
  41. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/core/machine_upgrades_v3.py +0 -0
  42. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/core/secrets.py +0 -0
  43. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/core/version_checker.py +0 -0
  44. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/core/vm_workload.py +0 -0
  45. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/events/__init__.py +0 -0
  46. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/events/backups.py +0 -0
  47. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/events/database.py +0 -0
  48. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/events/ldap.py +0 -0
  49. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/events/lifecycle.py +0 -0
  50. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/events/primary_action.py +0 -0
  51. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/lib/charms/certificate_transfer_interface/v0/certificate_transfer.py +0 -0
  52. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/lib/charms/data_platform_libs/v0/data_interfaces.py +0 -0
  53. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/lib/charms/data_platform_libs/v0/s3.py +0 -0
  54. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/lib/charms/glauth_k8s/v0/ldap.py +0 -0
  55. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/lib/charms/grafana_agent/v0/cos_agent.py +0 -0
  56. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/lib/charms/grafana_k8s/v0/grafana_dashboard.py +0 -0
  57. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/lib/charms/loki_k8s/v0/loki_push_api.py +0 -0
  58. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/lib/charms/operator_libs_linux/v0/sysctl.py +0 -0
  59. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/lib/charms/operator_libs_linux/v2/snap.py +0 -0
  60. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/lib/charms/prometheus_k8s/v0/prometheus_scrape.py +0 -0
  61. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/managers/__init__.py +0 -0
  62. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/managers/backups.py +0 -0
  63. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/managers/k8s.py +0 -0
  64. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/managers/ldap.py +0 -0
  65. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/managers/observability.py +0 -0
  66. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/managers/upgrade_v3.py +0 -0
  67. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/managers/upgrade_v3_status.py +0 -0
  68. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/observability_rules/__init__.py +0 -0
  69. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/observability_rules/grafana_dashboards/MongoDB_Cluster_Summary.json +0 -0
  70. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/observability_rules/grafana_dashboards/MongoDB_ReplSet_Summary.json +0 -0
  71. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/observability_rules/k8s_prometheus_alert_rules/percona-mongodb-exporter.rule +0 -0
  72. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/observability_rules/loki/.gitkeep +0 -0
  73. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/observability_rules/vm_prometheus_alert_rules/percona-mongodb-exporter.yml +0 -0
  74. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/state/__init__.py +0 -0
  75. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/state/abstract_state.py +0 -0
  76. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/state/app_peer_state.py +0 -0
  77. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/state/ldap_state.py +0 -0
  78. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/state/models.py +0 -0
  79. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/state/unit_peer_state.py +0 -0
  80. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/templates/__init__.py +0 -0
  81. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/templates/ldap.conf.j2 +0 -0
  82. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/templates/logrotate.j2 +0 -0
  83. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/utils/__init__.py +0 -0
  84. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/utils/event_helpers.py +0 -0
  85. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/utils/mongo_config.py +0 -0
  86. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/utils/mongo_connection.py +0 -0
  87. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/utils/mongo_error_codes.py +0 -0
  88. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/utils/mongodb_users.py +0 -0
  89. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/workload/__init__.py +0 -0
  90. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/workload/backup_workload.py +0 -0
  91. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/workload/log_rotate_workload.py +0 -0
  92. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/workload/mongodb_workload.py +0 -0
  93. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/single_kernel_mongo/workload/mongos_workload.py +0 -0
  94. {mongo_charms_single_kernel-1.8.7 → mongo_charms_single_kernel-1.8.9}/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.7
3
+ Version: 1.8.9
4
4
  Summary: Shared and reusable code for Mongo-related charms
5
5
  License-Expression: Apache-2.0
6
6
  License-File: LICENSE
@@ -38,9 +38,9 @@ dependencies = [
38
38
  "boto3 (~=1.37.12)",
39
39
  "mypy-boto3-s3 (~=1.37.0)",
40
40
  "python-ldap",
41
- "charm-refresh (>=3.1.0.2,<4.0.0.0)",
41
+ "charm-refresh (>=3.1.0.2,<4.0.0.0)"
42
42
  ]
43
- version = "1.8.7"
43
+ version = "1.8.9"
44
44
 
45
45
  [project.urls]
46
46
  homepage = "https://github.com/canonical/mongo-single-kernel-library"
@@ -137,12 +137,6 @@ httpx = "*"
137
137
  boto3 = "^1.37.12"
138
138
  mypy-boto3-s3 = "^1.37.0"
139
139
 
140
- [tool.poetry.group.build-refresh-version]
141
- optional = true
142
-
143
- [tool.poetry.group.build-refresh-version.dependencies]
144
- charm-refresh-build-version = "^0.4.0"
145
-
146
140
  [tool.ruff]
147
141
  target-version = "py310"
148
142
  line-length = 100
@@ -34,6 +34,13 @@ class Scope(str, Enum):
34
34
  UNIT = "unit"
35
35
 
36
36
 
37
+ class TLSType(str, Enum):
38
+ """TLS types."""
39
+
40
+ PEER = "peer"
41
+ CLIENT = "client"
42
+
43
+
37
44
  class MongoPorts(IntEnum):
38
45
  """The default Mongo ports."""
39
46
 
@@ -93,9 +100,7 @@ PBM_RESTART_DELAY = 5
93
100
  FEATURE_VERSION = "8.0"
94
101
 
95
102
 
96
- OS_REQUIREMENTS = {
97
- "vm.max_map_count": "262144",
98
- }
103
+ OS_REQUIREMENTS = {"vm.max_map_count": "262144", "vm.overcommit_memory": "1"}
99
104
 
100
105
  TRUST_STORE_PATH = Path("/usr/local/share/ca-certificates")
101
106
 
@@ -62,6 +62,18 @@ class LdapConfig:
62
62
  LDAP_CONFIG = LdapConfig()
63
63
 
64
64
 
65
+ @dataclass(frozen=True)
66
+ class THPConfig:
67
+ """Configuration for transparent huge tables."""
68
+
69
+ service_template: Traversable = TEMPLATE_DIRECTORY / "enable-transparent-huge-pages.service.j2"
70
+ service_file_path: Path = Path("/etc/systemd/system/enable-transparent-huge-pages.service")
71
+ service_name = "enable-transparent-huge-pages"
72
+
73
+
74
+ THP_CONFIG = THPConfig()
75
+
76
+
65
77
  @dataclass(frozen=True)
66
78
  class AuditLogConfig:
67
79
  """Audit log related configuration."""
@@ -35,7 +35,8 @@ class Scopes(str, Enum):
35
35
  class ExternalRequirerRelations(str, Enum):
36
36
  """The relations we require externally."""
37
37
 
38
- TLS = "certificates"
38
+ CLIENT_TLS = "client-certificates"
39
+ PEER_TLS = "peer-certificates"
39
40
  S3_CREDENTIALS = "s3-credentials"
40
41
  LDAP = "ldap"
41
42
  LDAP_CERT = "ldap-certificate-transfer"
@@ -118,24 +118,45 @@ class MongosStatuses(Enum):
118
118
  check="Config validation failed.",
119
119
  action="Set the expose-external config to a valid value: `nodeport` or `none`.",
120
120
  )
121
- MISSING_TLS_REL = StatusObject(
121
+ MISSING_PEER_TLS_REL = StatusObject(
122
122
  status="blocked",
123
- message="TLS must be enabled in mongos, since it is enabled on the config-server in the cluster relation.",
124
- short_message="Missing certificates relation.",
123
+ message="Peer TLS must be enabled in mongos, since it is enabled on the config-server in the cluster relation.",
124
+ short_message="Missing peer-certificates relation.",
125
125
  check="Relation validation failed.",
126
- action="Add the certificates relation (tls-certificates interface) to mongos.",
126
+ action="Add the peer-certificates relation to mongos.",
127
127
  )
128
- INVALID_TLS_REL = StatusObject(
128
+ INVALID_PEER_TLS_REL = StatusObject(
129
129
  status="blocked",
130
- message="TLS must be disabled in mongos, since it is disabled on the config-server in the cluster relation.",
131
- short_message="Invalid certificates relation.",
130
+ message="Peer TLS must be disabled in mongos, since it is disabled on the config-server in the cluster relation.",
131
+ short_message="Invalid peer-certificates relation.",
132
132
  check="Relation validation failed.",
133
- action="Remove the certificates relation (tls-certificates interface) from this application.",
133
+ action="Remove the peer-certificates relation from this application.",
134
134
  )
135
- CA_MISMATCH = StatusObject(
135
+ MISSING_CLIENT_TLS_REL = StatusObject(
136
136
  status="blocked",
137
- message="The mongos CA and Config-Server CA don't match.",
138
- short_message="CA mismatch.",
137
+ message="Client TLS must be enabled in mongos, since it is enabled on the config-server in the cluster relation.",
138
+ short_message="Missing client-certificates relation.",
139
+ check="Relation validation failed.",
140
+ action="Add the client-certificates relation to mongos.",
141
+ )
142
+ INVALID_CLIENT_TLS_REL = StatusObject(
143
+ status="blocked",
144
+ message="Client TLS must be disabled in mongos, since it is disabled on the config-server in the cluster relation.",
145
+ short_message="Invalid client-certificates relation.",
146
+ check="Relation validation failed.",
147
+ action="Remove the client-certificates relation from this application.",
148
+ )
149
+ PEER_CA_MISMATCH = StatusObject(
150
+ status="blocked",
151
+ message="The mongos peer CA and Config-Server peer CA don't match.",
152
+ short_message="Peer CA mismatch.",
153
+ check="Relation validation failed.",
154
+ action="Verify the certificates relations. Use the same CA for all cluster components.",
155
+ )
156
+ CLIENT_CA_MISMATCH = StatusObject(
157
+ status="blocked",
158
+ message="The mongos client CA and Config-Server client CA don't match.",
159
+ short_message="Client CA mismatch.",
139
160
  check="Relation validation failed.",
140
161
  action="Verify the certificates relations. Use the same CA for all cluster components.",
141
162
  )
@@ -153,6 +174,27 @@ class MongosStatuses(Enum):
153
174
  status="maintenance", message="Starting mongos.", running="blocking"
154
175
  )
155
176
 
177
+ @classmethod
178
+ def missing_tls(cls, internal: bool) -> StatusObject:
179
+ """Correct status."""
180
+ if internal:
181
+ return cls.MISSING_PEER_TLS_REL.value
182
+ return cls.MISSING_CLIENT_TLS_REL.value
183
+
184
+ @classmethod
185
+ def invalid_tls(cls, internal: bool) -> StatusObject:
186
+ """Correct status."""
187
+ if internal:
188
+ return cls.INVALID_PEER_TLS_REL.value
189
+ return cls.INVALID_CLIENT_TLS_REL.value
190
+
191
+ @classmethod
192
+ def incompatible_ca(cls, internal: bool) -> StatusObject:
193
+ """Correct status."""
194
+ if internal:
195
+ return cls.PEER_CA_MISMATCH.value
196
+ return cls.CLIENT_CA_MISMATCH.value
197
+
156
198
 
157
199
  class CharmStatuses(Enum):
158
200
  """Charm Statuses."""
@@ -182,11 +224,28 @@ class CharmStatuses(Enum):
182
224
  class TLSStatuses(Enum):
183
225
  """TLS statuses."""
184
226
 
185
- # RUNNING statuses:
186
- DISABLING_TLS = StatusObject(
227
+ INVALID_PEER_PRIVATE_KEY = StatusObject(
228
+ status="blocked",
229
+ message="Invalid peer private key",
230
+ check="Peer private key format validation failed",
231
+ action="Update the peer private key secret.",
232
+ )
233
+ INVALID_CLIENT_PRIVATE_KEY = StatusObject(
234
+ status="blocked",
235
+ message="Invalid client private key",
236
+ check="Client private key format validation failed.",
237
+ action="Update the client privatekey secret.",
238
+ )
239
+ DISABLING_PEER_TLS = StatusObject(
187
240
  status="maintenance",
188
- message="Disabling TLS...",
189
- check="Certificates relation (tls-certificates interface) removed.",
241
+ message="Disabling peer TLS...",
242
+ check="Peer certificates relation (tls-certificates interface) removed.",
243
+ running="blocking",
244
+ )
245
+ DISABLING_CLIENT_TLS = StatusObject(
246
+ status="maintenance",
247
+ message="Disabling client TLS...",
248
+ check="Client certificates relation (tls-certificates interface) removed.",
190
249
  running="blocking",
191
250
  )
192
251
  # Enabling TLS takes a while because we wait for multiple certs so it's
@@ -343,12 +402,39 @@ class ConfigServerStatuses(Enum):
343
402
  class ShardStatuses(Enum):
344
403
  """Shard statuses."""
345
404
 
346
- REQUIRES_TLS = StatusObject(status="blocked", message="Shard requires TLS to be enabled.")
347
- REQUIRES_NO_TLS = StatusObject(
348
- status="blocked", message="Shard has TLS enabled, but config-server does not."
405
+ MISSING_PEER_TLS_REL = StatusObject(
406
+ status="blocked", message="Shard requires peer TLS to be enabled."
349
407
  )
350
- CA_MISMATCH = StatusObject(
351
- status="blocked", message="Shard CA and Config-Server CA don't match."
408
+ INVALID_PEER_TLS_REL = StatusObject(
409
+ status="blocked",
410
+ message="Peer TLS must be disabled in shard, since it is disabled in the related config-server.",
411
+ short_message="Invalid peer-certificates relation.",
412
+ check="Relation validation failed.",
413
+ action="Align the peer TLS configuration in all the cluster components: remove the peer-certificates relation from the shard.",
414
+ )
415
+ MISSING_CLIENT_TLS_REL = StatusObject(
416
+ status="blocked", message="Shard requires client TLS to be enabled."
417
+ )
418
+ INVALID_CLIENT_TLS_REL = StatusObject(
419
+ status="blocked",
420
+ message="Peer TLS must be disabled in shard, since it is disabled in the related config-server.",
421
+ short_message="Invalid client-certificates relation.",
422
+ check="Relation validation failed.",
423
+ action="Align the peer TLS configuration in all the cluster components: remove the client-certificates relation from the shard.",
424
+ )
425
+ PEER_CA_MISMATCH = StatusObject(
426
+ status="blocked",
427
+ message="Shard internal CA and Config-Server internal CA don't match.",
428
+ short_message="Peer CA mismatch.",
429
+ check="Relation validation failed.",
430
+ action="Verify the peer-certificates relations. Use the same CA for all cluster components.",
431
+ )
432
+ CLIENT_CA_MISMATCH = StatusObject(
433
+ status="blocked",
434
+ message="Shard client CA and Config-Server client CA don't match.",
435
+ short_message="Client CA mismatch.",
436
+ check="Relation validation failed.",
437
+ action="Verify the client-certificates relations. Use the same CA for all cluster components.",
352
438
  )
353
439
 
354
440
  MISSING_CONF_SERVER_REL = StatusObject(
@@ -399,6 +485,27 @@ class ShardStatuses(Enum):
399
485
  message=f"Charm revision ({current_charms_version}{local_identifier}) is not up-to date with config-server.",
400
486
  )
401
487
 
488
+ @classmethod
489
+ def missing_tls(cls, internal: bool) -> StatusObject:
490
+ """Correct status."""
491
+ if internal:
492
+ return cls.MISSING_PEER_TLS_REL.value
493
+ return cls.MISSING_CLIENT_TLS_REL.value
494
+
495
+ @classmethod
496
+ def invalid_tls(cls, internal: bool) -> StatusObject:
497
+ """Correct status."""
498
+ if internal:
499
+ return cls.INVALID_PEER_TLS_REL.value
500
+ return cls.INVALID_CLIENT_TLS_REL.value
501
+
502
+ @classmethod
503
+ def incompatible_ca(cls, internal: bool) -> StatusObject:
504
+ """Correct status."""
505
+ if internal:
506
+ return cls.PEER_CA_MISMATCH.value
507
+ return cls.CLIENT_CA_MISMATCH.value
508
+
402
509
 
403
510
  class MongodStatuses(Enum):
404
511
  """MongoD statuses."""
@@ -22,6 +22,7 @@ from pathlib import Path
22
22
  from typing import TYPE_CHECKING, ClassVar, TypeAlias
23
23
 
24
24
  import charm_refresh
25
+ import jinja2
25
26
  from data_platform_helpers.advanced_statuses.models import StatusObject
26
27
  from data_platform_helpers.advanced_statuses.protocol import ManagerStatusProtocol
27
28
  from ops.charm import RelationDepartedEvent
@@ -29,17 +30,27 @@ from ops.framework import Object
29
30
  from ops.model import Relation, Unit
30
31
 
31
32
  from single_kernel_mongo.config.literals import (
33
+ OS_REQUIREMENTS,
32
34
  TRUST_STORE_PATH,
33
35
  Scope,
34
36
  Substrates,
35
37
  TrustStoreFiles,
36
38
  )
37
- from single_kernel_mongo.config.models import CharmSpec, LogRotateConfig
39
+ from single_kernel_mongo.config.models import SNAP_NAME, THP_CONFIG, CharmSpec, LogRotateConfig
40
+ from single_kernel_mongo.core.structured_config import MongoConfigModel
38
41
  from single_kernel_mongo.events.ldap import LDAPEventHandler
39
42
  from single_kernel_mongo.exceptions import (
40
43
  DeferrableFailedHookChecksError,
41
44
  NonDeferrableFailedHookChecksError,
42
45
  )
46
+ from single_kernel_mongo.lib.charms.operator_libs_linux.v0 import sysctl
47
+ from single_kernel_mongo.lib.charms.operator_libs_linux.v1.systemd import (
48
+ SystemdError,
49
+ daemon_reload,
50
+ service_disable,
51
+ service_enable,
52
+ service_start,
53
+ )
43
54
  from single_kernel_mongo.managers.config import FileBasedConfigManager
44
55
  from single_kernel_mongo.managers.mongo import MongoManager
45
56
  from single_kernel_mongo.state.charm_state import CharmState
@@ -50,6 +61,7 @@ if TYPE_CHECKING:
50
61
  from single_kernel_mongo.abstract_charm import AbstractMongoCharm
51
62
  from single_kernel_mongo.events.database import DatabaseEventsHandler
52
63
  from single_kernel_mongo.events.tls import TLSEventsHandler
64
+ from single_kernel_mongo.lib.charms.operator_libs_linux.v0.sysctl import Config
53
65
  from single_kernel_mongo.managers.ldap import LDAPManager
54
66
  from single_kernel_mongo.managers.tls import TLSManager
55
67
  from single_kernel_mongo.managers.upgrade_v3 import MongoDBUpgradesManager
@@ -89,11 +101,18 @@ class OperatorProtocol(ABC, Object, ManagerStatusProtocol):
89
101
  client_events: DatabaseEventsHandler
90
102
  tls_events: TLSEventsHandler
91
103
  ldap_events: LDAPEventHandler
104
+ sysctl_config: Config
92
105
 
93
106
  if TYPE_CHECKING:
94
107
 
95
108
  def __init__(self, dependent: AbstractMongoCharm): ...
96
109
 
110
+ @property
111
+ @abstractmethod
112
+ def config(self) -> MongoConfigModel:
113
+ """The pydantic model of the config."""
114
+ ...
115
+
97
116
  @property
98
117
  @abstractmethod
99
118
  def components(self) -> tuple[ManagerStatusProtocol, ...]:
@@ -280,6 +299,17 @@ class OperatorProtocol(ABC, Object, ManagerStatusProtocol):
280
299
  f"{path}",
281
300
  ]
282
301
  )
302
+
303
+ if self.substrate == Substrates.VM:
304
+ self.workload.exec(
305
+ [
306
+ "chown",
307
+ "-R",
308
+ f"{self.workload.users.user}:{self.workload.users.group}",
309
+ f"{self.workload.paths.common_path}",
310
+ ]
311
+ )
312
+
283
313
  for path in (
284
314
  self.workload.paths.config_file,
285
315
  self.workload.paths.mongos_config_file,
@@ -315,6 +345,43 @@ class OperatorProtocol(ABC, Object, ManagerStatusProtocol):
315
345
  # Restart the service
316
346
  self.restart_charm_services(force=True)
317
347
 
348
+ def write_thp_config_file(self):
349
+ """Writes the unit file to enable Transparent Huge Pages."""
350
+ data = THP_CONFIG.service_template.read_text()
351
+ template = jinja2.Template(data)
352
+
353
+ rendered_template = template.render(
354
+ service_file=f"snap.{SNAP_NAME}.{self.workload.service}.service"
355
+ )
356
+ self.workload.write(path=THP_CONFIG.service_file_path, content=rendered_template)
357
+ daemon_reload()
358
+ service_enable(THP_CONFIG.service_name)
359
+ service_start(THP_CONFIG.service_name)
360
+
361
+ def _set_os_config(self) -> None:
362
+ """Sets sysctl config for mongodb."""
363
+ try:
364
+ self.sysctl_config.configure(OS_REQUIREMENTS)
365
+ except (sysctl.ApplyError, sysctl.ValidationError, sysctl.CommandError) as e:
366
+ # we allow events to continue in the case that we are not able to correctly configure
367
+ # sysctl config, since we can still run the workload with wrong sysctl parameters
368
+ # even if it is not optimal.
369
+ logger.error(f"Error setting values on sysctl parameters: {e.message}")
370
+ # containers share the kernel with the host system, and some sysctl parameters are
371
+ # set at kernel level.
372
+ logger.warning("sysctl params cannot be set. Is the machine running on a container?")
373
+ try:
374
+ self.write_thp_config_file()
375
+ except SystemdError as e:
376
+ # we allow events to continue in the case that we are not able to correctly configure
377
+ # sysctl config, since we can still run the workload with wrong kernel parameters
378
+ # even if it is not optimal.
379
+ logger.error(f"Error setting values on kernel parameters: {e.args}")
380
+ # containers share the kernel with the host system, and some sysctl parameters are
381
+ # set at kernel level.
382
+ logger.warning("kernel params cannot be set. Is the machine running on a container?")
383
+ service_disable(THP_CONFIG.service_name)
384
+
318
385
  def build_local_tls_directory(self) -> None:
319
386
  """On Kubernetes, we need the local configuration directory.
320
387
 
@@ -100,6 +100,8 @@ class MongoConfigModel(BaseConfigModel):
100
100
  role: SerializeLiteralAsStr[MongoDBRoles]
101
101
  ldap_user_to_dn_mapping: str | None = Field(default=None, alias="ldap-user-to-dn-mapping")
102
102
  ldap_query_template: str | None = Field(default=None, alias="ldap-query-template")
103
+ tls_peer_private_key_id: str | None = Field(default=None, alias="tls-peer-private-key")
104
+ tls_client_private_key_id: str | None = Field(default=None, alias="tls-client-private-key")
103
105
 
104
106
  @field_validator("expose_external", mode="before")
105
107
  @classmethod
@@ -93,15 +93,21 @@ class MongoPaths:
93
93
  return Path(f"{self.conf_path}/internal-ca.crt")
94
94
 
95
95
  @property
96
- def tls_files(self) -> set[Path]:
97
- """Set of all TLS files."""
96
+ def tls_peer_files(self) -> set[Path]:
97
+ """Set of peer TLS files."""
98
98
  return {
99
- self.ext_pem_file,
100
- self.ext_ca_file,
101
99
  self.int_pem_file,
102
100
  self.int_ca_file,
103
101
  }
104
102
 
103
+ @property
104
+ def tls_client_files(self) -> set[Path]:
105
+ """Set of client TLS files."""
106
+ return {
107
+ self.ext_pem_file,
108
+ self.ext_ca_file,
109
+ }
110
+
105
111
  @property
106
112
  def ldap_path(self) -> Path:
107
113
  """The LDAP conf path."""
@@ -136,6 +136,11 @@ class ClusterMongosEventHandler(Object):
136
136
  def _on_relation_created(self, event: RelationCreatedEvent) -> None:
137
137
  """Relation created event handler."""
138
138
  self.manager.set_relation_created_status()
139
+ # Edge condition: mongos was integrated with the certificates provider
140
+ # before being integrated with the config-server. We trigger the refresh
141
+ # of the certificates to use the config-server as CSR subject.
142
+ if self.manager.state.peer_tls_relation or self.manager.state.client_tls_relation:
143
+ self.dependent.tls_events.refresh_certificates()
139
144
 
140
145
  def _on_database_created(self, event: DatabaseCreatedEvent) -> None:
141
146
  """Database Created event handler.
@@ -162,8 +162,10 @@ class ShardEventHandler(Object):
162
162
  """SecretChanged event handler, which is used to propagate the updated passwords."""
163
163
  try:
164
164
  self.manager.handle_secret_changed(event.secret.label or "")
165
- except (NotReadyError, FailedToUpdateCredentialsError):
165
+ except (NotReadyError, FailedToUpdateCredentialsError, DeferrableFailedHookChecksError):
166
166
  event.defer()
167
+ except NonDeferrableFailedHookChecksError as e:
168
+ logger.info(f"Skipping {str(type(event))}: {str(e)}")
167
169
  except WaitingForSecretsError:
168
170
  logger.info("Missing secrets, ignoring")
169
171