Skip to content

Commit 65f70b7

Browse files
authored
[DPE-6955] Integrate Advanced Statuses in MongoDB K8S (#402)
* wip: statuses integration * fix: tls + charmcraft * fix: tests * fix: relock * fix: more fixes * fix: post rebase * fix: unit tests * fix: charm version * fix: relock * fix: relock * fix: relock * fix: extend ci * revert: extend ci * fix: remove constraints after update of pydantic * fix: relock + fix test * fix: relock * fix: relock * fix: don't remove shard on scale down * fix: relock + unit test fixes * fix: relock * fix: relock * fix: poetry * feat: use published library * fix: remove breakpoint * fix: use status-detail to get full message * feat: Add CLA checker
1 parent 70f1a80 commit 65f70b7

15 files changed

+547
-403
lines changed

.github/workflows/cla.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
name: cla-check
2+
on: [pull_request]
3+
4+
jobs:
5+
cla-check:
6+
runs-on: ubuntu-latest
7+
steps:
8+
- name: Check if CLA signed
9+
uses: canonical/has-signed-canonical-cla@v2

actions.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,11 @@ force-refresh-start:
7171
description: |
7272
Force refresh of this unit.
7373
Potential of data loss and downtime.
74+
75+
status-detail:
76+
description: Gets statuses of the charm
77+
params:
78+
recompute:
79+
type: boolean
80+
default: false
81+
description: a boolean indicating whether a unit should recompute all statuses.

charmcraft.yaml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,6 @@ parts:
5151
after:
5252
- poetry-deps
5353
poetry-export-extra-args: ['--only', 'main,charm-libs']
54-
build-environment:
55-
- PIP_CONSTRAINT: constraints.txt # Workaround for typing-extensions / pydantic-core incompatibility
5654
build-packages:
5755
- libffi-dev # Needed to build Python dependencies with Rust from source
5856
- libssl-dev # Needed to build Python dependencies with Rust from source

constraints.txt

Lines changed: 0 additions & 1 deletion
This file was deleted.

metadata.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ peers:
2626
ldap-peers:
2727
# Stores the data for the ldap relation.
2828
interface: ldap-peers
29+
status-peers:
30+
interface: status-peers
2931

3032
provides:
3133
database:

poetry.lock

Lines changed: 341 additions & 324 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 & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ requires-poetry = ">=2.0.0"
88

99
[tool.poetry.dependencies]
1010
python = "^3.10.12"
11-
mongo-charms-single-kernel = "==0.0.6"
11+
mongo-charms-single-kernel = "0.0.9"
1212
ops = "~2.15.0"
1313
pymongo = "^4.7.3"
1414
tenacity = "^8.2.3"
@@ -20,7 +20,6 @@ overrides = "^7.7.0"
2020
lightkube = "^0.15.3"
2121
setuptools = "^72.0.0"
2222
rpds-py = "0.18.0"
23-
typing-extensions = "<4.14" # Workaround for typing-extensions / pydantic-core incompatibility
2423

2524
[tool.poetry.group.charm-libs.dependencies]
2625
ops = "~2.15.0"
@@ -58,12 +57,12 @@ coverage = {extras = ["toml"], version = "^7.5.0"}
5857
pytest = "^8.1.1"
5958
pytest-mock = "*"
6059
parameterized = "^0.9.0"
61-
mongo-charms-single-kernel = "==0.0.6"
60+
mongo-charms-single-kernel = "0.0.9"
6261

6362
[tool.poetry.group.integration.dependencies]
6463
allure-pytest = "^2.13.5"
6564
ops = "~2.15.0"
66-
mongo-charms-single-kernel = "==0.0.6"
65+
mongo-charms-single-kernel = "0.0.9"
6766
tenacity = "^8.2.3"
6867
pymongo = "^4.7.3"
6968
parameterized = "^0.9.0"

tests/integration/helpers.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,10 @@ async def get_address_of_unit(ops_test: OpsTest, unit_id: int, app_name: str = A
110110

111111

112112
async def get_password(
113-
ops_test: OpsTest, unit_id: int = 0, username: str = "operator", app_name: str = APP_NAME
113+
ops_test: OpsTest,
114+
unit_id: int = 0,
115+
username: str = "operator",
116+
app_name: str = APP_NAME,
114117
) -> str:
115118
"""Use the charm action to retrieve the password from provided unit.
116119
@@ -670,8 +673,9 @@ async def check_all_units_blocked_with_status(
670673
unit.workload_status.value == "blocked"
671674
), f"unit {unit.name} not in blocked state, in {unit.workload_status.value}"
672675
if status:
676+
# We can have extra info but we care for the most important status
673677
assert (
674-
unit.workload_status.message == status
678+
status in unit.workload_status.message
675679
), f"unit {unit.name} not in blocked state, in {unit.workload_status.value}"
676680

677681

@@ -693,6 +697,20 @@ async def wait_for_mongodb_units_blocked(
693697
await ops_test.model.set_config({hook_interval_key: old_interval})
694698

695699

700+
async def check_status_detail(ops_test: OpsTest, app_name: str, status: str, message: str) -> None:
701+
"""Checks that the first status returned by status-detail is the one expected."""
702+
for unit in ops_test.model.applications[app_name].units:
703+
action = await unit.run_action("status-detail")
704+
action = await action.wait()
705+
result = action.results["json-output"]
706+
707+
# juju messes up the string formatting here.
708+
unit_statuses = json.loads(result["unit"].replace("'", '"'))
709+
710+
assert unit_statuses[0]["Status"].lower() == status
711+
assert unit_statuses[0]["Message"] == message
712+
713+
696714
def is_relation_joined(ops_test: OpsTest, endpoint_one: str, endpoint_two: str) -> bool:
697715
"""Check if a relation is joined.
698716

tests/integration/sharding_tests/test_sharding.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
BACKUP_USERNAME = "backup"
3838
PASSWORD = "operator-password"
3939
DIFFERENT_PASSWORD = "shard-set-password"
40-
CONFIG_SERVER_NEEDS_SHARD_STATUS = "missing relation to shard(s)"
40+
CONFIG_SERVER_NEEDS_SHARD_STATUS = "Missing relation to shard(s)."
4141
SHARD_NEEDS_CONFIG_SERVER_STATUS = "Missing relation to config-server."
4242

4343
# for now we have a large timeout due to the slow drainage of the `config.system.sessions`
@@ -220,6 +220,7 @@ async def test_sharding(ops_test: OpsTest) -> None:
220220

221221
@pytest.mark.group(1)
222222
@pytest.mark.parametrize("username", [OPERATOR_USERNAME, BACKUP_USERNAME])
223+
@pytest.mark.abort_on_fail
223224
async def test_set_operator_password(ops_test: OpsTest, username):
224225
"""Tests that the cluster can safely set the operator password."""
225226
for cluster_app_name in CLUSTER_APPS:
@@ -273,6 +274,7 @@ async def test_set_operator_password(ops_test: OpsTest, username):
273274

274275

275276
@pytest.mark.group(1)
277+
@pytest.mark.abort_on_fail
276278
async def test_shard_removal(ops_test: OpsTest) -> None:
277279
"""Test shard removal.
278280
@@ -329,6 +331,7 @@ async def test_shard_removal(ops_test: OpsTest) -> None:
329331

330332

331333
@pytest.mark.group(1)
334+
@pytest.mark.abort_on_fail
332335
async def test_removal_of_non_primary_shard(ops_test: OpsTest):
333336
"""Tests safe removal of a shard that is not primary."""
334337
# add back a shard so we can safely remove a shard.
@@ -381,6 +384,7 @@ async def test_removal_of_non_primary_shard(ops_test: OpsTest):
381384

382385

383386
@pytest.mark.group(1)
387+
@pytest.mark.abort_on_fail
384388
async def test_unconventual_shard_removal(ops_test: OpsTest):
385389
"""Tests that removing a shard application safely drains data.
386390

tests/integration/sharding_tests/test_sharding_relations.py

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,12 @@
55
from juju.errors import JujuAPIError
66
from pytest_operator.plugin import OpsTest
77

8-
from ..helpers import DEPLOYMENT_TIMEOUT, METADATA, wait_for_mongodb_units_blocked
8+
from ..helpers import (
9+
DEPLOYMENT_TIMEOUT,
10+
METADATA,
11+
check_status_detail,
12+
wait_for_mongodb_units_blocked,
13+
)
914

1015
S3_APP_NAME = "s3-integrator"
1116
SHARD_ONE_APP_NAME = "shard"
@@ -163,7 +168,7 @@ async def test_replication_config_server_relation(ops_test: OpsTest):
163168
await wait_for_mongodb_units_blocked(
164169
ops_test,
165170
REPLICATION_APP_NAME,
166-
status="sharding interface cannot be used by replicas",
171+
status="Sharding interface cannot be used by replicas.",
167172
timeout=300,
168173
)
169174

@@ -193,7 +198,7 @@ async def test_replication_shard_relation(ops_test: OpsTest):
193198
await wait_for_mongodb_units_blocked(
194199
ops_test,
195200
REPLICATION_APP_NAME,
196-
status="sharding interface cannot be used by replicas",
201+
status="Sharding interface cannot be used by replicas.",
197202
timeout=300,
198203
)
199204

@@ -255,9 +260,15 @@ async def test_shard_mongos_relation(ops_test: OpsTest) -> None:
255260
await wait_for_mongodb_units_blocked(
256261
ops_test,
257262
SHARD_ONE_APP_NAME,
258-
status="Relation to mongos not supported, config role must be config-server",
263+
status="Relation to mongos not supported",
259264
timeout=300,
260265
)
266+
await check_status_detail(
267+
ops_test,
268+
SHARD_ONE_APP_NAME,
269+
status="blocked",
270+
message="Relation to mongos not supported, config role must be config-server.",
271+
)
261272

262273
# clean up relations
263274
await ops_test.model.applications[SHARD_ONE_APP_NAME].remove_relation(
@@ -285,9 +296,15 @@ async def test_shard_s3_relation(ops_test: OpsTest) -> None:
285296
await wait_for_mongodb_units_blocked(
286297
ops_test,
287298
SHARD_ONE_APP_NAME,
288-
status="Relation to s3-integrator is not supported, config role must be config-server.",
299+
status="Relation to s3-integrator is not support",
289300
timeout=300,
290301
)
302+
await check_status_detail(
303+
ops_test,
304+
SHARD_ONE_APP_NAME,
305+
status="blocked",
306+
message="Relation to s3-integrator is not supported, config role must be config-server.",
307+
)
291308

292309
# clean up relations
293310
await ops_test.model.applications[SHARD_ONE_APP_NAME].remove_relation(

0 commit comments

Comments
 (0)