Skip to content

Commit bab6842

Browse files
committed
test relate legacy+modern endpoints simultaneously
1 parent c9bc9f8 commit bab6842

File tree

3 files changed

+102
-101
lines changed

3 files changed

+102
-101
lines changed

src/relations/db.py

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,9 @@
2121
from ops.model import ActiveStatus, BlockedStatus, Relation, Unit
2222
from pgconnstr import ConnectionString
2323

24-
from constants import APP_SCOPE, DATABASE_PORT
24+
from constants import ALL_LEGACY_RELATIONS, APP_SCOPE, DATABASE_PORT
2525
from utils import new_password
2626

27-
from src.constants import ALL_LEGACY_RELATIONS
28-
2927
logger = logging.getLogger(__name__)
3028

3129
EXTENSIONS_BLOCKING_MESSAGE = (
@@ -121,9 +119,9 @@ def _on_relation_changed(self, event: RelationChangedEvent) -> None:
121119
return
122120

123121
if (
124-
"cluster_initialised" not in self.charm._peers.data[self.charm.app]
125-
or not self.charm._patroni.member_started
126-
or not self.charm.primary_endpoint
122+
"cluster_initialised" not in self.charm._peers.data[self.charm.app]
123+
or not self.charm._patroni.member_started
124+
or not self.charm.primary_endpoint
127125
):
128126
logger.debug(
129127
"Deferring on_relation_changed: cluster not initialized, Patroni not started or primary endpoint not available"
@@ -246,9 +244,9 @@ def _on_relation_departed(self, event: RelationDepartedEvent) -> None:
246244
return
247245

248246
if (
249-
"cluster_initialised" not in self.charm._peers.data[self.charm.app]
250-
or not self.charm._patroni.member_started
251-
or not self.charm.primary_endpoint
247+
"cluster_initialised" not in self.charm._peers.data[self.charm.app]
248+
or not self.charm._patroni.member_started
249+
or not self.charm.primary_endpoint
252250
):
253251
logger.debug(
254252
"Deferring on_relation_departed: cluster not initialized, Patroni not started or primary endpoint not available"
@@ -271,10 +269,10 @@ def _on_relation_broken(self, event: RelationBrokenEvent) -> None:
271269
"""Remove the user created for this relation."""
272270
# Check for some conditions before trying to access the PostgreSQL instance.
273271
if (
274-
not self.charm.unit.is_leader()
275-
or "cluster_initialised" not in self.charm._peers.data[self.charm.app]
276-
or not self.charm._patroni.member_started
277-
or not self.charm.primary_endpoint
272+
not self.charm.unit.is_leader()
273+
or "cluster_initialised" not in self.charm._peers.data[self.charm.app]
274+
or not self.charm._patroni.member_started
275+
or not self.charm.primary_endpoint
278276
):
279277
logger.debug(
280278
"Early exit on_relation_broken: Not leader, cluster not initialized, Patroni not started or no primary endpoint"
@@ -304,7 +302,10 @@ def _update_unit_status(self, relation: Relation) -> None:
304302

305303
def _update_unit_status_on_blocking_endpoint_simultaneously(self):
306304
"""# Clean up Blocked status if this is due related of multiple endpoints."""
307-
if self.charm.is_blocked and self.charm.unit.status.message == ENDPOINT_SIMULTANEOUSLY_BLOCKING_MESSAGE:
305+
if (
306+
self.charm.is_blocked
307+
and self.charm.unit.status.message == ENDPOINT_SIMULTANEOUSLY_BLOCKING_MESSAGE
308+
):
308309
if not self._check_multiple_endpoints():
309310
self.charm.unit.status = ActiveStatus()
310311

src/relations/postgresql_provider.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77

88
from charms.data_platform_libs.v0.data_interfaces import (
99
DatabaseProvides,
10-
DatabaseRequestedEvent, diff,
10+
DatabaseRequestedEvent,
11+
diff,
1112
)
1213
from charms.postgresql_k8s.v0.postgresql import (
1314
INVALID_EXTRA_USER_ROLE_BLOCKING_MESSAGE,
@@ -31,6 +32,7 @@
3132
"Please choose one endpoint to use. No need to relate all of them simultaneously!"
3233
)
3334

35+
3436
class PostgreSQLProvider(Object):
3537
"""Defines functionality for the 'provides' side of the 'postgresql-client' relation.
3638
@@ -236,7 +238,10 @@ def _on_relation_changed_event(self, event: RelationChangedEvent) -> None:
236238

237239
def _update_unit_status_on_blocking_endpoint_simultaneously(self):
238240
"""# Clean up Blocked status if this is due related of multiple endpoints."""
239-
if self.charm.is_blocked and self.charm.unit.status.message == ENDPOINT_SIMULTANEOUSLY_BLOCKING_MESSAGE:
241+
if (
242+
self.charm.is_blocked
243+
and self.charm.unit.status.message == ENDPOINT_SIMULTANEOUSLY_BLOCKING_MESSAGE
244+
):
240245
if not self._check_multiple_endpoints():
241246
self.charm.unit.status = ActiveStatus()
242247

tests/integration/relations/test_relations.py

Lines changed: 80 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,14 @@
33
# See LICENSE file for licensing details.
44
import asyncio
55
import logging
6-
import secrets
7-
import string
8-
from pathlib import Path
9-
from time import sleep
106

117
import psycopg2
128
import pytest
13-
import yaml
14-
from pytest_operator.plugin import OpsTest, FileResource
9+
from pytest_operator.plugin import OpsTest
1510
from tenacity import Retrying, stop_after_delay, wait_fixed
1611

1712
from ..helpers import CHARM_SERIES, DATABASE_APP_NAME, METADATA
18-
from ..new_relations.test_new_relations import APPLICATION_APP_NAME
19-
from ..new_relations.test_new_relations import build_connection_string
13+
from ..new_relations.test_new_relations import APPLICATION_APP_NAME, build_connection_string
2014
from ..relations.helpers import get_legacy_db_connection_str
2115

2216
logger = logging.getLogger(__name__)
@@ -61,80 +55,81 @@ async def test_deploy_charms(ops_test: OpsTest, charm):
6155

6256
await ops_test.model.wait_for_idle(apps=APP_NAMES, status="active", timeout=3000)
6357

64-
# @pytest.mark.group(1)
65-
# async def test_legacy_modern_endpoints(ops_test: OpsTest):
66-
# await ops_test.model.relate(MAILMAN3_CORE_APP_NAME, f"{APP_NAME}:{DB_RELATION}")
67-
# await ops_test.model.relate(APP_NAME, f"{APPLICATION_APP_NAME}:{FIRST_DATABASE_RELATION}")
68-
#
69-
# app = ops_test.model.applications[APP_NAME]
70-
# await ops_test.model.block_until(
71-
# lambda: "blocked" in {unit.workload_status for unit in app.units},
72-
# timeout=1500,
73-
# )
74-
#
75-
# logger.info(f" remove relation with modern endpoints")
76-
# await ops_test.model.applications[APP_NAME].remove_relation(
77-
# f"{APP_NAME}:{DATABASE_RELATION}", f"{APPLICATION_APP_NAME}:{FIRST_DATABASE_RELATION}"
78-
# )
79-
# async with ops_test.fast_forward():
80-
# await ops_test.model.wait_for_idle(
81-
# status="active",
82-
# timeout=1500,
83-
# raise_on_error=False,
84-
# )
85-
#
86-
# legacy_interface_connect = await get_legacy_db_connection_str(ops_test, MAILMAN3_CORE_APP_NAME, DB_RELATION,
87-
# remote_unit_name=f"{APP_NAME}/0")
88-
# logger.info(f" check connect to = {legacy_interface_connect}")
89-
# for attempt in Retrying(stop=stop_after_delay(60 * 3), wait=wait_fixed(10)):
90-
# with attempt:
91-
# with psycopg2.connect(legacy_interface_connect) as connection:
92-
# assert connection.status == psycopg2.extensions.STATUS_READY
93-
#
94-
# logger.info(f"==== remove relation mailman3-core")
95-
# async with ops_test.fast_forward():
96-
# await ops_test.model.applications[APP_NAME].remove_relation(
97-
# f"{APP_NAME}:db", f"mailman3-core:db"
98-
# )
99-
# await ops_test.model.wait_for_idle(apps=[APP_NAME], status="active", timeout=1000)
100-
# with pytest.raises(psycopg2.OperationalError):
101-
# psycopg2.connect(legacy_interface_connect)
102-
#
103-
# async def test_legacy_modern_endpoints_a(ops_test: OpsTest):
104-
# await ops_test.model.relate(MAILMAN3_CORE_APP_NAME, f"{APP_NAME}:{DB_RELATION}")
105-
# await ops_test.model.relate(APP_NAME, f"{APPLICATION_APP_NAME}:{FIRST_DATABASE_RELATION}")
106-
#
107-
# app = ops_test.model.applications[APP_NAME]
108-
# await ops_test.model.block_until(
109-
# lambda: "blocked" in {unit.workload_status for unit in app.units},
110-
# timeout=1500,
111-
# )
112-
#
113-
# logger.info(f" remove relation with legacy endpoints")
114-
# await ops_test.model.applications[APP_NAME].remove_relation(
115-
# f"{MAILMAN3_CORE_APP_NAME}:{DB_RELATION}", f"{APP_NAME}:{DB_RELATION}"
116-
# )
117-
# async with ops_test.fast_forward():
118-
# await ops_test.model.wait_for_idle(
119-
# status="active",
120-
# timeout=3000,
121-
# raise_on_error=False
122-
# )
123-
#
124-
# modern_interface_connect = await build_connection_string(ops_test, APPLICATION_APP_NAME, FIRST_DATABASE_RELATION)
125-
# logger.info(f" ==================== modern database_unit_name ={modern_interface_connect}")
126-
# for attempt in Retrying(stop=stop_after_delay(60 * 3), wait=wait_fixed(10)):
127-
# with attempt:
128-
# with psycopg2.connect(modern_interface_connect) as connection:
129-
# assert connection.status == psycopg2.extensions.STATUS_READY
130-
#
131-
# logger.info(f"==== modern remove relation {APPLICATION_APP_NAME}")
132-
# async with ops_test.fast_forward():
133-
# await ops_test.model.applications[APP_NAME].remove_relation(
134-
# f"{APP_NAME}:{DATABASE_RELATION}", f"{APPLICATION_APP_NAME}:{FIRST_DATABASE_RELATION}"
135-
# )
136-
# await ops_test.model.wait_for_idle(apps=[APP_NAME], status="active", timeout=1000)
137-
# for attempt in Retrying(stop=stop_after_delay(60 * 5), wait=wait_fixed(10)):
138-
# with attempt:
139-
# with pytest.raises(psycopg2.OperationalError):
140-
# psycopg2.connect(modern_interface_connect)
58+
59+
@pytest.mark.group(1)
60+
async def test_legacy_endpoint_with_multiple_related_endpoints(ops_test: OpsTest):
61+
await ops_test.model.relate(MAILMAN3_CORE_APP_NAME, f"{APP_NAME}:{DB_RELATION}")
62+
await ops_test.model.relate(APP_NAME, f"{APPLICATION_APP_NAME}:{FIRST_DATABASE_RELATION}")
63+
64+
app = ops_test.model.applications[APP_NAME]
65+
await ops_test.model.block_until(
66+
lambda: "blocked" in {unit.workload_status for unit in app.units},
67+
timeout=1500,
68+
)
69+
70+
logger.info(" remove relation with modern endpoints")
71+
await ops_test.model.applications[APP_NAME].remove_relation(
72+
f"{APP_NAME}:{DATABASE_RELATION}", f"{APPLICATION_APP_NAME}:{FIRST_DATABASE_RELATION}"
73+
)
74+
async with ops_test.fast_forward():
75+
await ops_test.model.wait_for_idle(
76+
status="active",
77+
timeout=1500,
78+
raise_on_error=False,
79+
)
80+
81+
legacy_interface_connect = await get_legacy_db_connection_str(
82+
ops_test, MAILMAN3_CORE_APP_NAME, DB_RELATION, remote_unit_name=f"{APP_NAME}/0"
83+
)
84+
logger.info(f" check connect to = {legacy_interface_connect}")
85+
for attempt in Retrying(stop=stop_after_delay(60 * 3), wait=wait_fixed(10)):
86+
with attempt:
87+
with psycopg2.connect(legacy_interface_connect) as connection:
88+
assert connection.status == psycopg2.extensions.STATUS_READY
89+
90+
logger.info(" remove relation mailman3-core")
91+
async with ops_test.fast_forward():
92+
await ops_test.model.applications[APP_NAME].remove_relation(
93+
f"{APP_NAME}:{DB_RELATION}", f"{MAILMAN3_CORE_APP_NAME}:{DB_RELATION}"
94+
)
95+
await ops_test.model.wait_for_idle(apps=[APP_NAME], status="active", timeout=1000)
96+
with pytest.raises(psycopg2.OperationalError):
97+
psycopg2.connect(legacy_interface_connect)
98+
99+
100+
async def test_modern_endpoint_with_multiple_related_endpoints(ops_test: OpsTest):
101+
await ops_test.model.relate(MAILMAN3_CORE_APP_NAME, f"{APP_NAME}:{DB_RELATION}")
102+
await ops_test.model.relate(APP_NAME, f"{APPLICATION_APP_NAME}:{FIRST_DATABASE_RELATION}")
103+
104+
app = ops_test.model.applications[APP_NAME]
105+
await ops_test.model.block_until(
106+
lambda: "blocked" in {unit.workload_status for unit in app.units},
107+
timeout=1500,
108+
)
109+
110+
logger.info(" remove relation with legacy endpoints")
111+
await ops_test.model.applications[APP_NAME].remove_relation(
112+
f"{MAILMAN3_CORE_APP_NAME}:{DB_RELATION}", f"{APP_NAME}:{DB_RELATION}"
113+
)
114+
async with ops_test.fast_forward():
115+
await ops_test.model.wait_for_idle(status="active", timeout=3000, raise_on_error=False)
116+
117+
modern_interface_connect = await build_connection_string(
118+
ops_test, APPLICATION_APP_NAME, FIRST_DATABASE_RELATION
119+
)
120+
logger.info(f" check connect to = {modern_interface_connect}")
121+
for attempt in Retrying(stop=stop_after_delay(60 * 3), wait=wait_fixed(10)):
122+
with attempt:
123+
with psycopg2.connect(modern_interface_connect) as connection:
124+
assert connection.status == psycopg2.extensions.STATUS_READY
125+
126+
logger.info(f" remove relation {APPLICATION_APP_NAME}")
127+
async with ops_test.fast_forward():
128+
await ops_test.model.applications[APP_NAME].remove_relation(
129+
f"{APP_NAME}:{DATABASE_RELATION}", f"{APPLICATION_APP_NAME}:{FIRST_DATABASE_RELATION}"
130+
)
131+
await ops_test.model.wait_for_idle(apps=[APP_NAME], status="active", timeout=1000)
132+
for attempt in Retrying(stop=stop_after_delay(60 * 5), wait=wait_fixed(10)):
133+
with attempt:
134+
with pytest.raises(psycopg2.OperationalError):
135+
psycopg2.connect(modern_interface_connect)

0 commit comments

Comments
 (0)