Skip to content

Commit ebf4756

Browse files
[MISC] Skip backup tests without creds (#884)
* Bump libs * Skip backups tests if no creds are set * Check that the cloud config is set to a value * Typo * Update tests/integration/conftest.py Co-authored-by: Carl Csaposs <[email protected]> * Switch all checks to gets * Typo --------- Co-authored-by: Carl Csaposs <[email protected]>
1 parent e1684df commit ebf4756

File tree

6 files changed

+120
-231
lines changed

6 files changed

+120
-231
lines changed

lib/charms/tempo_coordinator_k8s/v0/charm_tracing.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,10 @@ def _remove_stale_otel_sdk_packages():
325325
SpanExportResult,
326326
)
327327
from opentelemetry.sdk.trace.export.in_memory_span_exporter import InMemorySpanExporter
328-
from opentelemetry.trace import INVALID_SPAN, Tracer
328+
from opentelemetry.trace import (
329+
INVALID_SPAN,
330+
Tracer,
331+
)
329332
from opentelemetry.trace import get_current_span as otlp_get_current_span
330333
from opentelemetry.trace import (
331334
get_tracer,
@@ -345,7 +348,7 @@ def _remove_stale_otel_sdk_packages():
345348
# Increment this PATCH version before using `charmcraft publish-lib` or reset
346349
# to 0 if you are raising the major API version
347350

348-
LIBPATCH = 6
351+
LIBPATCH = 7
349352

350353
PYDEPS = ["opentelemetry-exporter-otlp-proto-http==1.21.0"]
351354

tests/integration/conftest.py

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,20 @@
11
# Copyright 2022 Canonical Ltd.
22
# See LICENSE file for licensing details.
3+
import logging
4+
import os
5+
import uuid
6+
7+
import boto3
38
import pytest
9+
from pytest_operator.plugin import OpsTest
410

511
from . import architecture
12+
from .helpers import construct_endpoint
13+
14+
AWS = "AWS"
15+
GCP = "GCP"
16+
17+
logger = logging.getLogger(__name__)
618

719

820
@pytest.fixture(scope="session")
@@ -11,3 +23,74 @@ def charm():
1123
# juju bundle files expect local charms to begin with `./` or `/` to distinguish them from
1224
# Charmhub charms.
1325
return f"./[email protected]{architecture.architecture}.charm"
26+
27+
28+
def get_cloud_config(cloud: str) -> tuple[dict[str, str], dict[str, str]]:
29+
# Define some configurations and credentials.
30+
if cloud == AWS:
31+
return {
32+
"endpoint": "https://s3.amazonaws.com",
33+
"bucket": "data-charms-testing",
34+
"path": f"/postgresql-k8s/{uuid.uuid1()}",
35+
"region": "us-east-1",
36+
}, {
37+
"access-key": os.environ["AWS_ACCESS_KEY"],
38+
"secret-key": os.environ["AWS_SECRET_KEY"],
39+
}
40+
elif cloud == GCP:
41+
return {
42+
"endpoint": "https://storage.googleapis.com",
43+
"bucket": "data-charms-testing",
44+
"path": f"/postgresql-k8s/{uuid.uuid1()}",
45+
"region": "",
46+
}, {
47+
"access-key": os.environ["GCP_ACCESS_KEY"],
48+
"secret-key": os.environ["GCP_SECRET_KEY"],
49+
}
50+
51+
52+
def cleanup_cloud(config: dict[str, str], credentials: dict[str, str]) -> None:
53+
# Delete the previously created objects.
54+
logger.info("deleting the previously created backups")
55+
session = boto3.session.Session(
56+
aws_access_key_id=credentials["access-key"],
57+
aws_secret_access_key=credentials["secret-key"],
58+
region_name=config["region"],
59+
)
60+
s3 = session.resource(
61+
"s3", endpoint_url=construct_endpoint(config["endpoint"], config["region"])
62+
)
63+
bucket = s3.Bucket(config["bucket"])
64+
# GCS doesn't support batch delete operation, so delete the objects one by one.
65+
for bucket_object in bucket.objects.filter(Prefix=config["path"].lstrip("/")):
66+
bucket_object.delete()
67+
68+
69+
@pytest.fixture(scope="module")
70+
async def aws_cloud_configs(ops_test: OpsTest) -> None:
71+
if (
72+
not os.environ.get("AWS_ACCESS_KEY", "").strip()
73+
or not os.environ.get("AWS_SECRET_KEY", "").strip()
74+
):
75+
pytest.skip("AWS configs not set")
76+
return
77+
78+
config, credentials = get_cloud_config(AWS)
79+
yield config, credentials
80+
81+
cleanup_cloud(config, credentials)
82+
83+
84+
@pytest.fixture(scope="module")
85+
async def gcp_cloud_configs(ops_test: OpsTest) -> None:
86+
if (
87+
not os.environ.get("GCP_ACCESS_KEY", "").strip()
88+
or not os.environ.get("GCP_SECRET_KEY", "").strip()
89+
):
90+
pytest.skip("GCP configs not set")
91+
return
92+
93+
config, credentials = get_cloud_config(GCP)
94+
yield config, credentials
95+
96+
cleanup_cloud(config, credentials)

tests/integration/test_backups_aws.py

Lines changed: 5 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,16 @@
22
# Copyright 2023 Canonical Ltd.
33
# See LICENSE file for licensing details.
44
import logging
5-
import os
6-
import uuid
75

8-
import boto3
9-
import pytest as pytest
6+
import pytest
107
from pytest_operator.plugin import OpsTest
118
from tenacity import Retrying, stop_after_attempt, wait_exponential
129

1310
from . import architecture
11+
from .conftest import AWS
1412
from .helpers import (
1513
DATABASE_APP_NAME,
1614
backup_operations,
17-
construct_endpoint,
1815
db_connect,
1916
get_password,
2017
get_primary,
@@ -41,60 +38,12 @@
4138

4239
logger = logging.getLogger(__name__)
4340

44-
AWS = "AWS"
45-
GCP = "GCP"
46-
47-
48-
@pytest.fixture(scope="module")
49-
async def cloud_configs(ops_test: OpsTest) -> None:
50-
# Define some configurations and credentials.
51-
configs = {
52-
AWS: {
53-
"endpoint": "https://s3.amazonaws.com",
54-
"bucket": "data-charms-testing",
55-
"path": f"/postgresql-k8s/{uuid.uuid1()}",
56-
"region": "us-east-1",
57-
},
58-
GCP: {
59-
"endpoint": "https://storage.googleapis.com",
60-
"bucket": "data-charms-testing",
61-
"path": f"/postgresql-k8s/{uuid.uuid1()}",
62-
"region": "",
63-
},
64-
}
65-
credentials = {
66-
AWS: {
67-
"access-key": os.environ["AWS_ACCESS_KEY"],
68-
"secret-key": os.environ["AWS_SECRET_KEY"],
69-
},
70-
GCP: {
71-
"access-key": os.environ["GCP_ACCESS_KEY"],
72-
"secret-key": os.environ["GCP_SECRET_KEY"],
73-
},
74-
}
75-
yield configs, credentials
76-
# Delete the previously created objects.
77-
logger.info("deleting the previously created backups")
78-
for cloud, config in configs.items():
79-
session = boto3.session.Session(
80-
aws_access_key_id=credentials[cloud]["access-key"],
81-
aws_secret_access_key=credentials[cloud]["secret-key"],
82-
region_name=config["region"],
83-
)
84-
s3 = session.resource(
85-
"s3", endpoint_url=construct_endpoint(config["endpoint"], config["region"])
86-
)
87-
bucket = s3.Bucket(config["bucket"])
88-
# GCS doesn't support batch delete operation, so delete the objects one by one.
89-
for bucket_object in bucket.objects.filter(Prefix=config["path"].lstrip("/")):
90-
bucket_object.delete()
91-
9241

9342
@pytest.mark.abort_on_fail
94-
async def test_backup_aws(ops_test: OpsTest, charm, cloud_configs: tuple[dict, dict]) -> None:
43+
async def test_backup_aws(ops_test: OpsTest, charm, aws_cloud_configs: tuple[dict, dict]) -> None:
9544
"""Build and deploy two units of PostgreSQL in AWS and then test the backup and restore actions."""
96-
config = cloud_configs[0][AWS]
97-
credentials = cloud_configs[1][AWS]
45+
config = aws_cloud_configs[0]
46+
credentials = aws_cloud_configs[1]
9847

9948
await backup_operations(
10049
ops_test,

tests/integration/test_backups_gcp.py

Lines changed: 13 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,21 @@
22
# Copyright 2023 Canonical Ltd.
33
# See LICENSE file for licensing details.
44
import logging
5-
import os
65
import uuid
76

8-
import boto3
9-
import pytest as pytest
7+
import pytest
108
from lightkube.core.client import Client
119
from lightkube.resources.core_v1 import Pod
1210
from pytest_operator.plugin import OpsTest
1311
from tenacity import Retrying, stop_after_attempt, wait_exponential
1412

1513
from . import architecture
14+
from .conftest import GCP
1615
from .helpers import (
1716
DATABASE_APP_NAME,
1817
backup_operations,
1918
build_and_deploy,
2019
cat_file_from_unit,
21-
construct_endpoint,
2220
db_connect,
2321
get_password,
2422
get_unit_address,
@@ -43,60 +41,12 @@
4341

4442
logger = logging.getLogger(__name__)
4543

46-
AWS = "AWS"
47-
GCP = "GCP"
48-
49-
50-
@pytest.fixture(scope="module")
51-
async def cloud_configs(ops_test: OpsTest) -> None:
52-
# Define some configurations and credentials.
53-
configs = {
54-
AWS: {
55-
"endpoint": "https://s3.amazonaws.com",
56-
"bucket": "data-charms-testing",
57-
"path": f"/postgresql-k8s/{uuid.uuid1()}",
58-
"region": "us-east-1",
59-
},
60-
GCP: {
61-
"endpoint": "https://storage.googleapis.com",
62-
"bucket": "data-charms-testing",
63-
"path": f"/postgresql-k8s/{uuid.uuid1()}",
64-
"region": "",
65-
},
66-
}
67-
credentials = {
68-
AWS: {
69-
"access-key": os.environ["AWS_ACCESS_KEY"],
70-
"secret-key": os.environ["AWS_SECRET_KEY"],
71-
},
72-
GCP: {
73-
"access-key": os.environ["GCP_ACCESS_KEY"],
74-
"secret-key": os.environ["GCP_SECRET_KEY"],
75-
},
76-
}
77-
yield configs, credentials
78-
# Delete the previously created objects.
79-
logger.info("deleting the previously created backups")
80-
for cloud, config in configs.items():
81-
session = boto3.session.Session(
82-
aws_access_key_id=credentials[cloud]["access-key"],
83-
aws_secret_access_key=credentials[cloud]["secret-key"],
84-
region_name=config["region"],
85-
)
86-
s3 = session.resource(
87-
"s3", endpoint_url=construct_endpoint(config["endpoint"], config["region"])
88-
)
89-
bucket = s3.Bucket(config["bucket"])
90-
# GCS doesn't support batch delete operation, so delete the objects one by one.
91-
for bucket_object in bucket.objects.filter(Prefix=config["path"].lstrip("/")):
92-
bucket_object.delete()
93-
9444

9545
@pytest.mark.abort_on_fail
96-
async def test_backup_gcp(ops_test: OpsTest, charm, cloud_configs: tuple[dict, dict]) -> None:
46+
async def test_backup_gcp(ops_test: OpsTest, charm, gcp_cloud_configs: tuple[dict, dict]) -> None:
9747
"""Build and deploy two units of PostgreSQL in GCP and then test the backup and restore actions."""
98-
config = cloud_configs[0][GCP]
99-
credentials = cloud_configs[1][GCP]
48+
config = gcp_cloud_configs[0]
49+
credentials = gcp_cloud_configs[1]
10050

10151
await backup_operations(
10252
ops_test,
@@ -123,7 +73,9 @@ async def test_backup_gcp(ops_test: OpsTest, charm, cloud_configs: tuple[dict, d
12373
)
12474

12575

126-
async def test_restore_on_new_cluster(ops_test: OpsTest, charm) -> None:
76+
async def test_restore_on_new_cluster(
77+
ops_test: OpsTest, charm, gcp_cloud_configs: tuple[dict, dict]
78+
) -> None:
12779
"""Test that is possible to restore a backup to another PostgreSQL cluster."""
12880
previous_database_app_name = f"{DATABASE_APP_NAME}-gcp"
12981
database_app_name = f"new-{DATABASE_APP_NAME}"
@@ -217,7 +169,7 @@ async def test_restore_on_new_cluster(ops_test: OpsTest, charm) -> None:
217169

218170

219171
async def test_invalid_config_and_recovery_after_fixing_it(
220-
ops_test: OpsTest, cloud_configs: tuple[dict, dict]
172+
ops_test: OpsTest, gcp_cloud_configs: tuple[dict, dict]
221173
) -> None:
222174
"""Test that the charm can handle invalid and valid backup configurations."""
223175
database_app_name = f"new-{DATABASE_APP_NAME}"
@@ -251,10 +203,10 @@ async def test_invalid_config_and_recovery_after_fixing_it(
251203
logger.info(
252204
"configuring S3 integrator for a valid cloud, but with the path of another cluster repository"
253205
)
254-
await ops_test.model.applications[S3_INTEGRATOR_APP_NAME].set_config(cloud_configs[0][GCP])
206+
await ops_test.model.applications[S3_INTEGRATOR_APP_NAME].set_config(gcp_cloud_configs[0])
255207
action = await ops_test.model.units.get(f"{S3_INTEGRATOR_APP_NAME}/0").run_action(
256208
"sync-s3-credentials",
257-
**cloud_configs[1][GCP],
209+
**gcp_cloud_configs[1],
258210
)
259211
await action.wait()
260212
await wait_for_idle_on_blocked(
@@ -267,7 +219,7 @@ async def test_invalid_config_and_recovery_after_fixing_it(
267219

268220
# Provide valid backup configurations, with another path in the S3 bucket.
269221
logger.info("configuring S3 integrator for a valid cloud")
270-
config = cloud_configs[0][GCP].copy()
222+
config = gcp_cloud_configs[0].copy()
271223
config["path"] = f"/postgresql-k8s/{uuid.uuid1()}"
272224
await ops_test.model.applications[S3_INTEGRATOR_APP_NAME].set_config(config)
273225
logger.info("waiting for the database charm to become active")
@@ -276,7 +228,7 @@ async def test_invalid_config_and_recovery_after_fixing_it(
276228
)
277229

278230

279-
async def test_delete_pod(ops_test: OpsTest) -> None:
231+
async def test_delete_pod(ops_test: OpsTest, gcp_cloud_configs: tuple[dict, dict]) -> None:
280232
logger.info("Getting original backup config")
281233
database_app_name = f"new-{DATABASE_APP_NAME}"
282234
original_pgbackrest_config = await cat_file_from_unit(

0 commit comments

Comments
 (0)