Skip to content

Commit 8216935

Browse files
committed
Fix Postgres and Synapse Media storageClassName configuration not being respected.
1 parent 9681812 commit 8216935

6 files changed

Lines changed: 105 additions & 5 deletions

File tree

charts/matrix-stack/source/common/persistentVolumeClaim.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"size": {
88
"type": "string"
99
},
10-
"storageClass": {
10+
"storageClassName": {
1111
"type": "string"
1212
},
1313
"resourcePolicy": {

charts/matrix-stack/values.schema.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4856,7 +4856,7 @@
48564856
"size": {
48574857
"type": "string"
48584858
},
4859-
"storageClass": {
4859+
"storageClassName": {
48604860
"type": "string"
48614861
},
48624862
"resourcePolicy": {
@@ -5454,7 +5454,7 @@
54545454
"size": {
54555455
"type": "string"
54565456
},
5457-
"storageClass": {
5457+
"storageClassName": {
54585458
"type": "string"
54595459
},
54605460
"resourcePolicy": {

newsfragments/582.fixed.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Fix Postgres and Synapse Media `storageClassName` configuration not being respected.
2+
3+
**Warning** Previously `synapse.media.storage.storageClass` and `postgres.storage.storageClass`
4+
were in the values file and associated schema. These values were accidentally silently ignored
5+
and all chart-managed `PersistentVolumeClaims` were constructed without `spec.storageClassName`
6+
set, using the cluster default `StorageClass`.
7+
8+
The values file and associated schema have been updated so that the values are now
9+
`synapse.media.storage.storageClassName` and `postgres.storage.storageClassName`. The previous
10+
values are disallowed by the schema. Setting these values after the initial install could
11+
cause the `PersistentVolumeClaims` to be recreated, with associated data-loss. Only set
12+
`synapse.media.storage.storageClassName` or `postgres.storage.storageClassName` on initial
13+
installation.

newsfragments/582.internal.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
CI: improve testing of chart managed `PersistentVolumeClaims`.

tests/manifests/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class PropertyType(Enum):
2424
StartupProbe = "startupProbe"
2525
ServiceAccount = "serviceAccount"
2626
ServiceMonitor = "serviceMonitors"
27+
Storage = "storage"
2728
Tolerations = "tolerations"
2829
TopologySpreadConstraints = "topologySpreadConstraints"
2930

@@ -535,6 +536,9 @@ def make_synapse_worker_sub_component(worker_name: str, worker_type: str) -> Sub
535536
),
536537
ComponentDetails(
537538
name="synapse",
539+
values_file_path_overrides={
540+
PropertyType.Storage: ValuesFilePath.read_write("synapse", "media", "storage"),
541+
},
538542
has_db=True,
539543
has_storage=True,
540544
has_replicas=False,

tests/manifests/test_pvcs.py

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@
22
#
33
# SPDX-License-Identifier: AGPL-3.0-only
44

5+
import random
6+
import string
7+
58
import pytest
69

7-
from . import values_files_to_test
8-
from .utils import template_to_deployable_details
10+
from . import DeployableDetails, PropertyType, values_files_to_test
11+
from .utils import iterate_deployables_parts, template_id, template_to_deployable_details
912

1013

1114
@pytest.mark.parametrize("values_file", values_files_to_test)
@@ -31,3 +34,82 @@ async def test_pvcs_marked_as_being_kept_on_helm_uninstall_by_default(templates)
3134
if template["kind"] == "PersistentVolumeClaim":
3235
assert "helm.sh/resource-policy" in template["metadata"]["annotations"]
3336
assert template["metadata"]["annotations"]["helm.sh/resource-policy"] == "keep"
37+
38+
39+
@pytest.mark.parametrize("values_file", values_files_to_test)
40+
@pytest.mark.asyncio_cooperative
41+
async def test_pvcs_can_be_marked_as_to_be_deleted_on_helm_uninstall(values, make_templates):
42+
iterate_deployables_parts(
43+
lambda deployable_details: deployable_details.set_helm_values(
44+
values, PropertyType.Storage, {"resourcePolicy": "delete"}
45+
),
46+
lambda deployable_details: deployable_details.has_storage,
47+
)
48+
49+
for template in await make_templates(values):
50+
if template["kind"] == "PersistentVolumeClaim":
51+
assert "helm.sh/resource-policy" in template["metadata"]["annotations"]
52+
assert template["metadata"]["annotations"]["helm.sh/resource-policy"] == "delete"
53+
54+
55+
@pytest.mark.parametrize("values_file", values_files_to_test)
56+
@pytest.mark.asyncio_cooperative
57+
async def test_no_pvcs_created_if_existing_claims_specified(values, make_templates):
58+
iterate_deployables_parts(
59+
lambda deployable_details: deployable_details.set_helm_values(
60+
values, PropertyType.Storage, {"existingClaim": "something"}
61+
),
62+
lambda deployable_details: deployable_details.has_storage,
63+
)
64+
65+
for template in await make_templates(values):
66+
assert template["kind"] != "PersistentVolumeClaim", (
67+
f"{template_id(template)} was created despite referencing existingClaims for all PVCs"
68+
)
69+
70+
71+
@pytest.mark.parametrize("values_file", values_files_to_test)
72+
@pytest.mark.asyncio_cooperative
73+
async def test_size_passed_through_to_created_pvcs(values, make_templates):
74+
counter = 1
75+
76+
def set_pvc_size(deployable_details: DeployableDetails):
77+
nonlocal counter
78+
deployable_details.set_helm_values(values, PropertyType.Storage, {"size": f"{counter}Gi"})
79+
counter += 1
80+
81+
iterate_deployables_parts(set_pvc_size, lambda deployable_details: deployable_details.has_storage)
82+
83+
for template in await make_templates(values):
84+
if template["kind"] == "PersistentVolumeClaim":
85+
deployable_details = template_to_deployable_details(template)
86+
pvc_requests = template["spec"]["resources"]["requests"]
87+
assert "storage" in pvc_requests, f"{template_id(template)} didn't specify any storage requests"
88+
89+
expected_size = deployable_details.get_helm_values(values, PropertyType.Storage)["size"]
90+
assert expected_size == pvc_requests["storage"], (
91+
f"{template_id(template)} didn't respect the configured PVC size"
92+
)
93+
94+
95+
@pytest.mark.parametrize("values_file", values_files_to_test)
96+
@pytest.mark.asyncio_cooperative
97+
async def test_storageClassName_passed_through_to_created_pvcs(values, make_templates):
98+
iterate_deployables_parts(
99+
lambda deployable_details: deployable_details.set_helm_values(
100+
values, PropertyType.Storage, {"storageClassName": "".join(random.choices(string.ascii_lowercase, k=10))}
101+
),
102+
lambda deployable_details: deployable_details.has_storage,
103+
)
104+
105+
for template in await make_templates(values):
106+
if template["kind"] == "PersistentVolumeClaim":
107+
assert "storageClassName" in template["spec"], (
108+
f"{template_id(template)} did not set spec.storageClassName despite being configured to"
109+
)
110+
deployable_details = template_to_deployable_details(template)
111+
112+
expected_storageClassName = deployable_details.get_helm_values(values, PropertyType.Storage)["storageClassName"]
113+
assert expected_storageClassName == template["spec"]["storageClassName"], (
114+
f"{template_id(template)} didn't respect the configured PVC storageClassName"
115+
)

0 commit comments

Comments
 (0)