Skip to content

Commit 0a73743

Browse files
author
Lucas Gameiro
authored
[DPE-5386] Add microceph (local backup) integration test + bump snap version (#633)
* try add ceph test * fix lint * use another dir * fix quotes * fix echo command * fix linting * fix command * fix boto3 client call * fix s3 config * reposition relate operation * remove cleanup * add backup operations * remove DNS workaround for pgbackrest 2.48 * use newer version of pgbackrest * review improvements
1 parent ef94d6c commit 0a73743

File tree

3 files changed

+216
-2
lines changed

3 files changed

+216
-2
lines changed

src/constants.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
(
4242
POSTGRESQL_SNAP_NAME,
4343
{
44-
"revision": {"aarch64": "125", "x86_64": "124"},
44+
"revision": {"aarch64": "132", "x86_64": "133"},
4545
"channel": "14/stable",
4646
},
4747
)

tests/integration/helpers.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1125,7 +1125,6 @@ async def backup_operations(
11251125
await ops_test.model.relate(database_app_name, tls_certificates_app_name)
11261126
async with ops_test.fast_forward(fast_interval="60s"):
11271127
await ops_test.model.wait_for_idle(apps=[database_app_name], status="active", timeout=1000)
1128-
await ops_test.model.relate(database_app_name, s3_integrator_app_name)
11291128

11301129
# Configure and set access and secret keys.
11311130
logger.info(f"configuring S3 integrator for {cloud}")
@@ -1135,6 +1134,8 @@ async def backup_operations(
11351134
**credentials,
11361135
)
11371136
await action.wait()
1137+
1138+
await ops_test.model.relate(database_app_name, s3_integrator_app_name)
11381139
async with ops_test.fast_forward(fast_interval="60s"):
11391140
await ops_test.model.wait_for_idle(
11401141
apps=[database_app_name, s3_integrator_app_name], status="active", timeout=1500
Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
#!/usr/bin/env python3
2+
# Copyright 2024 Canonical Ltd.
3+
# See LICENSE file for licensing details.
4+
import dataclasses
5+
import json
6+
import logging
7+
import os
8+
import socket
9+
import subprocess
10+
import time
11+
12+
import boto3
13+
import botocore.exceptions
14+
import pytest
15+
from pytest_operator.plugin import OpsTest
16+
17+
from . import architecture, markers
18+
from .helpers import (
19+
backup_operations,
20+
)
21+
from .juju_ import juju_major_version
22+
23+
logger = logging.getLogger(__name__)
24+
25+
S3_INTEGRATOR_APP_NAME = "s3-integrator"
26+
if juju_major_version < 3:
27+
tls_certificates_app_name = "tls-certificates-operator"
28+
if architecture.architecture == "arm64":
29+
tls_channel = "legacy/edge"
30+
else:
31+
tls_channel = "legacy/stable"
32+
tls_config = {"generate-self-signed-certificates": "true", "ca-common-name": "Test CA"}
33+
else:
34+
tls_certificates_app_name = "self-signed-certificates"
35+
if architecture.architecture == "arm64":
36+
tls_channel = "latest/edge"
37+
else:
38+
tls_channel = "latest/stable"
39+
tls_config = {"ca-common-name": "Test CA"}
40+
41+
backup_id, value_before_backup, value_after_backup = "", None, None
42+
43+
44+
@dataclasses.dataclass(frozen=True)
45+
class ConnectionInformation:
46+
access_key_id: str
47+
secret_access_key: str
48+
bucket: str
49+
50+
51+
@pytest.fixture(scope="session")
52+
def microceph():
53+
if not os.environ.get("CI") == "true":
54+
raise Exception("Not running on CI. Skipping microceph installation")
55+
logger.info("Setting up TLS certificates")
56+
subprocess.run(["openssl", "genrsa", "-out", "./ca.key", "2048"], check=True)
57+
subprocess.run(
58+
[
59+
"openssl",
60+
"req",
61+
"-x509",
62+
"-new",
63+
"-nodes",
64+
"-key",
65+
"./ca.key",
66+
"-days",
67+
"1024",
68+
"-out",
69+
"./ca.crt",
70+
"-outform",
71+
"PEM",
72+
"-subj",
73+
"/C=US/ST=Denial/L=Springfield/O=Dis/CN=www.example.com",
74+
],
75+
check=True,
76+
)
77+
subprocess.run(["openssl", "genrsa", "-out", "./server.key", "2048"], check=True)
78+
subprocess.run(
79+
[
80+
"openssl",
81+
"req",
82+
"-new",
83+
"-key",
84+
"./server.key",
85+
"-out",
86+
"./server.csr",
87+
"-subj",
88+
"/C=US/ST=Denial/L=Springfield/O=Dis/CN=www.example.com",
89+
],
90+
check=True,
91+
)
92+
host_ip = socket.gethostbyname(socket.gethostname())
93+
subprocess.run(
94+
f'echo "subjectAltName = IP:{host_ip}" > ./extfile.cnf',
95+
shell=True,
96+
check=True,
97+
)
98+
subprocess.run(
99+
[
100+
"openssl",
101+
"x509",
102+
"-req",
103+
"-in",
104+
"./server.csr",
105+
"-CA",
106+
"./ca.crt",
107+
"-CAkey",
108+
"./ca.key",
109+
"-CAcreateserial",
110+
"-out",
111+
"./server.crt",
112+
"-days",
113+
"365",
114+
"-extfile",
115+
"./extfile.cnf",
116+
],
117+
check=True,
118+
)
119+
120+
logger.info("Setting up microceph")
121+
subprocess.run(["sudo", "snap", "install", "microceph", "--revision", "1169"], check=True)
122+
subprocess.run(["sudo", "microceph", "cluster", "bootstrap"], check=True)
123+
subprocess.run(["sudo", "microceph", "disk", "add", "loop,1G,3"], check=True)
124+
subprocess.run(
125+
'sudo microceph enable rgw --ssl-certificate="$(sudo base64 -w0 ./server.crt)" --ssl-private-key="$(sudo base64 -w0 ./server.key)"',
126+
shell=True,
127+
check=True,
128+
)
129+
output = subprocess.run(
130+
[
131+
"sudo",
132+
"microceph.radosgw-admin",
133+
"user",
134+
"create",
135+
"--uid",
136+
"test",
137+
"--display-name",
138+
"test",
139+
],
140+
capture_output=True,
141+
check=True,
142+
encoding="utf-8",
143+
).stdout
144+
key = json.loads(output)["keys"][0]
145+
key_id = key["access_key"]
146+
secret_key = key["secret_key"]
147+
logger.info("Creating microceph bucket")
148+
for attempt in range(3):
149+
try:
150+
boto3.client(
151+
"s3",
152+
endpoint_url=f"https://{host_ip}",
153+
aws_access_key_id=key_id,
154+
aws_secret_access_key=secret_key,
155+
verify="./ca.crt",
156+
).create_bucket(Bucket=_BUCKET)
157+
except botocore.exceptions.EndpointConnectionError:
158+
if attempt == 2:
159+
raise
160+
# microceph is not ready yet
161+
logger.info("Unable to connect to microceph via S3. Retrying")
162+
time.sleep(1)
163+
else:
164+
break
165+
logger.info("Set up microceph")
166+
return ConnectionInformation(key_id, secret_key, _BUCKET)
167+
168+
169+
_BUCKET = "testbucket"
170+
logger = logging.getLogger(__name__)
171+
172+
173+
@pytest.fixture(scope="session")
174+
def cloud_credentials(microceph: ConnectionInformation) -> dict[str, str]:
175+
"""Read cloud credentials."""
176+
return {
177+
"access-key": microceph.access_key_id,
178+
"secret-key": microceph.secret_access_key,
179+
}
180+
181+
182+
@pytest.fixture(scope="session")
183+
def cloud_configs(microceph: ConnectionInformation):
184+
host_ip = socket.gethostbyname(socket.gethostname())
185+
result = subprocess.run(
186+
"sudo base64 -w0 ./ca.crt", shell=True, check=True, stdout=subprocess.PIPE, text=True
187+
)
188+
base64_output = result.stdout
189+
return {
190+
"endpoint": f"https://{host_ip}",
191+
"bucket": microceph.bucket,
192+
"path": "/pg",
193+
"region": "",
194+
"s3-uri-style": "path",
195+
"tls-ca-chain": f"{base64_output}",
196+
}
197+
198+
199+
@pytest.mark.group("ceph")
200+
@markers.amd64_only
201+
async def test_backup_ceph(ops_test: OpsTest, cloud_configs, cloud_credentials, charm) -> None:
202+
"""Build and deploy two units of PostgreSQL in microceph, test backup and restore actions."""
203+
await backup_operations(
204+
ops_test,
205+
S3_INTEGRATOR_APP_NAME,
206+
tls_certificates_app_name,
207+
tls_config,
208+
tls_channel,
209+
cloud_credentials,
210+
"ceph",
211+
cloud_configs,
212+
charm,
213+
)

0 commit comments

Comments
 (0)