mongo-charms-single-kernel 1.8.7__py3-none-any.whl → 1.8.9__py3-none-any.whl
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.
- {mongo_charms_single_kernel-1.8.7.dist-info → mongo_charms_single_kernel-1.8.9.dist-info}/METADATA +1 -1
- {mongo_charms_single_kernel-1.8.7.dist-info → mongo_charms_single_kernel-1.8.9.dist-info}/RECORD +30 -28
- single_kernel_mongo/config/literals.py +8 -3
- single_kernel_mongo/config/models.py +12 -0
- single_kernel_mongo/config/relations.py +2 -1
- single_kernel_mongo/config/statuses.py +127 -20
- single_kernel_mongo/core/operator.py +68 -1
- single_kernel_mongo/core/structured_config.py +2 -0
- single_kernel_mongo/core/workload.py +10 -4
- single_kernel_mongo/events/cluster.py +5 -0
- single_kernel_mongo/events/sharding.py +3 -1
- single_kernel_mongo/events/tls.py +183 -157
- single_kernel_mongo/exceptions.py +0 -8
- single_kernel_mongo/lib/charms/operator_libs_linux/v1/systemd.py +288 -0
- single_kernel_mongo/lib/charms/tls_certificates_interface/v4/tls_certificates.py +1995 -0
- single_kernel_mongo/managers/cluster.py +70 -28
- single_kernel_mongo/managers/config.py +14 -8
- single_kernel_mongo/managers/mongo.py +1 -1
- single_kernel_mongo/managers/mongodb_operator.py +53 -56
- single_kernel_mongo/managers/mongos_operator.py +18 -20
- single_kernel_mongo/managers/sharding.py +154 -127
- single_kernel_mongo/managers/tls.py +223 -206
- single_kernel_mongo/state/charm_state.py +39 -16
- single_kernel_mongo/state/cluster_state.py +8 -0
- single_kernel_mongo/state/config_server_state.py +9 -0
- single_kernel_mongo/state/tls_state.py +39 -12
- single_kernel_mongo/templates/enable-transparent-huge-pages.service.j2 +14 -0
- single_kernel_mongo/utils/helpers.py +4 -19
- single_kernel_mongo/lib/charms/tls_certificates_interface/v3/tls_certificates.py +0 -2123
- {mongo_charms_single_kernel-1.8.7.dist-info → mongo_charms_single_kernel-1.8.9.dist-info}/WHEEL +0 -0
- {mongo_charms_single_kernel-1.8.7.dist-info → mongo_charms_single_kernel-1.8.9.dist-info}/licenses/LICENSE +0 -0
|
@@ -212,9 +212,14 @@ class CharmState(Object, StatusesStateProtocol):
|
|
|
212
212
|
return set(self.model.relations[RelationNames.CONFIG_SERVER.value])
|
|
213
213
|
|
|
214
214
|
@property
|
|
215
|
-
def
|
|
216
|
-
"""The TLS relation."""
|
|
217
|
-
return self.model.get_relation(ExternalRequirerRelations.
|
|
215
|
+
def client_tls_relation(self) -> Relation | None:
|
|
216
|
+
"""The client TLS relation if it exists."""
|
|
217
|
+
return self.model.get_relation(ExternalRequirerRelations.CLIENT_TLS.value)
|
|
218
|
+
|
|
219
|
+
@property
|
|
220
|
+
def peer_tls_relation(self) -> Relation | None:
|
|
221
|
+
"""The peer TLS relation if it exists."""
|
|
222
|
+
return self.model.get_relation(ExternalRequirerRelations.PEER_TLS.value)
|
|
218
223
|
|
|
219
224
|
@property
|
|
220
225
|
def s3_relation(self) -> Relation | None:
|
|
@@ -342,7 +347,11 @@ class CharmState(Object, StatusesStateProtocol):
|
|
|
342
347
|
@property
|
|
343
348
|
def tls(self) -> TLSState:
|
|
344
349
|
"""A view of the TLS status from the local unit databag."""
|
|
345
|
-
return TLSState(
|
|
350
|
+
return TLSState(
|
|
351
|
+
peer_relation=self.peer_tls_relation,
|
|
352
|
+
client_relation=self.client_tls_relation,
|
|
353
|
+
secrets=self.secrets,
|
|
354
|
+
)
|
|
346
355
|
|
|
347
356
|
@property
|
|
348
357
|
def ldap(self) -> LdapState:
|
|
@@ -554,8 +563,8 @@ class CharmState(Object, StatusesStateProtocol):
|
|
|
554
563
|
return f"{replica_set_name}/{','.join(hosts)}"
|
|
555
564
|
|
|
556
565
|
# END: Helpers
|
|
557
|
-
def
|
|
558
|
-
"""Updates the CA secret
|
|
566
|
+
def _update_ca_secrets(self, new_ca: str | None, cluster_key: str, sharding_key: str) -> None:
|
|
567
|
+
"""Updates the CA secret for the right values on the right fields."""
|
|
559
568
|
# Only the leader can update the databag
|
|
560
569
|
if not self.charm.unit.is_leader():
|
|
561
570
|
return
|
|
@@ -564,22 +573,36 @@ class CharmState(Object, StatusesStateProtocol):
|
|
|
564
573
|
for relation in self.cluster_relations:
|
|
565
574
|
if new_ca is None:
|
|
566
575
|
self.cluster_provider_data_interface.delete_relation_data(
|
|
567
|
-
relation.id, [
|
|
576
|
+
relation.id, [cluster_key]
|
|
568
577
|
)
|
|
569
578
|
else:
|
|
570
579
|
self.cluster_provider_data_interface.update_relation_data(
|
|
571
|
-
relation.id, {
|
|
580
|
+
relation.id, {cluster_key: new_ca}
|
|
572
581
|
)
|
|
573
582
|
for relation in self.config_server_relation:
|
|
574
583
|
if new_ca is None:
|
|
575
|
-
self.config_server_data_interface.delete_relation_data(
|
|
576
|
-
relation.id, [AppShardingComponentKeys.INT_CA_SECRET.value]
|
|
577
|
-
)
|
|
584
|
+
self.config_server_data_interface.delete_relation_data(relation.id, [sharding_key])
|
|
578
585
|
else:
|
|
579
586
|
self.config_server_data_interface.update_relation_data(
|
|
580
|
-
relation.id, {
|
|
587
|
+
relation.id, {sharding_key: new_ca}
|
|
581
588
|
)
|
|
582
589
|
|
|
590
|
+
def update_peer_ca_secrets(self, new_ca: str | None) -> None:
|
|
591
|
+
"""Updates the peer CA secret in the cluster and config-server relations."""
|
|
592
|
+
self._update_ca_secrets(
|
|
593
|
+
new_ca=new_ca,
|
|
594
|
+
cluster_key=ClusterStateKeys.INT_CA_SECRET.value,
|
|
595
|
+
sharding_key=AppShardingComponentKeys.INT_CA_SECRET.value,
|
|
596
|
+
)
|
|
597
|
+
|
|
598
|
+
def update_client_ca_secrets(self, new_ca: str | None) -> None:
|
|
599
|
+
"""Updates the client CA secret in the cluster and config-server relations."""
|
|
600
|
+
self._update_ca_secrets(
|
|
601
|
+
new_ca=new_ca,
|
|
602
|
+
cluster_key=ClusterStateKeys.EXT_CA_SECRET.value,
|
|
603
|
+
sharding_key=AppShardingComponentKeys.EXT_CA_SECRET.value,
|
|
604
|
+
)
|
|
605
|
+
|
|
583
606
|
def is_scaling_down(self, rel_id: int) -> bool:
|
|
584
607
|
"""Returns True if the application is scaling down."""
|
|
585
608
|
rel_departed_key = generate_relation_departed_key(rel_id)
|
|
@@ -606,7 +629,7 @@ class CharmState(Object, StatusesStateProtocol):
|
|
|
606
629
|
return False
|
|
607
630
|
|
|
608
631
|
# We can't check if we don't have a valid certificate
|
|
609
|
-
if self.shard_state.
|
|
632
|
+
if self.shard_state.external_ca_secret is not None and not self.tls.client_enabled:
|
|
610
633
|
return False
|
|
611
634
|
|
|
612
635
|
try:
|
|
@@ -665,7 +688,7 @@ class CharmState(Object, StatusesStateProtocol):
|
|
|
665
688
|
hosts=hosts or user.hosts,
|
|
666
689
|
port=MongoPorts.MONGODB_PORT.value,
|
|
667
690
|
roles=user.roles,
|
|
668
|
-
tls_enabled=self.tls.
|
|
691
|
+
tls_enabled=self.tls.client_enabled,
|
|
669
692
|
tls_external_keyfile=self.paths.ext_pem_file,
|
|
670
693
|
tls_external_ca=self.paths.ext_ca_file,
|
|
671
694
|
standalone=standalone,
|
|
@@ -695,7 +718,7 @@ class CharmState(Object, StatusesStateProtocol):
|
|
|
695
718
|
hosts=hosts or user.hosts,
|
|
696
719
|
port=MongoPorts.MONGOS_PORT.value,
|
|
697
720
|
roles=user.roles,
|
|
698
|
-
tls_enabled=self.tls.
|
|
721
|
+
tls_enabled=self.tls.client_enabled,
|
|
699
722
|
tls_external_keyfile=self.paths.ext_pem_file,
|
|
700
723
|
tls_external_ca=self.paths.ext_ca_file,
|
|
701
724
|
)
|
|
@@ -751,7 +774,7 @@ class CharmState(Object, StatusesStateProtocol):
|
|
|
751
774
|
# unlike the vm mongos charm, the K8s charm does not communicate with the unix socket
|
|
752
775
|
port=port,
|
|
753
776
|
roles={RoleNames.ADMIN},
|
|
754
|
-
tls_enabled=self.tls.
|
|
777
|
+
tls_enabled=self.tls.client_enabled,
|
|
755
778
|
tls_external_keyfile=self.paths.ext_pem_file,
|
|
756
779
|
tls_external_ca=self.paths.ext_ca_file,
|
|
757
780
|
)
|
|
@@ -23,6 +23,7 @@ class ClusterStateKeys(str, Enum):
|
|
|
23
23
|
CONFIG_SERVER_DB = "config-server-db"
|
|
24
24
|
KEYFILE = "key-file"
|
|
25
25
|
INT_CA_SECRET = "int-ca-secret"
|
|
26
|
+
EXT_CA_SECRET = "ext-ca-secret"
|
|
26
27
|
LDAP_USER_TO_DN_MAPPING = "ldap-user-to-dn-mapping"
|
|
27
28
|
LDAP_HASH = "ldap-hash"
|
|
28
29
|
|
|
@@ -74,6 +75,13 @@ class ClusterState(AbstractRelationState[Data]):
|
|
|
74
75
|
return None
|
|
75
76
|
return self.relation_data.get(ClusterStateKeys.INT_CA_SECRET.value, None)
|
|
76
77
|
|
|
78
|
+
@property
|
|
79
|
+
def external_ca_secret(self) -> str | None:
|
|
80
|
+
"""Returns the external CA secret."""
|
|
81
|
+
if not self.relation:
|
|
82
|
+
return None
|
|
83
|
+
return self.relation_data.get(ClusterStateKeys.EXT_CA_SECRET.value, None)
|
|
84
|
+
|
|
77
85
|
@property
|
|
78
86
|
def ldap_user_to_dn_mapping(self) -> str | None:
|
|
79
87
|
"""Returns the userToDNMapping config option shared by the config-server."""
|
|
@@ -23,6 +23,7 @@ class AppShardingComponentKeys(str, Enum):
|
|
|
23
23
|
HOST = "host"
|
|
24
24
|
KEY_FILE = "key-file"
|
|
25
25
|
INT_CA_SECRET = "int-ca-secret"
|
|
26
|
+
EXT_CA_SECRET = "ext-ca-secret"
|
|
26
27
|
BACKUP_CA_SECRET = "backup-ca-secret"
|
|
27
28
|
|
|
28
29
|
# We don't use those except to check if we've received credentials
|
|
@@ -35,6 +36,7 @@ SECRETS_FIELDS = [
|
|
|
35
36
|
"backup-password",
|
|
36
37
|
"key-file",
|
|
37
38
|
"int-ca-secret",
|
|
39
|
+
"ext-ca-secret",
|
|
38
40
|
"backup-ca-secret",
|
|
39
41
|
]
|
|
40
42
|
|
|
@@ -75,6 +77,13 @@ class AppShardingComponentState(AbstractRelationState[Data]):
|
|
|
75
77
|
return None
|
|
76
78
|
return self.relation_data.get(AppShardingComponentKeys.INT_CA_SECRET.value, None)
|
|
77
79
|
|
|
80
|
+
@property
|
|
81
|
+
def external_ca_secret(self) -> str | None:
|
|
82
|
+
"""Returns the external CA secret."""
|
|
83
|
+
if not self.relation:
|
|
84
|
+
return None
|
|
85
|
+
return self.relation_data.get(AppShardingComponentKeys.EXT_CA_SECRET.value, None)
|
|
86
|
+
|
|
78
87
|
@property
|
|
79
88
|
def keyfile(self) -> str | None:
|
|
80
89
|
"""Returns the keyfile."""
|
|
@@ -4,44 +4,59 @@
|
|
|
4
4
|
|
|
5
5
|
"""The TLS state."""
|
|
6
6
|
|
|
7
|
+
from enum import Enum
|
|
8
|
+
|
|
7
9
|
from ops import Relation
|
|
8
10
|
from ops.model import Unit
|
|
9
11
|
|
|
10
12
|
from single_kernel_mongo.config.literals import Scope
|
|
11
13
|
from single_kernel_mongo.core.secrets import SecretCache
|
|
14
|
+
from single_kernel_mongo.lib.charms.tls_certificates_interface.v4.tls_certificates import PrivateKey
|
|
12
15
|
|
|
13
16
|
SECRET_KEY_LABEL = "key-secret"
|
|
14
17
|
SECRET_CA_LABEL = "ca-secret"
|
|
15
|
-
SECRET_CERT_LABEL = "cert-secret"
|
|
16
18
|
SECRET_CSR_LABEL = "csr-secret"
|
|
19
|
+
SECRET_CERT_LABEL = "cert-secret"
|
|
17
20
|
SECRET_CHAIN_LABEL = "chain-secret"
|
|
18
|
-
WAIT_CERT_UPDATE = "wait-cert-updated"
|
|
19
21
|
INT_CERT_SECRET_KEY = "int-cert-secret"
|
|
20
22
|
EXT_CERT_SECRET_KEY = "ext-cert-secret"
|
|
21
23
|
|
|
22
24
|
|
|
25
|
+
class TlsManagementState(Enum):
|
|
26
|
+
"""TLS management state that can be mapped to a status."""
|
|
27
|
+
|
|
28
|
+
EMPTY = ""
|
|
29
|
+
UPGRADE_IN_PROGRESS = "Upgrade in progress."
|
|
30
|
+
DB_NOT_INTIALIZED = "DB is not initialized."
|
|
31
|
+
MONGOS_MISSING_CONFIG_SERVER = "mongos is not running (not integrated to config-server)."
|
|
32
|
+
MONGOS_DB_NOT_INITIALIZED = "mongos DB is not initialized."
|
|
33
|
+
|
|
34
|
+
|
|
23
35
|
class TLSState:
|
|
24
36
|
"""The stored state for the TLS relation."""
|
|
25
37
|
|
|
26
38
|
component: Unit
|
|
27
39
|
|
|
28
|
-
def __init__(
|
|
29
|
-
self
|
|
40
|
+
def __init__(
|
|
41
|
+
self, peer_relation: Relation | None, client_relation: Relation | None, secrets: SecretCache
|
|
42
|
+
):
|
|
43
|
+
self.peer_relation = peer_relation
|
|
44
|
+
self.client_relation = client_relation
|
|
30
45
|
self.secrets = secrets
|
|
31
46
|
|
|
32
47
|
@property
|
|
33
|
-
def
|
|
34
|
-
"""Is
|
|
48
|
+
def peer_enabled(self) -> bool:
|
|
49
|
+
"""Is peer TLS enabled."""
|
|
35
50
|
return (
|
|
36
|
-
self.
|
|
51
|
+
self.peer_relation is not None
|
|
37
52
|
and self.secrets.get_for_key(Scope.UNIT, INT_CERT_SECRET_KEY) is not None
|
|
38
53
|
)
|
|
39
54
|
|
|
40
55
|
@property
|
|
41
|
-
def
|
|
42
|
-
"""Is
|
|
56
|
+
def client_enabled(self) -> bool:
|
|
57
|
+
"""Is client TLS enabled."""
|
|
43
58
|
return (
|
|
44
|
-
self.
|
|
59
|
+
self.client_relation is not None
|
|
45
60
|
and self.secrets.get_for_key(Scope.UNIT, EXT_CERT_SECRET_KEY) is not None
|
|
46
61
|
)
|
|
47
62
|
|
|
@@ -49,9 +64,9 @@ class TLSState:
|
|
|
49
64
|
"""Is TLS enabled for ::internal."""
|
|
50
65
|
match internal:
|
|
51
66
|
case True:
|
|
52
|
-
return self.
|
|
67
|
+
return self.peer_enabled
|
|
53
68
|
case False:
|
|
54
|
-
return self.
|
|
69
|
+
return self.client_enabled
|
|
55
70
|
|
|
56
71
|
def set_secret(self, internal: bool, label_name: str, contents: str | None) -> None:
|
|
57
72
|
"""Sets TLS secret, based on whether or not it is related to internal connections."""
|
|
@@ -67,3 +82,15 @@ class TLSState:
|
|
|
67
82
|
scope = "int" if internal else "ext"
|
|
68
83
|
label_name = f"{scope}-{label_name}"
|
|
69
84
|
return self.secrets.get_for_key(Scope.UNIT, label_name)
|
|
85
|
+
|
|
86
|
+
@property
|
|
87
|
+
def client_private_key(self) -> PrivateKey | None:
|
|
88
|
+
"""Private key for the client relation."""
|
|
89
|
+
private_key_str = self.get_secret(internal=False, label_name=SECRET_KEY_LABEL)
|
|
90
|
+
return PrivateKey(private_key_str) if private_key_str else None
|
|
91
|
+
|
|
92
|
+
@property
|
|
93
|
+
def peer_private_key(self) -> PrivateKey | None:
|
|
94
|
+
"""Private key for the peer relation."""
|
|
95
|
+
private_key_str = self.get_secret(internal=True, label_name=SECRET_KEY_LABEL)
|
|
96
|
+
return PrivateKey(private_key_str) if private_key_str else None
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
[Unit]
|
|
2
|
+
Description=Enable Transparent Hugepages (THP)
|
|
3
|
+
DefaultDependencies=no
|
|
4
|
+
After=sysinit.target local-fs.target
|
|
5
|
+
Before={{service_file}}
|
|
6
|
+
|
|
7
|
+
[Service]
|
|
8
|
+
Type=oneshot
|
|
9
|
+
ExecStartPre=/bin/sh -c 'echo 0 | tee /sys/kernel/mm/transparent_hugepage/khugepaged/max_ptes_none > /dev/null'
|
|
10
|
+
ExecStartPre=/bin/sh -c 'echo defer+madvise | tee /sys/kernel/mm/transparent_hugepage/defrag > /dev/null '
|
|
11
|
+
ExecStart=/bin/sh -c 'echo always | tee /sys/kernel/mm/transparent_hugepage/enabled > /dev/null'
|
|
12
|
+
|
|
13
|
+
[Install]
|
|
14
|
+
WantedBy=basic.target
|
|
@@ -4,8 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
"""Some helpers functions that doesn't belong anywhere else."""
|
|
6
6
|
|
|
7
|
-
import base64
|
|
8
|
-
import re
|
|
9
7
|
from functools import partial
|
|
10
8
|
from logging import getLogger
|
|
11
9
|
|
|
@@ -18,21 +16,6 @@ from single_kernel_mongo.exceptions import InvalidCharmKindError
|
|
|
18
16
|
logger = getLogger(__name__)
|
|
19
17
|
|
|
20
18
|
|
|
21
|
-
def parse_tls_file(raw_content: str) -> bytes:
|
|
22
|
-
"""Parse TLS files from both plain text or base64 format."""
|
|
23
|
-
if re.match(r"(-+(BEGIN|END) [A-Z ]+-+)", raw_content):
|
|
24
|
-
return (
|
|
25
|
-
re.sub(
|
|
26
|
-
r"(-+(BEGIN|END) [A-Z ]+-+)",
|
|
27
|
-
"\\1",
|
|
28
|
-
raw_content,
|
|
29
|
-
)
|
|
30
|
-
.rstrip()
|
|
31
|
-
.encode("utf-8")
|
|
32
|
-
)
|
|
33
|
-
return base64.b64decode(raw_content)
|
|
34
|
-
|
|
35
|
-
|
|
36
19
|
def generate_relation_departed_key(rel_id: int) -> str: # noqa
|
|
37
20
|
return f"relation_{rel_id}_departed"
|
|
38
21
|
|
|
@@ -61,7 +44,7 @@ def hostname_from_shardname(host: str) -> str:
|
|
|
61
44
|
return host.split("/")[0]
|
|
62
45
|
|
|
63
46
|
|
|
64
|
-
def is_valid_ldapusertodnmapping(ldap_user_to_dn_mapping: str) -> bool:
|
|
47
|
+
def is_valid_ldapusertodnmapping(ldap_user_to_dn_mapping: str | None) -> bool:
|
|
65
48
|
"""Validates the mapping, returning a boolean."""
|
|
66
49
|
if not ldap_user_to_dn_mapping:
|
|
67
50
|
return True
|
|
@@ -73,7 +56,9 @@ def is_valid_ldapusertodnmapping(ldap_user_to_dn_mapping: str) -> bool:
|
|
|
73
56
|
return False
|
|
74
57
|
|
|
75
58
|
|
|
76
|
-
def is_valid_ldap_options(
|
|
59
|
+
def is_valid_ldap_options(
|
|
60
|
+
ldap_user_to_dn_mapping: str | None, ldap_query_template: str | None
|
|
61
|
+
) -> bool:
|
|
77
62
|
"""Validates the combination of the two LDAP options.
|
|
78
63
|
|
|
79
64
|
Rules are the following:
|