Skip to content

Commit 70312f3

Browse files
committed
Merge remote-tracking branch 'altinity/0.25.5' into 0.25.5
2 parents af5bd91 + 7b234ca commit 70312f3

File tree

4 files changed

+169
-92
lines changed

4 files changed

+169
-92
lines changed

tests/e2e/manifests/chi/test-036-volume-re-provisioning-1.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ kind: "ClickHouseInstallation"
33
metadata:
44
name: "test-036-volume-re-provisioning"
55
spec:
6-
76
useTemplates:
87
- name: clickhouse-version
98
configuration:
@@ -16,6 +15,8 @@ spec:
1615
layout:
1716
shardsCount: 1
1817
replicasCount: 2
18+
profiles:
19+
clickhouse_operator/log_queries: 1
1920
defaults:
2021
storageManagement:
2122
provisioner: Operator
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
apiVersion: "clickhouse.altinity.com/v1"
2+
kind: "ClickHouseInstallation"
3+
metadata:
4+
name: "test-036-volume-re-provisioning"
5+
spec:
6+
useTemplates:
7+
- name: clickhouse-version
8+
configuration:
9+
zookeeper:
10+
nodes:
11+
- host: zookeeper
12+
port: 2181
13+
clusters:
14+
- name: simple
15+
layout:
16+
shardsCount: 1
17+
replicasCount: 2
18+
profiles:
19+
clickhouse_operator/log_queries: 1
20+
settings:
21+
storage_configuration/disks/disk2/path: /var/lib/clickhouse2/
22+
storage_configuration/policies/default/volumes/default/disk: default
23+
storage_configuration/policies/default/volumes/disk2/disk: disk2
24+
defaults:
25+
storageManagement:
26+
provisioner: Operator
27+
templates:
28+
volumeClaimTemplate: default
29+
templates:
30+
volumeClaimTemplates:
31+
- name: default
32+
spec:
33+
accessModes:
34+
- ReadWriteOnce
35+
resources:
36+
requests:
37+
storage: 1Gi
38+
- name: disk2
39+
spec:
40+
accessModes:
41+
- ReadWriteOnce
42+
resources:
43+
requests:
44+
storage: 1Gi
45+
podTemplates:
46+
- name: default
47+
spec:
48+
containers:
49+
- name: clickhouse-pod
50+
volumeMounts:
51+
- name: default
52+
mountPath: /var/lib/clickhouse
53+
- name: disk2
54+
mountPath: /var/lib/clickhouse2

tests/e2e/test_operator.py

Lines changed: 92 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1508,25 +1508,6 @@ def test_010014_0(self):
15081508
host=f"chi-{chi_name}-{cluster}-1-0",
15091509
)
15101510

1511-
def check_query_log(log, do_not_log, since = '1970-01-01', flags = None):
1512-
out = clickhouse.query(chi_name, f"select query, substring(hostname, 1, locate('.', hostname)-1) from cluster('all-sharded', system.query_log) where user = 'clickhouse_operator' and event_time>='{since}'")
1513-
for q in log:
1514-
found = 0
1515-
with Then(f"system.query_log should contain {q} statements", flags = flags):
1516-
for l in out.splitlines():
1517-
if l.lower().startswith(q.lower()):
1518-
found = 1
1519-
print(l)
1520-
assert found, error(out)
1521-
for q in do_not_log:
1522-
found = 0
1523-
with Then(f"system.query_log should NOT contain {q} statements", flags = flags):
1524-
for l in out.splitlines():
1525-
if l.lower().startswith(q.lower()):
1526-
found = 1
1527-
print(l)
1528-
assert not found, error(out)
1529-
15301511
def check_schema_propagation(replicas):
15311512
for replica in replicas:
15321513
host = f"chi-{chi_name}-{cluster}-0-{replica}"
@@ -1651,7 +1632,7 @@ def check_schema_propagation(replicas):
16511632

16521633
check_schema_propagation(replicas)
16531634

1654-
check_query_log(['CREATE'], [], query_log_start)
1635+
util.check_query_log(chi_name, ['CREATE'], [], query_log_start)
16551636

16561637
with When("Restart (Zoo)Keeper pod"):
16571638
if self.context.keeper_type == "zookeeper":
@@ -1707,7 +1688,7 @@ def check_schema_propagation(replicas):
17071688
)
17081689
assert out == "1"
17091690

1710-
check_query_log(['SYSTEM DROP REPLICA'], ['DROP TABLE', 'DROP DATABASE'], query_log_start)
1691+
util.check_query_log(chi_name, ['SYSTEM DROP REPLICA'], ['DROP TABLE', 'DROP DATABASE'], query_log_start)
17111692

17121693
with When("Add replica one more time"):
17131694
manifest = "manifests/chi/test-014-0-replication-2.yaml"
@@ -1743,7 +1724,7 @@ def check_schema_propagation(replicas):
17431724
note(f"Found {out} replicated tables in {self.context.keeper_type}")
17441725
assert "DB::Exception: No node" in out or out == "0"
17451726

1746-
check_query_log(['SYSTEM DROP REPLICA'], ['DROP TABLE', 'DROP DATABASE'], query_log_start, flags=XFAIL)
1727+
util.check_query_log(chi_name, ['SYSTEM DROP REPLICA'], ['DROP TABLE', 'DROP DATABASE'], query_log_start, flags=XFAIL)
17471728

17481729
with When("Delete chi"):
17491730
kubectl.delete_chi("test-014-replication")
@@ -3789,17 +3770,12 @@ def test_010036(self):
37893770
"""Check clickhouse operator recreates volumes and schema if volume is broken."""
37903771
create_shell_namespace_clickhouse_template()
37913772

3792-
with Given("I create shells"):
3793-
shell = get_shell()
3794-
self.context.shell = shell
3795-
shell_2 = get_shell()
3796-
3797-
manifest = f"manifests/chi/test-036-volume-re-provisioning-1.yaml"
3773+
manifest = "manifests/chi/test-036-volume-re-provisioning-1.yaml"
37983774
chi = yaml_manifest.get_name(util.get_full_path(manifest))
37993775
cluster = "simple"
38003776
util.require_keeper(keeper_type=self.context.keeper_type)
38013777

3802-
with Given("chi exists"):
3778+
with Given("CHI with two replicas is created"):
38033779
kubectl.create_and_check(
38043780
manifest=manifest,
38053781
check={
@@ -3812,33 +3788,31 @@ def test_010036(self):
38123788
wait_for_cluster(chi, cluster, 1, 2)
38133789

38143790
with And("I create replicated table with some data"):
3815-
clickhouse.query(chi, "CREATE DATABASE test_036 ON CLUSTER '{cluster}'")
3791+
clickhouse.query(chi, "CREATE DATABASE IF NOT EXISTS test_036 ON CLUSTER '{cluster}'")
38163792
create_table = """
3817-
CREATE TABLE test_036.test_local_036 ON CLUSTER '{cluster}' (a UInt32)
3793+
CREATE TABLE IF NOT EXISTS test_036.test_local_036 ON CLUSTER '{cluster}' (a UInt32)
38183794
Engine = ReplicatedMergeTree('/clickhouse/{installation}/tables/{shard}/{database}/{table}', '{replica}')
38193795
PARTITION BY tuple()
38203796
ORDER BY a
38213797
""".replace("\r", "").replace("\n", "")
38223798
clickhouse.query(chi, create_table)
38233799
clickhouse.query(chi, f"INSERT INTO test_036.test_local_036 select * from numbers(10000)")
38243800

3825-
clickhouse.query(chi, "CREATE DATABASE test_036_mem ON CLUSTER '{cluster}' Engine = Memory")
3826-
clickhouse.query(chi, "CREATE VIEW test_036_mem.test_view ON CLUSTER '{cluster}' AS SELECT * from system.tables")
3801+
clickhouse.query(chi, "CREATE DATABASE IF NOT EXISTS test_036_mem ON CLUSTER '{cluster}' Engine = Memory")
3802+
clickhouse.query(chi, "CREATE VIEW IF NOT EXISTS test_036_mem.test_view ON CLUSTER '{cluster}' AS SELECT * from system.tables")
38273803

3828-
def delete_pv():
3804+
def delete_pv(volume):
38293805
with When("Delete PV", description="delete PV on replica 0"):
38303806
# Prepare counters
38313807
pvc_count = kubectl.get_count("pvc", chi=chi)
38323808
pv_count = kubectl.get_count("pv")
38333809
print(f"pvc_count: {pvc_count}")
38343810
print(f"pv_count: {pv_count}")
38353811

3836-
pv_name = kubectl.get_pv_name("default-chi-test-036-volume-re-provisioning-simple-0-0-0")
3812+
pv_name = kubectl.get_pv_name(f"{volume}-chi-test-036-volume-re-provisioning-simple-0-0-0")
38373813
# retry
3838-
kubectl.launch(f"delete pv {pv_name} --force &", shell=shell_2)
3839-
kubectl.launch(
3840-
f"""patch pv {pv_name} --type='json' --patch='[{{"op":"remove","path":"/metadata/finalizers"}}]'"""
3841-
)
3814+
kubectl.launch(f"delete pv {pv_name} --force &")
3815+
kubectl.launch(f"""patch pv {pv_name} --type='json' --patch='[{{"op":"remove","path":"/metadata/finalizers"}}]'""")
38423816
# restart pod to make sure volume is unmounted
38433817
kubectl.launch("delete pod chi-test-036-volume-re-provisioning-simple-0-0-0")
38443818
# Give it some time to be deleted
@@ -3852,53 +3826,55 @@ def delete_pv():
38523826
assert new_pvc_count == pvc_count
38533827
assert new_pv_count < pv_count
38543828

3855-
with And("Wait for PVC to detect PV is lost"):
3856-
# Need to add more retries on real kubernetes
3857-
kubectl.wait_field(
3858-
kind="pvc",
3859-
name="default-chi-test-036-volume-re-provisioning-simple-0-0-0",
3860-
field=".status.phase",
3861-
value="Lost",
3862-
)
3829+
with And("Wait for PVC to detect PV is lost"):
3830+
# Need to add more retries on real kubernetes
3831+
kubectl.wait_field(
3832+
kind="pvc",
3833+
name=f"{volume}-chi-test-036-volume-re-provisioning-simple-0-0-0",
3834+
field=".status.phase",
3835+
value="Lost",
3836+
)
38633837

3864-
def delete_sts_and_pvc():
3838+
def delete_sts_and_pvc(volume):
38653839
with When("Delete StatefulSet and PVC", description="delete StatefulSet on replica 0"):
38663840
kubectl.launch("delete sts chi-test-036-volume-re-provisioning-simple-0-0")
3867-
kubectl.launch("delete pvc default-chi-test-036-volume-re-provisioning-simple-0-0-0")
3841+
kubectl.launch(f"delete pvc {volume}-chi-test-036-volume-re-provisioning-simple-0-0-0")
38683842

3869-
with Then("Wait for StatefulSet is deleted"):
3870-
for i in range(5):
3871-
if kubectl.get_count("sts", "chi-test-036-volume-re-provisioning-simple-0-0") == 0:
3872-
break
3873-
time.sleep(10)
3843+
with Then("Wait for StatefulSet is deleted"):
3844+
for i in range(5):
3845+
if kubectl.get_count("sts", "chi-test-036-volume-re-provisioning-simple-0-0") == 0:
3846+
break
3847+
time.sleep(10)
38743848

3875-
with Then("Wait for PVC is deleted"):
3876-
for i in range(5):
3877-
if kubectl.get_count("pvc", "default-chi-test-036-volume-re-provisioning-simple-0-0-0") == 0:
3878-
break
3879-
time.sleep(10)
3849+
with Then("Wait for PVC is deleted"):
3850+
for i in range(5):
3851+
if kubectl.get_count("pvc", f"{volume}-chi-test-036-volume-re-provisioning-simple-0-0-0") == 0:
3852+
break
3853+
time.sleep(10)
38803854

38813855
assert kubectl.get_count("sts", "chi-test-036-volume-re-provisioning-simple-0-0") == 0, "StatefulSet is not deleted"
3882-
assert kubectl.get_count("pvc", "default-chi-test-036-volume-re-provisioning-simple-0-0-0") == 0, "PVC is not deleted"
3856+
assert kubectl.get_count("pvc", f"{volume}-chi-test-036-volume-re-provisioning-simple-0-0-0") == 0, "PVC is not deleted"
38833857

3884-
def delete_pvc():
3885-
with When("Delete PVC", description="delete PVC on replica 0"):
3858+
def delete_pvc(volume):
3859+
with Then("Delete PVC", description="delete PVC on replica 0"):
38863860
# Prepare counters
38873861
pvc_count = kubectl.get_count("pvc", chi=chi)
38883862
pv_count = kubectl.get_count("pv")
38893863
print(f"pvc_count: {pvc_count}")
38903864
print(f"pv_count: {pv_count}")
38913865

3892-
pvc_name = f"default-chi-test-036-volume-re-provisioning-simple-0-0-0"
3866+
pvc_name = f"{volume}-chi-test-036-volume-re-provisioning-simple-0-0-0"
38933867
# retry
3894-
kubectl.launch(f"delete pvc {pvc_name} --force &", shell=shell_2)
3895-
kubectl.launch(
3896-
f"""patch pvc {pvc_name} --type='json' --patch='[{{"op":"remove","path":"/metadata/finalizers"}}]'"""
3897-
)
3868+
kubectl.launch(f"""patch pvc {pvc_name} --type='json' --patch='[{{"op":"remove","path":"/metadata/finalizers"}}]'""")
3869+
kubectl.launch(f"delete pvc {pvc_name} --force &")
3870+
38983871
# restart pod to make sure volume is unmounted
38993872
kubectl.launch("delete pod chi-test-036-volume-re-provisioning-simple-0-0-0")
3900-
# Give it some time to be deleted
3901-
time.sleep(10)
3873+
with Then("Wait for PVC is deleted"):
3874+
for i in range(5):
3875+
if kubectl.get_count("pvc", f"{volume}-chi-test-036-volume-re-provisioning-simple-0-0-0") == 0:
3876+
break
3877+
time.sleep(10)
39023878

39033879
with Then("PVC should be deleted, PV should be deleted as well"):
39043880
new_pvc_count = kubectl.get_count("pvc", chi=chi)
@@ -3908,25 +3884,26 @@ def delete_pvc():
39083884
assert new_pvc_count < pvc_count
39093885
assert new_pv_count < pv_count
39103886

3911-
def check_data_is_recovered(reconcile_task_id):
3912-
with Then(f"Kick operator to start reconcile cycle to fix lost {reconcile_task_id}"):
3887+
def recover_volume(volume, reconcile_task_id):
3888+
with When(f"Kick operator to start reconcile cycle to fix lost {volume} volume"):
39133889
kubectl.force_reconcile(chi, reconcile_task_id)
39143890
wait_for_cluster(chi, cluster, 1, 2)
39153891

3916-
with Then("I check PV is in place"):
3917-
kubectl.wait_field(
3918-
"pvc",
3919-
"default-chi-test-036-volume-re-provisioning-simple-0-0-0",
3920-
".status.phase",
3921-
"Bound",
3922-
)
3923-
kubectl.wait_object(
3924-
"pv",
3925-
kubectl.get_pv_name("default-chi-test-036-volume-re-provisioning-simple-0-0-0"),
3926-
)
3927-
size = kubectl.get_pv_size("default-chi-test-036-volume-re-provisioning-simple-0-0-0")
3928-
assert size == "1Gi", error()
3892+
with Then("I check PV is in place"):
3893+
kubectl.wait_field(
3894+
"pvc",
3895+
f"{volume}-chi-test-036-volume-re-provisioning-simple-0-0-0",
3896+
".status.phase",
3897+
"Bound",
3898+
)
3899+
kubectl.wait_object(
3900+
"pv",
3901+
kubectl.get_pv_name(f"{volume}-chi-test-036-volume-re-provisioning-simple-0-0-0"),
3902+
)
3903+
size = kubectl.get_pv_size(f"{volume}-chi-test-036-volume-re-provisioning-simple-0-0-0")
3904+
assert size == "1Gi", error()
39293905

3906+
def check_data_is_recovered():
39303907
with And("I check data on each replica"):
39313908
for replica in (0,1):
39323909
with By(f"Check that databases exist on replica {replica}"):
@@ -3951,14 +3928,39 @@ def check_data_is_recovered(reconcile_task_id):
39513928
)
39523929
assert r == "1", error()
39533930

3954-
delete_sts_and_pvc()
3955-
check_data_is_recovered("reconcile-after-STS-and-PVC-deleted")
3931+
delete_sts_and_pvc("default")
3932+
recover_volume("default", "reconcile-after-STS-and-PVC-deleted")
3933+
check_data_is_recovered()
39563934

3957-
delete_pvc()
3958-
check_data_is_recovered("reconcile-after-PVC-deleted")
3935+
query_log_start = clickhouse.query(chi, 'select now()')
3936+
delete_pvc("default")
3937+
recover_volume("default", "reconcile-after-PVC-deleted")
3938+
check_data_is_recovered()
3939+
util.check_query_log(chi, ['SYSTEM DROP REPLICA'], [], since = query_log_start)
3940+
3941+
delete_pv("default")
3942+
recover_volume("default", "reconcile-after-PV-deleted")
3943+
check_data_is_recovered()
3944+
3945+
with Then("Add a second disk"):
3946+
kubectl.create_and_check(
3947+
manifest="manifests/chi/test-036-volume-re-provisioning-2.yaml",
3948+
check={
3949+
"apply_templates": {current().context.clickhouse_template},
3950+
"pod_count": 2,
3951+
"do_not_delete": 1,
3952+
},
3953+
)
3954+
wait_for_cluster(chi, cluster, 1, 2)
3955+
with Then("Confirm there are two disks"):
3956+
out = clickhouse.query(chi, "select count() from system.disks")
3957+
assert out == "2"
39593958

3960-
delete_pv()
3961-
check_data_is_recovered("reconcile-after-PV-deleted")
3959+
query_log_start = clickhouse.query(chi, 'select now()')
3960+
delete_pvc("disk2")
3961+
recover_volume("disk2", "reconcile-after-disk2-PVC-deleted")
3962+
check_data_is_recovered()
3963+
util.check_query_log(chi, [], ['SYSTEM DROP REPLICA'], since = query_log_start)
39623964

39633965
with Finally("I clean up"):
39643966
delete_test_namespace()

tests/e2e/util.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import e2e.util as util
99

1010
from testflows.core import fail, Given, Then, But, current, message
11+
from testflows.asserts import error
1112

1213

1314
current_dir = os.path.dirname(os.path.abspath(__file__))
@@ -358,4 +359,23 @@ def require_expandable_storage_class():
358359
assert len(default_storage_class) > 0
359360
allow_volume_expansion = kubectl.get_field("storageclass", default_storage_class, ".allowVolumeExpansion")
360361
if allow_volume_expansion != "true":
361-
kubectl.launch(f"patch storageclass {default_storage_class} -p '{{\"allowVolumeExpansion\":true}}'")
362+
kubectl.launch(f"patch storageclass {default_storage_class} -p '{{\"allowVolumeExpansion\":true}}'")
363+
364+
def check_query_log(chi_name, log, do_not_log, since = '1970-01-01', flags = None):
365+
out = clickhouse.query(chi_name, f"select query, substring(hostname, 1, locate('.', hostname)-1) from cluster('all-sharded', system.query_log) where user = 'clickhouse_operator' and event_time>='{since}'")
366+
for q in log:
367+
found = 0
368+
with Then(f"system.query_log should contain {q} statements", flags = flags):
369+
for l in out.splitlines():
370+
if l.lower().startswith(q.lower()):
371+
found = 1
372+
print(l)
373+
assert found, error(out)
374+
for q in do_not_log:
375+
found = 0
376+
with Then(f"system.query_log should NOT contain {q} statements", flags = flags):
377+
for l in out.splitlines():
378+
if l.lower().startswith(q.lower()):
379+
found = 1
380+
print(l)
381+
assert not found, error(out)

0 commit comments

Comments
 (0)